]> git.bts.cx Git - benzene.git/blob - src/bz/game/scene.c
Fixed Aseprite rendering system
[benzene.git] / src / bz / game / scene.c
1 #include <bz/game/scene_internal.h>
2
3 #include <bz/collision/particle_collision.h>
4 //#include <bz/fx/agent_simulation.h>
5 #include <bz/fx/particle_simulation.h>
6 #include <bz/fx/particle_system.h>
7 #include <bz/game/actor_internal.h>
8 #include <bz/game/tilemap.h>
9 #include <bz/gfx/aseprite.h>
10 #include <bz/gfx/font_internal.h>
11 #include <bz/gfx/gfx_internal.h>
12 #include <bz/gfx/particle_drawing.h>
13 #include <bz/math/math.h>
14 #include <bz/memory/allocator.h>
15 #include <bz/resources/resource.h>
16 #include <bz/scripting/bindings_internal.h>
17 #include <bz/scripting/script.h>
18 #include <bz/types/identifier_internal.h>
19 #include <parson.h>
20 #include <string.h> // strncpy
21
22 struct BZSceneActorDefinition {
23 //char identifier[kBZMaxIdentifierLength]; // fixme
24 BZIdentifierHash identifierHash;
25 SVMModule *module;
26 size_t instanceSize;
27 int32_t priority;
28 size_t spawnCount;
29 };
30 typedef struct BZSceneActorDefinition BZSceneActorDefinition;
31
32 /*struct BZSceneParticleSystem {
33 char identifier[kBZMaxIdentifierLength]; // fixme
34 BZIdentifierHash identifierHash;
35 BZParticleSystemID particleSystem;
36 };
37 typedef struct BZSceneParticleSystem BZSceneParticleSystem;*/
38
39 struct BZSceneLayer {
40 char identifier[kBZMaxIdentifierLength]; // fixme
41 BZIdentifierHash identifierHash;
42 BZDrawQueueID drawQueue;
43 BZTilemapID tilemap;
44 BZParticleSimulationID particleSimulation;
45 BZCollisionSpaceID collisionSpace;
46 BZIdentifierHash particleCollisionTagHash;
47 float particleCollisionRadiusMultiplier;
48 int outputBuffer;
49 };
50
51 ////#define kMaxActorInstances 50//256
52
53 struct BZSceneActor {
54 BZActor actor;
55 BZScriptBindingMetadata scriptMetadata;
56 int32_t priority;
57 bool running;
58 };
59 typedef struct BZSceneActor BZSceneActor;
60
61 #define kBZScriptingEnvironmentPublicCount 256
62 #define kBZScriptingEnvironmentEventCount 256
63
64 struct BZScriptingEnvironmentPublic {
65 BZIdentifierHash identifierHash;
66 SVMOperand value;
67 };
68 typedef struct BZScriptingEnvironmentPublic BZScriptingEnvironmentPublic;
69
70 struct BZSceneEvent {
71 BZIdentifierHash identifierHash;
72 BZSceneEventData data;
73 };
74 typedef struct BZSceneEvent BZSceneEvent;
75
76 struct BZScene {
77 // BZScriptingEnvironmentID sceneEnvironment;
78 // BZScriptID sceneScript;
79 // BZScriptBindingMetadata sceneScriptMetadata;
80 // BZScriptInstanceID sceneScriptInstance;
81 BZSceneActorDefinition *actorDefinitions;
82 size_t actorDefinitionCount;
83 BZSceneLayer *layers;
84 size_t layerCount;
85 uint64_t ticks;
86
87 int32_t minActorPriority;
88 int32_t maxActorPriority;
89
90 size_t lastActorIndex;
91 size_t actorInstanceCount;
92 BZSceneActor *actorInstances;
93
94 BZScriptingEnvironmentPublic publics[kBZScriptingEnvironmentPublicCount];
95
96 BZAudioPlaybackEngineID audioEngine;
97
98 // BZAgentSimulationID agentSimulation;
99
100 size_t eventCount;
101 BZSceneEvent *currentEvents;
102 size_t nextEnqueuedEvent;
103 BZSceneEvent *enqueuedEvents;
104
105 // char targetSceneIdentifier[kBZMaxIdentifierLength]; // fixme
106 };
107
108 uint8_t gSystemTicksPerSecond;
109
110 static void bzGameSceneActorLoadDefinition(BZSceneActorDefinition *definitionOut, BZSceneID scene, BZMemoryArenaID arena, const char *identifierFmt, ...) {
111 bzMakeIdentifier(identifier, identifierFmt);
112 definitionOut->identifierHash = bzIdentifierHashFromIdentifier(identifier);
113
114 BZResourceID handle = bzResourcesOpenResource("scene", "assets/actors/%s.actor.json", identifier);
115 bzAssertMessage(handle != NULL, "Invalid actor definition '%s'", identifier);
116
117 size_t length = bzResourcesFileLength(handle);
118 char *data = alloca(length);//(char *)bzMemoryAlloc(kBZSystemMemoryArena, length);//alloca(length); // FIXME, need working space off the stack
119 bzResourcesReadBytes(handle, data, length);
120 bzResourcesCloseResource(handle);
121
122 //json_set_allocation_functions
123 JSON_Value *actorDefinitionJson = json_parse_string(data);
124 JSON_Object *actorDefinitionJsonObject = json_object(actorDefinitionJson);
125
126 const char *scriptName = json_object_get_string(actorDefinitionJsonObject, "script");
127 if (scriptName != NULL) {
128 definitionOut->module = bzScriptingLoadScriptModule(arena, "%s", scriptName);
129 definitionOut->instanceSize = svmGetModuleInstanceSize(definitionOut->module);
130 }
131
132 definitionOut->priority = json_object_get_number(actorDefinitionJsonObject, "priority");
133 scene->minActorPriority = bzMin(scene->minActorPriority, definitionOut->priority);
134 scene->maxActorPriority = bzMax(scene->maxActorPriority, definitionOut->priority);
135
136 json_value_free(actorDefinitionJson);
137
138 bzLog("Opened actor %s", identifier);
139 }
140
141 static BZActorID bzGameSceneSetupActor(BZSceneActor *sceneActor, BZSceneID scene, const BZSceneActorDefinition *definition, const char *identifierFmt, ...) {
142 BZActorID actor = &sceneActor->actor;
143 BZScriptBindingMetadata *metadata = &sceneActor->scriptMetadata;
144
145 bzInsertIdentifier(actor->identifier, identifierFmt);
146 actor->identifierHash = bzIdentifierHashFromIdentifier(actor->identifier);
147
148 bzAssertMessage(definition != NULL, "Could not find definition for '%s'", actor->identifier);
149
150 sceneActor->priority = definition->priority;
151
152 actor->instance = svnResetModuleInstanceMemory(definition->module, actor->instance, metadata, bzScriptingBindingsLookupNativeFunction);
153 bzScriptingInitialiseMetadata((BZScriptBindingMetadata *)&sceneActor->scriptMetadata, actor, scene, scene->lastActorIndex);
154
155 sceneActor->running = true;
156
157 return actor;
158 }
159
160 BZSceneID bzGameSceneSwitch(BZMemoryArenaID arena, BZAudioPlaybackEngineID audioEngine, const char *identifierFmt, ...) {
161 bzMakeIdentifier(identifier, identifierFmt);
162
163 BZSceneID scene = bzMemoryAlloc(arena, sizeof(BZScene));
164
165 BZResourceID handle = bzResourcesOpenResource("scene", "assets/scenes/%s.scene.json", identifier);
166 size_t length = bzResourcesFileLength(handle);
167 char *data = alloca(length);//(char *)bzMemoryAlloc(kBZSystemMemoryArena, length);//alloca(length); // FIXME, need working space off the stack
168 bzResourcesReadBytes(handle, data, length);
169 bzResourcesCloseResource(handle);
170
171 //json_set_allocation_functions
172 JSON_Value *sceneJson = json_parse_string(data);
173 JSON_Object *sceneJsonObject = json_object(sceneJson);
174
175 const char *soundbankName = json_object_get_string(sceneJsonObject, "soundbank");
176 if (soundbankName != NULL && audioEngine != NULL) {
177 scene->audioEngine = audioEngine;
178 bzAudioPlaybackUseSoundbank(scene->audioEngine, arena, soundbankName);
179 }
180
181 const char *spritesheetName = json_object_get_string(sceneJsonObject, "spritesheet");
182 if (spritesheetName != NULL) {
183 size_t imageFrames, imageWidth, imageHeight;
184 void *imageData = bzGfxLoadAsepriteImage(arena, &imageFrames, &imageWidth, &imageHeight, spritesheetName); // FIXME, temp arena
185 bzGfxPrepareSpritesheet(arena, imageFrames, imageWidth, imageHeight, imageData);
186 //free(imageData);
187 }
188
189 const char *fontName = json_object_get_string(sceneJsonObject, "font");
190 if (fontName != NULL) {
191 BZFont *font = bzGfxLoadFont(arena, fontName); // FIXME, temp arena??
192 bzGfxPrepareFont(arena, font);
193 }
194
195 JSON_Array *actorDefinitionsArray = json_object_get_array(sceneJsonObject, "actors");
196 size_t actorDefinitionsArrayCount = json_array_get_count(actorDefinitionsArray);
197 scene->actorDefinitionCount = actorDefinitionsArrayCount;
198
199 size_t startDefinition = 0;
200 const char *sceneActorName = json_object_get_string(sceneJsonObject, "scene_actor");
201 if (sceneActorName != NULL) {
202 scene->actorDefinitionCount += 1;
203 startDefinition = 1;
204 }
205
206 scene->actorDefinitions = (BZSceneActorDefinition *)bzMemoryAlloc(arena, scene->actorDefinitionCount * sizeof(BZSceneActorDefinition));
207
208 size_t maxInstanceSize = 0;
209
210 if (sceneActorName != NULL) {
211 bzGameSceneActorLoadDefinition(&scene->actorDefinitions[0], scene, arena, "%s", sceneActorName); // fixme
212 maxInstanceSize = scene->actorDefinitions[0].instanceSize;
213 }
214
215 for (size_t i = 0; i < actorDefinitionsArrayCount; ++i) {
216 const char *actorName = json_array_get_string(actorDefinitionsArray, i);
217 size_t outIdx = i + startDefinition;
218 bzGameSceneActorLoadDefinition(&scene->actorDefinitions[outIdx], scene, arena, "%s", actorName); // fixme
219 maxInstanceSize = bzMax(maxInstanceSize, scene->actorDefinitions[outIdx].instanceSize);
220 }
221
222 // FIXME, alignment for instance size
223
224 scene->lastActorIndex = 0;
225 scene->actorInstanceCount = 1024;
226
227 scene->actorInstances = (BZSceneActor *)bzMemoryAlloc(arena, scene->actorInstanceCount * sizeof(BZSceneActor));
228 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
229 scene->actorInstances[i].actor.instance = bzMemoryAlloc(arena, maxInstanceSize);
230 }
231
232 if (sceneActorName != NULL) {
233 bzGameSceneSetupActor(&scene->actorInstances[0], scene, &scene->actorDefinitions[0], "scene");
234 }
235
236 // int hasAgents = json_object_get_boolean(sceneJsonObject, "agents");
237 // if (hasAgents > 0) {
238 // scene->agentSimulation = bzFXCreateAgentSimulation(arena, scene->actorInstanceCount, "%s.agents", identifier);
239 // }
240
241 JSON_Array *layerDefinitionsArray = json_object_get_array(sceneJsonObject, "layers");
242 scene->layerCount = json_array_get_count(layerDefinitionsArray);
243 scene->layers = bzMemoryAlloc(arena, scene->layerCount * sizeof(BZSceneLayer));
244 for (size_t i = 0; i < scene->layerCount; ++i) {
245 JSON_Object *layerDefinition = json_array_get_object(layerDefinitionsArray, i);
246 stbsp_snprintf(scene->layers[i].identifier, kBZMaxIdentifierLength, "%s", json_object_get_string(layerDefinition, "identifier"));
247 scene->layers[i].identifierHash = bzIdentifierHashFromIdentifier(scene->layers[i].identifier);
248
249 const char *particleSystemName = json_object_get_string(layerDefinition, "particles");
250 if (particleSystemName != NULL) {
251 BZParticleSystemID particleSystem = bzFXLoadParticleSystem(arena, "%s", particleSystemName); // FIXME, pool these...
252 int hasCollision2 = json_object_get_boolean(layerDefinition, "collision"); // FIXME
253 scene->layers[i].particleSimulation = bzFXCreateParticleSimulation(arena, (hasCollision2 > 0) ? 1024 : (5 * 1024), particleSystem, "%s.particles", scene->layers[i].identifier); // FIXME, memory
254 }
255
256 if (json_object_has_value_of_type(layerDefinition, "output", JSONNumber)) {
257 scene->layers[i].outputBuffer = (int)json_object_get_number(layerDefinition, "output");
258 if (particleSystemName == NULL || json_object_get_boolean(layerDefinition, "custom-particle") > 0) {
259 scene->layers[i].drawQueue = bzGfxDrawQueueCreate(arena, "scene.%s.drawQueue", scene->layers[i].identifier);
260 }
261 }
262
263 const char *tilemapName = json_object_get_string(layerDefinition, "tilemap");
264 if (tilemapName != NULL) {
265 scene->layers[i].tilemap = bzGameLoadTilemap(arena, "%s", tilemapName);
266 }
267
268 int hasCollision = json_object_get_boolean(layerDefinition, "collision");
269 if (hasCollision > 0) {
270 if (scene->layers[i].particleSimulation == NULL) {
271 scene->layers[i].collisionSpace = bzCollisionMakeSpace(arena, scene->actorInstanceCount, "%s.collision", scene->layers[i].identifier);
272 } else {
273 scene->layers[i].collisionSpace = bzCollisionMakeSpace(arena, 1024, "%s.particle.collision", scene->layers[i].identifier);
274
275 if (json_object_has_value_of_type(layerDefinition, "collision-radius", JSONNumber)) {
276 scene->layers[i].particleCollisionRadiusMultiplier = json_object_get_number(layerDefinition, "collision-radius");
277 } else {
278 scene->layers[i].particleCollisionRadiusMultiplier = 1.0f;
279 }
280 scene->layers[i].particleCollisionTagHash = bzIdentifierHashFromIdentifier(particleSystemName);
281 }
282 }
283 }
284
285 scene->currentEvents = bzMemoryAlloc(arena, kBZScriptingEnvironmentEventCount * sizeof(BZSceneEvent));
286 scene->enqueuedEvents = bzMemoryAlloc(arena, kBZScriptingEnvironmentEventCount * sizeof(BZSceneEvent));
287
288 json_value_free(sceneJson);
289
290 bzLog("Opened scene %s", identifier);
291
292 return scene;
293 }
294
295 bool bzGameSceneUpdate(BZSceneID scene, uint8_t pauseFlags, uint8_t systemTicks) {
296 float deltaTime = (float)systemTicks / (float)gSystemTicksPerSecond;
297
298 for (size_t i = 0; i < scene->layerCount; ++i) {
299 BZSceneLayer *layer = &scene->layers[i];
300 if (layer->particleSimulation == NULL) {
301 bzGfxDrawQueueClear(layer->drawQueue);
302 }
303 if (layer->collisionSpace != NULL) {
304 bzCollisionResetSpace(layer->collisionSpace);
305 }
306 }
307
308 // if (scene->agentSimulation != NULL) {
309 // SVMOperand playerX;
310 // bzScriptingGetEnvironmentPublic(&playerX, scene, bzIdentifierHashFromIdentifier("shipX"));
311 //
312 // SVMOperand playerY;
313 // bzScriptingGetEnvironmentPublic(&playerY, scene, bzIdentifierHashFromIdentifier("shipY"));
314 //
315 // BZVector playerPos = bzVectorMake(FIXED_TO_FLOAT(playerX.floatLiteral), FIXED_TO_FLOAT(playerY.floatLiteral));
316 //
317 // bzFXUpdateAgentSimulation(scene->agentSimulation, deltaTime, NULL, &playerPos);
318 // }
319
320 for (size_t i = 0; i < scene->layerCount; ++i) {
321 BZSceneLayer *layer = &scene->layers[i];
322 if (layer->particleSimulation != NULL) {
323 bzFXUpdateParticleSystem(layer->particleSimulation, deltaTime);
324 if (layer->collisionSpace != NULL) {
325 bzCollisionPopulateParticles(layer->collisionSpace, layer->particleSimulation, layer->particleCollisionTagHash, layer->particleCollisionRadiusMultiplier);
326 }
327 }
328 }
329
330 for (int32_t priority = scene->minActorPriority; priority <= scene->maxActorPriority; ++priority) {
331 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
332 BZSceneActor *sceneActor = &scene->actorInstances[i];
333 if (sceneActor->running && sceneActor->priority == priority) {
334 SVMRunOutcome outcome = svmRunModuleInstance(sceneActor->actor.instance);
335 sceneActor->running = (outcome == SVMRunOutcomeSuspended);
336 }
337 }
338 }
339
340 scene->ticks += systemTicks;
341
342 scene->eventCount = scene->nextEnqueuedEvent;
343 scene->nextEnqueuedEvent = 0;
344
345 BZSceneEvent *tmp = scene->currentEvents;
346 scene->currentEvents = scene->enqueuedEvents;
347 scene->enqueuedEvents = tmp;
348
349 return scene->actorInstances[0].running;
350 }
351
352 void bzGameSceneDraw(BZSceneID scene) {
353 for (size_t i = 0; i < scene->layerCount; ++i) {
354 bzSetOutputBuffer(scene->layers[i].outputBuffer);
355 if (scene->layers[i].particleSimulation != NULL) {
356 bzGfxDrawParticles(scene->layers[i].particleSimulation, scene->layers[i].drawQueue);
357 } else {
358 bzGfxDrawQueueRun(scene->layers[i].drawQueue);
359 }
360
361 //if (scene->layers[i].collisionSpace != NULL) {
362 // bzCollisionDrawDebug(scene->layers[i].collisionSpace);
363 //}
364
365 // if (i == 3 && scene->agentSimulation != NULL) { // FIXME
366 // bzFXAgentSimulationDrawDebug(scene->agentSimulation);
367 // }
368 }
369
370
371 }
372
373 BZActorID bzGameSceneAddActor(BZSceneID scene, const char *identifierFmt, ...) {
374 bzMakeIdentifier(identifier, identifierFmt);
375
376 BZIdentifierHash definitionIdentifierHash = bzIdentifierHashFromIdentifier(identifier);
377 BZSceneActorDefinition *definition = NULL;
378 for (size_t i = 0; i < scene->actorDefinitionCount; ++i) { // fixme
379 if (definitionIdentifierHash == scene->actorDefinitions[i].identifierHash) {
380 definition = &scene->actorDefinitions[i];
381 break;
382 }
383 }
384 bzAssertMessage(definition != NULL, "Undefined actor '%s'", identifier);
385
386 BZSceneActor *sceneActor = NULL;
387 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
388 ++scene->lastActorIndex;
389
390 size_t idx = (scene->lastActorIndex % (scene->actorInstanceCount - 1)) + 1; // 0 is only for the scene script
391 if (scene->actorInstances[idx].running == false) {
392 sceneActor = &scene->actorInstances[idx];
393 break;
394 }
395 }
396 bzAssertMessage(sceneActor != NULL, "Out of actors");
397
398 definition->spawnCount += 1;
399
400 return bzGameSceneSetupActor(sceneActor, scene, definition, "%s-%u", identifier, definition->spawnCount);
401 }
402
403 BZActorID bzGameSceneFindActor(BZSceneID scene, const char *identifierFmt, ...) {
404 bzMakeIdentifier(identifier, identifierFmt);
405 BZIdentifierHash identifierHash = bzIdentifierHashFromIdentifier(identifier);
406 for (size_t i = 0; i < scene->actorInstanceCount; ++i) { // fixme
407 if (scene->actorInstances[i].actor.identifierHash == identifierHash) {
408 return &scene->actorInstances[i].actor;
409 }
410 }
411 return NULL;
412 }
413
414 float bzGameSceneGetTime(BZSceneID scene) {
415 float time = (float)scene->ticks / (float)gSystemTicksPerSecond;
416 return time;
417 }
418
419 bool bzGameSceneQueryEvent(BZSceneEventData *dataOut, BZSceneID scene, BZIdentifierHash eventIdentifier) {
420 for (size_t i = 0; i < scene->eventCount; ++i) {
421 BZSceneEvent *event = &scene->currentEvents[i];
422 if (event->identifierHash == eventIdentifier) {
423 if (dataOut != NULL) {
424 *dataOut = event->data;
425 }
426 return true;
427 }
428 }
429 return false;
430 }
431
432 void bzGameScenePostEvent(BZSceneID scene, BZIdentifierHash eventIdentifier, const BZSceneEventData *data) {
433 bzAssert(scene->nextEnqueuedEvent < kBZScriptingEnvironmentEventCount);
434 BZSceneEvent *event = &scene->enqueuedEvents[scene->nextEnqueuedEvent++];
435 event->identifierHash = eventIdentifier;
436 if (data != NULL) {
437 event->data = *data;
438 }
439 }
440
441 BZSceneLayer *getLayer(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
442 for (size_t i = 0; i < scene->layerCount; ++i) {
443 if (scene->layers[i].identifierHash == layerIdentifierHash) {
444 return &scene->layers[i];
445 }
446 }
447 return NULL;
448 }
449
450 BZTilemapID bzGameGetSceneLayerTilemap(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
451 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
452 if (layer != NULL) {
453 return layer->tilemap;
454 } else {
455 return NULL;
456 }
457 }
458
459 BZDrawQueueID bzGameGetSceneLayerDrawQueue(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
460 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
461 if (layer != NULL) {
462 return layer->drawQueue;
463 } else {
464 return NULL;
465 }
466 }
467
468 BZParticleSimulationID bzGameGetSceneLayerParticleSimulation(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
469 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
470 if (layer != NULL) {
471 return layer->particleSimulation;
472 } else {
473 return NULL;
474 }
475 }
476
477 BZCollisionSpaceID bzGameGetSceneLayerCollisionSpace(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
478 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
479 if (layer != NULL) {
480 return layer->collisionSpace;
481 } else {
482 return NULL;
483 }
484 }
485
486
487 /*
488 extern void bzGameSceneSetTimeTicksPerSecond(uint8_t tps);
489 extern void bzGameSceneSetTimePauseFlags(uint8_t timeIdx, uint8_t pauseFlags); // Pause timer on these flags
490 extern float bzGameSceneTime(uint8_t timeIdx);
491
492 void bzGameSceneSetTimeTicksPerSecond(uint8_t tps) {
493 sceneTPS = tps;
494 }
495
496 void bzGameSceneSetTimePauseFlags(uint8_t timeIdx, uint8_t pauseFlags) {
497 times[timeIdx].pauseFlags = pauseFlags;
498 }
499
500 float bzGameSceneTime(uint8_t timeIdx) {
501 float time = (float)times[timeIdx].ticks / (float)sceneTPS;
502 return time;
503 }
504 */
505
506 //BZAgentSimulationID bzGameGetAgentSimulation(BZSceneID scene) {
507 // return scene->agentSimulation;
508 //}
509
510 BZAudioPlaybackEngineID bzGameGetAudioPlaybackEngine(BZSceneID scene) {
511 return scene->audioEngine;
512 }
513
514 bool bzScriptingGetEnvironmentPublic(SVMOperand *out, BZSceneID scene, BZIdentifierHash identifierHash) {
515 for (size_t i = 0; i < kBZScriptingEnvironmentPublicCount; ++i) {
516 if (scene->publics[i].identifierHash == identifierHash) {
517 if (out != NULL) {
518 out->__raw = scene->publics[i].value.__raw;
519 }
520 return true;
521 }
522 }
523 return false;
524 }
525
526 void bzScriptingSetEnvironmentPublic(BZSceneID scene, BZIdentifierHash identifierHash, SVMOperand value) {
527 for (size_t i = 0; i < kBZScriptingEnvironmentPublicCount; ++i) {
528 if (scene->publics[i].identifierHash == 0) {
529 scene->publics[i].identifierHash = identifierHash;
530 }
531 if (scene->publics[i].identifierHash == identifierHash) {
532 scene->publics[i].value.__raw = value.__raw;
533 return;
534 }
535 }
536 bzError("Out of globals!!");
537 }
538
539 size_t bzGameGetSceneLayerCount(BZSceneID scene) {
540 return scene->layerCount;
541 }
542
543 BZSceneLayerID bzGameGetSceneLayerAtIndex(BZSceneID scene, size_t idx) {
544 bzAssert(idx < scene->layerCount);
545 return &scene->layers[idx];
546 }
547
548
549 BZCollisionSpaceID bzGameGetSceneLayerCollisionSpace2(BZSceneLayerID layer) {
550 return layer->collisionSpace;
551 }
552
553 BZParticleSimulationID bzGameGetSceneLayerParticleSimulation2(BZSceneLayerID layer) {
554 return layer->particleSimulation;
555 }