]> git.bts.cx Git - benzene.git/blob - src/bz/game/scene.c
907fccb03e72b55a1c54bc051ba8ff59524895f9
[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 imageWidth, imageHeight;
184 void *imageData = bzGfxLoadAsepriteImage(arena, &imageWidth, &imageHeight, spritesheetName); // FIXME, temp arena
185 bzGfxPrepareSpritesheet(arena, imageWidth, imageHeight, imageData);
186 //free(imageData);
187 }
188
189 const char *fontName = json_object_get_string(sceneJsonObject, "font");
190 BZFont *font = bzGfxLoadFont(arena, fontName); // FIXME, temp arena??
191 bzGfxPrepareFont(arena, font);
192
193 JSON_Array *actorDefinitionsArray = json_object_get_array(sceneJsonObject, "actors");
194 size_t actorDefinitionsArrayCount = json_array_get_count(actorDefinitionsArray);
195 scene->actorDefinitionCount = actorDefinitionsArrayCount;
196
197 size_t startDefinition = 0;
198 const char *sceneActorName = json_object_get_string(sceneJsonObject, "scene_actor");
199 if (sceneActorName != NULL) {
200 scene->actorDefinitionCount += 1;
201 startDefinition = 1;
202 }
203
204 scene->actorDefinitions = (BZSceneActorDefinition *)bzMemoryAlloc(arena, scene->actorDefinitionCount * sizeof(BZSceneActorDefinition));
205
206 size_t maxInstanceSize = 0;
207
208 if (sceneActorName != NULL) {
209 bzGameSceneActorLoadDefinition(&scene->actorDefinitions[0], scene, arena, "%s", sceneActorName); // fixme
210 maxInstanceSize = scene->actorDefinitions[0].instanceSize;
211 }
212
213 for (size_t i = 0; i < actorDefinitionsArrayCount; ++i) {
214 const char *actorName = json_array_get_string(actorDefinitionsArray, i);
215 size_t outIdx = i + startDefinition;
216 bzGameSceneActorLoadDefinition(&scene->actorDefinitions[outIdx], scene, arena, "%s", actorName); // fixme
217 maxInstanceSize = bzMax(maxInstanceSize, scene->actorDefinitions[outIdx].instanceSize);
218 }
219
220 // FIXME, alignment for instance size
221
222 scene->lastActorIndex = 0;
223 scene->actorInstanceCount = 1024;
224
225 scene->actorInstances = (BZSceneActor *)bzMemoryAlloc(arena, scene->actorInstanceCount * sizeof(BZSceneActor));
226 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
227 scene->actorInstances[i].actor.instance = bzMemoryAlloc(arena, maxInstanceSize);
228 }
229
230 if (sceneActorName != NULL) {
231 bzGameSceneSetupActor(&scene->actorInstances[0], scene, &scene->actorDefinitions[0], "scene");
232 }
233
234 // int hasAgents = json_object_get_boolean(sceneJsonObject, "agents");
235 // if (hasAgents > 0) {
236 // scene->agentSimulation = bzFXCreateAgentSimulation(arena, scene->actorInstanceCount, "%s.agents", identifier);
237 // }
238
239 JSON_Array *layerDefinitionsArray = json_object_get_array(sceneJsonObject, "layers");
240 scene->layerCount = json_array_get_count(layerDefinitionsArray);
241 scene->layers = bzMemoryAlloc(arena, scene->layerCount * sizeof(BZSceneLayer));
242 for (size_t i = 0; i < scene->layerCount; ++i) {
243 JSON_Object *layerDefinition = json_array_get_object(layerDefinitionsArray, i);
244 stbsp_snprintf(scene->layers[i].identifier, kBZMaxIdentifierLength, "%s", json_object_get_string(layerDefinition, "identifier"));
245 scene->layers[i].identifierHash = bzIdentifierHashFromIdentifier(scene->layers[i].identifier);
246
247 const char *particleSystemName = json_object_get_string(layerDefinition, "particles");
248 if (particleSystemName != NULL) {
249 BZParticleSystemID particleSystem = bzFXLoadParticleSystem(arena, "%s", particleSystemName); // FIXME, pool these...
250 int hasCollision2 = json_object_get_boolean(layerDefinition, "collision"); // FIXME
251 scene->layers[i].particleSimulation = bzFXCreateParticleSimulation(arena, (hasCollision2 > 0) ? 1024 : (5 * 1024), particleSystem, "%s.particles", scene->layers[i].identifier); // FIXME, memory
252 }
253
254 if (json_object_has_value_of_type(layerDefinition, "output", JSONNumber)) {
255 scene->layers[i].outputBuffer = (int)json_object_get_number(layerDefinition, "output");
256 if (particleSystemName == NULL || json_object_get_boolean(layerDefinition, "custom-particle") > 0) {
257 scene->layers[i].drawQueue = bzGfxDrawQueueCreate(arena, "scene.%s.drawQueue", scene->layers[i].identifier);
258 }
259 }
260
261 const char *tilemapName = json_object_get_string(layerDefinition, "tilemap");
262 if (tilemapName != NULL) {
263 scene->layers[i].tilemap = bzGameLoadTilemap(arena, "%s", tilemapName);
264 }
265
266 int hasCollision = json_object_get_boolean(layerDefinition, "collision");
267 if (hasCollision > 0) {
268 if (scene->layers[i].particleSimulation == NULL) {
269 scene->layers[i].collisionSpace = bzCollisionMakeSpace(arena, scene->actorInstanceCount, "%s.collision", scene->layers[i].identifier);
270 } else {
271 scene->layers[i].collisionSpace = bzCollisionMakeSpace(arena, 1024, "%s.particle.collision", scene->layers[i].identifier);
272
273 if (json_object_has_value_of_type(layerDefinition, "collision-radius", JSONNumber)) {
274 scene->layers[i].particleCollisionRadiusMultiplier = json_object_get_number(layerDefinition, "collision-radius");
275 } else {
276 scene->layers[i].particleCollisionRadiusMultiplier = 1.0f;
277 }
278 scene->layers[i].particleCollisionTagHash = bzIdentifierHashFromIdentifier(particleSystemName);
279 }
280 }
281 }
282
283 scene->currentEvents = bzMemoryAlloc(arena, kBZScriptingEnvironmentEventCount * sizeof(BZSceneEvent));
284 scene->enqueuedEvents = bzMemoryAlloc(arena, kBZScriptingEnvironmentEventCount * sizeof(BZSceneEvent));
285
286 json_value_free(sceneJson);
287
288 bzLog("Opened scene %s", identifier);
289
290 return scene;
291 }
292
293 bool bzGameSceneUpdate(BZSceneID scene, uint8_t pauseFlags, uint8_t systemTicks) {
294 float deltaTime = (float)systemTicks / (float)gSystemTicksPerSecond;
295
296 for (size_t i = 0; i < scene->layerCount; ++i) {
297 BZSceneLayer *layer = &scene->layers[i];
298 if (layer->particleSimulation == NULL) {
299 bzGfxDrawQueueClear(layer->drawQueue);
300 }
301 if (layer->collisionSpace != NULL) {
302 bzCollisionResetSpace(layer->collisionSpace);
303 }
304 }
305
306 // if (scene->agentSimulation != NULL) {
307 // SVMOperand playerX;
308 // bzScriptingGetEnvironmentPublic(&playerX, scene, bzIdentifierHashFromIdentifier("shipX"));
309 //
310 // SVMOperand playerY;
311 // bzScriptingGetEnvironmentPublic(&playerY, scene, bzIdentifierHashFromIdentifier("shipY"));
312 //
313 // BZVector playerPos = bzVectorMake(FIXED_TO_FLOAT(playerX.floatLiteral), FIXED_TO_FLOAT(playerY.floatLiteral));
314 //
315 // bzFXUpdateAgentSimulation(scene->agentSimulation, deltaTime, NULL, &playerPos);
316 // }
317
318 for (size_t i = 0; i < scene->layerCount; ++i) {
319 BZSceneLayer *layer = &scene->layers[i];
320 if (layer->particleSimulation != NULL) {
321 bzFXUpdateParticleSystem(layer->particleSimulation, deltaTime);
322 if (layer->collisionSpace != NULL) {
323 bzCollisionPopulateParticles(layer->collisionSpace, layer->particleSimulation, layer->particleCollisionTagHash, layer->particleCollisionRadiusMultiplier);
324 }
325 }
326 }
327
328 for (int32_t priority = scene->minActorPriority; priority <= scene->maxActorPriority; ++priority) {
329 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
330 BZSceneActor *sceneActor = &scene->actorInstances[i];
331 if (sceneActor->running && sceneActor->priority == priority) {
332 SVMRunOutcome outcome = svmRunModuleInstance(sceneActor->actor.instance);
333 sceneActor->running = (outcome == SVMRunOutcomeSuspended);
334 }
335 }
336 }
337
338 scene->ticks += systemTicks;
339
340 scene->eventCount = scene->nextEnqueuedEvent;
341 scene->nextEnqueuedEvent = 0;
342
343 BZSceneEvent *tmp = scene->currentEvents;
344 scene->currentEvents = scene->enqueuedEvents;
345 scene->enqueuedEvents = tmp;
346
347 return scene->actorInstances[0].running;
348 }
349
350 void bzGameSceneDraw(BZSceneID scene) {
351 for (size_t i = 0; i < scene->layerCount; ++i) {
352 bzSetOutputBuffer(scene->layers[i].outputBuffer);
353 if (scene->layers[i].particleSimulation != NULL) {
354 bzGfxDrawParticles(scene->layers[i].particleSimulation, scene->layers[i].drawQueue);
355 } else {
356 bzGfxDrawQueueRun(scene->layers[i].drawQueue);
357 }
358
359 //if (scene->layers[i].collisionSpace != NULL) {
360 // bzCollisionDrawDebug(scene->layers[i].collisionSpace);
361 //}
362
363 // if (i == 3 && scene->agentSimulation != NULL) { // FIXME
364 // bzFXAgentSimulationDrawDebug(scene->agentSimulation);
365 // }
366 }
367
368
369 }
370
371 BZActorID bzGameSceneAddActor(BZSceneID scene, const char *identifierFmt, ...) {
372 bzMakeIdentifier(identifier, identifierFmt);
373
374 BZIdentifierHash definitionIdentifierHash = bzIdentifierHashFromIdentifier(identifier);
375 BZSceneActorDefinition *definition = NULL;
376 for (size_t i = 0; i < scene->actorDefinitionCount; ++i) { // fixme
377 if (definitionIdentifierHash == scene->actorDefinitions[i].identifierHash) {
378 definition = &scene->actorDefinitions[i];
379 break;
380 }
381 }
382 bzAssertMessage(definition != NULL, "Undefined actor '%s'", identifier);
383
384 BZSceneActor *sceneActor = NULL;
385 for (size_t i = 0; i < scene->actorInstanceCount; ++i) {
386 ++scene->lastActorIndex;
387
388 size_t idx = (scene->lastActorIndex % (scene->actorInstanceCount - 1)) + 1; // 0 is only for the scene script
389 if (scene->actorInstances[idx].running == false) {
390 sceneActor = &scene->actorInstances[idx];
391 break;
392 }
393 }
394 bzAssertMessage(sceneActor != NULL, "Out of actors");
395
396 definition->spawnCount += 1;
397
398 return bzGameSceneSetupActor(sceneActor, scene, definition, "%s-%u", identifier, definition->spawnCount);
399 }
400
401 BZActorID bzGameSceneFindActor(BZSceneID scene, const char *identifierFmt, ...) {
402 bzMakeIdentifier(identifier, identifierFmt);
403 BZIdentifierHash identifierHash = bzIdentifierHashFromIdentifier(identifier);
404 for (size_t i = 0; i < scene->actorInstanceCount; ++i) { // fixme
405 if (scene->actorInstances[i].actor.identifierHash == identifierHash) {
406 return &scene->actorInstances[i].actor;
407 }
408 }
409 return NULL;
410 }
411
412 float bzGameSceneGetTime(BZSceneID scene) {
413 float time = (float)scene->ticks / (float)gSystemTicksPerSecond;
414 return time;
415 }
416
417 bool bzGameSceneQueryEvent(BZSceneEventData *dataOut, BZSceneID scene, BZIdentifierHash eventIdentifier) {
418 for (size_t i = 0; i < scene->eventCount; ++i) {
419 BZSceneEvent *event = &scene->currentEvents[i];
420 if (event->identifierHash == eventIdentifier) {
421 if (dataOut != NULL) {
422 *dataOut = event->data;
423 }
424 return true;
425 }
426 }
427 return false;
428 }
429
430 void bzGameScenePostEvent(BZSceneID scene, BZIdentifierHash eventIdentifier, const BZSceneEventData *data) {
431 bzAssert(scene->nextEnqueuedEvent < kBZScriptingEnvironmentEventCount);
432 BZSceneEvent *event = &scene->enqueuedEvents[scene->nextEnqueuedEvent++];
433 event->identifierHash = eventIdentifier;
434 if (data != NULL) {
435 event->data = *data;
436 }
437 }
438
439 BZSceneLayer *getLayer(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
440 for (size_t i = 0; i < scene->layerCount; ++i) {
441 if (scene->layers[i].identifierHash == layerIdentifierHash) {
442 return &scene->layers[i];
443 }
444 }
445 return NULL;
446 }
447
448 BZTilemapID bzGameGetSceneLayerTilemap(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
449 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
450 if (layer != NULL) {
451 return layer->tilemap;
452 } else {
453 return NULL;
454 }
455 }
456
457 BZDrawQueueID bzGameGetSceneLayerDrawQueue(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
458 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
459 if (layer != NULL) {
460 return layer->drawQueue;
461 } else {
462 return NULL;
463 }
464 }
465
466 BZParticleSimulationID bzGameGetSceneLayerParticleSimulation(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
467 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
468 if (layer != NULL) {
469 return layer->particleSimulation;
470 } else {
471 return NULL;
472 }
473 }
474
475 BZCollisionSpaceID bzGameGetSceneLayerCollisionSpace(BZSceneID scene, BZIdentifierHash layerIdentifierHash) {
476 BZSceneLayer *layer = getLayer(scene, layerIdentifierHash);
477 if (layer != NULL) {
478 return layer->collisionSpace;
479 } else {
480 return NULL;
481 }
482 }
483
484
485 /*
486 extern void bzGameSceneSetTimeTicksPerSecond(uint8_t tps);
487 extern void bzGameSceneSetTimePauseFlags(uint8_t timeIdx, uint8_t pauseFlags); // Pause timer on these flags
488 extern float bzGameSceneTime(uint8_t timeIdx);
489
490 void bzGameSceneSetTimeTicksPerSecond(uint8_t tps) {
491 sceneTPS = tps;
492 }
493
494 void bzGameSceneSetTimePauseFlags(uint8_t timeIdx, uint8_t pauseFlags) {
495 times[timeIdx].pauseFlags = pauseFlags;
496 }
497
498 float bzGameSceneTime(uint8_t timeIdx) {
499 float time = (float)times[timeIdx].ticks / (float)sceneTPS;
500 return time;
501 }
502 */
503
504 //BZAgentSimulationID bzGameGetAgentSimulation(BZSceneID scene) {
505 // return scene->agentSimulation;
506 //}
507
508 BZAudioPlaybackEngineID bzGameGetAudioPlaybackEngine(BZSceneID scene) {
509 return scene->audioEngine;
510 }
511
512 bool bzScriptingGetEnvironmentPublic(SVMOperand *out, BZSceneID scene, BZIdentifierHash identifierHash) {
513 for (size_t i = 0; i < kBZScriptingEnvironmentPublicCount; ++i) {
514 if (scene->publics[i].identifierHash == identifierHash) {
515 if (out != NULL) {
516 out->__raw = scene->publics[i].value.__raw;
517 }
518 return true;
519 }
520 }
521 return false;
522 }
523
524 void bzScriptingSetEnvironmentPublic(BZSceneID scene, BZIdentifierHash identifierHash, SVMOperand value) {
525 for (size_t i = 0; i < kBZScriptingEnvironmentPublicCount; ++i) {
526 if (scene->publics[i].identifierHash == 0) {
527 scene->publics[i].identifierHash = identifierHash;
528 }
529 if (scene->publics[i].identifierHash == identifierHash) {
530 scene->publics[i].value.__raw = value.__raw;
531 return;
532 }
533 }
534 bzError("Out of globals!!");
535 }
536
537 size_t bzGameGetSceneLayerCount(BZSceneID scene) {
538 return scene->layerCount;
539 }
540
541 BZSceneLayerID bzGameGetSceneLayerAtIndex(BZSceneID scene, size_t idx) {
542 bzAssert(idx < scene->layerCount);
543 return &scene->layers[idx];
544 }
545
546
547 BZCollisionSpaceID bzGameGetSceneLayerCollisionSpace2(BZSceneLayerID layer) {
548 return layer->collisionSpace;
549 }
550
551 BZParticleSimulationID bzGameGetSceneLayerParticleSimulation2(BZSceneLayerID layer) {
552 return layer->particleSimulation;
553 }