Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 409 additions & 23 deletions Cargo.Bazel.lock

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ crates_repository(
lockfile = "//:Cargo.Bazel.lock",
manifests = [
"//:Cargo.toml",
"//ecsact:Cargo.toml",
"//ecsact_dylib_runtime:Cargo.toml",
"//ecsact_env:Cargo.toml",
"//ecsact_macro:Cargo.toml",
"//ecsact_rtb:Cargo.toml",
"//ecsact_rust_codegen:Cargo.toml",
"//ecsact_system_execution_context:Cargo.toml",
"//example:Cargo.toml",
"//ecsact:Cargo.toml",
"//ecsact_rust_codegen:Cargo.toml",
],
)

Expand Down
20 changes: 20 additions & 0 deletions ecsact/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ typed_id!(FieldId);
typed_id!(VariantId);
typed_id!(RegistryId);
typed_id!(EntityId);
typed_id!(PlaceholderEntityId);
typed_id!(SystemGeneratesId);
typed_id!(AsyncRequestId);

Expand Down Expand Up @@ -195,18 +196,29 @@ pub trait SystemLike {
}

type ComponentVoidDataCallback<'a> = Box<dyn Fn(EntityId, *const c_void) + 'a>;
type EntityEventCallback<'a> = Box<dyn Fn(EntityId, PlaceholderEntityId) + 'a>;

#[derive(Default)]
pub struct ExecutionEventsCollector<'a> {
pub entity_created_callbacks: Vec<EntityEventCallback<'a>>,
pub init_callbacks:
HashMap<ComponentId, Vec<ComponentVoidDataCallback<'a>>>,
pub update_callbacks:
HashMap<ComponentId, Vec<ComponentVoidDataCallback<'a>>>,
pub remove_callbacks:
HashMap<ComponentId, Vec<ComponentVoidDataCallback<'a>>>,
pub entity_destroyed_callbacks: Vec<EntityEventCallback<'a>>,
}

impl<'a> ExecutionEventsCollector<'a> {
pub fn on_entity_created(
mut self,
callback: &'a dyn Fn(EntityId, PlaceholderEntityId),
) -> Self {
self.entity_created_callbacks.push(Box::new(callback));
self
}

pub fn on_init<C: Component>(
mut self,
callback: &'a dyn Fn(EntityId, &C),
Expand Down Expand Up @@ -255,4 +267,12 @@ impl<'a> ExecutionEventsCollector<'a> {
}));
self
}

