Skip to content

Commit 208b330

Browse files
authored
feat: indexed zipper (#378)
1 parent 09147d2 commit 208b330

4 files changed

Lines changed: 67 additions & 8 deletions

File tree

packages/ecs-lib/lib/libecs.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface Registry extends ClassHandle {
5050
getComponents(_0: Component): SparseArray;
5151
spawnEntity(): Entity;
5252
getZipper(_0: Component[]): any[];
53+
getIndexedZipper(_0: Component[]): any[];
5354
killEntity(_0: Entity): void;
5455
clearEntities(): void;
5556
removeComponent(_0: Entity, _1: Component): void;

packages/ecs-lib/test/Zipper.spec.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,18 +97,35 @@ describe("Zipper", () => {
9797
let zip = r.getZipper([Velocity]);
9898
expect(zip).toBeDefined();
9999

100-
for (let i = 0; i < 20; i++) {
101-
if (zip[i]) {
102-
zip[i]["Velocity"].y *= 2;
103-
}
104-
}
100+
zip.forEach(({ Velocity }) => {
101+
Velocity.y *= 2;
102+
});
105103

106104
zip = r.getZipper([Velocity]);
105+
expect(zip).toBeDefined();
106+
107+
zip.forEach((entity) => {
108+
expect(entity).toStrictEqual({ Velocity: new Velocity(0, 2) });
109+
});
110+
});
111+
});
112+
113+
describe("indexed zipper", () => {
114+
it("should reflect index of the zipped entities components", async () => {
115+
const m = await Module();
116+
const r = new m.Registry();
117+
107118
for (let i = 0; i < 20; i++) {
108-
if (zip[i]) {
109-
expect(zip[i]).toStrictEqual({ Velocity: new Velocity(0, 2) });
110-
}
119+
const e = r.spawnEntity();
120+
if (i % 5 === 0) r.addComponent(e, new Velocity(0, i));
111121
}
122+
123+
const zip = r.getIndexedZipper([Velocity]);
124+
expect(zip).toBeDefined();
125+
126+
zip.forEach((entity, index) => {
127+
expect(entity).toStrictEqual({ id: index * 5, Velocity: new Velocity(0, index * 5) });
128+
});
112129
});
113130
});
114131
});

packages/ecs-lib/wasm/Registry.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ namespace nfo {
5757
.function("removeSystem", &Registry::remove_system)
5858
.function("clearSystems", &Registry::clear_systems)
5959
.function("getZipper", &Registry::get_zipper)
60+
.function("getIndexedZipper", &Registry::get_indexed_zipper)
6061
.function("maxEntities", &Registry::max_entities);
6162
}
6263
} // namespace nfo

packages/ecs-lib/wasm/Registry.hpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,46 @@ namespace nfo {
323323
return ZipperOutput(arr);
324324
}
325325

326+
/**
327+
* Get the indexed zipper output for the given components.
328+
*
329+
* @param comps An array of component types to zip.
330+
* @return A ZipperOutput containing the id of the entity and it's zipped components.
331+
* @throws std::runtime_error if the input is not an array.
332+
*/
333+
ZipperOutput get_indexed_zipper(const ZipperInput &comps)
334+
{
335+
if (!comps.isArray())
336+
throw std::runtime_error("getIndexedZipper: need an array of comps as parameter");
337+
338+
std::size_t max = SIZE_MAX;
339+
std::map<std::string, SparseArray<emscripten::val> *> arrays;
340+
for (int i = 0; i < comps["length"].as<unsigned int>(); i++) {
341+
SparseArray<emscripten::val> &components = get_components(Component(comps[i]));
342+
arrays[get_js_class_name(comps[i])] = &components;
343+
max = (std::min)(components.size(), max);
344+
}
345+
346+
emscripten::val arr = emscripten::val::array();
347+
std:size_t zipper_idx = 0;
348+
for (std::size_t idx = 0; idx < max; idx++) {
349+
emscripten::val obj = emscripten::val::object();
350+
bool need_to_add = true;
351+
for (const auto &[name, sparse_array] : arrays) {
352+
if (!(*sparse_array)[idx].has_value()) {
353+
need_to_add = false;
354+
break;
355+
}
356+
obj.set(name, (*sparse_array)[idx].value());
357+
}
358+
if (need_to_add) {
359+
obj.set("id", idx);
360+
arr.set(zipper_idx++, obj);
361+
}
362+
}
363+
return ZipperOutput(arr);
364+
}
365+
326366
private:
327367
std::unordered_map<std::string, std::any> _components_arrays;
328368

0 commit comments

Comments
 (0)