*/}}
Browse Source

Material as library

YimingWu 8 tháng trước cách đây
mục cha
commit
9a4ac76620

+ 4 - 1
la_tns.h

@@ -158,6 +158,7 @@ struct _tnsWorld
 
     laListHandle AllObjects;
     laListHandle Materials;
+    laSafeString* MaterialLibraries;
 
     u16bit TimeYear;
     u8bit TimeMonth;
@@ -579,6 +580,7 @@ STRUCTURE(tnsMaterial){
     laSafeString *Name;
     real Color[4];
     int Colorful;
+    int AsLibrary;
     laRackPage* Page;
     tnsShader* Shader;
 };
@@ -822,7 +824,7 @@ void tnsSetuptnsFontManager();
 tnsShader *tnsNewShaderProgram(int VertexShaderID, int FragmentShaderID, int GeometryShaderID);
 int tnsNewGeometryShader(char *Content);
 int tnsNewFragmentShader(char *Content);
-int tnsNewFragmentShaderMaterial(char *Content, char* Material);
+int tnsNewFragmentShaderMaterial(char *Content, char* Library, char* Material);
 int tnsNewVertexShader(char *Content);
 void tnsDeleteShaderProgram(tnsShader* s);
 
@@ -1184,6 +1186,7 @@ tnsMaterialSlot* tnsNewMaterialSlot(tnsMeshObject* mo);
 void tnsRemoveMaterialSlot(tnsMeshObject* mo, tnsMaterialSlot* ms);
 void tnsAssignMaterialSlot(tnsMeshObject* mo, tnsMaterialSlot* ms);
 
+void tnsRefreshMaterialLibraries();
 void tnsEnsureMaterialShader(tnsMaterial* mat, int Refresh);
 
 void tnsClearAll();

+ 24 - 9
la_tns_kernel.c

@@ -319,12 +319,13 @@ void tnsShaderApplyShadowMatrix(tnsShader *tns, tnsMatrix44d m){
     glUniformMatrix4fv(tns->iShadow, 1, 0, mf);
 }
 