pub fn on_entity_destroyed(
mut self,
callback: &'a dyn Fn(EntityId, PlaceholderEntityId),
) -> Self {
self.entity_destroyed_callbacks.push(Box::new(callback));
self
}
}
4 changes: 1 addition & 3 deletions ecsact_dylib_runtime/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ cargo_build_script(
name = "build_script",
srcs = ["build.rs"],
aliases = aliases(),
deps = ["@rules_rust//tools/runfiles"] + all_crate_deps(
deps = ["//ecsact_env"] + all_crate_deps(
build = True,
),
build_script_env = {
"ECSACT_RUNTIME_HEADERS": "$(execpaths @ecsact_runtime//:headers)",
"ECSACT_RUST_DYLIB_CC": "$(execpath src/dylib.cc)",
"ECSACT_RUST_DYLIB_WRAPPER_H": "$(execpath src/dylib_wrapper.h)",
},
data = [
"@ecsact_runtime//:headers",
"src/dylib.cc",
"src/dylib_wrapper.h",
],
Expand Down
5 changes: 5 additions & 0 deletions ecsact_dylib_runtime/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ license = "MIT"
homepage = "https://ecsact.dev"
description = "Ecsact runtime dylib wrappers for rust"

[features]
cargo = []
default = ["cargo"]

[lib]
crate-type = ["rlib"]
bench = false
Expand All @@ -16,6 +20,7 @@ bench = false
ecsact = { path = "../ecsact", version = "0.1.0" }

[build-dependencies]
ecsact_env = { path = "../ecsact_env" }
bindgen = "0.63.0"
cc = "1.0.78"
json = "0.12.4"
Expand Down
39 changes: 4 additions & 35 deletions ecsact_dylib_runtime/build.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,8 @@
extern crate bindgen;

// TODO(zaucy): Optionally include runfiles only while compiling with bazel
use runfiles::Runfiles;
use ecsact_env::sdk_include_dir;
use std::env;
use std::path::PathBuf;
use std::process::Command;

fn ecsact_include_dir() -> String {
// This environment variable is really only for the bazel build. Users should
// just use the `ecsact` command line in their PATH
let rt_headers = env::var("ECSACT_RUNTIME_HEADERS");
if rt_headers.is_ok() {
let runfiles = Runfiles::create().unwrap();
let header = runfiles
.rlocation("ecsact_runtime/ecsact/runtime.h")
.into_os_string()
.into_string()
.unwrap()
.replace("\\", "/");
let header_index = header.find("/ecsact/").unwrap();
let include_dir = &header[..header_index];
return include_dir.into();
}

let ecsact_config = json::parse(&String::from_utf8_lossy(
&Command::new("ecsact")
.arg("config")
.output()
.expect("ecsact config failed")
.stdout,
))
.unwrap();

return ecsact_config["include_dir"].as_str().unwrap().into();
}

fn ecsact_dylib_cc_path() -> String {
env::var("ECSACT_RUST_DYLIB_CC")
Expand All @@ -54,7 +23,7 @@ fn main() {
println!("cargo:rerun-if-changed={}", dylib_wrapper_h_path);
println!("cargo:rerun-if-changed={}", dylib_cc_path);

let include_dir = ecsact_include_dir();
let include_dir = sdk_include_dir();

dbg!(&include_dir);
dbg!(std::env::current_dir()
Expand All @@ -66,7 +35,7 @@ fn main() {
cc::Build::new()
.cpp(true)
.file(dylib_cc_path)
.include(&include_dir)
.include(include_dir.to_str().unwrap())
.define("ECSACT_ASYNC_API_LOAD_AT_RUNTIME", "")
.define("ECSACT_CORE_API_LOAD_AT_RUNTIME", "")
.define("ECSACT_DYNAMIC_API_LOAD_AT_RUNTIME", "")
Expand All @@ -83,7 +52,7 @@ fn main() {
.allowlist_type("ecsact_.*")
.allowlist_function("ecsact_.*")
.newtype_enum("ecsact_.*")
.clang_arg("-I".to_string() + &include_dir)
.clang_arg(format!("-I{}", include_dir.to_str().unwrap()))
.header(dylib_wrapper_h_path)
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
Expand Down
2 changes: 0 additions & 2 deletions ecsact_dylib_runtime/src/dylib_wrapper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#define ECSACT_META_API

#define ECSACT_ASYNC_API_LOAD_AT_RUNTIME
#define ECSACT_CORE_API_LOAD_AT_RUNTIME
#define ECSACT_DYNAMIC_API_LOAD_AT_RUNTIME
Expand Down
16 changes: 16 additions & 0 deletions ecsact_env/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
load("@crate_index//:defs.bzl", "aliases", "all_crate_deps")
load("@rules_rust//rust:defs.bzl", "rust_library")

package(default_visibility = ["//visibility:public"])

rust_library(
name = "ecsact_env",
aliases = aliases(),
srcs = glob(["src/*.rs"]),
deps = ["@rules_rust//tools/runfiles"] + all_crate_deps(
normal = True,
),
data = [
"@ecsact_runtime//:headers",
],
)
5 changes: 5 additions & 0 deletions ecsact_env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
name = "ecsact_env"
version = "0.1.0"
edition = "2021"
readme = "README.md"
repository = "https://github.com/ecsact-dev/ecsact_lang_rust"
license = "MIT"
homepage = "https://ecsact.dev"
description = "Ecsact environment support crate"

[features]
cargo = []
Expand Down
31 changes: 28 additions & 3 deletions ecsact_rtb/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::ffi::OsStr;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
use std::process::{Command, Stdio};
Expand Down Expand Up @@ -49,7 +50,7 @@ impl EcsactRuntimeBuilder {
fn ecsact_codegen(&self) {
// TODO(zaucy): This path is only temporary until the Ecsact SDK with
// the rust codgen is released.
let rust_plugin_path = "../target/debug/ecsact_rust_source_codegen.dll";
let rust_plugin_path = "../target/debug/ecsact_rust_codegen.dll";

let codegen_output = Command::new("ecsact")
.arg("codegen")
Expand Down Expand Up @@ -82,10 +83,22 @@ impl EcsactRuntimeBuilder {
out_dir.to_string() + "/runtime/" + &crate_name + "_ecsact_rt.dll";
let out_tmp = out_dir + "/tmp";
let mut cmd = Command::new("ecsact_rtb");
cmd.current_dir(
std::env::var("CARGO_MANIFEST_DIR")
.expect("CARGO_MANIFEST_DIR unset"),
);
cmd.stdout(Stdio::piped());
cmd.args(&self.srcs);
cmd.arg("--output=".to_string() + &out_rt);
cmd.arg("--temp_dir=".to_string() + &out_tmp);
cmd.arg("--report_format=json".to_string());

let cmd_args_str = cmd
.get_args()
.collect::<Vec<&OsStr>>()
.join(OsStr::new(" "))
.to_string_lossy()
.to_string();
let mut cmd = cmd.spawn().unwrap();

let stdout = cmd.stdout.as_mut().unwrap();
Expand Down Expand Up @@ -134,7 +147,14 @@ impl EcsactRuntimeBuilder {
}
}

cmd.wait().unwrap();
let exit_status = cmd.wait().unwrap();

assert!(
exit_status.success(),
"Ecsact RTB exited with {}\nSubcommand: ecsact_rtb {}",
exit_status.code().unwrap(),
cmd_args_str
);

runtime
}
Expand Down Expand Up @@ -220,7 +240,7 @@ impl EcsactRuntimeBuilder {

for (file_name, file_content) in template_files {
let local_path =
PathBuf::from(self.output_dir.to_string() + "/" + file_name);
PathBuf::from(format!("{}/{}", self.output_dir, file_name));
std::fs::create_dir_all(local_path.parent().unwrap()).unwrap();
// TODO(zaucy): Set readonly permissions to prevent mistakes
std::fs::write(local_path, file_content).unwrap();
Expand All @@ -237,6 +257,11 @@ impl EcsactRuntimeBuilder {
if !target.contains("wasm") {
let output_dir =
std::path::Path::new(&runtime.output).parent().unwrap();
assert!(
std::path::Path::new(&runtime.output).exists(),
"Ecsact runtime '{}' does not exist",
&runtime.output
);
let output_file_no_ext = std::path::Path::new(&runtime.output)
.with_extension("")
.file_name()
Expand Down
32 changes: 32 additions & 0 deletions ecsact_rtb/src/template/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,30 @@ pub fn create_registry(registry_name: &str) -> RegistryId {
unsafe { ecsact_create_registry(registry_name_cstr.as_ptr()).into() }
}

unsafe extern "C" fn c_entity_created_callback_handler(
_event: crate::bindings::ecsact_event,
entity_id: crate::bindings::ecsact_entity_id,
placeholder_entity_id: crate::bindings::ecsact_placeholder_entity_id,
callback_user_data: *mut c_void,
) {
let evc = &*(callback_user_data as *const ecsact::ExecutionEventsCollector);
for cb in &evc.entity_created_callbacks {
cb(entity_id.into(), placeholder_entity_id.into());
}
}

unsafe extern "C" fn c_entity_destroyed_callback_handler(
_event: crate::bindings::ecsact_event,
entity_id: crate::bindings::ecsact_entity_id,
placeholder_entity_id: crate::bindings::ecsact_placeholder_entity_id,
callback_user_data: *mut c_void,
) {
let evc = &*(callback_user_data as *const ecsact::ExecutionEventsCollector);
for cb in &evc.entity_destroyed_callbacks {
cb(entity_id.into(), placeholder_entity_id.into());
}
}

unsafe extern "C" fn c_init_callback_handler(
_event: crate::bindings::ecsact_event,
entity_id: crate::bindings::ecsact_entity_id,
Expand Down Expand Up @@ -98,12 +122,20 @@ pub fn execute_systems(
let user_data =
&mut events_collector.unwrap() as *mut _ as *mut c_void;
c_ev_collector = Some(ecsact_execution_events_collector {
entity_created_callback: Some(
c_entity_created_callback_handler,
),
entity_created_callback_user_data: user_data,
init_callback: Some(c_init_callback_handler),
init_callback_user_data: user_data,
update_callback: Some(c_update_callback_handler),
update_callback_user_data: user_data,
remove_callback: Some(c_remove_callback_handler),
remove_callback_user_data: user_data,
entity_destroyed_callback: Some(
c_entity_destroyed_callback_handler,
),
entity_destroyed_callback_user_data: user_data,
});
}

Expand Down
4 changes: 2 additions & 2 deletions ecsact_rtb/src/wrapper.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#define ECSACT_CORE_API_VISIBILITY __attribute__((visibility("default")))
#define ECSACT_DYNAMIC_API_VISIBILITY __attribute__((visibility("default")))
#define ECSACT_CORE_API __attribute__((visibility("default")))
#define ECSACT_DYNAMIC_API __attribute__((visibility("default")))

#include "ecsact/runtime/core.h"
#include "ecsact/runtime/dynamic.h"
3 changes: 1 addition & 2 deletions ecsact_system_execution_context/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ cargo_build_script(
name = "build_script",
srcs = ["build.rs"],
aliases = aliases(),
deps = ["@rules_rust//tools/runfiles"] + all_crate_deps(
deps = ["//ecsact_env"] + all_crate_deps(
build = True,
),
build_script_env = {
"ECSACT_RUNTIME_HEADERS": "$(execpaths @ecsact_runtime//:headers)",
"ECSACT_RUST_WRAPPER_H": "$(execpath src/wrapper.h)",
},
data = [
Expand Down
1 change: 1 addition & 0 deletions ecsact_system_execution_context/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ edition = "2021"
ecsact = { path = "../ecsact" }

[build-dependencies]
ecsact_env = { path = "../ecsact_env" }
bindgen = "0.63.0"
json = "0.12.4"

Loading