|  | @@ -3742,6 +3742,7 @@ void tnsEvaluateInstancerObject(tnsInstancer* o, tnsEvaluateData* ed){
 | 
	
		
			
				|  |  |      ed->OverrideID=origid; ed->FillOutline=origoutline;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void tnsEvaluateThisObject(tnsObject *o, tnsEvaluateData* ed){
 | 
	
		
			
				|  |  | +    if(ed->EvaluateMode){ tnsEvaluateSyncNode(ed,o); }
 | 
	
		
			
				|  |  |      if (!o->Show) return;
 | 
	
		
			
				|  |  |      switch (o->Type){
 | 
	
		
			
				|  |  |      case TNS_OBJECT_MESH: tnsEvaluateMeshObject(o, ed); break;
 | 
	
	
		
			
				|  | @@ -3789,9 +3790,57 @@ void tnsSetObjectTreeEvaluationArgs(tnsObject* from, tnsObject* Active, int Fill
 | 
	
		
			
				|  |  |      SETARG(Active); SETARG(FillOutline); SETARG(FillSelectionID);
 | 
	
		
			
				|  |  |      if(set) ed->Done=0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +void tnsEvaluateNewNode(tnsEvaluateData* ed, tnsObject* ob){
 | 
	
		
			
				|  |  | +    tnsEvaluatedScene* s=ed->Scene;
 | 
	
		
			
				|  |  | +    tnsEvaluatedNode* en=memAcquire(sizeof(tnsEvaluatedNode)); en->Target=ob;
 | 
	
		
			
				|  |  | +    tnsMultiply44d(en->Mat,ed->MatArr[ed->NextMat-1],ob->GlobalTransform);
 | 
	
		
			
				|  |  | +    if(s->CurrentChild) lstInsertItemBefore(&s->CurrentParent->Children,en,s->CurrentChild);
 | 
	
		
			
				|  |  | +    else lstAppendItem(&s->CurrentParent->Children,en);
 | 
	
		
			
				|  |  | +    s->CurrentChild = en;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +int tnsEvaluateTryRelinkExistingNode(tnsEvaluateData* ed, tnsObject* ob){
 | 
	
		
			
				|  |  | +    tnsEvaluatedScene* s=ed->Scene;
 | 
	
		
			
				|  |  | +    if(!s->CurrentChild) return 0;
 | 
	
		
			
				|  |  | +    int done=0; for(tnsEvaluatedNode* en=s->CurrentChild->Item.pNext;en;en=en->Item.pNext){
 | 
	
		
			
				|  |  | +        if(ob==en->Target){ done=1; lstRemoveItem(&s->CurrentParent->Children,en);
 | 
	
		
			
				|  |  | +            lstInsertItemBefore(&s->CurrentParent->Children,en,s->CurrentChild); break; }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    return done;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsEvaluateFreeNode(tnsEvaluatedNode* en){
 | 
	
		
			
				|  |  | +    tnsEvaluatedNode* sen;
 | 
	
		
			
				|  |  | +    while(sen=lstPopItem(&en->Children)){ tnsEvaluateFreeNode(sen); }
 | 
	
		
			
				|  |  | +    memFree(sen);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsEvaluateSyncNode(tnsEvaluateData* ed, tnsObject* ob){
 | 
	
		
			
				|  |  | +    tnsEvaluatedScene* s=ed->Scene;
 | 
	
		
			
				|  |  | +    if(ob && ((!s->CurrentChild) || (s->CurrentChild->Target!=ob))){
 | 
	
		
			
				|  |  | +        if(!tnsEvaluateTryRelinkExistingNode(ed,ob)) tnsEvaluateNewNode(ed,ob);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if((!ob) && s->CurrentChild){ tnsEvaluatedNode* en=s->CurrentChild->Item.pPrev;
 | 
	
		
			
				|  |  | +        if(en) while(en->Item.pNext){ tnsEvaluatedNode* den=en->Item.pNext;
 | 
	
		
			
				|  |  | +            lstRemoveItem(&s->CurrentParent->Children,den); tnsEvaluateFreeNode(den); }
 | 
	
		
			
				|  |  | +        s->CurrentChild=0;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsEnsureEvalueatedScene(tnsEvaluateData* ed, tnsObject* root){
 | 
	
		
			
				|  |  | +    if(!ed->Scene) ed->Scene=memAcquire(sizeof(tnsEvaluatedScene));
 | 
	
		
			
				|  |  | +    if(!ed->Scene->Root) ed->Scene->Root=memAcquire(sizeof(tnsEvaluatedNode));
 | 
	
		
			
				|  |  | +    ed->Scene->CurrentChild=ed->Scene->Root;
 | 
	
		
			
				|  |  | +    ed->Scene->CurrentChild->Target=root; tnsLoadIdentity44d(ed->Scene->CurrentChild->Mat);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +void tnsPrintEvaluatedNode(tnsEvaluatedNode* en,int level){
 | 
	
		
			
				|  |  | +    for(int i=0;i<level;i++){ printf("  "); }
 | 
	
		
			
				|  |  | +    printf("%s\n",en->Target->Name?en->Target->Name->Ptr:"?");
 | 
	
		
			
				|  |  | +    for(tnsEvaluatedNode* sen=en->Children.pFirst;sen;sen=sen->Item.pNext){
 | 
	
		
			
				|  |  | +        tnsPrintEvaluatedNode(sen,level+1);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if(level==0){printf("\n");}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED){
 | 
	
		
			
				|  |  |      if(!from) return;
 | 
	
		
			
				|  |  |      tnsEvaluateData* ed=UseED?UseED:(from->InRoot?(&from->InRoot->Evaluated):(&from->Evaluated));
 | 
	
		
			
				|  |  | +    //ed->EvaluateMode=TNS_EVAL_MODE_ALWAYS;
 | 
	
		
			
				|  |  |      if(ed->Done) return;
 | 
	
		
			
				|  |  |      elif(!UseED){ ed->NextCommand=ed->NextOverlay=ed->NextSelection=ed->NextOutline=ed->NextMat=0;
 | 
	
		
			
				|  |  |          if(!ed->Commands) arrInitLength(&ed->Commands,16,&ed->MaxCommand,sizeof(tnsEvaluatedInstance));
 | 
	
	
		
			
				|  | @@ -3801,14 +3850,22 @@ void tnsEvaluateObjectTree(tnsObject* from, tnsEvaluateData* UseED){
 | 
	
		
			
				|  |  |          if(!ed->MatArr) arrInitLength(&ed->MatArr,8,&ed->MaxMat,sizeof(tnsMatrix44d));
 | 
	
		
			
				|  |  |          tnsLoadIdentity44d(ed->MatArr[0]); ed->NextMat=1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    tnsEvaluatedNode* CP,*CC;
 | 
	
		
			
				|  |  | +    if(ed->EvaluateMode){ if(!UseED){ tnsEnsureEvalueatedScene(ed,from); }
 | 
	
		
			
				|  |  | +        CP=ed->Scene->CurrentParent; CC=ed->Scene->CurrentChild;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    tnsEvaluateThisObject(from, ed);
 | 
	
		
			
				|  |  | +    
 | 
	
		
			
				|  |  | +    if(ed->EvaluateMode){ ed->Scene->CurrentParent=ed->Scene->CurrentChild; ed->Scene->CurrentChild=ed->Scene->CurrentParent->Children.pFirst; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      for (laListItemPointer* lip=from->ChildObjects.pFirst;lip;lip=lip->pNext){
 | 
	
		
			
				|  |  | -        tnsObject *o=lip->p;
 | 
	
		
			
				|  |  | -        tnsEvaluateThisObject(o, ed);
 | 
	
		
			
				|  |  | -        if (o->ChildObjects.pFirst){
 | 
	
		
			
				|  |  | -            tnsEvaluateObjectTree(o,ed);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +        tnsObject *o=lip->p; if (o){ tnsEvaluateObjectTree(o,ed); }
 | 
	
		
			
				|  |  | +        if(ed->EvaluateMode){ ed->Scene->CurrentChild=ed->Scene->CurrentChild?ed->Scene->CurrentChild->Item.pNext:0; }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -    if(!UseED)ed->Done=1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if(ed->EvaluateMode){ tnsEvaluateSyncNode(ed, 0); ed->Scene->CurrentParent=CP; ed->Scene->CurrentChild=CC; }
 | 
	
		
			
				|  |  | +    if(!UseED){ ed->Done=1; /* tnsPrintEvaluatedNode(ed->Scene->Root,0); */  }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void tnsDrawLayer(tnsEvaluateData* ed,int Layer,void* CustomData){
 | 
	
		
			
				|  |  |      tnsEvaluatedInstance* ei; int next=0;
 |