├── .gitignore ├── README.md ├── .vscode ├── update_flecs.sh ├── launch.json └── tasks.json ├── LICENSE ├── examples └── entities │ └── entities_basics.zig └── src ├── flecs.zig └── c.zig /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | src/raw.zig 3 | src/raw_old.zig 4 | src/raw_new.zig 5 | /zig-cache 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zig-flecs 2 | 3 | A semi-thin wrapper around the wonderful ecs [flecs](https://github.com/SanderMertens/flecs) for the [zig](https://ziglang.org) language. 4 | 5 | Flecs version: 3.1.1 6 | 7 | ## Current Goals 8 | - Provide the same functionality as using the flecs C macros using comptime. 9 | - Provide matching zig examples for all C examples to ensure capability. 10 | - Provide a higher level workflow that eases use for creating and using systems, queries, filters and observers. 11 | -------------------------------------------------------------------------------- /.vscode/update_flecs.sh: -------------------------------------------------------------------------------- 1 | echo "----- cd src/c" 2 | cd src/c 3 | 4 | echo "----- translate-c the old flecs.h file" 5 | zig translate-c -lc flecs.h > ../raw_old.zig 6 | 7 | echo "----- download flecs.h and flecs.c" 8 | curl -O https://raw.githubusercontent.com/SanderMertens/flecs/master/flecs.h 9 | curl -O https://raw.githubusercontent.com/SanderMertens/flecs/master/flecs.c 10 | 11 | echo "----- translate-c the new flecs.h file" 12 | zig translate-c -lc flecs.h > ../raw_new.zig 13 | 14 | echo "----- done" -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch Last Target", 6 | "type": "lldb", 7 | "request": "launch", 8 | "program": "${workspaceFolder}/zig-cache/bin/${input:zigLastTarget}", 9 | "args": [], 10 | } 11 | ], 12 | "inputs": [ 13 | { 14 | "id": "zigLastTarget", 15 | "type": "command", 16 | "command": "zig.build.getLastTargetOrPrompt" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Colton Franklin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "options": { 6 | "env": { 7 | "ZIG_SYSTEM_LINKER_HACK": "1" 8 | } 9 | }, 10 | "tasks": [ 11 | { 12 | "label": "Build Project", 13 | "type": "shell", 14 | "command": "zig build", 15 | "problemMatcher": [ 16 | "$gcc" 17 | ], 18 | }, 19 | { 20 | "label": "Build and Run Current Example", 21 | "type": "shell", 22 | "command": "zig build ${fileBasenameNoExtension}", 23 | "problemMatcher": [ 24 | "$gcc" 25 | ], 26 | "group": { 27 | "kind": "build", 28 | "isDefault": true 29 | }, 30 | "presentation": { 31 | "clear": true 32 | } 33 | }, 34 | { 35 | "label": "Build All Examples", 36 | "type": "shell", 37 | "command": "zig build all_examples", 38 | "problemMatcher": [ 39 | "$gcc" 40 | ], 41 | "group": { 42 | "kind": "build", 43 | "isDefault": true 44 | }, 45 | "presentation": { 46 | "clear": true 47 | } 48 | }, 49 | { 50 | "label": "Update Flecs", 51 | "type": "shell", 52 | "command": "zig build update_flecs", 53 | "problemMatcher": [ 54 | "$gcc" 55 | ], 56 | "group": { 57 | "kind": "build", 58 | "isDefault": true 59 | }, 60 | "presentation": { 61 | "clear": true 62 | } 63 | }, 64 | { 65 | "label": "Test Project", 66 | "type": "shell", 67 | "command": "zig build test", 68 | "problemMatcher": [ 69 | "$gcc" 70 | ], 71 | "group": { 72 | "kind": "build", 73 | "isDefault": true 74 | }, 75 | "presentation": { 76 | "clear": true 77 | } 78 | }, 79 | { 80 | "label": "Build and Run Project", 81 | "type": "shell", 82 | "command": "zig build run", 83 | "problemMatcher": [ 84 | "$gcc" 85 | ], 86 | "group": { 87 | "kind": "build", 88 | "isDefault": true 89 | }, 90 | "presentation": { 91 | "clear": true 92 | } 93 | }, 94 | { 95 | "label": "Build and Run Current File", 96 | "type": "shell", 97 | "command": "zig run ${file}", 98 | "problemMatcher": [ 99 | "$gcc" 100 | ], 101 | "presentation": { 102 | "clear": true 103 | }, 104 | "group": { 105 | "kind": "build", 106 | "isDefault": true 107 | } 108 | }, 109 | { 110 | "label": "Build and Run Tests in Current File", 111 | "type": "shell", 112 | "command": "zig test ${file}", 113 | "problemMatcher": [ 114 | "$gcc" 115 | ], 116 | "presentation": { 117 | "clear": true 118 | }, 119 | "group": { 120 | "kind": "build", 121 | "isDefault": true 122 | } 123 | }, 124 | ] 125 | } -------------------------------------------------------------------------------- /examples/entities/entities_basics.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const flecs = @import("flecs"); 3 | const game = @import("game"); 4 | 5 | pub fn system() flecs.EcsSystemDesc { 6 | var desc = std.mem.zeroes(flecs.EcsSystemDesc); 7 | desc.query.filter.terms[0] = std.mem.zeroInit(flecs.EcsTerm, .{ .id = flecs.ecs_id(Position) }); 8 | desc.query.filter.terms[1] = std.mem.zeroInit(flecs.EcsTerm, .{ .id = flecs.ecs_id(Velocity), .oper = flecs.EcsOperKind.ecs_optional }); 9 | desc.query.filter.terms[2] = std.mem.zeroInit(flecs.EcsTerm, .{ .id = flecs.ecs_pair(Likes, Apples)}); 10 | desc.run = run; 11 | return desc; 12 | } 13 | 14 | pub fn run(it: *flecs.EcsIter) callconv(.C) void { 15 | while (flecs.ecs_iter_next(it)) { 16 | var i: usize = 0; 17 | while (i < it.count) : (i += 1) { 18 | const name = flecs.ecs_get_name(it.world.?, it.entities[i]); 19 | if (flecs.ecs_field(it, Position, 1)) |positions| { 20 | if (name != null) { 21 | std.log.debug("{s}'s position: {any}", .{ name, positions[i] }); 22 | } 23 | 24 | positions[i].x += 5.0; 25 | positions[i].y += 5.0; 26 | } 27 | 28 | if (flecs.ecs_field(it, Velocity, 2)) |velocities| { 29 | if (name != null) { 30 | std.log.debug("{s}'s velocity: {any}", .{ name, velocities[i] }); 31 | } 32 | 33 | } 34 | 35 | if (flecs.ecs_field(it, Likes, 3)) |likes| { 36 | if (name != null) { 37 | std.log.debug("{s}'s likes apples how much? {d}!", .{ name, likes[i].amount }); 38 | } 39 | 40 | } 41 | } 42 | } 43 | } 44 | 45 | const Position = struct { x: f32, y: f32 }; 46 | const Walking = struct {}; 47 | const Velocity = struct { x: f32, y: f32 }; 48 | 49 | const Direction = enum { n, s, e, w }; 50 | 51 | const Has = struct {}; 52 | const Apples = struct { count: i32 }; 53 | const Eats = struct { count: i32 }; 54 | const Likes = struct { amount: i32, t: f32 = 0.0 }; 55 | 56 | pub fn main() !void { 57 | var world = flecs.ecs_init().?; 58 | 59 | flecs.ecs_component(world, Position); 60 | flecs.ecs_component(world, Walking); 61 | flecs.ecs_component(world, Velocity); 62 | flecs.ecs_component(world, Has); 63 | flecs.ecs_component(world, Apples); 64 | flecs.ecs_component(world, Eats); 65 | flecs.ecs_component(world, Likes); 66 | flecs.ecs_component(world, Direction); 67 | 68 | // Create an entity with name Bob 69 | const bob = flecs.ecs_new_entity(world, "Bob"); 70 | const jim = flecs.ecs_new_entity(world, "Jim"); 71 | 72 | // The set operation finds or creates a component, and sets it. 73 | flecs.ecs_set(world, bob, &Position{ .x = 10, .y = 20 }); 74 | flecs.ecs_set(world, bob, &Velocity{ .x = 1, .y = 2 }); 75 | 76 | flecs.ecs_set(world, jim, &Position{ .x = 10, .y = 20 }); 77 | flecs.ecs_set(world, jim, &Velocity{ .x = 1, .y = 2 }); 78 | 79 | // The add operation adds a component without setting a value. This is 80 | // useful for tags, or when adding a component with its default value. 81 | //flecs.ecs_add(world, bob, Walking); 82 | 83 | flecs.ecs_add(world, bob, Direction.e); 84 | 85 | if (flecs.ecs_get(world, bob, Direction)) |direction| { 86 | std.log.debug("bob's direction: {any}", .{ direction }); 87 | } 88 | 89 | flecs.ecs_add(world, bob, Direction.s); 90 | 91 | if (flecs.ecs_get(world, bob, Direction)) |direction| { 92 | std.log.debug("bob's direction: {any}", .{ direction }); 93 | } 94 | // Get the value for the Position component 95 | if (flecs.ecs_get(world, bob, Position)) |position| { 96 | std.log.debug("position: {any}", .{position}); 97 | } 98 | 99 | // Overwrite the value of the Position component 100 | flecs.ecs_set(world, bob, &Position{ .x = 20.0, .y = 30.0 }); 101 | 102 | if (flecs.ecs_get(world, bob, Position)) |position| { 103 | std.log.debug("position: {any}", .{position}); 104 | } 105 | 106 | const person = flecs.ecs_new_prefab(world, "Person"); 107 | flecs.ecs_add(world, person, Position); 108 | flecs.ecs_override(world, person, Position); 109 | flecs.ecs_set(world, person, &Velocity{ .x = 5, .y = 5}); 110 | flecs.ecs_add(world, person, Walking); 111 | 112 | // Create another named entity 113 | const alice = flecs.ecs_new_entity(world, "Alice"); 114 | flecs.ecs_add_pair(world, alice, flecs.Constants.EcsIsA, person); 115 | 116 | flecs.ecs_set_pair_second(world, alice, Has, &Apples{ .count = 5 }); 117 | 118 | if (flecs.ecs_get_pair_second(world, alice, Has, Apples)) |apples| { 119 | std.log.debug("Alice has {d} apples!", .{apples.count}); 120 | } 121 | 122 | flecs.ecs_set_pair(world, alice, &Eats{ 123 | .count = 2, 124 | }, Apples); 125 | 126 | if (flecs.ecs_get_pair(world, alice, Eats, Apples)) |eats| { 127 | std.log.debug("Alice eats {d} apples!", .{eats.count}); 128 | } 129 | 130 | flecs.ecs_set_pair(world, alice, Likes{ .amount = 10 }, bob); 131 | flecs.ecs_set_pair(world, alice, Likes{ .amount = 4 }, Apples); 132 | 133 | if (flecs.ecs_get_pair(world, alice, Likes, bob)) |b| { 134 | std.log.debug("How much does Alice like bob? {d}", .{b.amount}); 135 | } 136 | 137 | if (flecs.ecs_get_pair(world, alice, Likes, flecs.Constants.EcsWildcard)) |likes| { 138 | std.log.debug("Alice likes someone how much? {d}", .{likes.amount}); 139 | } 140 | 141 | const entities = flecs.ecs_bulk_new(world, Apples, 10); 142 | 143 | for (entities) |entity, i| { 144 | if (flecs.ecs_get(world, entity, Apples)) |apples| { 145 | std.log.debug("Bulk Entity {d}: {d} apples!", .{ i, apples.count }); 146 | } 147 | } 148 | 149 | var system_desc = system(); 150 | flecs.ecs_system(world, "Testing!", flecs.Constants.EcsOnUpdate, &system_desc); 151 | _ = flecs.ecs_progress(world, 0); 152 | 153 | //_ = flecs.ecs_fini(world); 154 | 155 | // TODO: add a getType method and wrapper for flecs types 156 | // Print all the components the entity has. This will output: 157 | // Position, Walking, (Identifier,Name) 158 | // const alice_type = alice.getType(); 159 | 160 | // // Remove tag 161 | // alice.remove(Walking); 162 | 163 | // // Iterate all entities with Position 164 | // var term = flecs.Term(Position).init(world); 165 | // defer term.deinit(); 166 | // var it = term.iterator(); 167 | 168 | // while (it.next()) |position| { 169 | // std.log.debug("{s}: {d}", .{ it.entity().getName(), position }); 170 | // } 171 | 172 | // world.deinit(); 173 | } 174 | -------------------------------------------------------------------------------- /src/flecs.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const c = @import("c.zig"); 3 | 4 | // Import wrapper function 5 | pub usingnamespace c; 6 | 7 | /// Returns the base type of the given type, useful for pointers. 8 | pub fn BaseType(comptime T: type) type { 9 | switch (@typeInfo(T)) { 10 | .Pointer => |info| switch (info.size) { 11 | .One => if (validComponentType(info.child)) return info.child, 12 | else => {}, 13 | }, 14 | .Optional => |opt_info| switch (@typeInfo(opt_info.child)) { 15 | .Pointer => |info| switch (info.size) { 16 | .One => if (validComponentType(info.child)) return info.child, 17 | else => {}, 18 | }, 19 | else => {}, 20 | }, 21 | .Enum, .Struct, .Union => return T, 22 | else => {}, 23 | } 24 | @compileError("Expected pointer or optional pointer to container type, found '" ++ @typeName(T) ++ "'"); 25 | } 26 | 27 | inline fn validComponentType(comptime T: type) bool { 28 | return comptime switch (@typeInfo(T)) { 29 | .Enum, .Struct, .Union => true, 30 | else => false, 31 | }; 32 | } 33 | 34 | /// Casts the anyopaque pointer to a const pointer of the given type. 35 | pub fn ecs_cast(comptime T: type, val: ?*const anyopaque) *const T { 36 | return @ptrCast(*const T, @alignCast(@alignOf(T), val)); 37 | } 38 | 39 | /// Casts the anyopaque pointer to a pointer of the given type. 40 | pub fn ecs_cast_mut(comptime T: type, val: ?*anyopaque) *T { 41 | return @ptrCast(*T, @alignCast(@alignOf(T), val)); 42 | } 43 | 44 | fn IdHandle(comptime T: type) type { 45 | comptime std.debug.assert(validComponentType(T)); 46 | return struct { 47 | var handle: c.EcsId = 0; 48 | }; 49 | } 50 | 51 | /// Returns a pointer to the EcsId of the given type. 52 | pub inline fn ecs_id_handle(comptime T: type) *c.EcsId { 53 | return comptime &IdHandle(T).handle; 54 | } 55 | 56 | /// Returns the id assigned to the given type. 57 | pub inline fn ecs_id(comptime T: type) c.EcsId { 58 | return ecs_id_handle(T).*; 59 | } 60 | 61 | /// Returns the full id of the first element of the pair. 62 | pub fn ecs_pair_first(pair: c.EcsId) c.EcsId { 63 | return @intCast(c.EcsId, @truncate(u32, (pair & c.Constants.ECS_COMPONENT_MASK) >> 32)); 64 | } 65 | 66 | /// returns the full id of the second element of the pair. 67 | pub fn ecs_pair_second(pair: c.EcsId) c.EcsId { 68 | return @intCast(c.EcsId, @truncate(u32, pair)); 69 | } 70 | 71 | /// Returns an EcsId for the given pair. 72 | /// 73 | /// first = EcsEntity or type 74 | /// second = EcsEntity or type 75 | pub fn ecs_pair(first: anytype, second: anytype) c.EcsId { 76 | const First = @TypeOf(first); 77 | const Second = @TypeOf(second); 78 | 79 | const first_type_info = @typeInfo(First); 80 | const second_type_info = @typeInfo(Second); 81 | 82 | comptime std.debug.assert(First == c.EcsEntity or First == type or first_type_info == .Enum); 83 | comptime std.debug.assert(Second == c.EcsEntity or Second == type or second_type_info == .Enum); 84 | 85 | const first_id = if (First == c.EcsEntity) first else if (first_type_info == .Enum) ecs_id(First) else ecs_id(first); 86 | const second_id = if (Second == c.EcsEntity) second else if (second_type_info == .Enum) ecs_id(Second) else ecs_id(second); 87 | return c.ecs_make_pair(first_id, second_id); 88 | } 89 | 90 | /// Registers the given type as a new component. 91 | pub fn ecs_component(world: *c.EcsWorld, comptime T: type) void { 92 | const handle = ecs_id_handle(T); 93 | 94 | const entity_desc = std.mem.zeroInit(c.EcsEntityDesc, .{ 95 | .name = @typeName(T), 96 | .id = handle.*, 97 | .use_low_id = true, 98 | }); 99 | 100 | const component_desc = std.mem.zeroInit(c.EcsComponentDesc, .{ 101 | .entity = c.ecs_entity_init(world, &entity_desc), 102 | .type = .{ 103 | .alignment = @alignOf(T), 104 | .size = @sizeOf(T), 105 | }, 106 | }); 107 | 108 | handle.* = c.ecs_component_init(world, &component_desc); 109 | } 110 | 111 | /// Registers a new system with the world run during the given phase. 112 | pub fn ecs_system(world: *c.EcsWorld, name: [*:0]const u8, phase: c.EcsEntity, desc: *c.EcsSystemDesc) void { 113 | var entity_desc = std.mem.zeroes(c.EcsEntityDesc); 114 | entity_desc.id = c.ecs_new_id(world); 115 | entity_desc.name = name; 116 | entity_desc.add[0] = ecs_dependson(phase); 117 | entity_desc.add[1] = phase; 118 | desc.entity = c.ecs_entity_init(world, &entity_desc); 119 | _ = c.ecs_system_init(world, desc); 120 | } 121 | 122 | /// Registers a new observer with the world. 123 | pub fn ecs_observer(world: *c.EcsWorld, name: [*:0]const u8, desc: *c.EcsObserverDesc) void { 124 | var entity_desc = std.mem.zeroes(c.EcsEntityDesc); 125 | entity_desc.id = c.ecs_new_id(world); 126 | entity_desc.name = name; 127 | desc.entity = c.ecs_entity_init(world, &entity_desc); 128 | _ = c.ecs_observer_init(world, desc); 129 | } 130 | 131 | // - New 132 | 133 | /// Returns a new entity with the given component. Pass null if no component is desired. 134 | pub fn ecs_new(world: *c.EcsWorld, comptime T: ?type) c.EcsEntity { 135 | if (T) |Type| { 136 | return c.ecs_new_w_id(world, ecs_id(Type)); 137 | } 138 | 139 | return c.ecs_new_id(world); 140 | } 141 | 142 | /// Returns a new entity with the given pair. 143 | /// 144 | /// first = EcsEntity or type 145 | /// second = EcsEntity or type 146 | pub fn ecs_new_w_pair(world: *c.EcsWorld, first: anytype, second: anytype) c.EcsEntity { 147 | return c.ecs_new_w_id(world, ecs_pair(first, second)); 148 | } 149 | 150 | /// Creates count entities in bulk with the given component, returning an array of those entities. 151 | /// Pass null for the component if none is desired. 152 | pub fn ecs_bulk_new(world: *c.EcsWorld, comptime Component: ?type, count: i32) []const c.EcsEntity { 153 | if (Component) |T| { 154 | return c.ecs_bulk_new_w_id(world, ecs_id(T), count)[0..@intCast(usize, count)]; 155 | } 156 | 157 | return c.ecs_bulk_new_w_id(world, 0, count)[0..@intCast(usize, count)]; 158 | } 159 | 160 | /// Returns a new entity with the given name. 161 | pub fn ecs_new_entity(world: *c.EcsWorld, name: [*:0]const u8) c.EcsEntity { 162 | const desc = std.mem.zeroInit(c.EcsEntityDesc, .{ .name = name }); 163 | return c.ecs_entity_init(world, &desc); 164 | } 165 | 166 | /// Returns a new prefab with the given name. 167 | pub fn ecs_new_prefab(world: *c.EcsWorld, name: [*:0]const u8) c.EcsEntity { 168 | var desc = std.mem.zeroInit(c.EcsEntityDesc, .{ .name = name }); 169 | desc.add[0] = c.Constants.EcsPrefab; 170 | return c.ecs_entity_init(world, &desc); 171 | } 172 | 173 | // - Add 174 | 175 | /// Adds a component to the entity. If the type is a non-zero struct, the values may be undefined! 176 | pub fn ecs_add(world: *c.EcsWorld, entity: c.EcsEntity, t: anytype) void { 177 | const T = @TypeOf(t); 178 | if (T == type) { 179 | c.ecs_add_id(world, entity, ecs_id(t)); 180 | } else { 181 | _ = c.ecs_set_id(world, entity, ecs_id(T), @sizeOf(T), &t); 182 | } 183 | } 184 | 185 | /// Adds the pair to the entity. 186 | /// 187 | /// first = EcsEntity or type 188 | /// second = EcsEntity or type 189 | pub fn ecs_add_pair(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, second: anytype) void { 190 | const First = @TypeOf(first); 191 | 192 | if (@typeInfo(First) == .Enum) { 193 | _ = c.ecs_set_id(world, entity, ecs_pair(first, second), @sizeOf(First), &first); 194 | } else c.ecs_add_id(world, entity, ecs_pair(first, second)); 195 | } 196 | 197 | // - Remove 198 | 199 | /// Removes the component or entity from the entity. 200 | /// 201 | /// t = EcsEntity or Type 202 | pub fn ecs_remove(world: *c.EcsWorld, entity: c.EcsEntity, t: anytype) void { 203 | const T = @TypeOf(t); 204 | 205 | const id = if (T == c.EcsEntity) t else ecs_id(T); 206 | c.ecs_remove_id(world, entity, id); 207 | } 208 | 209 | /// Removes the pair from the entity. 210 | /// 211 | /// first = EcsEntity or type 212 | /// second = EcsEntity or type 213 | pub fn ecs_remove_pair(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, second: anytype) void { 214 | c.ecs_remove_id(world, entity, ecs_pair(first, second)); 215 | } 216 | 217 | // - Override 218 | 219 | /// Overrides the component on the entity. 220 | pub fn ecs_override(world: *c.EcsWorld, entity: c.EcsEntity, comptime T: type) void { 221 | c.ecs_override_id(world, entity, ecs_id(T)); 222 | } 223 | 224 | /// Overrides the pair on the entity. 225 | /// 226 | /// first = EcsEntity or type 227 | /// second = EcsEntity or type 228 | pub fn ecs_override_pair(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, second: anytype) void { 229 | c.ecs_override_id(world, entity, ecs_pair(first, second)); 230 | } 231 | 232 | // Bulk remove/delete 233 | 234 | /// Deletes all children from parent entity. 235 | pub fn ecs_delete_children(world: *c.EcsWorld, parent: c.EcsEntity) void { 236 | c.ecs_delete_with(world, ecs_pair(c.Constants.EcsChildOf, parent)); 237 | } 238 | 239 | // - Set 240 | 241 | /// Sets the component on the entity. If the component is not already added, it will automatically be added and set. 242 | pub fn ecs_set(world: *c.EcsWorld, entity: c.EcsEntity, t: anytype) void { 243 | const T = BaseType(@TypeOf(t)); 244 | comptime std.debug.assert(@typeInfo(@TypeOf(t)) == .Pointer or @TypeOf(t) == T); 245 | const ptr = if (@typeInfo(@TypeOf(t)) == .Pointer) t else &t; 246 | _ = c.ecs_set_id(world, entity, ecs_id(T), @sizeOf(T), ptr); 247 | } 248 | 249 | /// Sets the component on the first element of the pair. If the component is not already added, it will automatically be added and set. 250 | /// 251 | /// first = pointer or struct 252 | /// second = type or EcsEntity 253 | pub fn ecs_set_pair(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, second: anytype) void { 254 | const First = @TypeOf(first); 255 | const FirstT = BaseType(First); 256 | 257 | comptime std.debug.assert(@typeInfo(First) == .Pointer or First == FirstT); 258 | comptime std.debug.assert(@sizeOf(FirstT) > 0); 259 | 260 | const pair_id = ecs_pair(FirstT, second); 261 | const ptr = if (@typeInfo(First) == .Pointer) first else &first; 262 | 263 | _ = c.ecs_set_id(world, entity, pair_id, @sizeOf(FirstT), ptr); 264 | } 265 | 266 | /// Sets the component on the second element of the pair. If the component is not already added, it will automatically be added and set. 267 | /// 268 | /// first = type or EcsEntity 269 | /// second = pointer or struct 270 | pub fn ecs_set_pair_second(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, second: anytype) void { 271 | const Second = @TypeOf(second); 272 | const SecondT = BaseType(Second); 273 | 274 | comptime std.debug.assert(@typeInfo(Second) == .Pointer or Second == SecondT); 275 | comptime std.debug.assert(@sizeOf(SecondT) > 0); 276 | 277 | const pair_id = ecs_pair(first, SecondT); 278 | const ptr = if (@typeInfo(Second) == .Pointer) second else &second; 279 | 280 | if (@TypeOf(first) == type and @sizeOf(first) > 0) { 281 | @compileError("Cannot set second element of a pair when the first element is a component (" ++ @typeName(first) ++ ")"); 282 | } 283 | 284 | _ = c.ecs_set_id(world, entity, pair_id, @sizeOf(SecondT), ptr); 285 | } 286 | 287 | // - Get 288 | 289 | /// Gets an optional const pointer to the given component type on the entity. 290 | pub fn ecs_get(world: *c.EcsWorld, entity: c.EcsEntity, comptime T: type) ?*const T { 291 | if (c.ecs_get_id(world, entity, ecs_id(T))) |ptr| { 292 | return ecs_cast(T, ptr); 293 | } 294 | return null; 295 | } 296 | 297 | /// Gets an optional pointer to the given component type on the entity. 298 | pub fn ecs_get_mut(world: *c.EcsWorld, entity: c.EcsEntity, comptime T: type) ?*T { 299 | if (c.ecs_get_mut_id(world, entity, ecs_id(T))) |ptr| { 300 | return ecs_cast_mut(T, ptr); 301 | } 302 | return null; 303 | } 304 | 305 | /// Gets an optional pointer to the first element of the pair. 306 | /// 307 | /// First = type 308 | /// second = type or entity 309 | pub fn ecs_get_pair(world: *c.EcsWorld, entity: c.EcsEntity, comptime First: type, second: anytype) ?*const First { 310 | comptime std.debug.assert(validComponentType(First) and @sizeOf(First) > 0); 311 | 312 | const Second = @TypeOf(second); 313 | comptime std.debug.assert(Second == c.EcsEntity or Second == type); 314 | 315 | if (c.ecs_get_id(world, entity, ecs_pair(First, second))) |ptr| { 316 | return ecs_cast(First, ptr); 317 | } 318 | return null; 319 | } 320 | 321 | /// Gets an optional pointer to the second element of the pair. 322 | /// 323 | /// first = type or entity 324 | /// Second = type 325 | pub fn ecs_get_pair_second(world: *c.EcsWorld, entity: c.EcsEntity, first: anytype, comptime Second: type) ?*const Second { 326 | comptime std.debug.assert(validComponentType(Second) and @sizeOf(Second) > 0); 327 | 328 | const First = @TypeOf(first); 329 | comptime std.debug.assert(First == c.EcsEntity or First == type); 330 | 331 | if (c.ecs_get_id(world, entity, ecs_pair(first, Second))) |ptr| { 332 | return ecs_cast(Second, ptr); 333 | } 334 | return null; 335 | } 336 | 337 | // - Iterators 338 | 339 | /// Returns an optional slice for the type given the field location. 340 | /// Use the entity's index from the iterator to access component. 341 | pub fn ecs_field(it: *c.EcsIter, comptime T: type, index: usize) ?[]T { 342 | if (c.ecs_field_w_size(it, @sizeOf(T), @intCast(i32, index))) |ptr| { 343 | const c_ptr = @ptrCast([*]T, @alignCast(@alignOf(T), ptr)); 344 | return c_ptr[0..@intCast(usize, it.count)]; 345 | } 346 | return null; 347 | } 348 | 349 | // - Utilities for commonly used operations 350 | 351 | /// Returns a pair id for isa e. 352 | pub fn ecs_isa(e: anytype) c.EcsId { 353 | return ecs_pair(c.Constants.EcsIsA, e); 354 | } 355 | 356 | /// Returns a pair id for child of e. 357 | pub fn ecs_childof(e: anytype) c.EcsId { 358 | return ecs_pair(c.Constants.EcsChildOf, e); 359 | } 360 | 361 | /// Returns a pair id for depends on e. 362 | pub fn ecs_dependson(e: anytype) c.EcsId { 363 | return ecs_pair(c.Constants.EcsDependsOn, e); 364 | } 365 | -------------------------------------------------------------------------------- /src/c.zig: -------------------------------------------------------------------------------- 1 | const builtin = @import("builtin"); 2 | 3 | pub const EcsInOutKind = enum(c_int) { 4 | ecs_in_out_default, 5 | ecs_in_out_none, 6 | ecs_in_out, 7 | ecs_in, 8 | ecs_out, 9 | }; 10 | 11 | pub const EcsOperKind = enum(c_int) { 12 | ecs_and, 13 | ecs_or, 14 | ecs_not, 15 | ecs_optional, 16 | ecs_and_from, 17 | ecs_or_from, 18 | ecs_not_from, 19 | }; 20 | 21 | pub const EcsEntityDesc = extern struct { 22 | _canary: i32, 23 | id: u64, 24 | name: [*c]const u8, 25 | sep: [*c]const u8, 26 | root_sep: [*c]const u8, 27 | symbol: [*c]const u8, 28 | use_low_id: bool, 29 | add: [32]u64, 30 | add_expr: [*c]const u8, 31 | }; 32 | 33 | pub const EcsId = u64; 34 | pub const EcsFlags8 = u8; 35 | pub const EcsFlags32 = u32; 36 | pub const EcsFlags64 = u64; 37 | pub const EcsEntity = u64; 38 | pub const EcsSize = i32; 39 | 40 | pub const EcsMixins = opaque {}; 41 | 42 | pub const EcsTermId = extern struct { 43 | id: EcsEntity, 44 | name: [*c]u8, 45 | trav: EcsEntity, 46 | flags: EcsFlags32, 47 | }; 48 | 49 | pub const EcsTerm = extern struct { 50 | id: EcsId, 51 | src: EcsTermId, 52 | first: EcsTermId, 53 | second: EcsTermId, 54 | inout: EcsInOutKind, 55 | oper: EcsOperKind, 56 | id_flags: EcsId, 57 | name: [*c]u8, 58 | field_index: i32, 59 | idr: ?*EcsIdRecord, 60 | move: bool, 61 | }; 62 | 63 | pub const EcsHeader = extern struct { 64 | magic: i32, 65 | type: i32, 66 | mixins: ?*EcsMixins, 67 | }; 68 | 69 | pub const EcsTable = opaque {}; 70 | 71 | pub const EcsTableRange = extern struct { 72 | table: ?*EcsTable, 73 | offset: i32, 74 | count: i32, 75 | }; 76 | 77 | pub const EcsVar = extern struct { 78 | range: EcsTableRange, 79 | entity: EcsEntity, 80 | }; 81 | 82 | pub const EcsTableRecord = opaque {}; 83 | 84 | pub const EcsRecord = extern struct { 85 | idr: ?*EcsIdRecord, 86 | table: ?*EcsTable, 87 | row: u32, 88 | }; 89 | 90 | pub const EcsIdRecord = opaque {}; 91 | 92 | pub const EcsRef = extern struct { 93 | entity: EcsEntity, 94 | id: EcsEntity, 95 | tr: ?*EcsTableRecord, 96 | record: [*c]EcsRecord, 97 | }; 98 | 99 | pub const EcsTableCacheHdr = opaque {}; 100 | 101 | pub const EcsTableCacheIter = extern struct { 102 | cur: ?*EcsTableCacheHdr, 103 | next: ?*EcsTableCacheHdr, 104 | next_list: ?*EcsTableCacheHdr, 105 | }; 106 | 107 | pub const EcsTermIter = extern struct { 108 | term: EcsTerm, 109 | self_index: ?*EcsIdRecord, 110 | set_index: ?*EcsIdRecord, 111 | cur: ?*EcsIdRecord, 112 | it: EcsTableCacheIter, 113 | index: i32, 114 | observed_table_count: i32, 115 | table: ?*EcsTable, 116 | cur_match: i32, 117 | match_count: i32, 118 | last_column: i32, 119 | empty_tables: bool, 120 | id: EcsId, 121 | column: i32, 122 | subject: EcsEntity, 123 | size: EcsSize, 124 | ptr: ?*anyopaque, 125 | }; 126 | 127 | pub const EcsIterKind = enum(c_int) { 128 | ecs_iter_eval_condition, 129 | ecs_iter_eval_tables, 130 | ecs_iter_eval_chain, 131 | ecs_iter_eval_none, 132 | }; 133 | 134 | pub const EcsFilterIter = extern struct { 135 | filter: [*c]const EcsFilter, 136 | kind: EcsIterKind, 137 | term_iter: EcsTermIter, 138 | matches_left: i32, 139 | pivot_term: i32, 140 | }; 141 | 142 | pub const EcsQuery = opaque {}; 143 | pub const EcsQueryTableNode = opaque {}; 144 | 145 | pub const EcsQueryIter = extern struct { 146 | query: ?*EcsQuery, 147 | node: ?*EcsQueryTableNode, 148 | prev: ?*EcsQueryTableNode, 149 | last: ?*EcsQueryTableNode, 150 | sparse_smallest: i32, 151 | sparse_first: i32, 152 | bitset_first: i32, 153 | skip_count: i32, 154 | }; 155 | 156 | pub const EcsRule = opaque {}; 157 | pub const EcsRuleOpCtx = opaque {}; 158 | 159 | pub const EcsRuleIter = extern struct { 160 | rule: ?*const EcsRule, 161 | registers: [*c]EcsVar, 162 | op_ctx: ?*EcsRuleOpCtx, 163 | columns: [*c]i32, 164 | entity: EcsEntity, 165 | redo: bool, 166 | op: i32, 167 | sp: i32, 168 | }; 169 | 170 | pub const EcsVector = opaque {}; 171 | 172 | pub const EcsSnapshotIter = extern struct { 173 | filter: EcsFilter, 174 | tables: ?*EcsVector, 175 | index: i32, 176 | }; 177 | 178 | pub const EcsPageIter = extern struct { 179 | offset: i32, 180 | limit: i32, 181 | remaining: i32, 182 | }; 183 | 184 | pub const EcsWorkerIter = extern struct { 185 | index: i32, 186 | count: i32, 187 | }; 188 | 189 | // TODO: hunt down what this is actually named or should be named 190 | const union_unnamed_1 = extern union { 191 | term: EcsTermIter, 192 | filter: EcsFilterIter, 193 | query: EcsQueryIter, 194 | rule: EcsRuleIter, 195 | snapshot: EcsSnapshotIter, 196 | page: EcsPageIter, 197 | worker: EcsWorkerIter, 198 | }; 199 | 200 | pub const EcsStackPage = opaque {}; 201 | 202 | pub const EcsStackCursor = extern struct { 203 | cur: ?*EcsStackPage, 204 | sp: i16, 205 | }; 206 | 207 | pub const EcsIterCache = extern struct { 208 | stack_cursor: EcsStackCursor, 209 | used: EcsFlags8, 210 | allocated: EcsFlags8, 211 | }; 212 | 213 | pub const EcsIterPrivate = extern struct { 214 | iter: union_unnamed_1, 215 | cache: EcsIterCache, 216 | }; 217 | 218 | pub const EcsIterNextAction = if (builtin.zig_backend == .stage1) fn ([*c]EcsIter) callconv(.C) bool else *const fn ([*c]EcsIter) callconv(.C) bool; 219 | pub const EcsIterAction = if (builtin.zig_backend == .stage1) fn (*EcsIter) callconv(.C) void else *const fn (*EcsIter) callconv(.C) void; 220 | pub const EcsIterFiniAction = if (builtin.zig_backend == .stage1) fn ([*c]EcsIter) callconv(.C) void else *const fn ([*c]EcsIter) callconv(.C) void; 221 | 222 | pub const EcsIter = extern struct { 223 | world: ?*EcsWorld, 224 | real_world: ?*EcsWorld, 225 | entities: [*c]EcsEntity, 226 | ptrs: [*c]?*anyopaque, 227 | sizes: [*c]EcsSize, 228 | table: ?*EcsTable, 229 | other_table: ?*EcsTable, 230 | ids: [*c]EcsId, 231 | variables: [*c]EcsVar, 232 | columns: [*c]i32, 233 | sources: [*c]EcsEntity, 234 | match_indices: [*c]i32, 235 | references: [*c]EcsRef, 236 | constrained_vars: EcsFlags64, 237 | group_id: u64, 238 | field_count: i32, 239 | system: EcsEntity, 240 | event: EcsEntity, 241 | event_id: EcsId, 242 | terms: [*c]EcsTerm, 243 | table_count: i32, 244 | term_index: i32, 245 | variable_count: i32, 246 | variable_names: [*c][*c]u8, 247 | param: ?*anyopaque, 248 | ctx: ?*anyopaque, 249 | binding_ctx: ?*anyopaque, 250 | delta_time: f32, 251 | delta_system_time: f32, 252 | frame_offset: i32, 253 | offset: i32, 254 | count: i32, 255 | instance_count: i32, 256 | flags: EcsFlags32, 257 | interrupted_by: EcsEntity, 258 | priv: EcsIterPrivate, 259 | next: if (builtin.zig_backend == .stage1) ?fn ([*c]EcsIter) callconv(.C) bool else ?*const fn ([*c]EcsIter) callconv(.C) bool, 260 | callback: if (builtin.zig_backend == .stage1) ?fn (*EcsIter) callconv(.C) void else ?*const fn (*EcsIter) callconv(.C) void, 261 | fini: if (builtin.zig_backend == .stage1) ?fn ([*c]EcsIter) callconv(.C) void else ?*const fn ([*c]EcsIter) callconv(.C) void, 262 | chain_it: [*c]EcsIter, 263 | }; 264 | 265 | pub const EcsWorld = opaque {}; 266 | pub const EcsPoly = anyopaque; 267 | 268 | pub const EcsIterInitAction = if (builtin.zig_backend == .stage1) fn ( 269 | ?*const EcsWorld, 270 | ?*const EcsPoly, 271 | [*c]EcsIter, 272 | [*c]EcsTerm, 273 | ) callconv(.C) void else *const fn ( 274 | ?*const EcsWorld, 275 | ?*const EcsPoly, 276 | [*c]EcsIter, 277 | [*c]EcsTerm, 278 | ) callconv(.C) void; 279 | 280 | pub const EcsIterable = extern struct { 281 | init: ?EcsIterInitAction, 282 | }; 283 | 284 | pub const EcsPolyDtor = ?*const fn (?*EcsPoly) callconv(.C) void; 285 | 286 | pub const EcsFilter = extern struct { 287 | hdr: EcsHeader, 288 | terms: [*c]EcsTerm, 289 | term_count: i32, 290 | field_count: i32, 291 | owned: bool, 292 | terms_owned: bool, 293 | flags: EcsFlags32, 294 | variable_names: [1][*c]u8, 295 | entity: EcsEntity, 296 | world: ?*EcsWorld, 297 | iterable: EcsIterable, 298 | dtor: EcsPolyDtor, 299 | }; 300 | 301 | pub const EcsFilterDesc = extern struct { 302 | _canary: i32, 303 | terms: [16]EcsTerm, 304 | terms_buffer: [*c]EcsTerm, 305 | terms_buffer_count: i32, 306 | storage: [*c]EcsFilter, 307 | instanced: bool, 308 | flags: EcsFlags32, 309 | expr: [*c]const u8, 310 | name: [*c]const u8, 311 | }; 312 | 313 | pub const EcsOrderByAction = if (builtin.zig_backend == .stage1) fn ( 314 | EcsEntity, 315 | ?*const anyopaque, 316 | EcsEntity, 317 | ?*const anyopaque, 318 | ) callconv(.C) c_int else *const fn ( 319 | EcsEntity, 320 | ?*const anyopaque, 321 | EcsEntity, 322 | ?*const anyopaque, 323 | ) callconv(.C) c_int; 324 | 325 | pub const EcsSortTableAction = if (builtin.zig_backend == .stage1) fn ( 326 | ?*EcsWorld, 327 | ?*EcsTable, 328 | [*c]EcsEntity, 329 | ?*anyopaque, 330 | i32, 331 | i32, 332 | i32, 333 | EcsOrderByAction, 334 | ) callconv(.C) void else *const fn ( 335 | ?*EcsWorld, 336 | ?*EcsTable, 337 | [*c]EcsEntity, 338 | ?*anyopaque, 339 | i32, 340 | i32, 341 | i32, 342 | EcsOrderByAction, 343 | ) callconv(.C) void; 344 | 345 | pub const EcsGroupByAction = if (builtin.zig_backend == .stage1) fn ( 346 | ?*EcsWorld, 347 | ?*EcsTable, 348 | EcsId, 349 | ?*anyopaque, 350 | ) callconv(.C) u64 else *const fn ( 351 | ?*EcsWorld, 352 | ?*EcsTable, 353 | EcsId, 354 | ?*anyopaque, 355 | ) callconv(.C) u64; 356 | 357 | pub const EcsCtxFree = if (builtin.zig_backend == .stage1) fn (?*anyopaque) callconv(.C) void else *const fn (?*anyopaque) callconv(.C) void; 358 | 359 | pub const EcsGroupCreateAction = ?*const fn (?*EcsWorld, u64, ?*anyopaque) callconv(.C) ?*anyopaque; 360 | pub const EcsGroupDeleteAction = ?*const fn (?*EcsWorld, u64, ?*anyopaque, ?*anyopaque) callconv(.C) void; 361 | 362 | pub const EcsQueryDesc = extern struct { 363 | _canary: i32, 364 | filter: EcsFilterDesc, 365 | order_by_component: EcsEntity, 366 | order_by: EcsOrderByAction, 367 | sort_table: EcsSortTableAction, 368 | group_by_id: EcsId, 369 | group_by: EcsGroupByAction, 370 | on_group_create: EcsGroupCreateAction, 371 | on_group_delete: EcsGroupDeleteAction, 372 | group_by_ctx: ?*anyopaque, 373 | group_by_ctx_free: ?EcsCtxFree, 374 | parent: ?*EcsQuery, 375 | }; 376 | 377 | pub const EcsRunAction = if (builtin.zig_backend == .stage1) fn (*EcsIter) callconv(.C) void else *const fn (*EcsIter) callconv(.C) void; 378 | 379 | pub const EcsSystemDesc = extern struct { 380 | _canary: i32, 381 | entity: EcsEntity, 382 | query: EcsQueryDesc, 383 | run: ?EcsRunAction, 384 | callback: ?EcsIterAction, 385 | ctx: ?*anyopaque, 386 | binding_ctx: ?*anyopaque, 387 | ctx_free: ?EcsCtxFree, 388 | binding_ctx_free: ?EcsCtxFree, 389 | interval: f32, 390 | rate: i32, 391 | tick_source: EcsEntity, 392 | multi_threaded: bool, 393 | no_staging: bool, 394 | }; 395 | 396 | pub const EcsTypeInfo = extern struct { 397 | size: EcsSize, 398 | alignment: EcsSize, 399 | hooks: EcsTypeHooks, 400 | component: EcsEntity, 401 | }; 402 | 403 | pub const EcsFiniAction = if (builtin.zig_backend == .stage1) fn ( 404 | ?*EcsWorld, 405 | ?*anyopaque, 406 | ) callconv(.C) void else *const fn ( 407 | ?*EcsWorld, 408 | ?*anyopaque, 409 | ) callconv(.C) void; 410 | 411 | pub const EcsXtor = if (builtin.zig_backend == .stage1) fn ( 412 | ?*anyopaque, 413 | i32, 414 | [*c]const EcsTypeInfo, 415 | ) callconv(.C) void else *const fn ( 416 | ?*anyopaque, 417 | i32, 418 | [*c]const EcsTypeInfo, 419 | ) callconv(.C) void; 420 | 421 | pub const EcsCopy = if (builtin.zig_backend == .stage1) fn ( 422 | ?*anyopaque, 423 | ?*const anyopaque, 424 | i32, 425 | [*c]const EcsTypeInfo, 426 | ) callconv(.C) void else *const fn ( 427 | ?*anyopaque, 428 | ?*const anyopaque, 429 | i32, 430 | [*c]const EcsTypeInfo, 431 | ) callconv(.C) void; 432 | 433 | pub const EcsMove = if (builtin.zig_backend == .stage1) fn ( 434 | ?*anyopaque, 435 | ?*anyopaque, 436 | i32, 437 | [*c]const EcsTypeInfo, 438 | ) callconv(.C) void else *const fn ( 439 | ?*anyopaque, 440 | ?*anyopaque, 441 | i32, 442 | [*c]const EcsTypeInfo, 443 | ) callconv(.C) void; 444 | 445 | pub const EcsTypeHooks = extern struct { 446 | ctor: ?EcsXtor, 447 | dtor: ?EcsXtor, 448 | copy: ?EcsCopy, 449 | move: ?EcsMove, 450 | copy_ctor: ?EcsCopy, 451 | move_ctor: ?EcsMove, 452 | ctor_move_dtor: ?EcsMove, 453 | move_dtor: ?EcsMove, 454 | on_add: ?EcsIterAction, 455 | on_set: ?EcsIterAction, 456 | on_remove: ?EcsIterAction, 457 | ctx: ?*anyopaque, 458 | binding_ctx: ?*anyopaque, 459 | ctx_free: ?EcsCtxFree, 460 | binding_ctx_free: ?EcsCtxFree, 461 | }; 462 | 463 | pub const EcsType = extern struct { 464 | array: [*c]EcsId, 465 | count: i32, 466 | }; 467 | 468 | pub const EcsEventDesc = extern struct { 469 | event: EcsEntity, 470 | ids: [*c]const EcsType, 471 | table: ?*EcsTable, 472 | other_table: ?*EcsTable, 473 | offset: i32, 474 | count: i32, 475 | entity: EcsEntity, 476 | param: ?*const anyopaque, 477 | observable: ?*EcsPoly, 478 | flags: EcsFlags32, 479 | }; 480 | 481 | pub const EcsCmd = extern struct { 482 | add_count: i64, 483 | remove_count: i64, 484 | delete_count: i64, 485 | clear_count: i64, 486 | set_count: i64, 487 | get_mut_count: i64, 488 | modified_count: i64, 489 | other_count: i64, 490 | discard_count: i64, 491 | batched_entity_count: i64, 492 | batched_command_count: i64, 493 | }; 494 | 495 | pub const EcsWorldInfo = extern struct { 496 | last_component_id: EcsEntity, 497 | last_id: EcsEntity, 498 | min_id: EcsEntity, 499 | max_id: EcsEntity, 500 | delta_time_raw: f32, 501 | delta_time: f32, 502 | time_scale: f32, 503 | target_fps: f32, 504 | frame_time_total: f32, 505 | system_time_total: f32, 506 | emit_time_total: f32, 507 | merge_time_total: f32, 508 | world_time_total: f32, 509 | world_time_total_raw: f32, 510 | rematch_time_total: f32, 511 | frame_count_total: i64, 512 | merge_count_total: i64, 513 | rematch_count_total: i64, 514 | id_create_total: i64, 515 | id_delete_total: i64, 516 | table_create_total: i64, 517 | table_delete_total: i64, 518 | pipeline_build_count_total: i64, 519 | systems_ran_frame: i64, 520 | observers_ran_frame: i64, 521 | frame_count_total: i32, 522 | merge_count_total: i32, 523 | id_create_total: i32, 524 | id_delete_total: i32, 525 | table_create_total: i32, 526 | table_delete_total: i32, 527 | pipeline_build_count_total: i32, 528 | systems_ran_frame: i32, 529 | id_count: i32, 530 | tag_id_count: i32, 531 | component_id_count: i32, 532 | pair_id_count: i32, 533 | wildcard_id_count: i32, 534 | table_count: i32, 535 | tag_table_count: i32, 536 | trivial_table_count: i32, 537 | empty_table_count: i32, 538 | table_record_count: i32, 539 | table_storage_count: i32, 540 | cmd: EcsCmd, 541 | name_prefix: [*c]const u8, 542 | }; 543 | 544 | pub const EcsBulkDesc = extern struct { 545 | _canary: i32, 546 | entities: [*c]EcsEntity, 547 | count: i32, 548 | ids: [32]EcsId, 549 | data: [*c]?*anyopaque, 550 | table: ?*EcsTable, 551 | }; 552 | 553 | pub const EcsComponentDesc = extern struct { 554 | _canary: i32, 555 | entity: EcsEntity, 556 | type: EcsTypeInfo, 557 | }; 558 | 559 | pub const EcsStrBufElement = extern struct { 560 | buffer_embedded: bool, 561 | pos: i32, 562 | buf: [*c]u8, 563 | next: [*c]EcsStrBufElement, 564 | }; 565 | 566 | pub const EcsStrBufElementEmbedded = extern struct { 567 | super: EcsStrBufElement, 568 | buf: [512]u8, 569 | }; 570 | 571 | pub const EcsStrBufListElem = extern struct { 572 | count: i32, 573 | separator: [*c]const u8, 574 | }; 575 | 576 | pub const EcsStrBuf = extern struct { 577 | buf: [*c]u8, 578 | max: i32, 579 | size: i32, 580 | elementCount: i32, 581 | firstElement: EcsStrBufElementEmbedded, 582 | current: [*c]EcsStrBufElement, 583 | list_stack: [32]EcsStrBufListElem, 584 | list_sp: i32, 585 | content: [*c]u8, 586 | length: i32, 587 | }; 588 | 589 | pub const EcsMapKey = u64; 590 | 591 | pub const EcsBucketEntry = extern struct { 592 | next: [*c]EcsBucketEntry, 593 | key: EcsMapKey, 594 | }; 595 | 596 | pub const EcsBucket = extern struct { 597 | first: [*c]EcsBucketEntry, 598 | }; 599 | 600 | pub const EcsBlockAllocatorChunkHeader = extern struct { 601 | next: [*c]EcsBlockAllocatorChunkHeader, 602 | }; 603 | 604 | pub const EcsBlockAllocatorBlock = extern struct { 605 | memory: ?*anyopaque, 606 | next: [*c]EcsBlockAllocatorBlock, 607 | }; 608 | 609 | pub const EcsBlockAllocator = extern struct { 610 | head: [*c]EcsBlockAllocatorChunkHeader, 611 | block_head: [*c]EcsBlockAllocatorBlock, 612 | block_tail: [*c]EcsBlockAllocatorBlock, 613 | chunk_size: i32, 614 | data_size: i32, 615 | chunks_per_block: i32, 616 | block_size: i32, 617 | alloc_count: i32, 618 | }; 619 | 620 | pub const EcsSparse = extern struct { 621 | dense: ?*EcsVector, 622 | chunks: ?*EcsVector, 623 | size: EcsSize, 624 | count: i32, 625 | max_id_local: u64, 626 | max_id: [*c]u64, 627 | allocator: [*c]EcsAllocator, 628 | chunk_allocator: [*c]EcsBlockAllocator, 629 | }; 630 | 631 | pub const EcsAllocator = extern struct { 632 | chunks: EcsBlockAllocator, 633 | sizes: EcsSparse, 634 | }; 635 | 636 | pub const EcsMap = extern struct { 637 | buckets: [*c]EcsBucket, 638 | buckets_end: [*c]EcsBucket, 639 | elem_size: i16, 640 | bucket_shift: u8, 641 | shared_allocator: bool, 642 | bucket_count: i32, 643 | count: i32, 644 | allocator: [*c]EcsAllocator, 645 | entry_allocator: [*c]EcsBlockAllocator, 646 | }; 647 | 648 | pub const EcsEventIdRecord = opaque {}; 649 | pub const EcsEventRecord = extern struct { 650 | any: ?*EcsEventIdRecord, 651 | wildcard: ?*EcsEventIdRecord, 652 | wildcard_pair: ?*EcsEventIdRecord, 653 | event_ids: EcsMap, 654 | event: EcsEntity, 655 | }; 656 | 657 | pub const EcsObservable = extern struct { 658 | on_add: EcsEventRecord, 659 | on_remove: EcsEventRecord, 660 | on_set: EcsEventRecord, 661 | un_set: EcsEventRecord, 662 | on_wildcard: EcsEventRecord, 663 | events: [*c]EcsSparse, 664 | }; 665 | 666 | pub const EcsObserverDesc = extern struct { 667 | _canary: i32, 668 | entity: EcsEntity, 669 | filter: EcsFilterDesc, 670 | events: [8]EcsEntity, 671 | yield_existing: bool, 672 | callback: EcsIterAction, 673 | run: EcsRunAction, 674 | ctx: ?*anyopaque, 675 | binding_ctx: ?*anyopaque, 676 | ctx_free: ?EcsCtxFree, 677 | binding_ctx_free: ?EcsCtxFree, 678 | observable: ?*EcsPoly, 679 | last_event_id: [*c]i32, 680 | term_index: i32, 681 | }; 682 | 683 | pub const EcsPipelineDesc = extern struct { 684 | entity: EcsEntity, 685 | query: EcsQueryDesc, 686 | }; 687 | 688 | pub const EcsSnapshot = opaque {}; 689 | 690 | pub const EcsAppInitAction = if (builtin.zig_backend == .stage1) fn (?*EcsWorld) callconv(.C) c_int else *const fn (?*EcsWorld) callconv(.C) c_int; 691 | pub const EcsAppRunAction = if (builtin.zig_backend == .stage1) fn ( 692 | ?*EcsWorld, 693 | [*c]EcsAppDesc, 694 | ) callconv(.C) c_int else *const fn ( 695 | ?*EcsWorld, 696 | [*c]EcsAppDesc, 697 | ) callconv(.C) c_int; 698 | 699 | pub const EcsAppFrameAction = if (builtin.zig_backend == .stage1) fn ( 700 | ?*EcsWorld, 701 | [*c]const EcsAppDesc, 702 | ) callconv(.C) c_int else *const fn ( 703 | ?*EcsWorld, 704 | [*c]const EcsAppDesc, 705 | ) callconv(.C) c_int; 706 | 707 | pub const EcsAppDesc = extern struct { 708 | target_fps: f32, 709 | delta_time: f32, 710 | threads: i32, 711 | frames: i32, 712 | enable_rest: bool, 713 | enable_monitor: bool, 714 | init: ?EcsAppInitAction, 715 | ctx: ?*anyopaque, 716 | }; 717 | 718 | pub extern fn ecs_init() ?*EcsWorld; 719 | pub extern fn ecs_mini() ?*EcsWorld; 720 | pub extern fn ecs_init_w_args(argc: c_int, argv: [*c][*c]u8) ?*EcsWorld; 721 | pub extern fn ecs_fini(world: ?*EcsWorld) c_int; 722 | pub extern fn ecs_is_fini(world: ?*const EcsWorld) bool; 723 | pub extern fn ecs_atfini(world: ?*EcsWorld, action: EcsFiniAction, ctx: ?*anyopaque) void; 724 | pub extern fn ecs_run_post_frame(world: ?*EcsWorld, action: EcsFiniAction, ctx: ?*anyopaque) void; 725 | pub extern fn ecs_quit(world: ?*EcsWorld) void; 726 | pub extern fn ecs_should_quit(world: ?*const EcsWorld) bool; 727 | pub extern fn ecs_set_hooks_id(world: ?*EcsWorld, id: EcsEntity, hooks: [*c]const EcsTypeHooks) void; 728 | pub extern fn ecs_get_hooks_id(world: ?*EcsWorld, id: EcsEntity) [*c]const EcsTypeHooks; 729 | pub extern fn ecs_set_context(world: ?*EcsWorld, ctx: ?*anyopaque) void; 730 | pub extern fn ecs_get_context(world: ?*const EcsWorld) ?*anyopaque; 731 | pub extern fn ecs_get_world_info(world: ?*const EcsWorld) [*c]const EcsWorldInfo; 732 | pub extern fn ecs_dim(world: ?*EcsWorld, entity_count: i32) void; 733 | pub extern fn ecs_set_entity_range(world: ?*EcsWorld, id_start: EcsEntity, id_end: EcsEntity) void; 734 | pub extern fn ecs_set_entity_generation(world: ?*EcsWorld, entity_with_generation: EcsEntity) void; 735 | pub extern fn ecs_enable_range_check(world: ?*EcsWorld, enable: bool) bool; 736 | pub extern fn ecs_measure_frame_time(world: ?*EcsWorld, enable: bool) void; 737 | pub extern fn ecs_measure_system_time(world: ?*EcsWorld, enable: bool) void; 738 | pub extern fn ecs_set_target_fps(world: ?*EcsWorld, fps: f32) void; 739 | pub extern fn ecs_run_aperiodic(world: ?*EcsWorld, flags: EcsFlags32) void; 740 | pub extern fn ecs_delete_empty_tables(world: ?*EcsWorld, id: EcsId, clear_generation: u16, delete_generation: u16, min_id_count: i32, time_budget_seconds: f64) i32; 741 | pub extern fn ecs_new_id(world: ?*EcsWorld) EcsEntity; 742 | pub extern fn ecs_new_low_id(world: ?*EcsWorld) EcsEntity; 743 | pub extern fn ecs_new_w_id(world: ?*EcsWorld, id: EcsId) EcsEntity; 744 | pub extern fn ecs_entity_init(world: ?*EcsWorld, desc: [*c]const EcsEntityDesc) EcsEntity; 745 | pub extern fn ecs_bulk_init(world: ?*EcsWorld, desc: [*c]const EcsBulkDesc) [*c]const EcsEntity; 746 | pub extern fn ecs_component_init(world: ?*EcsWorld, desc: [*c]const EcsComponentDesc) EcsEntity; 747 | pub extern fn ecs_bulk_new_w_id(world: ?*EcsWorld, id: EcsId, count: i32) [*c]const EcsEntity; 748 | pub extern fn ecs_clone(world: ?*EcsWorld, dst: EcsEntity, src: EcsEntity, copy_value: bool) EcsEntity; 749 | pub extern fn ecs_add_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) void; 750 | pub extern fn ecs_remove_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) void; 751 | pub extern fn ecs_override_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) void; 752 | pub extern fn ecs_enable_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId, enable: bool) void; 753 | pub extern fn ecs_is_enabled_id(world: ?*const EcsWorld, entity: EcsEntity, id: EcsId) bool; 754 | pub extern fn ecs_make_pair(first: EcsEntity, second: EcsEntity) EcsId; 755 | pub extern fn ecs_clear(world: ?*EcsWorld, entity: EcsEntity) void; 756 | pub extern fn ecs_delete(world: ?*EcsWorld, entity: EcsEntity) void; 757 | pub extern fn ecs_delete_with(world: ?*EcsWorld, id: EcsId) void; 758 | pub extern fn ecs_remove_all(world: ?*EcsWorld, id: EcsId) void; 759 | pub extern fn ecs_get_id(world: ?*const EcsWorld, entity: EcsEntity, id: EcsId) ?*const anyopaque; 760 | pub extern fn ecs_ref_init_id(world: ?*const EcsWorld, entity: EcsEntity, id: EcsId) EcsRef; 761 | pub extern fn ecs_ref_get_id(world: ?*const EcsWorld, ref: [*c]EcsRef, id: EcsId) ?*anyopaque; 762 | pub extern fn ecs_get_mut_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) ?*anyopaque; 763 | pub extern fn ecs_write_begin(world: ?*EcsWorld, entity: EcsEntity) [*c]EcsRecord; 764 | pub extern fn ecs_write_end(record: [*c]EcsRecord) void; 765 | pub extern fn ecs_read_begin(world: ?*EcsWorld, entity: EcsEntity) [*c]const EcsRecord; 766 | pub extern fn ecs_read_end(record: [*c]const EcsRecord) void; 767 | pub extern fn ecs_record_get_id(world: ?*EcsWorld, record: [*c]const EcsRecord, id: EcsId) ?*const anyopaque; 768 | pub extern fn ecs_record_get_mut_id(world: ?*EcsWorld, record: [*c]EcsRecord, id: EcsId) ?*anyopaque; 769 | pub extern fn ecs_emplace_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) ?*anyopaque; 770 | pub extern fn ecs_modified_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId) void; 771 | pub extern fn ecs_set_id(world: ?*EcsWorld, entity: EcsEntity, id: EcsId, size: usize, ptr: ?*const anyopaque) EcsEntity; 772 | pub extern fn ecs_is_valid(world: ?*const EcsWorld, e: EcsEntity) bool; 773 | pub extern fn ecs_is_alive(world: ?*const EcsWorld, e: EcsEntity) bool; 774 | pub extern fn ecs_strip_generation(e: EcsEntity) EcsId; 775 | pub extern fn ecs_get_alive(world: ?*const EcsWorld, e: EcsEntity) EcsEntity; 776 | pub extern fn ecs_ensure(world: ?*EcsWorld, entity: EcsEntity) void; 777 | pub extern fn ecs_ensure_id(world: ?*EcsWorld, id: EcsId) void; 778 | pub extern fn ecs_exists(world: ?*const EcsWorld, entity: EcsEntity) bool; 779 | pub extern fn ecs_get_type(world: ?*const EcsWorld, entity: EcsEntity) [*c]const EcsType; 780 | pub extern fn ecs_get_table(world: ?*const EcsWorld, entity: EcsEntity) ?*EcsTable; 781 | pub extern fn ecs_get_storage_table(world: ?*const EcsWorld, entity: EcsEntity) ?*EcsTable; 782 | pub extern fn ecs_get_type_info(world: ?*const EcsWorld, id: EcsId) [*c]const EcsTypeInfo; 783 | pub extern fn ecs_get_typeid(world: ?*const EcsWorld, id: EcsId) EcsEntity; 784 | pub extern fn ecs_id_is_tag(world: ?*const EcsWorld, id: EcsId) EcsEntity; 785 | pub extern fn ecs_id_in_use(world: ?*EcsWorld, id: EcsId) bool; 786 | pub extern fn ecs_get_name(world: ?*const EcsWorld, entity: EcsEntity) [*c]const u8; 787 | pub extern fn ecs_get_symbol(world: ?*const EcsWorld, entity: EcsEntity) [*c]const u8; 788 | pub extern fn ecs_set_name(world: ?*EcsWorld, entity: EcsEntity, name: [*c]const u8) EcsEntity; 789 | pub extern fn ecs_set_symbol(world: ?*EcsWorld, entity: EcsEntity, symbol: [*c]const u8) EcsEntity; 790 | pub extern fn ecs_set_alias(world: ?*EcsWorld, entity: EcsEntity, alias: [*c]const u8) void; 791 | pub extern fn ecs_id_flag_str(id_flags: EcsId) [*c]const u8; 792 | pub extern fn ecs_id_str(world: ?*const EcsWorld, id: EcsId) [*c]u8; 793 | pub extern fn ecs_id_str_buf(world: ?*const EcsWorld, id: EcsId, buf: [*c]EcsStrBuf) void; 794 | pub extern fn ecs_type_str(world: ?*const EcsWorld, @"type": [*c]const EcsType) [*c]u8; 795 | pub extern fn ecs_table_str(world: ?*const EcsWorld, table: ?*const EcsTable) [*c]u8; 796 | pub extern fn ecs_entity_str(world: ?*const EcsWorld, entity: EcsEntity) [*c]u8; 797 | pub extern fn ecs_has_id(world: ?*const EcsWorld, entity: EcsEntity, id: EcsId) bool; 798 | pub extern fn ecs_get_target(world: ?*const EcsWorld, entity: EcsEntity, rel: EcsEntity, index: i32) EcsEntity; 799 | pub extern fn ecs_get_target_for_id(world: ?*const EcsWorld, entity: EcsEntity, rel: EcsEntity, id: EcsId) EcsEntity; 800 | pub extern fn ecs_enable(world: ?*EcsWorld, entity: EcsEntity, enabled: bool) void; 801 | pub extern fn ecs_count_id(world: ?*const EcsWorld, entity: EcsId) i32; 802 | pub extern fn ecs_lookup(world: ?*const EcsWorld, name: [*c]const u8) EcsEntity; 803 | pub extern fn ecs_lookup_child(world: ?*const EcsWorld, parent: EcsEntity, name: [*c]const u8) EcsEntity; 804 | pub extern fn ecs_lookup_path_w_sep(world: ?*const EcsWorld, parent: EcsEntity, path: [*c]const u8, sep: [*c]const u8, prefix: [*c]const u8, recursive: bool) EcsEntity; 805 | pub extern fn ecs_lookup_symbol(world: ?*const EcsWorld, symbol: [*c]const u8, lookup_as_path: bool) EcsEntity; 806 | pub extern fn ecs_get_path_w_sep(world: ?*const EcsWorld, parent: EcsEntity, child: EcsEntity, sep: [*c]const u8, prefix: [*c]const u8) [*c]u8; 807 | pub extern fn ecs_get_path_w_sep_buf(world: ?*const EcsWorld, parent: EcsEntity, child: EcsEntity, sep: [*c]const u8, prefix: [*c]const u8, buf: [*c]EcsStrBuf) void; 808 | pub extern fn ecs_new_from_path_w_sep(world: ?*EcsWorld, parent: EcsEntity, path: [*c]const u8, sep: [*c]const u8, prefix: [*c]const u8) EcsEntity; 809 | pub extern fn ecs_add_path_w_sep(world: ?*EcsWorld, entity: EcsEntity, parent: EcsEntity, path: [*c]const u8, sep: [*c]const u8, prefix: [*c]const u8) EcsEntity; 810 | pub extern fn ecs_set_scope(world: ?*EcsWorld, scope: EcsEntity) EcsEntity; 811 | pub extern fn ecs_get_scope(world: ?*const EcsWorld) EcsEntity; 812 | pub extern fn ecs_set_with(world: ?*EcsWorld, id: EcsId) EcsEntity; 813 | pub extern fn ecs_get_with(world: ?*const EcsWorld) EcsId; 814 | pub extern fn ecs_set_name_prefix(world: ?*EcsWorld, prefix: [*c]const u8) [*c]const u8; 815 | pub extern fn ecs_set_lookup_path(world: ?*EcsWorld, lookup_path: [*c]const EcsEntity) [*c]EcsEntity; 816 | pub extern fn ecs_get_lookup_path(world: ?*const EcsWorld) [*c]EcsEntity; 817 | pub extern fn ecs_term_iter(world: ?*const EcsWorld, term: [*c]EcsTerm) EcsIter; 818 | pub extern fn ecs_term_chain_iter(it: [*c]const EcsIter, term: [*c]EcsTerm) EcsIter; 819 | pub extern fn ecs_term_next(it: [*c]EcsIter) bool; 820 | pub extern fn ecs_children(world: ?*const EcsWorld, parent: EcsEntity) EcsIter; 821 | pub extern fn ecs_children_next(it: [*c]EcsIter) bool; 822 | pub extern fn ecs_term_id_is_set(id: [*c]const EcsTermId) bool; 823 | pub extern fn ecs_term_is_initialized(term: [*c]const EcsTerm) bool; 824 | pub extern fn ecs_term_match_this(term: [*c]const EcsTerm) bool; 825 | pub extern fn ecs_term_match_0(term: [*c]const EcsTerm) bool; 826 | pub extern fn ecs_term_finalize(world: ?*const EcsWorld, term: [*c]EcsTerm) c_int; 827 | pub extern fn ecs_term_copy(src: [*c]const EcsTerm) EcsTerm; 828 | pub extern fn ecs_term_move(src: [*c]EcsTerm) EcsTerm; 829 | pub extern fn ecs_term_fini(term: [*c]EcsTerm) void; 830 | pub extern fn ecs_id_match(id: EcsId, pattern: EcsId) bool; 831 | pub extern fn ecs_id_is_pair(id: EcsId) bool; 832 | pub extern fn ecs_id_is_wildcard(id: EcsId) bool; 833 | pub extern fn ecs_id_is_valid(world: ?*const EcsWorld, id: EcsId) bool; 834 | pub extern fn ecs_id_get_flags(world: ?*const EcsWorld, id: EcsId) EcsFlags32; 835 | pub extern fn ecs_filter_init(world: ?*EcsWorld, desc: [*c]const EcsFilterDesc) [*c]EcsFilter; 836 | pub extern fn ecs_filter_fini(filter: [*c]EcsFilter) void; 837 | pub extern fn ecs_filter_finalize(world: ?*const EcsWorld, filter: [*c]EcsFilter) c_int; 838 | pub extern fn ecs_filter_find_this_var(filter: [*c]const EcsFilter) i32; 839 | pub extern fn ecs_term_str(world: ?*const EcsWorld, term: [*c]const EcsTerm) [*c]u8; 840 | pub extern fn ecs_filter_str(world: ?*const EcsWorld, filter: [*c]const EcsFilter) [*c]u8; 841 | pub extern fn ecs_filter_iter(world: ?*const EcsWorld, filter: [*c]const EcsFilter) EcsIter; 842 | pub extern fn ecs_filter_chain_iter(it: [*c]const EcsIter, filter: [*c]const EcsFilter) EcsIter; 843 | pub extern fn ecs_filter_pivot_term(world: ?*const EcsWorld, filter: [*c]const EcsFilter) i32; 844 | pub extern fn ecs_filter_next(it: [*c]EcsIter) bool; 845 | pub extern fn ecs_filter_next_instanced(it: [*c]EcsIter) bool; 846 | pub extern fn ecs_query_next_table(iter: [*c]EcsIter) bool; 847 | pub extern fn ecs_query_populate(iter: [*c]EcsIter) void; 848 | pub extern fn ecs_filter_move(dst: [*c]EcsFilter, src: [*c]EcsFilter) void; 849 | pub extern fn ecs_filter_copy(dst: [*c]EcsFilter, src: [*c]const EcsFilter) void; 850 | pub extern fn ecs_query_init(world: ?*EcsWorld, desc: [*c]const EcsQueryDesc) ?*EcsQuery; 851 | pub extern fn ecs_query_fini(query: ?*EcsQuery) void; 852 | pub extern fn ecs_query_get_filter(query: ?*EcsQuery) [*c]const EcsFilter; 853 | pub extern fn ecs_query_iter(world: ?*const EcsWorld, query: ?*EcsQuery) EcsIter; 854 | pub extern fn ecs_query_next(iter: [*c]EcsIter) bool; 855 | pub extern fn ecs_query_next_instanced(iter: [*c]EcsIter) bool; 856 | pub extern fn ecs_query_changed(query: ?*EcsQuery, it: [*c]const EcsIter) bool; 857 | pub extern fn ecs_query_skip(it: [*c]EcsIter) void; 858 | pub extern fn ecs_query_set_group(it: [*c]EcsIter, group_id: u64) void; 859 | pub extern fn ecs_query_orphaned(query: ?*EcsQuery) bool; 860 | pub extern fn ecs_query_str(query: ?*const EcsQuery) [*c]u8; 861 | pub extern fn ecs_query_table_count(query: ?*const EcsQuery) i32; 862 | pub extern fn ecs_query_empty_table_count(query: ?*const EcsQuery) i32; 863 | pub extern fn ecs_query_entity_count(query: ?*const EcsQuery) i32; 864 | pub extern fn ecs_query_entity(query: ?*const EcsQuery) EcsEntity; 865 | 866 | pub extern fn ecs_emit(world: ?*EcsWorld, desc: [*c]EcsEventDesc) void; 867 | pub extern fn ecs_observer_init(world: ?*EcsWorld, desc: [*c]const EcsObserverDesc) EcsEntity; 868 | pub extern fn ecs_observer_default_run_action(it: [*c]EcsIter) bool; 869 | pub extern fn ecs_get_observer_ctx(world: ?*const EcsWorld, observer: EcsEntity) ?*anyopaque; 870 | pub extern fn ecs_get_observer_binding_ctx(world: ?*const EcsWorld, observer: EcsEntity) ?*anyopaque; 871 | pub extern fn ecs_iter_poly(world: ?*const EcsWorld, poly: ?*const EcsPoly, iter: [*c]EcsIter, filter: [*c]EcsTerm) void; 872 | pub extern fn ecs_iter_next(it: [*c]EcsIter) bool; 873 | pub extern fn ecs_iter_fini(it: [*c]EcsIter) void; 874 | pub extern fn ecs_iter_count(it: [*c]EcsIter) i32; 875 | pub extern fn ecs_iter_is_true(it: [*c]EcsIter) bool; 876 | pub extern fn ecs_iter_first(it: [*c]EcsIter) EcsEntity; 877 | pub extern fn ecs_iter_set_var(it: [*c]EcsIter, var_id: i32, entity: EcsEntity) void; 878 | pub extern fn ecs_iter_set_var_as_table(it: [*c]EcsIter, var_id: i32, table: ?*const EcsTable) void; 879 | pub extern fn ecs_iter_set_var_as_range(it: [*c]EcsIter, var_id: i32, range: [*c]const EcsTableRange) void; 880 | pub extern fn ecs_iter_get_var(it: [*c]EcsIter, var_id: i32) EcsEntity; 881 | pub extern fn ecs_iter_get_var_as_table(it: [*c]EcsIter, var_id: i32) ?*EcsTable; 882 | pub extern fn ecs_iter_get_var_as_range(it: [*c]EcsIter, var_id: i32) EcsTableRange; 883 | pub extern fn ecs_iter_var_is_constrained(it: [*c]EcsIter, var_id: i32) bool; 884 | pub extern fn ecs_page_iter(it: [*c]const EcsIter, offset: i32, limit: i32) EcsIter; 885 | pub extern fn ecs_page_next(it: [*c]EcsIter) bool; 886 | pub extern fn ecs_worker_iter(it: [*c]const EcsIter, index: i32, count: i32) EcsIter; 887 | pub extern fn ecs_worker_next(it: [*c]EcsIter) bool; 888 | pub extern fn ecs_field_w_size(it: [*c]const EcsIter, size: usize, index: i32) ?*anyopaque; 889 | pub extern fn ecs_field_is_readonly(it: [*c]const EcsIter, index: i32) bool; 890 | pub extern fn ecs_field_is_writeonly(it: [*c]const EcsIter, index: i32) bool; 891 | pub extern fn ecs_field_is_set(it: [*c]const EcsIter, index: i32) bool; 892 | pub extern fn ecs_field_id(it: [*c]const EcsIter, index: i32) EcsId; 893 | pub extern fn ecs_field_src(it: [*c]const EcsIter, index: i32) EcsEntity; 894 | pub extern fn ecs_field_size(it: [*c]const EcsIter, index: i32) usize; 895 | pub extern fn ecs_field_is_self(it: [*c]const EcsIter, index: i32) bool; 896 | pub extern fn ecs_iter_str(it: [*c]const EcsIter) [*c]u8; 897 | pub extern fn ecs_iter_find_column(it: [*c]const EcsIter, id: EcsId) i32; 898 | pub extern fn ecs_iter_column_w_size(it: [*c]const EcsIter, size: usize, index: i32) ?*anyopaque; 899 | pub extern fn ecs_iter_column_size(it: [*c]const EcsIter, index: i32) usize; 900 | pub extern fn ecs_frame_begin(world: ?*EcsWorld, delta_time: f32) f32; 901 | pub extern fn ecs_frame_end(world: ?*EcsWorld) void; 902 | pub extern fn ecs_readonly_begin(world: ?*EcsWorld) bool; 903 | pub extern fn ecs_readonly_end(world: ?*EcsWorld) void; 904 | pub extern fn ecs_merge(world: ?*EcsWorld) void; 905 | pub extern fn ecs_defer_begin(world: ?*EcsWorld) bool; 906 | pub extern fn ecs_is_deferred(world: ?*const EcsWorld) bool; 907 | pub extern fn ecs_defer_end(world: ?*EcsWorld) bool; 908 | pub extern fn ecs_defer_suspend(world: ?*EcsWorld) void; 909 | pub extern fn ecs_defer_resume(world: ?*EcsWorld) void; 910 | pub extern fn ecs_set_automerge(world: ?*EcsWorld, automerge: bool) void; 911 | pub extern fn ecs_set_stage_count(world: ?*EcsWorld, stages: i32) void; 912 | pub extern fn ecs_get_stage_count(world: ?*const EcsWorld) i32; 913 | pub extern fn ecs_get_stage_id(world: ?*const EcsWorld) i32; 914 | pub extern fn ecs_get_stage(world: ?*const EcsWorld, stage_id: i32) ?*EcsWorld; 915 | pub extern fn ecs_get_world(world: ?*const EcsPoly) ?*const EcsWorld; 916 | pub extern fn ecs_stage_is_readonly(world: ?*const EcsWorld) bool; 917 | pub extern fn ecs_async_stage_new(world: ?*EcsWorld) ?*EcsWorld; 918 | pub extern fn ecs_async_stage_free(stage: ?*EcsWorld) void; 919 | pub extern fn ecs_stage_is_async(stage: ?*EcsWorld) bool; 920 | pub extern fn ecs_search(world: ?*const EcsWorld, table: ?*const EcsTable, id: EcsId, id_out: [*c]EcsId) i32; 921 | pub extern fn ecs_search_offset(world: ?*const EcsWorld, table: ?*const EcsTable, offset: i32, id: EcsId, id_out: [*c]EcsId) i32; 922 | pub extern fn ecs_search_relation(world: ?*const EcsWorld, table: ?*const EcsTable, offset: i32, id: EcsId, rel: EcsEntity, flags: EcsFlags32, subject_out: [*c]EcsEntity, id_out: [*c]EcsId, tr_out: [*c]?*EcsTableRecord) i32; 923 | pub extern fn ecs_table_get_type(table: ?*const EcsTable) [*c]const EcsType; 924 | pub extern fn ecs_table_get_column(table: ?*EcsTable, index: i32) ?*anyopaque; 925 | pub extern fn ecs_table_get_index(world: ?*const EcsWorld, table: ?*const EcsTable, id: EcsId) i32; 926 | pub extern fn ecs_table_get_storage_table(table: ?*const EcsTable) ?*EcsTable; 927 | pub extern fn ecs_table_type_to_storage_index(table: ?*const EcsTable, index: i32) i32; 928 | pub extern fn ecs_table_storage_to_type_index(table: ?*const EcsTable, index: i32) i32; 929 | pub extern fn ecs_table_count(table: ?*const EcsTable) i32; 930 | pub extern fn ecs_table_add_id(world: ?*EcsWorld, table: ?*EcsTable, id: EcsId) ?*EcsTable; 931 | pub extern fn ecs_table_remove_id(world: ?*EcsWorld, table: ?*EcsTable, id: EcsId) ?*EcsTable; 932 | pub extern fn ecs_table_lock(world: ?*EcsWorld, table: ?*EcsTable) void; 933 | pub extern fn ecs_table_unlock(world: ?*EcsWorld, table: ?*EcsTable) void; 934 | pub extern fn ecs_table_has_module(table: ?*EcsTable) bool; 935 | pub extern fn ecs_table_swap_rows(world: ?*EcsWorld, table: ?*EcsTable, row_1: i32, row_2: i32) void; 936 | pub extern fn ecs_commit(world: ?*EcsWorld, entity: EcsEntity, record: [*c]EcsRecord, table: ?*EcsTable, added: [*c]const EcsType, removed: [*c]const EcsType) bool; 937 | pub extern fn ecs_record_find(world: ?*const EcsWorld, entity: EcsEntity) [*c]EcsRecord; 938 | pub extern fn ecs_record_get_column(r: [*c]const EcsRecord, column: i32, c_size: usize) ?*anyopaque; 939 | pub extern fn ecs_should_log(level: i32) bool; 940 | pub extern fn ecs_strerror(error_code: i32) [*c]const u8; 941 | pub extern fn ecs_log_set_level(level: c_int) c_int; 942 | pub extern fn ecs_log_enable_colors(enabled: bool) bool; 943 | pub extern fn ecs_log_enable_timestamp(enabled: bool) bool; 944 | pub extern fn ecs_log_enable_timedelta(enabled: bool) bool; 945 | pub extern fn ecs_log_last_error() c_int; 946 | 947 | pub extern fn ecs_app_run(world: ?*EcsWorld, desc: [*c]EcsAppDesc) c_int; 948 | pub extern fn ecs_app_run_frame(world: ?*EcsWorld, desc: [*c]const EcsAppDesc) c_int; 949 | pub extern fn ecs_app_set_run_action(callback: EcsAppRunAction) c_int; 950 | pub extern fn ecs_app_set_frame_action(callback: EcsAppFrameAction) c_int; 951 | 952 | pub extern fn ecs_set_timeout(world: ?*EcsWorld, tick_source: EcsEntity, timeout: f32) EcsEntity; 953 | pub extern fn ecs_get_timeout(world: ?*const EcsWorld, tick_source: EcsEntity) f32; 954 | pub extern fn ecs_set_interval(world: ?*EcsWorld, tick_source: EcsEntity, interval: f32) EcsEntity; 955 | pub extern fn ecs_get_interval(world: ?*const EcsWorld, tick_source: EcsEntity) f32; 956 | pub extern fn ecs_start_timer(world: ?*EcsWorld, tick_source: EcsEntity) void; 957 | pub extern fn ecs_stop_timer(world: ?*EcsWorld, tick_source: EcsEntity) void; 958 | pub extern fn ecs_set_rate(world: ?*EcsWorld, tick_source: EcsEntity, rate: i32, source: EcsEntity) EcsEntity; 959 | pub extern fn ecs_set_tick_source(world: ?*EcsWorld, system: EcsEntity, tick_source: EcsEntity) void; 960 | 961 | pub extern fn ecs_pipeline_init(world: ?*EcsWorld, desc: [*c]const EcsPipelineDesc) EcsEntity; 962 | pub extern fn ecs_set_pipeline(world: ?*EcsWorld, pipeline: EcsEntity) void; 963 | pub extern fn ecs_get_pipeline(world: ?*const EcsWorld) EcsEntity; 964 | pub extern fn ecs_progress(world: ?*EcsWorld, delta_time: f32) bool; 965 | pub extern fn ecs_set_time_scale(world: ?*EcsWorld, scale: f32) void; 966 | pub extern fn ecs_reset_clock(world: ?*EcsWorld) void; 967 | pub extern fn ecs_run_pipeline(world: ?*EcsWorld, pipeline: EcsEntity, delta_time: f32) void; 968 | pub extern fn ecs_set_threads(world: ?*EcsWorld, threads: i32) void; 969 | 970 | pub extern fn ecs_system_init(world: ?*EcsWorld, desc: [*c]const EcsSystemDesc) EcsEntity; 971 | pub extern fn ecs_run(world: ?*EcsWorld, system: EcsEntity, delta_time: f32, param: ?*anyopaque) EcsEntity; 972 | pub extern fn ecs_run_worker(world: ?*EcsWorld, system: EcsEntity, stage_current: i32, stage_count: i32, delta_time: f32, param: ?*anyopaque) EcsEntity; 973 | pub extern fn ecs_run_w_filter(world: ?*EcsWorld, system: EcsEntity, delta_time: f32, offset: i32, limit: i32, param: ?*anyopaque) EcsEntity; 974 | pub extern fn ecs_system_get_query(world: ?*const EcsWorld, system: EcsEntity) ?*EcsQuery; 975 | pub extern fn ecs_get_system_ctx(world: ?*const EcsWorld, system: EcsEntity) ?*anyopaque; 976 | pub extern fn ecs_get_system_binding_ctx(world: ?*const EcsWorld, system: EcsEntity) ?*anyopaque; 977 | 978 | // pub extern fn ecs_parse_json(world: ?*const EcsWorld, ptr: [*c]const u8, @"type": EcsEntity, data_out: ?*anyopaque, desc: [*c]const ecs_parse_json_desc_t) [*c]const u8; 979 | // pub extern fn ecs_array_to_json(world: ?*const EcsWorld, @"type": EcsEntity, data: ?*const anyopaque, count: i32) [*c]u8; 980 | // pub extern fn ecs_array_to_json_buf(world: ?*const EcsWorld, @"type": EcsEntity, data: ?*const anyopaque, count: i32, buf_out: [*c]EcsStrBuf) c_int; 981 | // pub extern fn ecs_ptr_to_json(world: ?*const EcsWorld, @"type": EcsEntity, data: ?*const anyopaque) [*c]u8; 982 | // pub extern fn ecs_ptr_to_json_buf(world: ?*const EcsWorld, @"type": EcsEntity, data: ?*const anyopaque, buf_out: [*c]EcsStrBuf) c_int; 983 | // pub extern fn ecs_type_info_to_json(world: ?*const EcsWorld, @"type": EcsEntity) [*c]u8; 984 | // pub extern fn ecs_type_info_to_json_buf(world: ?*const EcsWorld, @"type": EcsEntity, buf_out: [*c]EcsStrBuf) c_int; 985 | 986 | // pub extern fn EcsEntityo_json(world: ?*const EcsWorld, entity: EcsEntity, desc: [*c]const EcsEntityo_json_desc_t) [*c]u8; 987 | // pub extern fn EcsEntityo_json_buf(world: ?*const EcsWorld, entity: EcsEntity, buf_out: [*c]EcsStrBuf, desc: [*c]const EcsEntityo_json_desc_t) c_int; 988 | 989 | // pub extern fn ecs_iter_to_json(world: ?*const EcsWorld, iter: [*c]EcsIter, desc: [*c]const ecs_iter_to_json_desc_t) [*c]u8; 990 | // pub extern fn ecs_iter_to_json_buf(world: ?*const EcsWorld, iter: [*c]EcsIter, buf_out: [*c]EcsStrBuf, desc: [*c]const ecs_iter_to_json_desc_t) c_int; 991 | 992 | pub extern fn ecs_snapshot_take(world: ?*EcsWorld) ?*EcsSnapshot; 993 | pub extern fn ecs_snapshot_take_w_iter(iter: [*c]EcsIter) ?*EcsSnapshot; 994 | pub extern fn ecs_snapshot_restore(world: ?*EcsWorld, snapshot: ?*EcsSnapshot) void; 995 | pub extern fn ecs_snapshot_iter(snapshot: ?*EcsSnapshot) EcsIter; 996 | pub extern fn ecs_snapshot_next(iter: [*c]EcsIter) bool; 997 | pub extern fn ecs_snapshot_free(snapshot: ?*EcsSnapshot) void; 998 | pub extern fn ecs_parse_whitespace(ptr: [*c]const u8) [*c]const u8; 999 | pub extern fn ecs_parse_eol_and_whitespace(ptr: [*c]const u8) [*c]const u8; 1000 | pub extern fn ecs_parse_digit(ptr: [*c]const u8, token: [*c]u8) [*c]const u8; 1001 | pub extern fn ecs_parse_fluff(ptr: [*c]const u8, last_comment: [*c][*c]u8) [*c]const u8; 1002 | pub extern fn ecs_parse_token(name: [*c]const u8, expr: [*c]const u8, ptr: [*c]const u8, token_out: [*c]u8) [*c]const u8; 1003 | pub extern fn ecs_parse_term(world: ?*const EcsWorld, name: [*c]const u8, expr: [*c]const u8, ptr: [*c]const u8, term_out: [*c]EcsTerm) [*c]u8; 1004 | 1005 | pub const Constants = struct { 1006 | pub const ECS_ID_FLAGS_MASK: u64 = @as(u64, 0xFF) << 60; 1007 | pub const ECS_COMPONENT_MASK: u64 = ~ECS_ID_FLAGS_MASK; 1008 | 1009 | pub extern const ECS_PAIR: EcsId; 1010 | pub extern const ECS_OVERRIDE: EcsId; 1011 | pub extern const ECS_TOGGLE: EcsId; 1012 | pub extern const ECS_AND: EcsId; 1013 | pub extern const ECS_OR: EcsId; 1014 | pub extern const ECS_NOT: EcsId; 1015 | 1016 | pub extern const EcsQuery: EcsEntity; 1017 | pub extern const EcsObserver: EcsEntity; 1018 | pub extern const EcsSystem: EcsEntity; 1019 | pub extern const EcsFlecs: EcsEntity; 1020 | pub extern const EcsFlecsCore: EcsEntity; 1021 | pub extern const EcsWorld: EcsEntity; 1022 | pub extern const EcsWildcard: EcsEntity; 1023 | pub extern const EcsAny: EcsEntity; 1024 | pub extern const EcsThis: EcsEntity; 1025 | pub extern const EcsVariable: EcsEntity; 1026 | pub extern const EcsTransitive: EcsEntity; 1027 | pub extern const EcsReflexive: EcsEntity; 1028 | pub extern const EcsFinal: EcsEntity; 1029 | pub extern const EcsDontInherit: EcsEntity; 1030 | pub extern const EcsSymmetric: EcsEntity; 1031 | pub extern const EcsExclusive: EcsEntity; 1032 | pub extern const EcsAcyclic: EcsEntity; 1033 | pub extern const EcsWith: EcsEntity; 1034 | pub extern const EcsOneOf: EcsEntity; 1035 | pub extern const EcsTag: EcsEntity; 1036 | pub extern const EcsUnion: EcsEntity; 1037 | pub extern const EcsName: EcsEntity; 1038 | pub extern const EcsSymbol: EcsEntity; 1039 | pub extern const EcsAlias: EcsEntity; 1040 | pub extern const EcsChildOf: EcsEntity; 1041 | pub extern const EcsIsA: EcsEntity; 1042 | pub extern const EcsDependsOn: EcsEntity; 1043 | pub extern const EcsSlotOf: EcsEntity; 1044 | pub extern const EcsModule: EcsEntity; 1045 | pub extern const EcsPrivate: EcsEntity; 1046 | pub extern const EcsPrefab: EcsEntity; 1047 | pub extern const EcsDisabled: EcsEntity; 1048 | pub extern const EcsOnAdd: EcsEntity; 1049 | pub extern const EcsOnRemove: EcsEntity; 1050 | pub extern const EcsOnSet: EcsEntity; 1051 | pub extern const EcsUnSet: EcsEntity; 1052 | pub extern const EcsMonitor: EcsEntity; 1053 | pub extern const EcsOnDelete: EcsEntity; 1054 | pub extern const EcsOnTableEmpty: EcsEntity; 1055 | pub extern const EcsOnTableFill: EcsEntity; 1056 | pub extern const EcsOnDeleteTarget: EcsEntity; 1057 | pub extern const EcsRemove: EcsEntity; 1058 | pub extern const EcsDelete: EcsEntity; 1059 | pub extern const EcsPanic: EcsEntity; 1060 | pub extern const EcsDefaultChildComponent: EcsEntity; 1061 | pub extern const EcsEmpty: EcsEntity; 1062 | pub extern const EcsPreFrame: EcsEntity; 1063 | pub extern const EcsOnLoad: EcsEntity; 1064 | pub extern const EcsPostLoad: EcsEntity; 1065 | pub extern const EcsPreUpdate: EcsEntity; 1066 | pub extern const EcsOnUpdate: EcsEntity; 1067 | pub extern const EcsOnValidate: EcsEntity; 1068 | pub extern const EcsPostUpdate: EcsEntity; 1069 | pub extern const EcsPreStore: EcsEntity; 1070 | pub extern const EcsOnStore: EcsEntity; 1071 | pub extern const EcsPostFrame: EcsEntity; 1072 | pub extern const EcsPhase: EcsEntity; 1073 | }; 1074 | --------------------------------------------------------------------------------