*/}}
Browse Source

Customizable behavior

Yiming Wu 1 year ago
parent
commit
bb9332bc87
3 changed files with 115 additions and 31 deletions
  1. 105 30
      ouroperations.c
  2. 6 0
      ourpaint.c
  3. 4 1
      ourpaint.h

+ 105 - 30
ouroperations.c

@@ -235,17 +235,17 @@ void ourui_ToolsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps
 
         laShowSeparator(uil,c);
         laShowLabel(uil,c,"Display:",0,0);
-        laShowItem(uil,c,0,"our.enable_brush_circle");
+        laShowItem(uil,c,0,"our.preferences.enable_brush_circle");
     }laEndCondition(uil,bt);
 
     bt=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.tool"),laIntExpression(OUR_TOOL_CROP)));{
-        laShowItemFull(uil,c,0,"our.show_border",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0);
-        laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.show_border"));{
+        laShowItemFull(uil,c,0,"our.canvas.show_border",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0);
+        laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.canvas.show_border"));{
             laShowLabel(uil,cl,"Position:",0,0); laShowItem(uil,cr,0,"our.canvas.position")->Flags|=LA_UI_FLAGS_TRANSPOSE;
             laShowSeparator(uil,c);
             laShowLabel(uil,cl,"Size:",0,0); laShowItem(uil,cr,0,"our.canvas.size")->Flags|=LA_UI_FLAGS_TRANSPOSE;
             laShowSeparator(uil,c);
-            laShowItem(uil,c,0,"our.border_alpha");
+            laShowItem(uil,c,0,"our.canvas.border_alpha");
         }laEndCondition(uil,b);
     }laEndCondition(uil,bt);
 }
@@ -257,7 +257,7 @@ void ourui_BrushesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedPro
             laShowItemFull(uil,c,0,"our.tools.current_brush.size",0,0,0,0);
             laShowItemFull(uil,c,0,"our.tools.current_brush.size_100",0,0,0,0);
             laShowItemFull(uil,c,0,"our.tools.current_brush.size_10",0,0,0,0);
-            OUR_BR laShowSeparator(uil,c)->Expand=1; laShowItemFull(uil,c,0,"our.lock_radius",LA_WIDGET_ENUM_HIGHLIGHT,"text=Lock;",0,0); OUR_ER
+            OUR_BR laShowSeparator(uil,c)->Expand=1; laShowItemFull(uil,c,0,"our.preferences.lock_radius",LA_WIDGET_ENUM_HIGHLIGHT,"text=Lock;",0,0); OUR_ER
         }laEndCondition(uil,b);
         laShowItemFull(uil,c,0,"our.tools.brushes",0,0,0,0);
         laShowItem(uil,c,0,"OUR_new_brush");
@@ -278,6 +278,40 @@ void ourui_BrushPage(laUiList *uil, laPropPack *This, laPropPack *DetachedProps,
         laShowItemFull(uil,c,0,"our.tools.current_brush.rack_page",LA_WIDGET_COLLECTION_SINGLE,0,0,0)->Extra->HeightCoeff=-1;
     }laEndCondition(uil,b);
 }
