forked from LeenkxTeam/LNXSDK
Repe [T3DU] and Moises Jpelaez updates
This commit is contained in:
@ -64,7 +64,6 @@ class Scene {
|
||||
#end
|
||||
public var empties: Array<Object>;
|
||||
public var animations: Array<Animation>;
|
||||
public var tilesheets: Array<Tilesheet>;
|
||||
#if lnx_skin
|
||||
public var armatures: Array<Armature>;
|
||||
#end
|
||||
@ -78,6 +77,9 @@ class Scene {
|
||||
public var traitRemoves: Array<Void->Void> = [];
|
||||
|
||||
var initializing: Bool; // Is the scene in its initialization phase?
|
||||
var spawnDepth: Int = 0; // Nested spawn counter (defer trait creation while > 0)
|
||||
var spawning(get, never): Bool;
|
||||
inline function get_spawning(): Bool return spawnDepth > 0;
|
||||
|
||||
public function new() {
|
||||
uid = uidCounter++;
|
||||
@ -101,7 +103,6 @@ class Scene {
|
||||
#end
|
||||
empties = [];
|
||||
animations = [];
|
||||
tilesheets = [];
|
||||
#if lnx_skin
|
||||
armatures = [];
|
||||
#end
|
||||
@ -124,9 +125,8 @@ class Scene {
|
||||
|
||||
// Startup scene
|
||||
active.addScene(format.name, null, function(sceneObject: Object) {
|
||||
for (object in sceneObject.getChildren(true)) {
|
||||
createTraits(object.raw.traits, object);
|
||||
}
|
||||
// Create traits bottom-up (children first, then parents)
|
||||
createTraitsBottomUp(sceneObject);
|
||||
|
||||
#if lnx_terrain
|
||||
if (format.terrain_ref != null) {
|
||||
@ -141,17 +141,29 @@ class Scene {
|
||||
active.camera = active.getCamera(format.camera_ref);
|
||||
active.sceneParent = sceneObject;
|
||||
|
||||
active.ready = true;
|
||||
|
||||
for (f in active.traitInits) f();
|
||||
active.traitInits = [];
|
||||
|
||||
active.ready = true;
|
||||
active.initializing = false;
|
||||
done(sceneObject);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Create traits in post-order (bottom-up): children's traits are created before parents.
|
||||
// This ensures that when a parent's notifyOnInit runs, children are already initialized.
|
||||
static function createTraitsBottomUp(object: Object) {
|
||||
// First, recursively process all children
|
||||
for (child in object.children) {
|
||||
createTraitsBottomUp(child);
|
||||
}
|
||||
// Then create traits for this object
|
||||
if (object.raw != null) {
|
||||
createTraits(object.raw.traits, object);
|
||||
}
|
||||
}
|
||||
|
||||
#if lnx_patch
|
||||
public static var getRenderPath: Void->RenderPath;
|
||||
public static function patch() {
|
||||
@ -212,6 +224,8 @@ class Scene {
|
||||
|
||||
Data.getSceneRaw(sceneName, function(format: TSceneFormat) {
|
||||
Scene.create(format, function(o: Object) {
|
||||
framePassed = true;
|
||||
|
||||
if (done != null) done(o);
|
||||
|
||||
#if (rp_background == "World")
|
||||
@ -242,10 +256,6 @@ class Scene {
|
||||
if (!ready || RenderPath.active == null) return;
|
||||
framePassed = true;
|
||||
|
||||
for (tilesheet in tilesheets) {
|
||||
tilesheet.update();
|
||||
}
|
||||
|
||||
// Render probes
|
||||
#if rp_probes
|
||||
var activeCamera = camera;
|
||||
@ -289,33 +299,39 @@ class Scene {
|
||||
return root.children.length > 0 ? root.children[0].getTrait(c) : null;
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getMesh(name: String): MeshObject {
|
||||
for (m in meshes) if (m.name == name) return m;
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getLight(name: String): LightObject {
|
||||
for (l in lights) if (l.name == name) return l;
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getCamera(name: String): CameraObject {
|
||||
for (c in cameras) if (c.name == name) return c;
|
||||
return null;
|
||||
}
|
||||
|
||||
#if lnx_audio
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getSpeaker(name: String): SpeakerObject {
|
||||
for (s in speakers) if (s.name == name) return s;
|
||||
return null;
|
||||
}
|
||||
#end
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getEmpty(name: String): Object {
|
||||
for (e in empties) if (e.name == name) return e;
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function getGroup(name: String): Array<Object> {
|
||||
if (groups == null) groups = new Map();
|
||||
var g = groups.get(name);
|
||||
@ -391,6 +407,7 @@ class Scene {
|
||||
#end
|
||||
|
||||
var objectsCount = getObjectsCount(format.objects);
|
||||
spawnDepth++; // Defer trait creation until all objects are ready
|
||||
function traverseObjects(parent: Object, objects: Array<TObj>, parentObject: TObj, done: Void->Void) {
|
||||
if (objects == null) return;
|
||||
for (i in 0...objects.length) {
|
||||
@ -408,11 +425,16 @@ class Scene {
|
||||
}
|
||||
|
||||
if (format.objects == null || format.objects.length == 0) {
|
||||
spawnDepth--;
|
||||
createTraits(format.traits, parent); // Scene traits
|
||||
done(parent);
|
||||
}
|
||||
else {
|
||||
traverseObjects(parent, format.objects, null, function() { // Scene objects
|
||||
spawnDepth--;
|
||||
if (!initializing) {
|
||||
createTraitsBottomUp(parent);
|
||||
}
|
||||
createTraits(format.traits, parent); // Scene traits
|
||||
done(parent);
|
||||
});
|
||||
@ -426,7 +448,7 @@ class Scene {
|
||||
var result = objects.length;
|
||||
for (o in objects) {
|
||||
if (discardNoSpawn && o.spawn != null && o.spawn == false) continue; // Do not count children of non-spawned objects
|
||||
if (o.children != null) result += getObjectsCount(o.children);
|
||||
if (o.children != null) result += getObjectsCount(o.children, discardNoSpawn);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -440,11 +462,16 @@ class Scene {
|
||||
@param srcRaw If not `null`, spawn the object from the given scene data instead of using the scene this function is called on. Useful to spawn objects from other scenes.
|
||||
**/
|
||||
public function spawnObject(name: String, parent: Null<Object>, done: Null<Object->Void>, spawnChildren = true, srcRaw: Null<TSceneFormat> = null) {
|
||||
spawnObjectInternal(name, parent, done, spawnChildren, srcRaw, true);
|
||||
}
|
||||
|
||||
function spawnObjectInternal(name: String, parent: Null<Object>, done: Null<Object->Void>, spawnChildren: Bool, srcRaw: Null<TSceneFormat>, createTraits: Bool) {
|
||||
if (srcRaw == null) srcRaw = raw;
|
||||
var objectsTraversed = 0;
|
||||
var obj = getRawObjectByName(srcRaw, name);
|
||||
var objectsCount = spawnChildren ? getObjectsCount([obj], false) : 1;
|
||||
var rootId = -1;
|
||||
spawnDepth++; // Defer trait creation until all objects are ready
|
||||
function spawnObjectTree(obj: TObj, parent: Object, parentObject: TObj, done: Object->Void) {
|
||||
createObject(obj, srcRaw, parent, parentObject, function(object: Object) {
|
||||
if (rootId == -1) {
|
||||
@ -453,20 +480,27 @@ class Scene {
|
||||
if (spawnChildren && obj.children != null) {
|
||||
for (child in obj.children) spawnObjectTree(child, object, obj, done);
|
||||
}
|
||||
if (++objectsTraversed == objectsCount && done != null) {
|
||||
if (++objectsTraversed == objectsCount) {
|
||||
// Retrieve the originally spawned object from the current
|
||||
// child object to ensure done() is called with the right
|
||||
// object
|
||||
while (object.uid != rootId) {
|
||||
object = object.parent;
|
||||
}
|
||||
done(object);
|
||||
// Create traits bottom-up after all objects are ready
|
||||
spawnDepth--;
|
||||
if (createTraits) {
|
||||
createTraitsBottomUp(object);
|
||||
}
|
||||
// Then call user callback
|
||||
if (done != null) done(object);
|
||||
}
|
||||
});
|
||||
}
|
||||
spawnObjectTree(obj, parent, null, done);
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function parseObject(sceneName: String, objectName: String, parent: Object, done: Object->Void) {
|
||||
Data.getSceneRaw(sceneName, function(format: TSceneFormat) {
|
||||
var o: TObj = getRawObjectByName(format, objectName);
|
||||
@ -495,6 +529,10 @@ class Scene {
|
||||
static function traverseObjs(children: Array<TObj>, name: String): TObj {
|
||||
for (o in children) {
|
||||
if (o.name == name) return o;
|
||||
else if (o.filename != "") {
|
||||
var n: String = name + "_" + o.filename;
|
||||
if (o.name == n) return o;
|
||||
}
|
||||
if (o.children != null) {
|
||||
var res = traverseObjs(o.children, name);
|
||||
if (res != null) return res;
|
||||
@ -592,7 +630,7 @@ class Scene {
|
||||
else {
|
||||
for (object_ref in object_refs) {
|
||||
// Spawn top-level collection objects and their children
|
||||
spawnObject(object_ref, groupOwner, function(spawnedObject: Object) {
|
||||
spawnObjectInternal(object_ref, groupOwner, function(spawnedObject: Object) {
|
||||
// Apply collection/group instance offset to all
|
||||
// top-level parents of that group
|
||||
if (!isObjectInGroup(groupRef, spawnedObject.parent, format)) {
|
||||
@ -610,9 +648,10 @@ class Scene {
|
||||
}
|
||||
if (++spawned == object_refs.length) {
|
||||
groupOwner.transform.reset();
|
||||
groupOwner.transform.buildMatrix();
|
||||
done();
|
||||
}
|
||||
}, true, format);
|
||||
}, true, format, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -764,6 +803,7 @@ class Scene {
|
||||
#end
|
||||
}
|
||||
|
||||
// TODO: solve name referencing for linked objects
|
||||
public function returnMeshObject(object_file: String, data_ref: String, sceneName: String, armature: #if lnx_skin Armature #else Null<Int> #end, materials: Vector<MaterialData>, parent: Object, parentObject: TObj, o: TObj, done: Object->Void) {
|
||||
Data.getMesh(object_file, data_ref, function(mesh: MeshData) {
|
||||
var object = addMeshObject(mesh, materials, parent);
|
||||
@ -779,9 +819,9 @@ class Scene {
|
||||
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
|
||||
}
|
||||
#end
|
||||
// Attach tilesheet
|
||||
if (o.tilesheet_ref != null) {
|
||||
cast(object, MeshObject).setupTilesheet(sceneName, o.tilesheet_ref, o.tilesheet_action_ref);
|
||||
// Attach tilesheet from embedded object data
|
||||
if (o.tilesheet != null) {
|
||||
cast(object, MeshObject).setupTilesheet(o.tilesheet);
|
||||
}
|
||||
|
||||
if (o.camera_list != null){
|
||||
@ -820,6 +860,7 @@ class Scene {
|
||||
if (object != null) {
|
||||
object.raw = o;
|
||||
object.name = o.name;
|
||||
if (o.filename != null) object.filename = o.filename;
|
||||
if (o.visible != null) object.visible = o.visible;
|
||||
if (o.visible_mesh != null) object.visibleMesh = o.visible_mesh;
|
||||
if (o.visible_shadow != null) object.visibleShadow = o.visible_shadow;
|
||||
@ -848,9 +889,9 @@ class Scene {
|
||||
}
|
||||
}
|
||||
|
||||
// If the scene is still initializing, traits will be created later
|
||||
// If the scene is still initializing or spawning, traits will be created later
|
||||
// to ensure that object references for trait properties are valid
|
||||
if (!active.initializing) createTraits(o.traits, object);
|
||||
if (!active.initializing && !active.spawning) createTraits(o.traits, object);
|
||||
}
|
||||
done(object);
|
||||
}
|
||||
@ -882,17 +923,15 @@ class Scene {
|
||||
|
||||
// Set trait properties
|
||||
if (t.props != null) {
|
||||
var traitFields = Type.getInstanceFields(Type.getClass(traitInst));
|
||||
for (i in 0...Std.int(t.props.length / 3)) {
|
||||
var pname: String = t.props[i * 3];
|
||||
var ptype: String = t.props[i * 3 + 1];
|
||||
var pval: Dynamic = t.props[i * 3 + 2];
|
||||
if (traitFields.indexOf(pname) == -1) continue;
|
||||
|
||||
if (StringTools.endsWith(ptype, "Object") && pval != "" && pval != null) {
|
||||
Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval));
|
||||
} else if (ptype == "TSceneFormat" && pval != "") {
|
||||
Data.getSceneRaw(pval, function (r: TSceneFormat) {
|
||||
Reflect.setProperty(traitInst, pname, r);
|
||||
});
|
||||
}
|
||||
else {
|
||||
switch (ptype) {
|
||||
|
||||
Reference in New Issue
Block a user