|  | @@ -471,18 +471,17 @@ void laui_MathNode(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
 | 
	
		
			
				|  |  |  int OPINV_AddInputMapperPage(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |      laRackPage* dp=memAcquireHyper(sizeof(laRackPage));
 | 
	
		
			
				|  |  |      strSafeSet(&dp->Name,"New Page");
 | 
	
		
			
				|  |  | -    lstAppendItem(&MAIN.InputMapping->Pages, dp); MAIN.InputMapping->CurrentPage=dp;
 | 
	
		
			
				|  |  | +    lstAppendItem(&MAIN.InputMapping->Pages, dp); MAIN.InputMapping->CurrentPage=dp; dp->RackType=LA_RACK_TYPE_INPUT;
 | 
	
		
			
				|  |  |      laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add Page", 0);
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  int OPINV_AddNodesRack(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |      laRackPage* dp=a->This?a->This->EndInstance:0; if(!dp) return LA_FINISHED;
 | 
	
		
			
				|  |  |      laNodeRack* ir=memAcquire(sizeof(laNodeRack));
 | 
	
		
			
				|  |  | -    char* type=strGetArgumentString(a->ExtraInstructionsP, "type");
 | 
	
		
			
				|  |  |      strSafeSet(&ir->Name,"New Rack");
 | 
	
		
			
				|  |  |      lstAppendItem(&dp->Racks, ir); ir->ParentPage=dp;
 | 
	
		
			
				|  |  | -    if(strSame(type,"DRIVER")){ ir->RackType=LA_RACK_TYPE_DRIVER; laNotifyUsers("la.drivers"); laRecordAndPush(0,"la.drivers","Add rack", 0); }
 | 
	
		
			
				|  |  | -    else{ ir->RackType=LA_RACK_TYPE_INPUT; laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add rack", 0); }
 | 
	
		
			
				|  |  | +    ir->RackType=dp->RackType;
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_node_rack"); laPushDifferences("Add Rack", 0);
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -494,8 +493,7 @@ int OPINV_RebuildInputMapping(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |  laBaseNode* la_CreateNode(laNodeRack* ir, laBaseNodeType* NodeType){
 | 
	
		
			
				|  |  |      laBaseNode* bn=memAcquire(NodeType->NodeSize);
 | 
	
		
			
				|  |  |      bn->Type=NodeType; NodeType->Init(bn); lstAppendItem(&ir->Nodes, bn); bn->InRack=ir;
 | 
	
		
			
				|  |  | -    if(ir->RackType==LA_RACK_TYPE_INPUT){ laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Add node", 0); }
 | 
	
		
			
				|  |  | -    else{ laNotifyUsers("la.drivers"); laRecordAndPush(0,"la.drivers","Add node", 0); }
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(ir); laRecordInstanceDifferences(ir,"la_node_rack"); laPushDifferences("Add Node", 0);
 | 
	
		
			
				|  |  |      return bn;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  void la_DestroyInputMapperNode(laBaseNode* bn){
 | 
	
	
		
			
				|  | @@ -548,22 +546,22 @@ int OPINV_MoveNodeToRack(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
 | 
	
		
			
				|  |  |      
 | 
	
		
			
				|  |  | -    if(n->InRack->RackType==LA_RACK_TYPE_DRIVER){ laNotifyUsers("la.drivers"); }
 | 
	
		
			
				|  |  | -    else{ laNotifyUsers("la.input_mapping"); }
 | 
	
		
			
				|  |  |      if(strSame(direction,"left")) target=n->InRack->Item.pPrev; else target=n->InRack->Item.pNext;
 | 
	
		
			
				|  |  |      if(!target) return LA_CANCELED;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      lstRemoveItem(&n->InRack->Nodes, n); lstAppendItem(&target->Nodes,n); n->InRack=target;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(n->InRack->ParentPage); laRecordInstanceDifferences(n->InRack->ParentPage,"la_node_page"); laPushDifferences("Move Node", 0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  int OPINV_DeleteNode(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |      laBaseNode* n=a->This?a->This->EndInstance:0; if(!n||!n->InRack) return LA_CANCELED;
 | 
	
		
			
				|  |  |      laBaseNodeType* bnt=0; laNodeRack* target;
 | 
	
		
			
				|  |  | +    laNodeRack* parent=n->InRack;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if(n->InRack->RackType==LA_RACK_TYPE_DRIVER){ laDriverRequestRebuild(); laNotifyUsers("la.drivers"); }
 | 
	
		
			
				|  |  | -    else{ laMappingRequestRebuild(); laNotifyUsers("la.input_mapping"); }
 | 
	
		
			
				|  |  |      lstRemoveItem(&n->InRack->Nodes, n); n->Type->Destroy(n); memLeave(n);
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(parent); laRecordInstanceDifferences(parent,"la_node_rack"); laPushDifferences("Delete Node", 0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -573,8 +571,7 @@ int OPINV_MoveRack(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if(strSame(direction,"left")) lstMoveUp(&r->ParentPage->Racks,r); else lstMoveDown(&r->ParentPage->Racks,r);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if(r->RackType==LA_RACK_TYPE_DRIVER){ laNotifyUsers("la.drivers");  laRecordAndPush(0,"la.drivers","Move rack", 0); }
 | 
	
		
			
				|  |  | -    else{ laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Move rack", 0); }
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Move Rack", 0);
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  int OPINV_InsertRack(laOperator* a, laEvent *e){
 | 
	
	
		
			
				|  | @@ -582,17 +579,16 @@ int OPINV_InsertRack(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |      laNodeRack* r=memAcquire(sizeof(laNodeRack));
 | 
	
		
			
				|  |  |      strSafeSet(&r->Name,"New Rack");
 | 
	
		
			
				|  |  |      lstInsertItemAfter(&rr->ParentPage->Racks,r,rr); r->ParentPage=rr->ParentPage; r->RackType=rr->RackType;
 | 
	
		
			
				|  |  | -    if(r->RackType==LA_RACK_TYPE_DRIVER){ laNotifyUsers("la.drivers"); laRecordAndPush(0,"la.drivers","Insert rack", 0); }
 | 
	
		
			
				|  |  | -    else{ laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Insert rack", 0); }
 | 
	
		
			
				|  |  | +    laNotifyInstanceUsers(r->ParentPage); laRecordInstanceDifferences(r->ParentPage,"la_rack_page"); laPushDifferences("Insert Rack", 0);
 | 
	
		
			
				|  |  |      return LA_FINISHED;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  int OPINV_DeleteRack(laOperator* a, laEvent *e){
 | 
	
		
			
				|  |  |      laNodeRack* rr=a->This?a->This->EndInstance:0; if(!rr) return LA_CANCELED;
 | 
	
		
			
				|  |  |      if(strSame(strGetArgumentString(a->ExtraInstructionsP,"confirm"),"true")){
 | 
	
		
			
				|  |  |          laBaseNode* n; while(n=lstPopItem(&rr->Nodes)){ n->Type->Destroy(n); memLeave(n); }
 | 
	
		
			
				|  |  | +        laRackPage* page=rr->ParentPage;
 | 
	
		
			
				|  |  |          strSafeDestroy(&rr->Name); lstRemoveItem(&rr->ParentPage->Racks, rr); memLeave(rr);
 | 
	
		
			
				|  |  | -        if(rr->RackType==LA_RACK_TYPE_DRIVER){ laNotifyUsers("la.drivers"); laRecordAndPush(0,"la.input_mapping","Delete rack", 0); }
 | 
	
		
			
				|  |  | -        else{ laNotifyUsers("la.input_mapping"); laRecordAndPush(0,"la.input_mapping","Delete rack", 0); }
 | 
	
		
			
				|  |  | +        laNotifyInstanceUsers(page); laRecordInstanceDifferences(page,"la_rack_page"); laPushDifferences("Delete Rack", 0);
 | 
	
		
			
				|  |  |          return LA_FINISHED;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      laEnableOperatorPanel(a,a->This,e->x,e->y,200,200,0,0,0,0,0,0,0,0,e);
 |