+void ourui_AboutAuthor(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laUiItem* g; laUiList* gu; laColumn* gc;
+    g = laMakeGroup(uil, c, "OurPaint", 0);
+    gu = g->Page;{
+        gc = laFirstColumn(gu);
+        laShowLabel(gu,gc,"OurPaint is made by Wu Yiming.",0,0)->Flags|=LA_TEXT_LINE_WRAP;
+        laShowItemFull(gu, gc, 0, "LA_open_internet_link", 0, "link=http://www.ChengduLittleA.com/ourpaint;text=OurPaint Blog", 0, 0);
+    }
+}
+void ourui_AboutVersion(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); laUiItem* g; laUiList* gu; laColumn* gc;
+    g = laMakeGroup(uil, c, "OurPaint", 0);
+    gu = g->Page;{
+        gc = laFirstColumn(gu); char buf[128]; sprintf(buf,"OurPaint %d.%d",OUR_VERSION_MAJOR,OUR_VERSION_MINOR);
+        laShowLabel(gu,gc,buf,0,0)->Flags|=LA_TEXT_MONO;
+    }
+}
+void ourui_AboutContent(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+    laColumn* c=laFirstColumn(uil); 
+
+    laShowLabel(uil, c, "OurPaint", 0, 0);
+    laShowLabel(uil, c, "A simple yet flexible node-based GPU painting program.", 0, 0)->Flags|=LA_TEXT_LINE_WRAP;
+    laShowLabel(uil, c, "(C)Yiming Wu", 0, 0);
+}
+void ourui_OurPreference(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+    laColumn* c = laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.5);cl=laLeftColumn(c,0);cr=laRightColumn(c,0);
+
+    laShowLabel(uil,c,"Generic:",0,0);
+    laShowItem(uil,cl,0,"our.preferences.enable_brush_circle");
+    laShowItem(uil,cr,0,"our.preferences.lock_radius");
+
+    laShowLabel(uil,c,"Developer:",0,0);
+    laShowItem(uil,cl,0,"our.preferences.show_debug_tiles");
+}
 
 void our_CanvasDrawTextures(){
     tnsUseImmShader; tnsEnableShaderv(T->immShader);
@@ -354,7 +388,6 @@ void our_CanvasDrawInit(laUiItem* ui){
     ocd->Base.ImageDrawBorder = 1;
     ocd->Base.AdaptiveLineWidth = 1;
     ocd->Base.ClearBackground = 1;
-    ocd->ShowTiles=1;
 
     int work_grp_cnt[3];
     glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &work_grp_cnt[0]);
@@ -391,7 +424,7 @@ void our_CanvasDrawCanvas(laBoxedTheme *bt, OurPaint *unused_c, laUiItem* ui){
     tnsResetViewMatrix();tnsResetModelMatrix();tnsResetProjectionMatrix();
     tnsOrtho(e->PanX - W * e->ZoomX / 2, e->PanX + W * e->ZoomX / 2, e->PanY - e->ZoomY * H / 2, e->PanY + e->ZoomY * H / 2, 100, -100);
     tnsClearColor(LA_COLOR3(Our->BackgroundColor),1); tnsClearAll();
-    if(ocd->ShowTiles){ our_CanvasDrawTiles(); }
+    if(Our->ShowTiles){ our_CanvasDrawTiles(); }
     our_CanvasDrawTextures();
     if(Our->ShowBorder){ our_CanvasDrawCropping(ocd); }
 
@@ -1096,13 +1129,13 @@ void our_DoCropping(OurCanvasDraw* cd, real x, real y){
 
 int ourinv_NewLayer(laOperator* a, laEvent* e){
     our_NewLayer("Our Layer"); laNotifyUsers("our.canvas.layers"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst);
-    laRecordDifferences(0,"our.canvas.layers");laRecordDifferences(0,"our.canvas.current_layer");
+    laRecordDifferences(0,"our.canvas.layers");laRecordDifferences(0,"our.canvas.current_layer");laPushDifferences("New Layer",0);
     return LA_FINISHED;
 }
 int ourinv_RemoveLayer(laOperator* a, laEvent* e){
     OurLayer* l=a->This?a->This->EndInstance:0; if(!l) return LA_CANCELED;
     our_RemoveLayer(l); laNotifyUsers("our.canvas.layers"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst);
-    laRecordDifferences(0,"our.canvas.layers");laRecordDifferences(0,"our.canvas.current_layer");
+    laRecordDifferences(0,"our.canvas.layers");laRecordDifferences(0,"our.canvas.current_layer");laPushDifferences("Remove Layer",0);
     return LA_FINISHED;
 }
 int ourinv_MoveLayer(laOperator* a, laEvent* e){
@@ -1110,7 +1143,7 @@ int ourinv_MoveLayer(laOperator* a, laEvent* e){
     char* direction=strGetArgumentString(a->ExtraInstructionsP,"direction");
     if(strSame(direction,"up")&&l->Item.pPrev){ lstMoveUp(&Our->Layers, l); changed=1; }
     elif(l->Item.pNext){ lstMoveDown(&Our->Layers, l); changed=1; }
-    if(changed){ laNotifyUsers("our.canvas.layers"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst); laRecordDifferences(0,"our.canvas.layers"); }
+    if(changed){ laNotifyUsers("our.canvas.layers"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst); laRecordDifferences(0,"our.canvas.layers"); laPushDifferences("Move Layer",0); }
     return LA_FINISHED;
 }
 int ourchk_MergeLayer(laPropPack *This, laStringSplitor *ss){
@@ -1121,9 +1154,12 @@ int ourinv_MergeLayer(laOperator* a, laEvent* e){
     if(our_MergeLayer(l)){ laNotifyUsers("our.canvas"); laNotifyUsers("our.canvas.layers"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst); }
     return LA_FINISHED;
 }
+int ourchk_ExportLayer(laPropPack *This, laStringSplitor *ss){
+    OurLayer* ol=This?This->EndInstance:0; if(!ol) ol=Our->CurrentLayer; if(!ol) return 0; return 1;
+}
 int ourinv_ExportLayer(laOperator* a, laEvent* e){
     OurLayer* ol=a->This?a->This->EndInstance:0; if(!ol) ol=Our->CurrentLayer; if(!ol) return LA_FINISHED;
-    laInvoke(a, "LA_file_dialog", e, 0, "warn_file_exists=true;", 0);
+    laInvoke(a, "LA_file_dialog", e, 0, "warn_file_exists=true;filter_extensions=png;use_extension=png", 0);
     return LA_RUNNING;
 }
 int ourmod_ExportLayer(laOperator* a, laEvent* e){
@@ -1143,7 +1179,7 @@ int ourmod_ExportLayer(laOperator* a, laEvent* e){
 }
 int ourinv_ImportLayer(laOperator* a, laEvent* e){
     OurLayer* ol=a->This?a->This->EndInstance:0;
-    laInvoke(a, "LA_file_dialog", e, 0, 0, 0);
+    laInvoke(a, "LA_file_dialog", e, 0, "filter_extensions=png;use_extension=png", 0);
     return LA_RUNNING;
 }
 int ourmod_ImportLayer(laOperator* a, laEvent* e){
@@ -1160,6 +1196,9 @@ int ourmod_ImportLayer(laOperator* a, laEvent* e){
     }
     return LA_RUNNING;
 }
+int ourchk_ExportImage(laPropPack *This, laStringSplitor *ss){
+    OurLayer* ol=This?This->EndInstance:0; if(!ol) ol=Our->CurrentLayer; if(!ol) return 0; return 1;
+}
 int ourinv_ExportImage(laOperator* a, laEvent* e){
     OurLayer* ol=a->This?a->This->EndInstance:0; if(!ol) ol=Our->CurrentLayer; if(!ol) return LA_FINISHED;
     laInvoke(a, "LA_file_dialog", e, 0, "warn_file_exists=true;", 0);
@@ -1348,6 +1387,9 @@ void ourset_Tool(void* unused, int a){
 void ourset_ShowBorder(void* unused, int a){
     Our->ShowBorder=a; laNotifyUsers("our.canvas"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst);
 }
+void ourset_ShowTiles(void* unused, int a){
+    Our->ShowTiles=a; laNotifyUsers("our.canvas");
+}
 void ourset_CanvasSize(void* unused, int* wh){
     Our->W=wh[0]; Our->H=wh[1]; if(Our->W<32) Our->W=32; if(Our->H<32) Our->H=32; laNotifyUsers("our.canvas"); laMarkMemChanged(Our->CanvasSaverDummyList.pFirst);
 }
@@ -1360,6 +1402,9 @@ void ourset_LayerPosition(OurLayer* l, int* xy){
 void ourreset_Canvas(OurPaint* op){
     while(op->Layers.pFirst){ our_RemoveLayer(op->Layers.pFirst); }
 }
+void ourreset_Preferences(OurPaint* op){
+    return; //does nothing.
+}
 void ourpropagate_Tools(OurPaint* p, laUDF* udf, int force){
     for(OurBrush* b=p->Brushes.pFirst;b;b=b->Item.pNext){
         if(force || !laget_InstanceActiveUDF(b)){ laset_InstanceUDF(b, udf); }
@@ -1371,7 +1416,9 @@ void ourset_CurrentBrush(void* unused, OurBrush* b){
     if(b->DefaultAsEraser){ Our->Erasing=1; Our->EraserID=b->Binding; }else{ Our->Erasing=0; Our->PenID=b->Binding; }
     laNotifyUsers("our.tools.current_brush"); laDriverRequestRebuild();
 }
-
+void ourset_CurrentLayer(void* unused, OurLayer*l){
+    memAssignRef(Our, &Our->CurrentLayer, l); laNotifyUsers("our.canvas");
+}
 #define OUR_ADD_PRESSURE_SWITCH(p)\
     laAddEnumItemAs(p,"NONE","None","Not using pressure",0,0);\
     laAddEnumItemAs(p,"ENABLED","Enabled","Using pressure",1,0);
@@ -1380,12 +1427,21 @@ void ourui_MenuButtons(laUiList *uil, laPropPack *pp, laPropPack *actinst, laCol
     laUiList *muil; laColumn *mc,*c = laFirstColumn(uil);
     muil = laMakeMenuPage(uil, c, "File");{
         mc = laFirstColumn(muil);
-        laShowLabel(muil, mc, "Our Paint", 0, 0);
+        laShowLabel(muil, mc, "OurPaint", 0, 0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
+        laShowItem(muil, mc, 0, "LA_udf_read");
+        laShowItemFull(muil, mc, 0, "LA_managed_save",0,"quiet=true;text=Save;",0,0);
+        laShowItem(muil, mc, 0, "LA_managed_save");
+        laShowLabel(muil, mc, "Image", 0, 0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
         laShowItem(muil, mc, 0, "OUR_export_image");
-        laShowSeparator(muil,mc);
+        laShowLabel(muil, mc, "Layer", 0, 0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
         laShowItem(muil, mc, 0, "OUR_export_layer");
         laShowItem(muil, mc, 0, "OUR_import_layer");
-        laui_DefaultMenuButtonsFileEntries(muil,pp,actinst,extracol,0);
+        laShowLabel(muil, mc, "Others", 0, 0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
+        laShowItem(muil, mc, 0, "LA_terminate_program");
+        //laui_DefaultMenuButtonsFileEntries(muil,pp,actinst,extracol,0);
+    }
+    muil = laMakeMenuPage(uil, c, "Edit");{
+        mc = laFirstColumn(muil); laui_DefaultMenuButtonsEditEntries(muil,pp,actinst,extracol,0);
     }
     muil = laMakeMenuPage(uil, c, "Options"); {
         mc = laFirstColumn(muil); laui_DefaultMenuButtonsOptionEntries(muil,pp,actinst,extracol,0);
@@ -1404,7 +1460,7 @@ void ourRegisterEverything(){
     laCreateOperatorType("OUR_remove_layer","Remove Layer","Remove this layer",0,0,0,ourinv_RemoveLayer,0,L'🗴',0);
     laCreateOperatorType("OUR_move_layer","Move Layer","Remove this layer",0,0,0,ourinv_MoveLayer,0,0,0);
     laCreateOperatorType("OUR_merge_layer","Merge Layer","Merge this layer with the layer below it",ourchk_MergeLayer,0,0,ourinv_MergeLayer,0,0,0);
-    laCreateOperatorType("OUR_export_layer","Export Layer","Export this layer",0,0,0,ourinv_ExportLayer,ourmod_ExportLayer,L'🖫',0);
+    laCreateOperatorType("OUR_export_layer","Export Layer","Export this layer",ourchk_ExportLayer,0,0,ourinv_ExportLayer,ourmod_ExportLayer,L'🖫',0);
     laCreateOperatorType("OUR_import_layer","Import Layer","Import a PNG into a layer",0,0,0,ourinv_ImportLayer,ourmod_ImportLayer,L'🗁',0);
     laCreateOperatorType("OUR_new_brush","New Brush","Create a new brush",0,0,0,ourinv_NewBrush,0,'+',0);
     laCreateOperatorType("OUR_remove_brush","Remove Brush","Remove this brush",0,0,0,ourinv_RemoveBrush,0,L'🗴',0);
@@ -1413,7 +1469,7 @@ void ourRegisterEverything(){
     laCreateOperatorType("OUR_brush_resize","Brush Resize","Brush resize",0,0,0,ourinv_BrushResize,0,0,0);
     laCreateOperatorType("OUR_action","Action","Doing action on a layer",0,0,0,ourinv_Action,ourmod_Action,0,LA_EXTRA_TO_PANEL);
     laCreateOperatorType("OUR_pick","Pick color","Pick color on the widget",0,0,0,ourinv_PickColor,ourmod_PickColor,0,LA_EXTRA_TO_PANEL);
-    laCreateOperatorType("OUR_export_image","Export Image","Export the image",0,0,0,ourinv_ExportImage,ourmod_ExportImage,L'🖼',0);
+    laCreateOperatorType("OUR_export_image","Export Image","Export the image",ourchk_ExportImage,0,0,ourinv_ExportImage,ourmod_ExportImage,L'🖼',0);
 
     laRegisterUiTemplate("panel_canvas", "Canvas", ourui_CanvasPanel, 0, 0,"Our Paint");
     laRegisterUiTemplate("panel_layers", "Layers", ourui_LayersPanel, 0, 0,0);
@@ -1428,23 +1484,27 @@ void ourRegisterEverything(){
     pc=laAddPropertyContainer("our_paint","Our Paint","OurPaint main",0,0,sizeof(OurPaint),0,0,1);
     laAddSubGroup(pc,"canvas","Canvas","OurPaint canvas","our_canvas",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddSubGroup(pc,"tools","Tools","OurPaint tools","our_tools",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
+    laAddSubGroup(pc,"preferences","Preferences","OurPaint preferences","our_preferences",0,0,0,0,0,0,0,0,0,0,0,LA_UDF_LOCAL);
     laAddFloatProperty(pc,"current_color","Current Color","Current color used to paint",0,0,0,1,0,0.05,0.8,0,offsetof(OurPaint,CurrentColor),0,0,3,0,0,0,0,0,0,0,LA_PROP_IS_LINEAR_SRGB);
-    laAddFloatProperty(pc,"border_alpha","Border Alpha","Alpha of the border region around the canvas",0,0,0,1,0,0.05,0.5,0,offsetof(OurPaint,BorderAlpha),0,0,0,0,0,0,0,ourset_BorderAlpha,0,0,0);
     p=laAddEnumProperty(pc,"tool","Tool","Tool to use on the canvas",0,0,0,0,0,offsetof(OurPaint,Tool),0,ourset_Tool,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"PAINT","Paint","Paint stuff on the canvas",OUR_TOOL_PAINT,L'🖌');
     laAddEnumItemAs(p,"CROP","Cropping","Crop the focused region",OUR_TOOL_CROP,L'🖼');
-    p=laAddEnumProperty(pc,"show_border","Show Border","Whether to show border on the canvas",0,0,0,0,0,offsetof(OurPaint,ShowBorder),0,ourset_ShowBorder,0,0,0,0,0,0,0,0);
-    laAddEnumItemAs(p,"FALSE","No","Dont' show border on the canvas",0,0);
-    laAddEnumItemAs(p,"TRUE","Yes","Show border on the canvas",1,0);
-    p=laAddEnumProperty(pc,"lock_radius","Lock Radius","Lock radius when changing brushes",0,0,0,0,0,offsetof(OurPaint,LockRadius),0,0,0,0,0,0,0,0,0,0);
+    
+    p=laAddEnumProperty(pc,"erasing","Erasing","Is in erasing mode",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,Erasing),0,0,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"FALSE","Draw","Is drawing mode",0,0);
+    laAddEnumItemAs(p,"TRUE","Erase","Is erasing mode",1,0);
+
+    pc=laAddPropertyContainer("our_preferences","Our Preferences","OurPaint preferences",0,0,sizeof(OurPaint),0,0,1);
+    laPropContainerExtraFunctions(pc,0,ourreset_Preferences,0,0,0);
+    p=laAddEnumProperty(pc,"lock_radius","Lock Radius","Lock radius when changing brushes",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,LockRadius),0,0,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"FALSE","No","Dont' lock radius",0,0);
     laAddEnumItemAs(p,"TRUE","Yes","Lock radius when changing brushes",1,0);
     p=laAddEnumProperty(pc,"enable_brush_circle","Brush Circle","Enable brush circle when hovering",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,EnableBrushCircle),0,0,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"FALSE","No","Dont' show brush circle",0,0);
     laAddEnumItemAs(p,"TRUE","Yes","Show brush circle on hover",1,0);
-    p=laAddEnumProperty(pc,"erasing","Erasing","Is in erasing mode",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,Erasing),0,0,0,0,0,0,0,0,0,0);
-    laAddEnumItemAs(p,"FALSE","Draw","Is drawing mode",0,0);
-    laAddEnumItemAs(p,"TRUE","Erase","Is erasing mode",1,0);
+    p=laAddEnumProperty(pc,"show_debug_tiles","Show debug tiles","Whether to show debug tiles",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,ShowTiles),0,ourset_ShowTiles,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"FALSE","No","Dont' show debug tiles on the canvas",0,0);
+    laAddEnumItemAs(p,"TRUE","Yes","Show debug tiles on the canvas",1,0);
 
     pc=laAddPropertyContainer("our_tools","Our Tools","OurPaint tools",0,0,sizeof(OurPaint),0,0,1);
     laPropContainerExtraFunctions(pc,0,0,0,ourpropagate_Tools,0);
@@ -1477,7 +1537,7 @@ void ourRegisterEverything(){
     p=laAddEnumProperty(pc,"use_nodes","Use Nodes","Use nodes to control brush dynamics",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurBrush,UseNodes),0,0,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"NONE","None","Not using nodes",0,0);
     laAddEnumItemAs(p,"ENABLED","Enabled","Using nodes",1,0);
-    laAddSubGroup(pc,"rack_page","Rack Page","Nodes rack page of this brush","la_rack_page",0,0,laui_RackPage,offsetof(OurBrush,Rack),0,0,0,0,0,0,0,LA_UDF_SINGLE);
+    laAddSubGroup(pc,"rack_page","Rack Page","Nodes rack page of this brush","la_rack_page",0,0,laui_RackPage,offsetof(OurBrush,Rack),0,0,0,0,0,0,0,LA_UDF_SINGLE|LA_HIDE_IN_SAVE);
     p=laAddEnumProperty(pc,"default_as_eraser","Default as eraser","Use this brush as a eraser by default",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurBrush,DefaultAsEraser),0,0,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"NONE","None","Default as brush",0,0);
     laAddEnumItemAs(p,"ENABLED","Enabled","Default as eraser",1,0);
@@ -1494,7 +1554,11 @@ void ourRegisterEverything(){
     laAddIntProperty(pc,"size","Size","Size of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,W),0,0,2,0,0,0,0,ourset_CanvasSize,0,0,0);
     laAddIntProperty(pc,"position","Position","Position of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,X),0,0,2,0,0,0,0,ourset_CanvasPosition,0,0,0);
     laAddFloatProperty(pc,"background_color","Background Color","Background color of the canvas",0,0,0,1,0,0.05,0.8,0,offsetof(OurPaint,BackgroundColor),0,0,3,0,0,0,0,ourset_BackgroundColor,0,0,LA_PROP_IS_LINEAR_SRGB);
-    
+    laAddFloatProperty(pc,"border_alpha","Border Alpha","Alpha of the border region around the canvas",0,0,0,1,0,0.05,0.5,0,offsetof(OurPaint,BorderAlpha),0,0,0,0,0,0,0,ourset_BorderAlpha,0,0,0);
+    p=laAddEnumProperty(pc,"show_border","Show Border","Whether to show border on the canvas",0,0,0,0,0,offsetof(OurPaint,ShowBorder),0,ourset_ShowBorder,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"FALSE","No","Dont' show border on the canvas",0,0);
+    laAddEnumItemAs(p,"TRUE","Yes","Show border on the canvas",1,0);
+
     pc=laAddPropertyContainer("our_layer","Our Layer","OurPaint layer",0,0,sizeof(OurLayer),0,0,1);
     laPropContainerExtraFunctions(pc,ourbeforefree_Layer,ourbeforefree_Layer,0,0,0);
     laAddStringProperty(pc,"name","Name","Name of the layer",0,0,0,0,1,offsetof(OurLayer,Name),0,0,0,0,LA_AS_IDENTIFIER);
@@ -1533,10 +1597,14 @@ void ourRegisterEverything(){
     laSaveProp("our.canvas");
     laSaveProp("our.tools");
 
-    laAddRootDBInst("our.canvas");
-
     laGetSaverDummy(Our,Our->CanvasSaverDummyProp);
 
+    laAddExtraExtension(LA_FILETYPE_UDF,"ourpaint","ourbrush",0);
+    laAddExtraPreferencePath("our.preferences");
+    laAddExtraPreferencePage("OurPaint",ourui_OurPreference);
+
+    laSetAboutTemplates(ourui_AboutContent,ourui_AboutVersion,ourui_AboutAuthor);
+
     laSetFrameCallbacks(ourPreFrame,0,0);
 }
 
@@ -1611,6 +1679,13 @@ int ourInit(){
 
     tnsEnableShaderv(T->immShader);
 
+    tnsVectorSet3(Our->BackgroundColor,0.2,0.2,0.2);
+    our_NewLayer("Our Layer");
+    OurBrush* ob=our_NewBrush("Our Brush",15,0.95,9,0.5,0.5,5,0,0,0,0); laset_InstanceUID(ob,"OURBRUSH_DEFAULT_YIMING");
+    laMarkMemClean(ob); laMarkMemClean(Our->CanvasSaverDummyList.pFirst);
+
+    laAddRootDBInst("our.canvas");
+
     return 1;
 }
 

+ 6 - 0
ourpaint.c

@@ -12,6 +12,12 @@ int main(int argc, char *argv[]){
     laRefreshUDFRegistries();
     laEnsureUserPreferences();
 
+    for(int i=1;i<argc;i++){
+        char* file=argv[i]; 
+        laManagedUDF* m; laUDF* udf = laOpenUDF(file, 1, 0, &m);
+        if(udf){ laExtractUDF(udf,m,LA_UDF_MODE_APPEND,0); laCloseUDF(udf); }
+    }
+
     //laAddRootDBInst("la.input_mapping");
     //laAddRootDBInst("la.drivers");
     //laAddRootDBInst("our.tools");

+ 4 - 1
ourpaint.h

@@ -10,9 +10,11 @@
 #define OUR_AT_CROP_BL 7
 #define OUR_AT_CROP_BR 8
 
+#define OUR_VERSION_MAJOR 0
+#define OUR_VERSION_MINOR 1
+
 STRUCTURE(OurCanvasDraw){
     laCanvasExtra Base;
-    int ShowTiles;
     int HideBrushCircle;
     int AtCrop;
     real CanvasLastX,CanvasLastY;
@@ -177,6 +179,7 @@ STRUCTURE(OurPaint){
     int PenID,EraserID;
     int X,Y,W,H; //border
     int ShowBorder,UseBorder;
+    int ShowTiles;
 
     int LockRadius;
     int EnableBrushCircle;