| 
					
				 | 
			
			
				@@ -3265,6 +3265,15 @@ void tnsRotateObjectLocalValues(tnsObject *o, real x, real y, real z){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     o->Rotation[0] += x; o->Rotation[1] += y; o->Rotation[2] += z; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tnsSelfTransformValueChanged(o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void tnsSetObjectPositionLocal(tnsObject*o, real x, real y, real z){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tnsVectorSet3(o->Location,x,y,z); tnsSelfTransformValueChanged(o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void tnsResetObjectTransformations(tnsObject* o, int reset_loc,int reset_rot,int reset_sca){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(reset_loc){ tnsVectorSet3(o->Location,0,0,0); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(reset_rot){ tnsVectorSet4(o->Rotation,0,0,0,0); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(reset_sca){ o->Scale=1; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tnsSelfTransformValueChanged(o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsMoveObjectLocal(tnsObject *o, real x, real y, real z){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tnsMatrix44d mat, res1, res2, res3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tnsMakeTranslationMatrix44d(res2, x, y, z); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3723,7 +3732,7 @@ void tnsEvaluateInstancerObject(tnsInstancer* o, tnsEvaluateData* ed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int origoutline=ed->FillOutline; ed->FillOutline=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(o->Instance){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tnsObject* inst=o->Instance; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        inst=tnsEnsurePlayDuplicate(inst); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(ed->SceneEvaluateMode){ inst=tnsEnsurePlayDuplicate(inst); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tnsPushEvaluateMatrixWith(ed,o->Base.GlobalTransform); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tnsEvaluateObjectTree(inst, ed, ed->SceneEvaluateMode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tnsPopEvaluateMatrix(ed); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3731,18 +3740,28 @@ void tnsEvaluateInstancerObject(tnsInstancer* o, tnsEvaluateData* ed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ed->OverrideID=origid; ed->FillOutline=origoutline; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void tnsLuaEnsureNode(lua_State* L,int index,tnsObject* o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsLuaRunNode(lua_State* L, tnsEvaluatedNode* en, char* func, tnsObject* root); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(ed->SceneEvaluateMode){ tnsEvaluateSyncNode(ed,o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    tnsEvaluatedNode* CP,*CC; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(ed->SceneEvaluateMode){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tnsEvaluateSyncNode(ed,o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(o->Type==TNS_OBJECT_INSTANCER){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            CP=ed->Scene->CurrentParent; CC=ed->Scene->CurrentChild; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ed->Scene->CurrentParent=ed->Scene->CurrentChild; ed->Scene->CurrentChild=ed->Scene->CurrentParent->Children.pFirst; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(o->Type==TNS_OBJECT_ROOT){ tnsEvaluatedNode* en=ed->Scene->CurrentChild; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            tnsLuaEnsureNode(ed->L,en->LuaID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            tnsLuaEnsureNode(ed->L,en->LuaID,o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             tnsLuaRunNode(ed->L,en,"run",o); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!o->Show) return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     switch (o->Type){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case TNS_OBJECT_MESH: tnsEvaluateMeshObject(o, ed); break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    case TNS_OBJECT_INSTANCER: tnsEvaluateInstancerObject(o,ed); break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    case TNS_OBJECT_INSTANCER: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        tnsEvaluateInstancerObject(o,ed); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(ed->SceneEvaluateMode){ ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC;} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     case TNS_OBJECT_CAMERA: tnsDrawCamera(o); break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     default: tnsEvaluateEmptyObject(o,ed); break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3754,11 +3773,13 @@ void tnsClearPlayDuplicate(tnsObject* o){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     for(laListItemPointer* lip=o->ChildObjects.pFirst;lip;lip=lip->pNext){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         tnsObject*co=lip->p; tnsClearPlayDuplicate(co); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(o->Type==TNS_OBJECT_INSTANCER){ tnsInstancer* oi=o; tnsClearPlayDuplicate(oi->Instance); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     memFree(o->PlayDuplicate); o->PlayDuplicate=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsFreeEvaluatedNode(tnsEvaluatedNode* n){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     tnsEvaluatedNode* en; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while(en=lstPopItem(&n->Children)){ tnsFreeEvaluatedNode(en); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    n->Target->LuaCacheID=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     memFree(n); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsFreeEvaluatedScene(tnsEvaluateData* ed){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3785,6 +3806,7 @@ tnsObject* tnsEnsurePlayDuplicate(tnsObject* o){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         lstAppendPointer(&dup->ChildObjects,co->PlayDuplicate); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         co->PlayDuplicate->ParentObject=o->ParentObject?dup:0; //objects directly under root doesn't have parent object 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(o->Type==TNS_OBJECT_INSTANCER){ tnsInstancer* oi=o; tnsEnsurePlayDuplicate(oi->Instance); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     dup->Flags|=TNS_OBJECT_FLAGS_PLAY_DUPLICATE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return o->PlayDuplicate; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3805,14 +3827,14 @@ void tnsLuaInit(lua_State* L){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_getglobal(L,"scene"); lua_pushstring(L,"nodes"); lua_newtable(L); lua_settable(L,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_pushnil(L); lua_setfield(L,1,"node"); lua_pop(L,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void tnsLuaEnsureNode(lua_State* L,int index){ lua_settop(L,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void tnsLuaEnsureNode(lua_State* L,int index,tnsObject* o){ lua_settop(L,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_getglobal(L,"scene"); lua_getfield(L,1,"nodes"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_pushinteger(L,index); lua_gettable(L,2); if(lua_isnil(L,3) || (!lua_istable(L,3))){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         lua_pushinteger(L,index); lua_newtable(L); lua_settable(L,2); lua_pop(L,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         lua_pushinteger(L,index); lua_gettable(L,2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         lua_pushlightuserdata(L,0); lua_setfield(L,3,"object"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lua_pop(L,3); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lua_settop(L,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsLuaRemoveNode(lua_State* L,int index){ lua_settop(L,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_getglobal(L,"scene"); lua_pushstring(L,"nodes"); lua_gettable(L,1); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3820,24 +3842,39 @@ void tnsLuaRemoveNode(lua_State* L,int index){ lua_settop(L,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsLuaRunNode(lua_State* L, tnsEvaluatedNode* en, char* func, tnsObject* root){ lua_settop(L,0); int index=en->LuaID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_getglobal(L,"scene"); lua_getfield(L,1,"nodes"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lua_pushinteger(L,index); lua_gettable(L,2); lua_setfield(L,1,"node"); lua_pop(L,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lua_pushinteger(L,index); lua_gettable(L,-2); lua_setfield(L,1,"node"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     lua_getfield(L,1,"node"); tnsLuaSetObject(L,root); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lua_getfield(L,2,"scripts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(lua_isnil(L,3) || (!lua_istable(L,3))){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        lua_pop(L,1); lua_newtable(L); lua_setfield(L,2,"scripts"); lua_getfield(L,2,"scripts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lua_getfield(L,-1,"scripts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(lua_isnil(L,-1) || (!lua_istable(L,-1))){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        lua_pop(L,1); lua_newtable(L); lua_setfield(L,-2,"scripts"); lua_getfield(L,-1,"scripts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(!en->LuaLoaded){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(root->Drivers) for(laRackPage*rp=root->Drivers->Pages.pFirst;rp;rp=rp->Item.pNext){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(!(rp->UseScript&&rp->Script&&rp->Script->Ptr)){ continue; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            char* debug_name=rp->Name&&rp->Name->Ptr?rp->Name->Ptr:"unamed_driver_page"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            lua_pushinteger(L,lua_objlen(L,3)+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(!luaL_loadbuffer(L,rp->Script->Ptr,strlen(rp->Script->Ptr),debug_name)){ lua_call(L,0,1); lua_settable(L,3); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            else{ lua_pop(L,2); /* pop error and index */ } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(root->Drivers){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(root->LuaCacheID){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int scrtable=lua_gettop(L); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lua_pushinteger(L,root->LuaCacheID); lua_gettable(L,2); lua_getfield(L,-1,"scripts"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lua_pushnil(L); while(lua_next(L,-2)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lua_pushvalue(L,-2); lua_pushvalue(L,-2); lua_settable(L,scrtable); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lua_pop(L,1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                lua_pop(L,2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }else{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                for(laRackPage*rp=root->Drivers->Pages.pFirst;rp;rp=rp->Item.pNext){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if(!(rp->UseScript&&rp->Script&&rp->Script->Ptr)){ continue; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    char* debug_name=rp->Name&&rp->Name->Ptr?rp->Name->Ptr:"unamed_driver_page"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    lua_pushinteger(L,lua_objlen(L,-1)+1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if(!luaL_loadbuffer(L,rp->Script->Ptr,strlen(rp->Script->Ptr),debug_name)){ lua_call(L,0,1); lua_settable(L,-3); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    else{ lua_pop(L,2); /* pop error and index */ } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                root->LuaCacheID=en->LuaID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         en->LuaLoaded=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    //lua_getglobal(L,"ddump"); lua_getglobal(L,"scene"); lua_call(L,1,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    lua_pushnil(L); while(lua_next(L,3)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    lua_pushnil(L); while(lua_next(L,-2)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         lua_getfield(L,-1,func); if((!lua_isnil(L,-1))&&lua_isfunction(L,-1)){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             lua_pushvalue(L,-2); lua_call(L,1,0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3887,7 +3924,8 @@ void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int Fill 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(set) ed->Done=0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 tnsEvaluatedNode* tnsAcquireEvaluateNode(tnsEvaluateData* ed){ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(!ed->Scene->WastedEvaluateNodes.pFirst){ return memAcquire(sizeof(tnsEvaluatedNode)); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!ed->Scene->WastedEvaluateNodes.pFirst){ tnsEvaluatedNode* en=memAcquire(sizeof(tnsEvaluatedNode)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        ed->Scene->NextLuaID++; en->LuaID=ed->Scene->NextLuaID; return en; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     else{ return lstPopItem(&ed->Scene->WastedEvaluateNodes); } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void tnsEvaluateNewNode(tnsEvaluateData* ed, tnsObject* ob){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -3977,7 +4015,7 @@ void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED, int Evaluate 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(ed->SceneEvaluateMode){ ed->Scene->CurrentChild=ed->Scene->CurrentChild?ed->Scene->CurrentChild->Item.pNext:0; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(ed->SceneEvaluateMode){ tnsEvaluateSyncNode(ed, 0); ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(ed->SceneEvaluateMode){ ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC; } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(!UseED){ ed->Done=1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //if(ed->Scene){ tnsPrintEvaluatedNode(ed->Scene->Root,0);} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 |