-char* tnsEnsureShaderCommoms(char* Content, char* Material){
+char* tnsEnsureShaderCommoms(char* Content, char* Library, char* Material){
     char* c=0,*c1=0;
     c1=strSub(Content,"#with TNS_SHADER_COLOR_COMMON",TNS_SHADER_COLOR_COMMON);
     c=strSub(c1,"#with LA_SHADER_LIB_FXAA",LA_SHADER_LIB_FXAA); free(c1);
     c1=strSub(c,"#with TNS_SHADER_MATERIAL",Material?Material:""); free(c);
-    return c1;
+    c=strSub(c1,"#with TNS_SHADER_LIBRARY",Library?Library:""); free(c1);
+    return c;
 }
 int tnsNewVertexShader(char *Content){
     int status = 0;
@@ -336,7 +337,7 @@ int tnsNewVertexShader(char *Content){
 
     VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
 
-    char* UseContent=tnsEnsureShaderCommoms(Content,0);
+    char* UseContent=tnsEnsureShaderCommoms(Content,0,0);
     glShaderSource(VertexShaderObject, 1, &UseContent, 0);
     glCompileShader(VertexShaderObject);
     glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &status);
@@ -350,7 +351,7 @@ int tnsNewVertexShader(char *Content){
 
     return VertexShaderObject;
 }
-int tnsNewFragmentShaderMaterial(char *Content, char* Material){
+int tnsNewFragmentShaderMaterial(char *Content, char* Library, char* Material){
     int status = 0;
     char error[1024];
     GLuint FragmentShaderObject;
@@ -360,7 +361,7 @@ int tnsNewFragmentShaderMaterial(char *Content, char* Material){
 
     FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
 
-    char* UseContent=tnsEnsureShaderCommoms(Content,Material);
+    char* UseContent=tnsEnsureShaderCommoms(Content,Library,Material);
     glShaderSource(FragmentShaderObject, 1, &UseContent, 0);
     glCompileShader(FragmentShaderObject);
     glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &status);
@@ -375,7 +376,7 @@ int tnsNewFragmentShaderMaterial(char *Content, char* Material){
     return FragmentShaderObject;
 }
 int tnsNewFragmentShader(char *Content){
-    return tnsNewFragmentShaderMaterial(Content,0);
+    return tnsNewFragmentShaderMaterial(Content,0,0);
 }
 int tnsNewGeometryShader(char *Content){
     int status = 0;
@@ -387,7 +388,7 @@ int tnsNewGeometryShader(char *Content){
 
     GeometryShaderObject = glCreateShader(GL_GEOMETRY_SHADER);
 
-    char* UseContent=tnsEnsureShaderCommoms(Content,0);
+    char* UseContent=tnsEnsureShaderCommoms(Content,0,0);
     glShaderSource(GeometryShaderObject, 1, &UseContent, 0);
     glCompileShader(GeometryShaderObject);
     glGetShaderiv(GeometryShaderObject, GL_COMPILE_STATUS, &status);
@@ -4156,14 +4157,28 @@ void tnsAssignMaterialSlot(tnsMeshObject* mo, tnsMaterialSlot* ms){
     }
 }
 
+void tnsRefreshMaterialLibraries(){
+    strSafeDestroy(&T->World->MaterialLibraries);
+    for(tnsMaterial* mat=T->World->Materials.pFirst;mat;mat=mat->Item.pNext){
+        if(!mat->AsLibrary || !mat->Page->UseScript) continue;
+        if(mat->Page->Script) strSafeAppend(&T->World->MaterialLibraries,mat->Page->Script->Ptr);
+        tnsEnsureMaterialShader(mat,1);
+    }
+    for(tnsMaterial* mat=T->World->Materials.pFirst;mat;mat=mat->Item.pNext){
+        if(mat->AsLibrary || !mat->Page->UseScript) continue;
+        tnsEnsureMaterialShader(mat,1); tns_InvalidateMeshWithMaterial(mat);
+    }
+    laNotifyUsers("tns.world");
+}
 void tnsEnsureMaterialShader(tnsMaterial* mat, int Refresh){
     if(Refresh){
         if(mat->Shader && mat->Shader!=T->immShader){ tnsDeleteShaderProgram(mat->Shader); mat->Shader=0; }
     }
-    if(!(mat->Page->Script&&mat->Page->Script->Ptr)){ mat->Shader=T->immShader; return; }
+    if((!(mat->Page->Script&&mat->Page->Script->Ptr))||mat->AsLibrary){ mat->Shader=T->immShader; return; }
     char* str=mat->Page->Script->Ptr;
+    char* lib=T->World->MaterialLibraries?T->World->MaterialLibraries->Ptr:0;
     mat->Shader = tnsNewShaderProgram(
-        tnsNewVertexShader(LA_IMM_VERTEX_SHADER),tnsNewFragmentShaderMaterial(LA_OBJECT_FRAGMENT_SHADER,str),-1);
+        tnsNewVertexShader(LA_IMM_VERTEX_SHADER),tnsNewFragmentShaderMaterial(LA_OBJECT_FRAGMENT_SHADER,lib,str),-1);
     if(!mat->Shader){ mat->Shader=T->immShader; }
 }
 

+ 1 - 0
resources/la_modelling.c

@@ -1701,6 +1701,7 @@ int OPCHK_RefreshMaterialShader(laPropPack *This, laStringSplitor *ss){
 int OPINV_RefreshMaterialShader(laOperator *a, laEvent *e){
     if(!a->This || !a->This->EndInstance){ return LA_FINISHED; }
     tnsMaterial* m=a->This->EndInstance;
+    if(m->AsLibrary){ tnsRefreshMaterialLibraries(); return LA_FINISHED; }
     tnsEnsureMaterialShader(m,1); tns_InvalidateMeshWithMaterial(m); laNotifyUsers("tns.world");
     return LA_FINISHED;
 }

+ 10 - 2
resources/la_properties.c

@@ -798,8 +798,12 @@ int lafilter_NodeCategory(void* unused, laNodeCategory* c){
     if(c->For&MAIN.FilterNodeCategory) return 1; return 0;
 }
 
+void tnspost_World(tnsWorld *w){
+    tnsRefreshMaterialLibraries();
+}
 void tnspost_Material(tnsMaterial *m){
-    tnsEnsureMaterialShader(m,1);
+    //if(m->AsLibrary){ tnsRefreshMaterialLibraries(); return; }
+    //tnsEnsureMaterialShader(m,1);
 }
 void tnspost_Object(tnsObject *o){
     laListItemPointer* NextLip;
@@ -1052,7 +1056,7 @@ void la_RegisterTNSProps(){
 
     if(!MAIN.InitArgs.HasWorldObjects) return;
 
-    p = laAddPropertyContainer("tns_world", "World", "3D World Structure", 0,0,sizeof(tnsWorld), 0,0,1);{
+    p = laAddPropertyContainer("tns_world", "World", "3D World Structure", 0,0,sizeof(tnsWorld),tnspost_World,0,1);{
         sp = laAddSubGroup(p, "root_objects", "Root Objects", "List of all root objects", "tns_object",0,0,0,-1,0,0,0,0,0,0,offsetof(tnsWorld, RootObjects), 0);
         laSubGroupDetachable(sp, tnsget_detached_FirstRootObject, laget_ListNext);
         laAddSubGroup(p, "active_root", "Active Root Object", "Global active root object", "tns_object",0,0,0,offsetof(tnsWorld,ActiveRoot),tnsget_detached_FirstRootObject,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
@@ -1074,6 +1078,10 @@ void la_RegisterTNSProps(){
             laAddEnumItemAs(ep, "NONE", "None", "Display materials normally",0,0);
             laAddEnumItemAs(ep, "COLORFUL", "Colorful", "Display material with colorful halftone",1,0);
         }
+        ep = laAddEnumProperty(p, "as_library", "As Library", "As commom library", 0,0,0,0,0,offsetof(tnsMaterial, AsLibrary), 0,0,0,0,0,0,0,0,0,0);{
+            laAddEnumItemAs(ep, "NONE", "None", "Use as normal material",0,0);
+            laAddEnumItemAs(ep, "LIBRARY", "LIBRARY", "As commom library",1,0);
+        }
         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);
     }

+ 33 - 21
resources/la_templates.c

@@ -1622,10 +1622,12 @@ void laui_Materials(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
                 ->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;\
         }\
         laShowItem(uil,cr,&rb->PP,"name");\
-        laShowItemFull(uil,cr,&cp->PP,"use_script",0,"icon=📃",0,0)\
-            ->Flags|=LA_UI_FLAGS_HIGHLIGHT|LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_ICON;\
-        laShowSeparator(uil,cr);\
+        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);\
     }laEndCondition(uil,b2);\
     b2=laOnConditionThat(uil,c,laPropExpression(&rb->PP,"shader_page"));{\
@@ -1642,6 +1644,7 @@ void laui_Materials(laUiList *uil, laPropPack *This, laPropPack *Extra, laColumn
         laUiItem* rb=laShowInvisibleItem(uil,cr,Extra,"material");
         ADD_PAGE(1)
     }laElse(uil,b1);{
+        laShowInvisibleItem(uil,cr,0,"tns.world.active_root.active.as_mesh.materials"); // for switching updates.
         laUiItem* rb=laShowInvisibleItem(uil,cr,0,"tns.world.active_root.active.as_mesh.current_material.material");
         ADD_PAGE(0)
     }laEndCondition(uil,b1);
@@ -1782,20 +1785,24 @@ void tnsui_InstancerObjectProperties(laUiList *uil, laPropPack *This, laPropPack
     laShowLabel(uil,cl,"Instance",0,0); laShowItemFull(uil,cr,This,"instance",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0);
 }
 void tnsui_Material(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
-    laColumn* c=laFirstColumn(uil),*cl,*cr; laUiItem* b,*b1;
+    laColumn* c=laFirstColumn(uil),*cl,*cr; laUiItem* b,*b1,*b2;
     laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,8); cr=laRightColumn(c,0);
     if(!context){
         laShowLabel(uil,cl,"Name",0,0); laShowItem(uil,cr,This,"name");
     }
-    b=laBeginRow(uil,cl,0,0);
-    laShowLabel(uil,cl,"Color",0,0)->Expand=1;
-    b1=laOnConditionThat(uil,cl,laOr(laPropExpression(This,"shader_page.racks"),
-                                    laPropExpression(This,"shader_page.use_script")));{
-        laShowLabel(uil,cl,"🎨",0,0);
-    }laEndCondition(uil,b1);
-    laEndRow(uil,b);
-    laShowItemFull(uil,cr,This,"color",LA_WIDGET_FLOAT_COLOR,0,0,0)->Flags|=LA_UI_FLAGS_COLORFUL;
-    laShowItemFull(uil,cr,This,"colorful",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0);
+    b2=laOnConditionThat(uil,c,laPropExpression(This,"as_library"));{
+        laShowLabel(uil,c,"Material is common library.",0,0);
+    }laElse(uil,b2);{
+        b=laBeginRow(uil,cl,0,0);
+        laShowLabel(uil,cl,"Color",0,0)->Expand=1;
+        b1=laOnConditionThat(uil,cl,laOr(laPropExpression(This,"shader_page.racks"),
+                                        laPropExpression(This,"shader_page.use_script")));{
+            laShowLabel(uil,cl,"🎨",0,0);
+        }laEndCondition(uil,b1);
+        laEndRow(uil,b);
+        laShowItemFull(uil,cr,This,"color",LA_WIDGET_FLOAT_COLOR,0,0,0)->Flags|=LA_UI_FLAGS_COLORFUL;
+        laShowItemFull(uil,cr,This,"colorful",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0);
+    }laEndCondition(uil,b2);
 }
 void tnsui_MaterialListItem(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
     laColumn* c=laFirstColumn(uil); laUiItem* b,*b1;
@@ -1809,16 +1816,21 @@ void tnsui_MaterialListItem(laUiList *uil, laPropPack *This, laPropPack *UNUSED_
     laEndRow(uil,b);
 }
 void tnsui_MaterialSlot(laUiList *uil, laPropPack *This, laPropPack *UNUSED_Extra, laColumn *UNUSED_Colums, int context){
-    laColumn* c=laFirstColumn(uil); laUiItem* b,*b1,*b2;
+    laColumn* c=laFirstColumn(uil); laUiItem* b,*b1,*b2,*b3;
     b1=laOnConditionThat(uil,c,laPropExpression(This,"material"));{
         b=laBeginRow(uil,c,0,0);
-        laShowItemFull(uil,c,This,"material.color",LA_WIDGET_FLOAT_COLOR,0,0,0)
-            ->Flags|=LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_ICON|LA_UI_FLAGS_COLORFUL;
-        laUiItem* ui=laShowItem(uil,c,This,"material.name"); ui->Flags|=LA_UI_FLAGS_PLAIN; ui->Expand=1;
-        b2=laOnConditionThat(uil,c,laOr(laPropExpression(This,"material.shader_page.racks"),
-                                    laPropExpression(This,"material.shader_page.use_script")));{
-            laShowLabel(uil,c,"🎨",0,0);
-        }laEndCondition(uil,b2);
+        b3=laOnConditionThat(uil,c,laPropExpression(This,"material.as_library"));{
+            laShowLabel(uil,c,"LIB ",0,0)->Flags|=LA_UI_DISABLED;
+            laShowItem(uil,c,This,"material.name")->Flags|=LA_UI_FLAGS_PLAIN|LA_UI_FLAGS_DISABLED;
+        }laElse(uil,b3);{
+            laShowItemFull(uil,c,This,"material.color",LA_WIDGET_FLOAT_COLOR,0,0,0)
+                ->Flags|=LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_ICON|LA_UI_FLAGS_COLORFUL;
+            laUiItem* ui=laShowItem(uil,c,This,"material.name"); ui->Flags|=LA_UI_FLAGS_PLAIN; ui->Expand=1;
+            b2=laOnConditionThat(uil,c,laOr(laPropExpression(This,"material.shader_page.racks"),
+                                        laPropExpression(This,"material.shader_page.use_script")));{
+                laShowLabel(uil,c,"🎨",0,0);
+            }laEndCondition(uil,b2);
+        }laEndCondition(uil,b3);
         laEndRow(uil,b);
     }laElse(uil,b1);{
         laShowItem(uil,c,This,"name")->Flags|=LA_UI_FLAGS_DISABLED;

+ 3 - 0
resources/la_tns_shaders.cpp

@@ -682,6 +682,8 @@ layout(location = 1) out vec3 outNormal;
 layout(location = 2) out vec3 outGPos;
 
 #with TNS_SHADER_COLOR_COMMON
+#with TNS_SHADER_LIBRARY
+
 vec3 ConvertColorSpace(vec3 color){
     if(InputColorSpace!=OutputColorSpace){
         if(ColorMode==0){
@@ -769,6 +771,7 @@ layout(location = 1) out vec3 outNormal;
 layout(location = 2) out vec3 outGPos;
 
 #with TNS_SHADER_COLOR_COMMON
+#with TNS_SHADER_LIBRARY
 
 void main(){
     vec4 color=fColor;

+ 3 - 3
resources/la_widgets.c

@@ -243,10 +243,10 @@ int la_EnumGetMinWidth(laUiItem *ui){
     int SharedWidth;
     if(!IsIcon){
         SharedWidth = bt->LM + bt->RM + ((IsCycle||IsExpand)?0:LA_RH); int HasIcon=0;
-        if(Highlight){
+        if(Highlight){ int ico=0;
             if (ui->ExtraInstructions){
                 if (ui->Type->OperatorType->ParseArgs){
-                    int ico; char buf[256]; buf[0]=0;
+                    char buf[256]; buf[0]=0;
                     ui->Type->OperatorType->ParseArgs(ui->Instructions, &ico, buf);
                     tW = tnsStringGetWidth(transLate(buf), 0, ui->Flags&LA_TEXT_MONO) + SharedWidth;
                 }
@@ -255,7 +255,7 @@ int la_EnumGetMinWidth(laUiItem *ui){
                 tW = tnsStringGetWidth(transLate(ep->Base.Name), 0, ui->Flags&LA_TEXT_MONO) + SharedWidth;
             }
             if (tW > W) W = tW;
-            if(HasIcon) W+=bt->LM+LA_RH;
+            if(HasIcon||ico) W+=bt->LM+LA_RH;
         }else{
             for (i = ep->Items.pFirst; i; i = i->Item.pNext){
                 tW = tnsStringGetWidth(transLate(i->Name), 0, ui->Flags&LA_TEXT_MONO) + SharedWidth;