*/}}
Browse Source

Material data and ui

YimingWu 8 months ago
parent
commit
20cdd83c66
9 changed files with 98 additions and 15 deletions
  1. 42 4
      la_data.c
  2. 3 0
      la_data.h
  3. 3 1
      la_kernel.c
  4. 15 1
      la_tns_kernel.c
  5. 11 4
      resources/la_modelling.c
  6. 1 1
      resources/la_nodes_basic.c
  7. 1 0
      resources/la_properties.c
  8. 11 3
      resources/la_templates.c
  9. 11 1
      resources/la_widgets.c

+ 42 - 4
la_data.c

@@ -379,9 +379,12 @@ void la_StepPropPack(laPropPack *pp){
                 continue;
             }else{
                 void *inst;
-                inst = laGetActiveInstanceStrict(ps->p, UseInstance);
-                if (!inst) inst = laGetInstance(ps->p, UseInstance, 0);
-                UseInstance = inst;
+                if(((laSubProp*)ps->p)->IsDetached){ UseInstance = ((laSubProp*)ps->p)->Detached; }
+                else{
+                    inst = laGetActiveInstanceStrict(ps->p, UseInstance);
+                    if (!inst) inst = laGetInstance(ps->p, UseInstance, 0);
+                    UseInstance = inst;
+                }
             }
             if (!ps->pNext){
                 pp->EndInstance = UseInstance;
@@ -553,6 +556,37 @@ void laThreadNotifyUsers(char *Path){
     lstAppendItem(&MAIN.ThreadNotifiers, tn);
     //laSpinUnlock(&MAIN.csNotifier);
 }
+void la_PanelResetDetachedReference(laPanel*p,void*Old,void*New){
+    for(laSubProp* sp=p->PropLinkContainer->Props.pFirst;sp;sp=sp->Base.Item.pNext){
+        if(sp->Base.PropertyType!=LA_PROP_SUB) continue;
+        if(sp->Detached == Old){ memAssignRef(sp, &sp->Detached, New); }
+    }
+    for(laPanel* sp=p->SubPanels.pFirst;sp;sp=sp->Item.pNext){
+        la_PanelResetDetachedReference(sp,Old,New);
+    }
+}
+void la_NotifyDetachedRecursive(laBlock* b, void* Old, void* New){
+    if(b->B1){ la_NotifyDetachedRecursive(b->B1,Old,New);la_NotifyDetachedRecursive(b->B2,Old,New); return; }
+    for(laPanel* p=b->Panels.pFirst;p;p=p->Item.pNext){
+        la_PanelResetDetachedReference(p,Old,New);
+    }
+}
+void laNotifyDetached(void* OldInstance, void* NewInstance){
+    for(laWindow* w=MAIN.Windows.pFirst;w;w=w->Item.pNext){
+        for(laLayout* l=w->Layouts.pFirst;l;l=l->Item.pNext){
+            la_NotifyDetachedRecursive(l->FirstBlock,OldInstance,NewInstance);
+        }
+        for(laPanel* p=w->Panels.pFirst;p;p=p->Item.pNext){
+            la_PanelResetDetachedReference(p,OldInstance,NewInstance);
+        }
+    }
+}
+void laDetachedTrySet(char* prop_identifier,void* NewInstance){
+    laPanel* p=MAIN.CurrentPanel; for(laSubProp* sp=p->PropLinkContainer->Props.pFirst;sp;sp=sp->Base.Item.pNext){
+        if(sp->Base.PropertyType!=LA_PROP_SUB){ continue; }
+        if(strSame(sp->Base.Identifier,prop_identifier)){ memAssignRef(sp,&sp->Detached,NewInstance); }
+    }
+}
 
 void la_SetPropMathcerContext(laPanel *p){
     MAIN.PropMatcherContextP = p;
@@ -881,6 +915,7 @@ laProp *la_MakeDetachedProp(laPanel* p, const char *From, const char *Rename){
         break;
     case LA_PROP_SUB:
         sp=np; sp->GetCategory=((laSubProp*)np)->GetCategory;
+        sp->IsDetached=1;
         break;
     }
     lstAppendItem(&p->PropLinkContainer->Props, np);
@@ -4141,6 +4176,7 @@ int la_GenerateListDifferences(laDBInst* dbi, laDBSubProp* dbp, laPropPack* pp,
     inst = laGetInstance(p, pp->LastPs->UseInstance, &pi);
     pp->EndInstance = inst;
     while (inst){
+        if(p->UDFIsSingle){ memTake(inst); /* For single must take or it will be freed. */ }
         lstAppendPointer(&New, inst);
         inst = laGetNextInstance(p, inst, &pi);
         pp->EndInstance = inst;
@@ -4413,7 +4449,7 @@ void la_UndoListDifferences(laDBSubProp* dsp, laDiffCommandSub* dcs){
     }
     for(laDiffCommandInst* dci=dcs->RemovedInst.pFirst;dci;dci=dci->Item.pNext){ if(dcs->Base.p->UDFNoCreate) continue;
         dci->DBInst->Item.pPrev = dci->OriginalPrev;
-        dci->DBInst->Item.pNext = dci->OriginalNext; printf("add removed %x \n", dci->DBInst->OriginalInstance);
+        dci->DBInst->Item.pNext = dci->OriginalNext; printf("add removed %s %x \n",dci->DBInst->pc->Identifier, dci->DBInst->OriginalInstance);
         void* orig = dci->DBInst->OriginalInstance;
     }
     for(laDiffCommandInst* dci=dcs->RemovedInst.pFirst;dci;dci=dci->Item.pNext){ if(dcs->Base.p->UDFNoCreate) continue;
@@ -4465,6 +4501,7 @@ laDBProp* la_FindDBProp(laDBInst* dbi, laProp* p){
     return 0;
 }
 
+void tnsPrintMaterials();
 laDiff* laSwapDBState(int Redo){
     laDiff* diff=MAIN.HeadDifference; if(!diff) return 0;
     if(Redo){ if(diff==MAIN.Differences.pLast) return 0; }else{ diff=diff->Item.pPrev; if(!diff) return 0; }
@@ -4501,6 +4538,7 @@ laDiff* laSwapDBState(int Redo){
     for(laDiffCommandCustom* dcc=diff->CustomCommands.pFirst;dcc;dcc=dcc->Item.pNext){
         if(Redo){ if(dcc->Redo) dcc->Redo(dcc->Data); } else { if(dcc->Undo) dcc->Undo(dcc->Data); }
     }
+    tnsPrintMaterials();
     if(Redo){ MAIN.HeadDifference=diff->Item.pNext; }
     else{ MAIN.HeadDifference=diff; }
     return diff;

+ 3 - 0
la_data.h

@@ -395,6 +395,7 @@ STRUCTURE(laSubProp){
     const char *TargetID;
     laGetNodeTypeFunc GetType;
 
+    int IsDetached;
     void *Detached;
 
     int IsRefList;
@@ -786,6 +787,8 @@ void laNotifySubPropUsers(laProp *p, void *Instance);
 void laNotifyUsers(char *Path);
 void laNotifyInstanceUsers(void *Instance);
 void laThreadNotifyUsers(char *Path);
+void laNotifyDetached(void* OldInstance, void* NewInstance);
+void laDetachedTrySet(char* prop_identifier,void* NewInstance);
 
 int laIsPropertyReadOnly(laPropPack *pp);
 

+ 3 - 1
la_kernel.c

@@ -4447,9 +4447,11 @@ int la_DoExpression(laUiConditionNode *Expression, int *IResult, real *FResult,
             else return 0;
             break;
         case LA_PROP_SUB:
+            sp=Expression->PP.LastPs->p;
+            if (sp->IsDetached){ *PtrResult = sp->Detached; if (sp->Detached) return 1; else return 0; }
             if (!Expression->PP.Go) Instance = Expression->PP.EndInstance;
             else Instance = laGetActiveInstance(Expression->PP.LastPs->p, Expression->PP.LastPs->UseInstance, &pi);
-            if(!Instance){ sp=Expression->PP.LastPs->p; if((!sp->GetActive) && (sp->Base.Offset<=0)){ 
+            if(!Instance){ Expression->PP.LastPs->p; if((!sp->GetActive) && (sp->Base.Offset<=0)){ 
                     Instance=laGetInstance(sp,Expression->PP.LastPs->UseInstance, &pi);
                 }
             }

+ 15 - 1
la_tns_kernel.c

@@ -4130,7 +4130,15 @@ tnsMaterial *tnsFindMaterial(char *name){
 }
 void tnsRemoveMaterial(tnsMaterial* mat){
     lstRemoveItem(&T->World->Materials,mat);
-    laNodeRack* rr; while(rr=lstPopItem(&mat->Page->Racks)){ laDestroyRack(rr); } memLeave(mat->Page);
+    laNodeRack* rr; while(rr=lstPopItem(&mat->Page->Racks)){ laDestroyRack(rr); }
+    strSafeDestroy(&mat->Page->Name); memLeave(mat->Page);
+    for(tnsObject* o=T->World->AllObjects.pFirst;o;o=o->Item.pNext){
+        if(o->Type!=TNS_OBJECT_MESH) continue; tnsMeshObject* mo=o;
+        for(tnsMaterialSlot* msi=mo->Materials.pFirst;msi;msi=msi->Item.pNext){
+            if(msi->Material==mat){ memAssignRef(msi,&msi->Material,0); }
+        }
+    }
+    tnsRefreshMaterialLibraries();
     memLeave(mat);
 }
 tnsMaterialSlot* tnsNewMaterialSlot(tnsMeshObject* mo){
@@ -4182,6 +4190,12 @@ void tnsEnsureMaterialShader(tnsMaterial* mat, int Refresh){
     if(!mat->Shader){ mat->Shader=T->immShader; }
 }
 
+void tnsPrintMaterials(){
+    for(tnsMaterial* m=T->World->Materials.pFirst;m;m=m->Item.pNext){
+        printf("%s %d %d\n",(m->Name&&m->Name->Ptr?m->Name->Ptr:""),m,m->Page->Racks.pFirst);
+    }
+}
+
 //==================================================================[Util]
 
 #define MAX3(a, b, c) \

+ 11 - 4
resources/la_modelling.c

@@ -1630,8 +1630,11 @@ int OPCHK_RemoveRootObjects(laPropPack *This, laStringSplitor *ss){
     return 1;
 }
 int OPINV_RemoveRootObject(laOperator *a, laEvent *e){
-    if(a->This && a->This->EndInstance){ tnsDestroyRootObject(a->This->EndInstance); }
-    else{ tnsDestroyRootObject(T->World->ActiveRoot); }
+    tnsObject* root=0;
+    if(a->This && a->This->EndInstance){ root=a->This->EndInstance; }
+    else{ root=T->World->ActiveRoot; }
+    laNotifyDetached(root,root->Item.pNext?root->Item.pNext:root->Item.pPrev);
+    tnsDestroyRootObject(root);
     laNotifyUsers("tns.world.root_objects"); laNotifyUsers("tns.world.active_root");
     laRecordDifferences(0,"tns.world"); laPushDifferences("Removed root object",0);
     return LA_FINISHED;
@@ -1642,9 +1645,11 @@ int OPINV_NewMaterial(laOperator *a, laEvent *e){
     if(a->This && a->This->EndInstance && la_EnsureSubTarget(a->This->LastPs->p,a->This->EndInstance)==TNS_PC_OBJECT_MESH){
         tnsMeshObject* mo=a->This->EndInstance; if(mo->CurrentMaterial){
             memAssignRef(mo->CurrentMaterial,&mo->CurrentMaterial->Material,mat);
+            tnsInvalidateMeshBatch(mo);
             laRecordInstanceDifferences(mo,"tns_mesh_object"); laNotifyInstanceUsers(mo);
         }
     }
+    laDetachedTrySet("material",mat);
     laRecordDifferences(0,"tns.world.materials"); laPushDifferences("New material",0);
     return LA_FINISHED;
 }
@@ -1654,8 +1659,10 @@ int OPCHK_RemoveMaterial(laPropPack *This, laStringSplitor *ss){
 }
 int OPINV_RemoveMaterial(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance){ return LA_FINISHED; }
-    tnsRemoveMaterial("Material"); laNotifyUsers("tns.world.materials");
-    laRecordDifferences(0,"tns.world.materials"); laPushDifferences("Removed material",0);
+    tnsMaterial* mat=a->This->EndInstance;
+    laNotifyDetached(mat,mat->Item.pNext?mat->Item.pNext:mat->Item.pPrev);
+    tnsRemoveMaterial(mat); laNotifyUsers("tns.world");
+    laRecordDifferences(0,"tns.world"); laPushDifferences("Removed material",0);
     return LA_FINISHED;
 }
 int OPCHK_NewMaterialSlot(laPropPack *This, laStringSplitor *ss){

+ 1 - 1
resources/la_nodes_basic.c

@@ -983,7 +983,7 @@ int OPINV_AddNodesRack(laOperator* a, laEvent *e){
     strSafeSet(&ir->Name,"New Rack");
     lstAppendItem(&dp->Racks, ir); ir->ParentPage=dp;
     ir->RackType=dp->RackType;
-    laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_node_rack"); laPushDifferences("Add Rack", 0);
+    laNotifyInstanceUsers(dp); laRecordInstanceDifferences(dp,"la_rack_page"); laPushDifferences("Add Rack", 0);
     return LA_FINISHED;
 
 }

+ 1 - 0
resources/la_properties.c

@@ -1084,6 +1084,7 @@ void la_RegisterTNSProps(){
         }
         laAddSubGroup(p, "shader_page", "Shader Page", "Shader page of this material","la_rack_page",0,0,0,offsetof(tnsMaterial,Page),0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_HIDE_IN_SAVE);
         laAddOperatorProperty(p,"refresh","Refresh","Refresh material shader","M_refresh_material_shader",L'🗘',0);
+        laAddOperatorProperty(p,"remove","Remove","Remove this material","M_remove_material",L'🗴',0);
     }
 
     p = laAddPropertyContainer("tns_material_slot", "Material Slot" "Material Slot", 0,0,0,sizeof(tnsMaterialSlot),0,0,1);{

+ 11 - 3
resources/la_templates.c

@@ -1614,22 +1614,30 @@ void laui_Materials(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
     laShowItemFull(uil,cl,Extra,"detached",0,0,0,0)->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_ICON;
 
 #define ADD_PAGE(SEL) \
-    laUiItem* b2=laOnConditionThat(uil,cl,laPropExpression(&rb->PP,""));{\
     laUiItem* b=laBeginRow(uil,cr,0,0);\
+    laUiItem* b2=laOnConditionThat(uil,cr,laPropExpression(&rb->PP,""));{\
         laUiItem* cp=laShowInvisibleItem(uil,cr,&rb->PP,"shader_page");\
         if(SEL){\
             laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)\
                 ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;\
         }\
         laShowItem(uil,cr,&rb->PP,"name");\
+        laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON;\
+        laShowItem(uil,cr,&rb->PP,"remove")->Flags|=LA_UI_FLAGS_ICON;\
+        laShowSeparator(uil,cr)->Expand=1;\
         laShowItemFull(uil,cr,&cp->PP,"use_script",0,"icon=📃;text=GLSL",0,0)\
             ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE;\
-        laShowSeparator(uil,cr)->Expand=1;\
         laShowItem(uil,cr,&rb->PP,"refresh");\
         laShowSeparator(uil,cr);\
         laShowItem(uil,cr,&rb->PP,"as_library")->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE;\
-        laEndRow(uil,b);\
+    }laElse(uil,b2);{\
+        if(SEL){\
+            laShowItemFull(uil,cr,&rb->PP,"",LA_WIDGET_COLLECTION_SELECTOR,"text=Select",laui_IdentifierOnly,0)\
+                ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR|LA_UI_FLAGS_EXPAND;\
+            laShowItem(uil,cr,0,"M_new_material")->Flags|=LA_UI_FLAGS_ICON;\
+        }\
     }laEndCondition(uil,b2);\
+    laEndRow(uil,b);\
     b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page"));{\
         laUiItem* b3=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page.use_script"));{\
             laShowItemFull(uil,c,&rb->PP,"shader_page.script",0,0,0,0)->Extra->HeightCoeff=-2;\

+ 11 - 1
resources/la_widgets.c

@@ -317,6 +317,13 @@ int la_ButtonGetMinWidth(laUiItem *ui){
 
     return ((IconID ? (LA_RH) : 0) + strw);
 }
+int la_CollectionSimpleGetMinWidth(laUiItem *ui){
+    laBoxedTheme *bt = *ui->Type->Theme;
+    int Simple=ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR;
+    int Expand=ui->Expand||(ui->Flags&LA_UI_FLAGS_EXPAND);
+    int w=LA_RH+((Simple&&Expand)?(tnsStringGetWidth("Select",0,0)+bt->RM+bt->LM):0);
+    return w;
+}
 int la_ColumnViewerGetMinWidth(laUiItem *ui){
     return 350;
 }
@@ -390,7 +397,7 @@ void la_CollectionSelectorDraw(laUiItem *ui, int h){
         tnsDrawStringAuto("🧹", laThemeColor(bt,ui->State|LA_BT_TEXT), ui->R - LA_RH, ui->R, ui->U, 0);
     }
     if(Simple){
-        int R=ui->R; if(ui->Expand){
+        int R=ui->R; if(ui->Expand || (ui->Flags&LA_UI_FLAGS_EXPAND)){
             R=ui->L+LA_RH; tnsDrawStringAuto(transLate("Select"), laThemeColor(bt,ui->State|LA_BT_TEXT), R+bt->LM, ui->R, ui->U, 0);
         }
         tnsDrawStringAuto("⯆", laThemeColor(bt,ui->State|LA_BT_TEXT), ui->L, R, ui->U, LA_TEXT_ALIGN_CENTER);
@@ -803,6 +810,7 @@ void la_EnumSelectorDraw(laUiItem *ui, int h){
         sprintf(buf,"%s",transLate(buft)); HasText=1;
     }
     for(int i=0;i<ArrLen;i++){
+        if(!Data[i]){ Data[i]=((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst; }
         _L=ui->L; _R=ui->R; _U=ui->U; _B=ui->B; ei = ep->Items.pFirst;
         for(int j=0;j<EnumLen;j++){ if(!HasText)buf[0]=0;
             ico=UseIco;
@@ -1693,6 +1701,7 @@ void la_RegisterUiTypesBasic(){
     LA_WIDGET_COLLECTION_SELECTOR->Type=
     _LA_UI_COLLECTION_SELECTOR = la_RegisterUiType("LA_collection_selector_default", LA_PROP_SUB, "LA_collection_selector_operator",
                         &_LA_THEME_COLLECTION_SELECTOR, la_CollectionSelectorDraw, 0, la_GeneralUiInit, la_GeneralUiDestroy);
+    _LA_UI_COLLECTION_SELECTOR->GetMinWidth = la_CollectionSimpleGetMinWidth;
 
     LA_WIDGET_COLLECTION_SINGLE->Type=
     _LA_UI_COLLECTION_SINGLE = la_RegisterUiType("LA_collection_single", LA_PROP_SUB, "LA_collection_operator",
@@ -2346,6 +2355,7 @@ int OPMOD_EnumSelector(laOperator *a, laEvent *e){
             laRedrawCurrentPanel();
         }elif(IsCycle){
             laEnumItem* ei=laGetEnumArrayIndexed(&ui->PP, ArrTarget);
+            if(!ei){ ei=((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst; }
             ei = ei->Item.pNext?ei->Item.pNext:((laEnumProp*)ui->PP.LastPs->p)->Items.pFirst;
             laSetEnumArrayIndexed(&ui->PP, ArrTarget, ei->Index);
             laConfirmInt(a,EnumTarget,LA_CONFIRM_DATA);