*/}}
浏览代码

Composition etc

YimingWu 1 周之前
父节点
当前提交
0dd13964e4
共有 5 个文件被更改,包括 351 次插入162 次删除
  1. 275 132
      ouroperations.c
  2. 17 6
      ourpaint.h
  3. 54 18
      ourshader.cpp
  4. 2 3
      ourtranslations_es-ES.c
  5. 3 3
      ourtranslations_zh-hans.c

+ 275 - 132
ouroperations.c

@@ -343,6 +343,10 @@ void ourui_PigmentItem(laUiList *uil, laPropPack *This, laPropPack *DetachedProp
     laEndRow(uil,b);
     laEndRow(uil,b);
     laShowItemFull(uil,cr,This,"name",LA_WIDGET_STRING_PLAIN,0,0,0);
     laShowItemFull(uil,cr,This,"name",LA_WIDGET_STRING_PLAIN,0,0,0);
 }
 }
+void ourui_PigmentOnlyPad(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *ExtraColumns, int context){
+    laColumn* c=context?ExtraColumns:laFirstColumn(uil);
+    laShowItemFull(uil,c,This,"pigment",OUR_WIDGET_COLOR_PAD,0,0,0)->Flags|=OUR_COLOR_PAD_PIGMENT_DATA|LA_UI_FLAGS_NO_GAP;
+}
 void ourui_PigmentMixingItem(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 void ourui_PigmentMixingItem(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.7); cl=laLeftColumn(c,0);cr=laRightColumn(c,1);
     laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.7); cl=laLeftColumn(c,0);cr=laRightColumn(c,1);
 }
 }
@@ -445,12 +449,16 @@ void ourui_CanvasSurfaceItemSimple(laUiList *uil, laPropPack *This, laPropPack *
 }
 }
 void ourui_ColorItemSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 void ourui_ColorItemSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);
     laColumn* c=laFirstColumn(uil);
-    laShowItemFull(uil,c,This,"color",LA_WIDGET_FLOAT_COLOR,0,0,0)->Flags|=LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_NO_DECAL;
+    laUiItem* b=laOnConditionThat(uil,c,laPropExpression(This,"is_pigment")); {
+        laShowItemFull(uil,c,This,"pigment",OUR_WIDGET_PIGMENT_PREVIEW,0,0,0)->Flags|=LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_NO_DECAL;
+    }laElse(uil,b);{
+        laShowItemFull(uil,c,This,"color",LA_WIDGET_FLOAT_COLOR,0,0,0)->Flags|=LA_UI_FLAGS_NO_EVENT|LA_UI_FLAGS_NO_DECAL;
+    }
 }
 }
-void ourui_Pallette(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+void ourui_Palette(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);
     laColumn* c=laFirstColumn(uil);
     laUiItem* ui=laShowItemFull(uil,c,This,"colors",0,0,ourui_ColorItemSimple,0);ui->Extent=7;
     laUiItem* ui=laShowItemFull(uil,c,This,"colors",0,0,ourui_ColorItemSimple,0);ui->Extent=7;
-    ui->Flags|=LA_UI_FLAGS_NO_DECAL;
+    ui->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
 }
 }
 void ourui_BrushSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 void ourui_BrushSimple(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil);
     laColumn* c=laFirstColumn(uil);
@@ -605,20 +613,56 @@ void ourui_BrushesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedPro
     }laEndCondition(uil,bt);
     }laEndCondition(uil,bt);
 }
 }
 void ourui_UsePigmentItem(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *ExtraColumns, int context){
 void ourui_UsePigmentItem(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *ExtraColumns, int context){
-    laColumn* c=context?ExtraColumns:laFirstColumn(uil); laColumn* cl,*cr;
-    laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,0);cr=laRightColumn(c,1);
-    laUiItem* ui=laShowItemFull(uil,cl,This,"__self",OUR_WIDGET_COLOR_PAD,0,0,0);ui->Flags|=LA_UI_FLAGS_NO_GAP;ui->Expand=1;
-    laShowHeightAdjuster(uil,cr,This,"__move",0)->Flags|=LA_UI_FLAGS_NO_GAP;
+    laColumn* c=context?ExtraColumns:laFirstColumn(uil);
+    laUiItem* br=laBeginRow(uil,c,0,0);{ br->Flags|=LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_GAP;
+        laUiItem* ui=laShowItemFull(uil,c,This,"__self",OUR_WIDGET_COLOR_PAD,0,0,0);ui->Flags|=LA_UI_FLAGS_NO_GAP;ui->Expand=1;
+        laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.preferences.reorder_pigments"));{
+            laShowHeightAdjuster(uil,c,This,"remove",0)->Flags|=LA_UI_FLAGS_NO_GAP|LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_ICON;
+            laShowHeightAdjuster(uil,c,This,"__move",0)->Flags|=LA_UI_FLAGS_NO_GAP;
+        }laEndCondition(uil,b);
+    }laEndRow(uil,br);
 }
 }
+void ourui_PalettesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context);
 void ourui_ColorPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 void ourui_ColorPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil); laSplitColumn(uil,c,0.6);
     laColumn* c=laFirstColumn(uil); laSplitColumn(uil,c,0.6);
-    laColumn *cl=laLeftColumn(c,0),*cr=laRightColumn(c,6);
+    laColumn *cl=laLeftColumn(c,0),*cr=laRightColumn(c,6); laSplitColumn(uil,cl,0.5);
+    laColumn *cll=laLeftColumn(cl,0),*clr=laRightColumn(cl,0);
 
 
     laUiItem* pigb=laOnConditionThat(uil,c,laPropExpression(0,"our.canvas.pigment_mode"));{
     laUiItem* pigb=laOnConditionThat(uil,c,laPropExpression(0,"our.canvas.pigment_mode"));{
-        laUiItem* mixui=laShowItemFull(uil,cl,0,"our.mixed_pigment",OUR_WIDGET_PIGMENT_MIXER,0,0,0); mixui->Extent=7;
+        laUiItem* mixui=laShowItemFull(uil,cl,0,"our.mixed_pigment",OUR_WIDGET_PIGMENT_MIXER,0,0,0); mixui->Extent=4;
+        laUiItem* bc=laOnConditionThat(uil,cll,laAnd(laPropExpression(0,"our.canvas.set_use_white"),laNot(laPropExpression(0,"our.preferences.reorder_pigments"))));{
+            laShowItemFull(uil,cll,0,"our.canvas.use_white",LA_WIDGET_COLLECTION_SINGLE,0,ourui_PigmentOnlyPad,0)
+                ->Flags|=LA_UI_FLAGS_NO_DECAL;
+        }laElse(uil,bc);{
+            laShowItemFull(uil,cll,0,"our.canvas.use_white",LA_WIDGET_COLLECTION_SELECTOR,0,0,0);
+        }laEndCondition(uil,bc);
+        bc=laOnConditionThat(uil,clr,laAnd(laPropExpression(0,"our.canvas.set_use_black"),laNot(laPropExpression(0,"our.preferences.reorder_pigments"))));{
+            laShowItemFull(uil,clr,0,"our.canvas.use_black",LA_WIDGET_COLLECTION_SINGLE,0,ourui_PigmentOnlyPad,0)
+                ->Flags|=LA_UI_FLAGS_NO_DECAL;
+        }laElse(uil,bc);{
+            laShowItemFull(uil,clr,0,"our.canvas.use_black",LA_WIDGET_COLLECTION_SELECTOR,0,0,0);
+        }laEndCondition(uil,bc);
         laShowItemFull(uil, cr, 0, "our.canvas.use_pigments",0,0,ourui_UsePigmentItem,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
         laShowItemFull(uil, cr, 0, "our.canvas.use_pigments",0,0,ourui_UsePigmentItem,0)->Flags|=LA_UI_FLAGS_NO_DECAL;
-        laShowItemFull(uil, cr, 0, "OUR_new_use_pigment", 0, "text=new;",0,0);
+        laUiItem* bedit=laOnConditionThat(uil,cr,laPropExpression(0,"our.preferences.reorder_pigments"));{
+            laShowItemFull(uil, cr, 0, "OUR_new_use_pigment", 0, "text=new;",0,0)->Expand=1;
+        }laEndCondition(uil,bedit);
+
+        laUiItem* uishowpalette;
+        laUiItem* bleft=laBeginRow(uil,cl,1,0);{
+            uishowpalette=laShowItemFull(uil,cl,0,"our.preferences.palette_in_colors_panel",LA_WIDGET_ENUM_HIGHLIGHT,"icon=🎨",0,0);
+            uishowpalette->Flags|=LA_UI_FLAGS_ICON;
+            laUiItem* cond=laOnConditionThat(uil,cl,laAnd(laPropExpression(0,"our.tools.current_pallette"),laPropExpression(&uishowpalette->PP,"")));{
+                laShowItem(uil,cl,0,"OUR_pallette_new_color")->Expand=1;
+            }laEndCondition(uil,cond);
+            laShowItemFull(uil, cl, 0, "our.preferences.reorder_pigments", 0, "icon=🖉;",0,0)
+                ->Flags|=LA_UI_FLAGS_ICON|LA_UI_FLAGS_CYCLE|LA_UI_FLAGS_HIGHLIGHT;
+        }laEndRow(uil,bleft);
+        laUiItem* bshowpalette=laOnConditionThat(uil,cl,laPropExpression(&uishowpalette->PP,""));{
+            ourui_PalettesPanel(uil,This,DetachedProps,UNUSED,1);
+        }laEndCondition(uil,bshowpalette);
+
     }laElse(uil,pigb);{
     }laElse(uil,pigb);{
+        laUiItem* uishowpalette;
         laUiItem* b=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.canvas.color_interpretation"),laIntExpression(OUR_CANVAS_INTERPRETATION_SRGB)));{
         laUiItem* b=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.canvas.color_interpretation"),laIntExpression(OUR_CANVAS_INTERPRETATION_SRGB)));{
             laShowItemFull(uil,c,0,"our.current_color",LA_WIDGET_FLOAT_COLOR_HCY,0,0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
             laShowItemFull(uil,c,0,"our.current_color",LA_WIDGET_FLOAT_COLOR_HCY,0,0,0)->Flags|=LA_UI_FLAGS_NO_CONFIRM;
         }laEndCondition(uil,b);
         }laEndCondition(uil,b);
@@ -629,38 +673,44 @@ void ourui_ColorPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps
             laShowItemFull(uil,c,0,"our.current_color",LA_WIDGET_FLOAT_COLOR_HCY,0,0,0)->Flags|=LA_UI_FLAGS_COLOR_SPACE_D65_P3|LA_UI_FLAGS_NO_CONFIRM;
             laShowItemFull(uil,c,0,"our.current_color",LA_WIDGET_FLOAT_COLOR_HCY,0,0,0)->Flags|=LA_UI_FLAGS_COLOR_SPACE_D65_P3|LA_UI_FLAGS_NO_CONFIRM;
         }laEndCondition(uil,b);
         }laEndCondition(uil,b);
         b=laBeginRow(uil,c,0,0);
         b=laBeginRow(uil,c,0,0);
-        laShowItem(uil,c,0,"our.preferences.spectral_mode")->Flags|=LA_UI_FLAGS_NO_CONFIRM;
-        laShowItem(uil,c,0,"our.current_color")->Expand=1;
+        uishowpalette=laShowItemFull(uil,cl,0,"our.preferences.palette_in_colors_panel",LA_WIDGET_ENUM_HIGHLIGHT,"text=Show Palette",0,0); uishowpalette->Expand=1;
+        laUiItem* uispect=laShowItem(uil,c,0,"our.preferences.spectral_mode"); uispect->Flags|=LA_UI_FLAGS_NO_CONFIRM; uispect->Expand=1;
         laUiItem* b2=laOnConditionToggle(uil,c,0,0,0,0,0);
         laUiItem* b2=laOnConditionToggle(uil,c,0,0,0,0,0);
         laEndRow(uil,b);
         laEndRow(uil,b);
-        laShowItem(uil,c,0,"our.color_boost")->Expand=1;
+        laShowItem(uil,c,0,"our.current_color");
+        laShowItem(uil,c,0,"our.color_boost");
+        laShowSeparator(uil,c);
         laElse(uil,b2); laEndRow(uil,b2); laEndCondition(uil,b2);
         laElse(uil,b2); laEndRow(uil,b2); laEndCondition(uil,b2);
+        laUiItem* bshowpalette=laOnConditionThat(uil,cl,laPropExpression(&uishowpalette->PP,""));{
+            ourui_PalettesPanel(uil,This,DetachedProps,UNUSED,0);
+        }laEndCondition(uil,bshowpalette);
     }laEndCondition(uil,pigb);
     }laEndCondition(uil,pigb);
 }
 }
-void ourui_PallettesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
+void ourui_PalettesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil); laUiItem* b,*b1,*b2;
     laColumn* c=laFirstColumn(uil); laUiItem* b,*b1,*b2;
-    laUiItem* bpig=laOnConditionThat(uil,c,laPropExpression(0,"our.canvas.pigment_mode"));{
+    laUiItem* ui=laShowInvisibleItem(uil,c,0,"our.tools.current_pallette");
+    b1=laOnConditionThat(uil,c,laPropExpression(&ui->PP,""));{
+        if(!context){
+            laShowItem(uil,c,0,"OUR_pallette_new_color");
+        }
+    
+        laShowItemFull(uil,c,0,"our.tools.current_pallette",LA_WIDGET_COLLECTION_SINGLE,0,ourui_Palette,0);
         
         
-    }laElse(uil,bpig);{
         b=laBeginRow(uil,c,0,0);
         b=laBeginRow(uil,c,0,0);
         laShowItemFull(uil,c,0,"our.tools.pallettes",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;
         laShowItemFull(uil,c,0,"our.tools.pallettes",LA_WIDGET_COLLECTION_SELECTOR,0,laui_IdentifierOnly,0)->Flags|=LA_UI_COLLECTION_SIMPLE_SELECTOR;
-        laUiItem* ui=laShowInvisibleItem(uil,c,0,"our.tools.current_pallette");
-        b1=laOnConditionThat(uil,c,laPropExpression(&ui->PP,""));{
-            laUiItem* name=laShowItem(uil,c,&ui->PP,"name");name->Flags|=LA_UI_FLAGS_NO_DECAL; name->Expand=1;
-            laShowItem(uil,c,0,"OUR_new_pallette")->Flags|=LA_UI_FLAGS_ICON;
-            laEndRow(uil,b);
-            laShowItemFull(uil,c,0,"our.tools.current_pallette",LA_WIDGET_COLLECTION_SINGLE,0,ourui_Pallette,0);
-            b2=laBeginRow(uil,c,0,0);
-            laShowItem(uil,c,0,"OUR_pallette_new_color")->Expand=1;
-            laUiList* muil=laMakeMenuPage(uil,c,"☰"); laColumn* mc=laFirstColumn(muil);{
-                laShowItem(muil,mc,0,"OUR_remove_pallette");
-            }
-            laEndRow(uil,b2);
-        }laElse(uil,b1);{
-            laShowItem(uil,c,0,"OUR_new_pallette")->Expand=1;
-            laEndRow(uil,b);
-        }laEndCondition(uil,b1);
-    }laEndCondition(uil,bpig);
+        laUiItem* bedit=laOnConditionToggle(uil,c,0,0,0,0,0);{ strSafeSet(&bedit->ExtraInstructions,"icon=🖉;");
+            laUiItem* name=laShowItem(uil,c,&ui->PP,"name"); name->Expand=1;
+        }laElse(uil,bedit);{
+            laUiItem* name=laShowItemFull(uil,c,&ui->PP,"name",LA_WIDGET_STRING_PLAIN,0,0,0); name->Expand=1;
+        }laEndCondition(uil,bedit);
+        laShowItem(uil,c,0,"OUR_new_pallette")->Flags|=LA_UI_FLAGS_ICON;
+        laUiList* muil=laMakeMenuPage(uil,c,"☰"); laColumn* mc=laFirstColumn(muil);{
+            laShowItem(muil,mc,0,"OUR_remove_pallette");
+        }
+        laEndRow(uil,b);
+    }laElse(uil,b1);{
+        laShowItem(uil,c,0,"OUR_new_pallette")->Expand=1;
+    }laEndCondition(uil,b1);
 }
 }
 void ourui_BrushPage(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
 void ourui_BrushPage(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
     laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,12);cr=laRightColumn(c,0);
     laColumn* c=laFirstColumn(uil); laColumn* cl,*cr; laSplitColumn(uil,c,0.5); cl=laLeftColumn(c,12);cr=laRightColumn(c,0);
@@ -748,6 +798,7 @@ void ourui_OurPreference(laUiList *uil, laPropPack *This, laPropPack *DetachedPr
     laShowItem(uil,crr,0,"our.preferences.show_grid")->Flags|=LA_UI_FLAGS_CHECKBOX;
     laShowItem(uil,crr,0,"our.preferences.show_grid")->Flags|=LA_UI_FLAGS_CHECKBOX;
     laShowItem(uil,cr,0,"our.preferences.multithread_write")->Flags|=LA_UI_FLAGS_CHECKBOX;
     laShowItem(uil,cr,0,"our.preferences.multithread_write")->Flags|=LA_UI_FLAGS_CHECKBOX;
     laShowItem(uil,cr,0,"our.preferences.canvas_default_scale");
     laShowItem(uil,cr,0,"our.preferences.canvas_default_scale");
+    laShowItemWithLabel(uil,cl,cr,0,"our.preferences.default_canvas_type",0,0,0,0,0,0,0)->Flags|=LA_UI_FLAGS_EXPAND;
     laShowItemWithLabel(uil,cl,cr,0,"our.preferences.pigment_display_method",0,0,0,0,0,0,c)->Flags|=LA_UI_FLAGS_EXPAND;
     laShowItemWithLabel(uil,cl,cr,0,"our.preferences.pigment_display_method",0,0,0,0,0,0,c)->Flags|=LA_UI_FLAGS_EXPAND;
     
     
     laShowSeparator(uil,c);
     laShowSeparator(uil,c);
@@ -880,8 +931,10 @@ void our_CanvasDrawTextures(tnsOffscreen* off1,tnsOffscreen* off2){
             elif(Our->SketchMode == 2){ a=0.0f; }
             elif(Our->SketchMode == 2){ a=0.0f; }
         }
         }
         tnsVectorSet4(MultiplyColor,a,a,a,a); int any=0;
         tnsVectorSet4(MultiplyColor,a,a,a,a); int any=0;
-        int mixmode=TNS_MIX_NORMAL;
-        if(l->BlendMode==OUR_BLEND_ADD){ mixmode=TNS_MIX_ADD; }
+        int mixmode=TNS_MIX_NORMAL; if(l->BlendMode==OUR_BLEND_ADD){ mixmode=TNS_MIX_ADD; }
+        if(Our->PigmentMode){
+            glUniform1f(OURU->uMixingTop,a);
+        }
         our_CanvasSaveOffscreen(off1,off2);
         our_CanvasSaveOffscreen(off1,off2);
         for(int row=0;row<OUR_TILES_PER_ROW;row++){
         for(int row=0;row<OUR_TILES_PER_ROW;row++){
             if(!l->TexTiles[row]) continue;
             if(!l->TexTiles[row]) continue;
@@ -1401,6 +1454,18 @@ void our_RefreshAllPigmentPreviews(){
             our_PigmentToPreview(&p->Pigment,bkgs[i],p->Pigment.PreviewColor[i]);
             our_PigmentToPreview(&p->Pigment,bkgs[i],p->Pigment.PreviewColor[i]);
         }
         }
     }
     }
+    for(OurColorPalette* cp=Our->Palettes.pFirst;cp;cp=cp->Item.pNext){
+        for(OurColorItem* ci=cp->Colors.pFirst;ci;ci=ci->Item.pNext){ if(!ci->IsPigment) continue;
+            for(int i=0;i<3;i++){
+                our_PigmentToPreview(&ci->Pigment,bkgs[i],ci->Pigment.PreviewColor[i]);
+            }
+        }
+    }
+    for(OurPigment* p=Our->Pigments.pFirst;p;p=p->Item.pNext){
+        for(int i=0;i<3;i++){
+            our_PigmentToPreview(&p->Pigment,bkgs[i],p->Pigment.PreviewColor[i]);
+        }
+    }
     for(OurLight* p=Our->Lights.pFirst;p;p=p->Item.pNext){
     for(OurLight* p=Our->Lights.pFirst;p;p=p->Item.pNext){
         our_LightToPreview(&p->Emission,p->Emission.PreviewColor[0]);
         our_LightToPreview(&p->Emission,p->Emission.PreviewColor[0]);
     }
     }
@@ -1434,57 +1499,63 @@ int ourmod_ColorPad(laOperator* a, laEvent* e){
         return LA_FINISHED_PASS;
         return LA_FINISHED_PASS;
     }
     }
 
 
-    OurUsePigment* up=ui->PP.EndInstance;
-    if(!up){ return LA_RUNNING; }
-
-    if(e->type==LA_L_MOUSE_DOWN || e->type==LA_R_MOUSE_DOWN){
-        if((!up->pigment) || e->type==LA_R_MOUSE_DOWN){
-            int evx=e->x,evy=e->y;
-            laLocalToWindow(a,MAIN.CurrentPanel,&evx,&evy);
-            laPanel* panel=laEnableEmptyPropertyPanel(MAIN.CurrentPanel,a,evx,evx+LA_RH*10,evy,LA_RH*20,e);{
-                laUiList* uil = &panel->UI;
-                laColumn* col = laFirstColumn(uil);
-                laShowItemFull(uil,col,&ui->PP,"pigment",0,0,ourui_PigmentItem,0);
-                laEnclosePanelContent(panel, uil);
+    OurPigmentData* pd=0;
+    if(ui->Flags&OUR_COLOR_PAD_PIGMENT_DATA){
+        pd=ui->PP.EndInstance; if(!pd){ return LA_RUNNING; }
+    }else{
+        OurUsePigment* up=ui->PP.EndInstance; if(!up){ return LA_RUNNING; }
+        pd=up->pigment?&up->pigment->Pigment:0;
+        if(e->type==LA_L_MOUSE_DOWN || e->type==LA_R_MOUSE_DOWN){
+            if((!up->pigment) || e->type==LA_R_MOUSE_DOWN){
+                int evx=e->x,evy=e->y;
+                laLocalToWindow(a,MAIN.CurrentPanel,&evx,&evy);
+                laPanel* panel=laEnableEmptyPropertyPanel(MAIN.CurrentPanel,a,evx,evx+LA_RH*10,evy,LA_RH*20,e);{
+                    laUiList* uil = &panel->UI;
+                    laColumn* col = laFirstColumn(uil);
+                    laShowItemFull(uil,col,&ui->PP,"pigment",0,0,ourui_PigmentItem,0);
+                    laEnclosePanelContent(panel, uil);
+                }
+                return LA_RUNNING;
+            }
+        }
+        if(a->ConfirmData){
+            if(a->ConfirmData->Mode=LA_CONFIRM_DATA){
+                OurPigment* p=a->ConfirmData->PointerData;
+                memAssignRef(up,&up->pigment,p); laNotifyInstanceUsers(up);
+                ui->State=LA_BT_NORMAL;
             }
             }
             return LA_RUNNING;
             return LA_RUNNING;
         }
         }
     }
     }
 
 
-    if(up->pigment){
+    if(pd){
         if(e->type==LA_L_MOUSE_DOWN){ ui->State=LA_BT_ACTIVE; }
         if(e->type==LA_L_MOUSE_DOWN){ ui->State=LA_BT_ACTIVE; }
         if(ui->State==LA_BT_ACTIVE){
         if(ui->State==LA_BT_ACTIVE){
-            our_PigmentMix(&Our->MixedPigment,&up->pigment->Pigment,OUR_MIXING_SPEED*e->Pressure);
+            our_PigmentMix(&Our->MixedPigment,pd,OUR_MIXING_SPEED*e->Pressure);
             our_PigmentToPreviewSelf(&Our->MixedPigment);
             our_PigmentToPreviewSelf(&Our->MixedPigment);
             laNotifyUsers("our.mixed_pigment");
             laNotifyUsers("our.mixed_pigment");
         }
         }
         if(e->type==LA_L_MOUSE_UP || (e->type==LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){ ui->State=LA_BT_NORMAL; }
         if(e->type==LA_L_MOUSE_UP || (e->type==LA_KEY_DOWN && e->key==LA_KEY_ESCAPE)){ ui->State=LA_BT_NORMAL; }
     }
     }
-    
-    if(a->ConfirmData){
-        if(a->ConfirmData->Mode=LA_CONFIRM_DATA){
-            OurPigment* p=a->ConfirmData->PointerData;
-            memAssignRef(up,&up->pigment,p); laNotifyInstanceUsers(up);
-            ui->State=LA_BT_NORMAL;
-        }
-        return LA_RUNNING;
-    }
 
 
     return LA_RUNNING;
     return LA_RUNNING;
 }
 }
 void our_ColorPadDraw(laUiItem *ui, int h){
 void our_ColorPadDraw(laUiItem *ui, int h){
-    laBoxedTheme *bt = (*ui->Type->Theme);
-    OurUsePigment* up=ui->PP.EndInstance;
+    laBoxedTheme *bt = (*ui->Type->Theme); OurPigmentData* pd;
     tnsUseNoTexture();
     tnsUseNoTexture();
+    if(ui->Flags&OUR_COLOR_PAD_PIGMENT_DATA){
+        pd=ui->PP.EndInstance;
+    }else{
+        OurUsePigment* up=ui->PP.EndInstance;
+        pd=(up&&up->pigment)?&up->pigment->Pigment:0;
+    }
 
 
-    if(!up || !up->pigment){
+    if(!pd){
         la_DrawBoxAuto(ui->L,ui->R,ui->U,ui->B,bt,LA_BT_NORMAL,0);
         la_DrawBoxAuto(ui->L,ui->R,ui->U,ui->B,bt,LA_BT_NORMAL,0);
         tnsDrawStringAutoM("?",0,laThemeColor(bt,LA_BT_TEXT),ui->L,ui->R,ui->U,LA_TEXT_ALIGN_CENTER);
         tnsDrawStringAutoM("?",0,laThemeColor(bt,LA_BT_TEXT),ui->L,ui->R,ui->U,LA_TEXT_ALIGN_CENTER);
         return;
         return;
     }
     }
-
-    our_PigmentDrawPreview(ui->L,ui->R,ui->U,ui->B,&up->pigment->Pigment,bt);
-
+    our_PigmentDrawPreview(ui->L,ui->R,ui->U,ui->B,pd,bt);
     tnsColor4dv(laThemeColor(bt,LA_BT_BORDER)); la_DrawBorder(ui->L,ui->R,ui->U,ui->B);
     tnsColor4dv(laThemeColor(bt,LA_BT_BORDER)); la_DrawBorder(ui->L,ui->R,ui->U,ui->B);
 }
 }
 
 
@@ -1609,13 +1680,17 @@ int our_MergeLayer(OurLayer* l){
     OurLayer* ol=l->Item.pNext; if(!ol) return 0; int xmin=INT_MAX,xmax=-INT_MAX,ymin=INT_MAX,ymax=-INT_MAX; int seam=OUR_TILE_SEAM;
     OurLayer* ol=l->Item.pNext; if(!ol) return 0; int xmin=INT_MAX,xmax=-INT_MAX,ymin=INT_MAX,ymax=-INT_MAX; int seam=OUR_TILE_SEAM;
     if(Our->PigmentMode){
     if(Our->PigmentMode){
         Our->u=&Our->uPigment;
         Our->u=&Our->uPigment;
+        glUseProgram(Our->PigmentCompositionProgram);
     }else{
     }else{
-        glUseProgram(Our->AlphaMode?Our->CompositionStraightProgram:Our->CompositionProgram);
         Our->u=&Our->uRGBA;
         Our->u=&Our->uRGBA;
+        glUseProgram(Our->AlphaMode?Our->CompositionStraightProgram:Our->CompositionProgram);
     }
     }
-    glUniform1i(OURU->uBlendMode, l->BlendMode);
     glUniform1f(OURU->uAlphaTop, 1-l->Transparency);
     glUniform1f(OURU->uAlphaTop, 1-l->Transparency);
     glUniform1f(OURU->uAlphaBottom, 1-ol->Transparency);
     glUniform1f(OURU->uAlphaBottom, 1-ol->Transparency);
+    int divfac=1;
+    if(Our->PigmentMode){ divfac=2; }
+    else{ glUniform1i(OURU->uBlendMode, l->BlendMode); }
+
     for(int row=0;row<OUR_TILES_PER_ROW;row++){ if(!l->TexTiles[row]) continue;// Should not happen.
     for(int row=0;row<OUR_TILES_PER_ROW;row++){ if(!l->TexTiles[row]) continue;// Should not happen.
         for(int col=0;col<OUR_TILES_PER_ROW;col++){ if(!l->TexTiles[row][col]) continue; OurTexTile*t=l->TexTiles[row][col];
         for(int col=0;col<OUR_TILES_PER_ROW;col++){ if(!l->TexTiles[row][col]) continue; OurTexTile*t=l->TexTiles[row][col];
             if(!t->Texture) continue;
             if(!t->Texture) continue;
@@ -1624,7 +1699,7 @@ int our_MergeLayer(OurLayer* l){
             if((!ot) || (!ot->Texture)) our_LayerEnsureTileDirect(ol,row,col);
             if((!ot) || (!ot->Texture)) our_LayerEnsureTileDirect(ol,row,col);
             glBindImageTexture(0, t->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, OUR_CANVAS_GL_PIX);
             glBindImageTexture(0, t->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, OUR_CANVAS_GL_PIX);
             glBindImageTexture(1, ot->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, OUR_CANVAS_GL_PIX);
             glBindImageTexture(1, ot->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, OUR_CANVAS_GL_PIX);
-            glDispatchCompute(OUR_TILE_W/OUR_WORKGROUP_SIZE,OUR_TILE_W/OUR_WORKGROUP_SIZE,1);
+            glDispatchCompute(OUR_TILE_W/OUR_WORKGROUP_SIZE/divfac,OUR_TILE_W/OUR_WORKGROUP_SIZE/divfac,1);
             xmin=TNS_MIN2(xmin,t->l+seam);xmax=TNS_MAX2(xmax,t->r-seam); ymin=TNS_MIN2(ymin,t->b+seam);ymax=TNS_MAX2(ymax,t->u-seam);
             xmin=TNS_MIN2(xmin,t->l+seam);xmax=TNS_MAX2(xmax,t->r-seam); ymin=TNS_MIN2(ymin,t->b+seam);ymax=TNS_MAX2(ymax,t->u-seam);
         }
         }
     }
     }
@@ -1645,16 +1720,21 @@ OurPigment* our_NewPigment(char* name){
     OurPigment* p=memAcquireHyper(sizeof(OurPigment)); strSafeSet(&p->Name,name); lstAppendItem(&Our->Pigments, p);
     OurPigment* p=memAcquireHyper(sizeof(OurPigment)); strSafeSet(&p->Name,name); lstAppendItem(&Our->Pigments, p);
     memAssignRef(Our,&Our->CurrentPigment,p);
     memAssignRef(Our,&Our->CurrentPigment,p);
     for(int i=0;i<16;i++){ p->Pigment.Absorption[i]=p->Pigment.Reflectance[i]=0.5f; }
     for(int i=0;i<16;i++){ p->Pigment.Absorption[i]=p->Pigment.Reflectance[i]=0.5f; }
+    our_PigmentToPreviewSelf(&p->Pigment);
     return p;
     return p;
 }
 }
 void our_RemovePigment(OurPigment* p){
 void our_RemovePigment(OurPigment* p){
+    OurPigment* np=p->Item.pNext?p->Item.pNext:p->Item.pPrev;
     strSafeDestroy(&p->Name); lstRemoveItem(&Our->Pigments, p); memLeave(p);
     strSafeDestroy(&p->Name); lstRemoveItem(&Our->Pigments, p); memLeave(p);
+    memAssignRef(Our,&Our->CurrentPigment,np);
 }
 }
 OurPigment* our_DuplicatePigment(OurPigment* p){
 OurPigment* our_DuplicatePigment(OurPigment* p){
     OurPigment* np=memAcquireHyper(sizeof(OurPigment));
     OurPigment* np=memAcquireHyper(sizeof(OurPigment));
+    memcpy(np,p,sizeof(OurPigment)); np->Item.pNext=np->Item.pPrev=0;
     np->Name=0; strSafePrint(&np->Name,"%s Copy",p->Name?p->Name->Ptr:"New Pigment");
     np->Name=0; strSafePrint(&np->Name,"%s Copy",p->Name?p->Name->Ptr:"New Pigment");
     lstInsertItemAfter(&Our->Pigments,np,p);
     lstInsertItemAfter(&Our->Pigments,np,p);
     memAssignRef(Our, &Our->CurrentPigment, np);
     memAssignRef(Our, &Our->CurrentPigment, np);
+    our_PigmentToPreviewSelf(&np->Pigment);
     return np;
     return np;
 }
 }
 
 
@@ -2807,7 +2887,8 @@ int our_PaintGetDabs(OurBrush* b, OurLayer* l, real x, real y, real xto, real yt
     b->BrushRemainingDist=alllen-uselen;
     b->BrushRemainingDist=alllen-uselen;
     if(Our->NextDab) {
     if(Our->NextDab) {
         our_LayerEnsureTiles(l,xmin,xmax,ymin,ymax,0,tl,tr,tu,tb);
         our_LayerEnsureTiles(l,xmin,xmax,ymin,ymax,0,tl,tr,tu,tb);
-        Our->xmin=TNS_MIN2(Our->xmin,xmin);Our->xmax=TNS_MAX2(Our->xmax,xmax);Our->ymin=TNS_MIN2(Our->ymin,ymin);Our->ymax=TNS_MAX2(Our->ymax,ymax);
+        int pxw=Our->PigmentMode?1:0;
+        Our->xmin=TNS_MIN2(Our->xmin,xmin);Our->xmax=TNS_MAX2(Our->xmax,xmax+pxw);Our->ymin=TNS_MIN2(Our->ymin,ymin);Our->ymax=TNS_MAX2(Our->ymax,ymax+pxw);
         return 1; 
         return 1; 
     }
     }
     return 0;
     return 0;
@@ -3495,7 +3576,7 @@ int ourinv_RemoveUsePigment(laOperator* a, laEvent* e){
     OurPigment* p=a->This?a->This->EndInstance:0; if(!p) return LA_CANCELED;
     OurPigment* p=a->This?a->This->EndInstance:0; if(!p) return LA_CANCELED;
     our_RemoveUsePigment(p); laNotifyUsers("our.canvas.use_pigments");
     our_RemoveUsePigment(p); laNotifyUsers("our.canvas.use_pigments");
     laRecordInstanceDifferences(Our,"our.canvas.use_pigments"); laPushDifferences("Remove uses pigment",0);
     laRecordInstanceDifferences(Our,"our.canvas.use_pigments"); laPushDifferences("Remove uses pigment",0);
-    return LA_RUNNING;
+    return LA_FINISH;
 }
 }
 
 
 void ourset_ChooseCanvasSurface(void* unsed, OurCanvasSurface* cs);
 void ourset_ChooseCanvasSurface(void* unsed, OurCanvasSurface* cs);
@@ -3852,51 +3933,67 @@ int ourinv_CropToRef(laOperator* a, laEvent* e){
     return LA_FINISHED;
     return LA_FINISHED;
 }
 }
 
 
-OurColorPallette* our_NewPallette(char* Name){
-    OurColorPallette* cp=memAcquireHyper(sizeof(OurColorPallette));
-    strSafeSet(&cp->Name,Name); lstAppendItem(&Our->Pallettes,cp); memAssignRef(Our,&Our->CurrentPallette,cp);
+OurColorPalette* our_NewPalette(char* Name){
+    OurColorPalette* cp=memAcquireHyper(sizeof(OurColorPalette));
+    strSafeSet(&cp->Name,Name); lstAppendItem(&Our->Palettes,cp); memAssignRef(Our,&Our->CurrentPalette,cp);
+    laRecordDifferences(0,"our.tools.pallettes"); laPushDifferences("New Palette",0);
     return cp;
     return cp;
 }
 }
-OurColorItem* our_PalletteNewColor(OurColorPallette* cp,tnsVector3d Color){
+OurColorItem* our_PaletteNewColor(OurColorPalette* cp,tnsVector3d Color){
     OurColorItem* ci=memAcquire(sizeof(OurColorItem)); memAssignRef(ci,&ci->Parent,cp);
     OurColorItem* ci=memAcquire(sizeof(OurColorItem)); memAssignRef(ci,&ci->Parent,cp);
-    tnsVectorSet3v(ci->Color,Color); lstAppendItem(&cp->Colors,ci); return ci;
-    laMarkMemChanged(cp);
+    if(Our->PigmentMode){ memcpy(&ci->Pigment,&Our->MixedPigment,sizeof(OurPigmentData)); ci->IsPigment=1; }
+    else{ tnsVectorSet3v(ci->Pigment.PreviewColor[0],Color); }
+    lstAppendItem(&cp->Colors,ci); return ci;
+    laMarkMemChanged(cp); laRecordInstanceDifferences(cp,"our_pallette"); laPushDifferences("New Color",0);
 }
 }
-void our_PalletteRemoveColor(OurColorItem* ci){
-    lstRemoveItem(&ci->Parent->Colors,ci); memLeave(ci); laMarkMemChanged(ci->Parent);
+void our_PaletteRemoveColor(OurColorItem* ci){
+    lstRemoveItem(&ci->Parent->Colors,ci); laMarkMemChanged(ci->Parent); memLeave(ci); laMarkMemChanged(ci->Parent);
 }
 }
-void our_RemovePallette(OurColorPallette* cp){
-    strSafeDestroy(&cp->Name); while(cp->Colors.pFirst){ our_PalletteRemoveColor(cp->Colors.pFirst); }
-    if(Our->CurrentPallette==cp){
-        if(cp->Item.pNext){ memAssignRef(Our,&Our->CurrentPallette,cp->Item.pNext); }
-        else { memAssignRef(Our,&Our->CurrentPallette,cp->Item.pPrev); }
+void our_RemovePalette(OurColorPalette* cp){
+    strSafeDestroy(&cp->Name); while(cp->Colors.pFirst){ our_PaletteRemoveColor(cp->Colors.pFirst); }
+    if(Our->CurrentPalette==cp){
+        if(cp->Item.pNext){ memAssignRef(Our,&Our->CurrentPalette,cp->Item.pNext); }
+        else { memAssignRef(Our,&Our->CurrentPalette,cp->Item.pPrev); }
     }
     }
-    lstRemoveItem(&Our->Pallettes,cp); memLeave(cp);
+    lstRemoveItem(&Our->Palettes,cp); memLeave(cp);
 }
 }
 
 
-int ourinv_NewPallette(laOperator* a, laEvent* e){
-    our_NewPallette("Our Pallette");
+int ourinv_NewPalette(laOperator* a, laEvent* e){
+    our_NewPalette("Our Palette");
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Add pallette",0);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Add pallette",0);
     return LA_FINISHED;
     return LA_FINISHED;
 }
 }
-int ourinv_RemovePallette(laOperator* a, laEvent* e){
-    OurColorPallette* cp=Our->CurrentPallette; if(a->This && a->This->EndInstance){ cp=a->This->EndInstance; }
+int ourinv_RemovePalette(laOperator* a, laEvent* e){
+    OurColorPalette* cp=Our->CurrentPalette; if(a->This && a->This->EndInstance){ cp=a->This->EndInstance; }
     if(!cp) return LA_FINISHED;
     if(!cp) return LA_FINISHED;
-    our_RemovePallette(cp);
-    laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Remove pallette",0);
-    return LA_FINISHED;
+    char buf[512]; sprintf(buf,"%s \"%s\"",transLate("Will remove palette"),SSTR(cp->Name));
+    laEnableYesNoPanel(a,0,"Confirm?",buf,e->x,e->y,200,e);
+    return LA_RUNNING;
 }
 }
-int ourinv_PalletteNewColor(laOperator* a, laEvent* e){
-    OurColorPallette* cp=Our->CurrentPallette; if(a->This && a->This->EndInstance){ cp=a->This->EndInstance; }
+int ourmod_RemovePalette(laOperator* a, laEvent* e){
+    OurColorPalette* cp=Our->CurrentPalette; if(a->This && a->This->EndInstance){ cp=a->This->EndInstance; }
     if(!cp) return LA_FINISHED;
     if(!cp) return LA_FINISHED;
-    our_PalletteNewColor(cp,Our->CurrentColor);
+    if(a->ConfirmData){
+        if(a->ConfirmData->Mode == LA_CONFIRM_OK){
+            our_RemovePalette(cp);
+            laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); 
+            laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Remove pallette",0);
+        }
+        return LA_FINISHED;
+    }
+    return LA_RUNNING;
+}
+int ourinv_PaletteNewColor(laOperator* a, laEvent* e){
+    OurColorPalette* cp=Our->CurrentPalette; if(a->This && a->This->EndInstance){ cp=a->This->EndInstance; }
+    if(!cp) return LA_FINISHED;
+    our_PaletteNewColor(cp,Our->CurrentColor);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Add color",0);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Add color",0);
     return LA_FINISHED;
     return LA_FINISHED;
 }
 }
-int ourinv_PalletteRemoveColor(laOperator* a, laEvent* e){
+int ourinv_PaletteRemoveColor(laOperator* a, laEvent* e){
     OurColorItem* ci=0; if(a->This && a->This->EndInstance){ ci=a->This->EndInstance; }
     OurColorItem* ci=0; if(a->This && a->This->EndInstance){ ci=a->This->EndInstance; }
     if(!ci) return LA_FINISHED;
     if(!ci) return LA_FINISHED;
-    our_PalletteRemoveColor(ci);
+    our_PaletteRemoveColor(ci);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Remove pallette",0);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes"); laRecordInstanceDifferences(Our,"our_tools"); laPushDifferences("Remove pallette",0);
     return LA_FINISHED;
     return LA_FINISHED;
 }
 }
@@ -3955,7 +4052,7 @@ int ourgetstate_H2Modified(void* any){
     if(m->Modified || !m->FromFile) return LA_BT_WARNING;
     if(m->Modified || !m->FromFile) return LA_BT_WARNING;
     return -1;
     return -1;
 }
 }
-int ourgetstate_Pallette(OurColorPallette* pallette){
+int ourgetstate_Palette(OurColorPalette* pallette){
     int level; laMemNodeHyper* m=memGetHead(pallette,&level); if(!m || level!=2) return -1;
     int level; laMemNodeHyper* m=memGetHead(pallette,&level); if(!m || level!=2) return -1;
     if(m->Modified || !m->FromFile) return LA_BT_WARNING;
     if(m->Modified || !m->FromFile) return LA_BT_WARNING;
     return -1;
     return -1;
@@ -3980,8 +4077,8 @@ void* ourget_FirstBrush(void* unused, void* unused1){
 void* ourget_FirstPigment(void* unused, void* unused1){
 void* ourget_FirstPigment(void* unused, void* unused1){
     return Our->Pigments.pFirst;
     return Our->Pigments.pFirst;
 }
 }
-void* ourget_FirstPallette(void* unused, void* unused1){
-    return Our->Pallettes.pFirst;
+void* ourget_FirstPalette(void* unused, void* unused1){
+    return Our->Palettes.pFirst;
 }
 }
 void* ourget_our(void* unused, void* unused1){
 void* ourget_our(void* unused, void* unused1){
     return Our;
     return Our;
@@ -4207,6 +4304,7 @@ void ourset_LayerPosition(OurLayer* l, int* xy){
 }
 }
 void ourreset_Canvas(OurPaint* op){
 void ourreset_Canvas(OurPaint* op){
     while(op->Layers.pFirst){ our_RemoveLayer(op->Layers.pFirst,1); }
     while(op->Layers.pFirst){ our_RemoveLayer(op->Layers.pFirst,1); }
+    while(op->UsePigments.pFirst){ our_RemoveUsePigment(op->UsePigments.pFirst); }
 }
 }
 void ourreset_Preferences(OurPaint* op){
 void ourreset_Preferences(OurPaint* op){
     return; //does nothing.
     return; //does nothing.
@@ -4215,7 +4313,7 @@ void ourpropagate_Tools(OurPaint* p, laUDF* udf, int force){
     for(OurBrush* b=p->Brushes.pFirst;b;b=b->Item.pNext){
     for(OurBrush* b=p->Brushes.pFirst;b;b=b->Item.pNext){
         if(force || !laget_InstanceActiveUDF(b)){ laset_InstanceUDF(b, udf); }
         if(force || !laget_InstanceActiveUDF(b)){ laset_InstanceUDF(b, udf); }
     }
     }
-    for(OurColorPallette* cp=p->Pallettes.pFirst;cp;cp=cp->Item.pNext){
+    for(OurColorPalette* cp=p->Palettes.pFirst;cp;cp=cp->Item.pNext){
         if(force || !laget_InstanceActiveUDF(cp)){ laset_InstanceUDF(cp, udf); }
         if(force || !laget_InstanceActiveUDF(cp)){ laset_InstanceUDF(cp, udf); }
     }
     }
 }
 }
@@ -4241,14 +4339,25 @@ void ourset_CurrentPigment(void* unused, OurPigment* p){
 void ourset_CurrentLayer(void* unused, OurLayer*l){
 void ourset_CurrentLayer(void* unused, OurLayer*l){
     memAssignRef(Our, &Our->CurrentLayer, l); laNotifyUsers("our.canvas_notify");
     memAssignRef(Our, &Our->CurrentLayer, l); laNotifyUsers("our.canvas_notify");
 }
 }
-void ourset_CurrentPallette(void* unused, OurColorPallette* cp){
-    memAssignRef(Our,&Our->CurrentPallette,cp);
+void ourset_CurrentPalette(void* unused, OurColorPalette* cp){
+    memAssignRef(Our,&Our->CurrentPalette,cp);
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes");
     laNotifyUsers("our.tools.current_pallette"); laNotifyUsers("our.tools.pallettes");
 }
 }
-void ourset_PalletteColor(void* unused, OurColorItem* ci){
-    tnsVectorSet3v(Our->CurrentColor,ci->Color);
+void ourset_PaletteColor(void* unused, OurColorItem* ci){
+    memcpy(&Our->MixedPigment,&ci->Pigment,sizeof(OurPigmentData));
+    tnsVectorSet3v(Our->CurrentColor,ci->Pigment.PreviewColor[0]);
     laNotifyUsers("our.current_color");
     laNotifyUsers("our.current_color");
 }
 }
+int ourfilter_PaletteColorItem(void* unused, OurColorItem* ci){
+    if(Our->PigmentMode){ if(ci->IsPigment) { return 1; } }
+    else                { if(!ci->IsPigment){ return 1; } }
+    return 0;
+}
+void ourundotouched_PaletteColorItem(OurColorItem* ci, int hint){
+    if(Our->PigmentMode && ci->IsPigment){
+        our_PigmentToPreviewSelf(&ci->Pigment);
+    }
+}
 float ourget_ColorBoost(void* unused){
 float ourget_ColorBoost(void* unused){
     return tnsLength3d(Our->CurrentColor);
     return tnsLength3d(Our->CurrentColor);
 }
 }
@@ -4365,6 +4474,7 @@ void ourui_MenuButtons(laUiList *uil, laPropPack *pp, laPropPack *actinst, laCol
         mc = laFirstColumn(muil); laui_DefaultMenuButtonsEditEntries(muil,pp,actinst,extracol,0);
         mc = laFirstColumn(muil); laui_DefaultMenuButtonsEditEntries(muil,pp,actinst,extracol,0);
         laShowSeparator(muil,mc);
         laShowSeparator(muil,mc);
         laShowLabel(muil,mc,"Canvas",0,0)->Flags|=LA_UI_FLAGS_DISABLED;
         laShowLabel(muil,mc,"Canvas",0,0)->Flags|=LA_UI_FLAGS_DISABLED;
+        laShowItemFull(muil, mc, 0, "LA_panel_activator", 0, "panel_id=panel_canvas_properties;", 0, 0);
         laUiItem* row=laBeginRow(muil,mc,0,0);
         laUiItem* row=laBeginRow(muil,mc,0,0);
         laShowItem(muil,mc,0,"OUR_clear_empty_tiles");
         laShowItem(muil,mc,0,"OUR_clear_empty_tiles");
         laShowItemFull(muil,mc,0,"our.preferences.show_debug_tiles",LA_WIDGET_ENUM_HIGHLIGHT,"text=👁",0,0);
         laShowItemFull(muil,mc,0,"our.preferences.show_debug_tiles",LA_WIDGET_ENUM_HIGHLIGHT,"text=👁",0,0);
@@ -4657,10 +4767,10 @@ void ourRegisterEverything(){
 
 
     laCreateOperatorType("OUR_crop_to_ref","Crop To Ref","Crop to reference lines",ourchk_CropToRef,0,0,ourinv_CropToRef,0,0,0);
     laCreateOperatorType("OUR_crop_to_ref","Crop To Ref","Crop to reference lines",ourchk_CropToRef,0,0,ourinv_CropToRef,0,0,0);
 
 
-    laCreateOperatorType("OUR_new_pallette","New Pallette","New pallette",0,0,0,ourinv_NewPallette,0,'+',0);
-    laCreateOperatorType("OUR_remove_pallette","Remove Pallette","Remove selected pallette",0,0,0,ourinv_RemovePallette,0,U'🗴',0);
-    laCreateOperatorType("OUR_pallette_new_color","New Color","New color in this pallette",0,0,0,ourinv_PalletteNewColor,0,'+',0);
-    laCreateOperatorType("OUR_pallette_remove_color","Remove Color","Remove this color from the pallette",0,0,0,ourinv_PalletteRemoveColor,0,U'🗴',0);
+    laCreateOperatorType("OUR_new_pallette","New Palette","New pallette",0,0,0,ourinv_NewPalette,0,'+',0);
+    laCreateOperatorType("OUR_remove_pallette","Remove Palette","Remove selected pallette",0,0,0,ourinv_RemovePalette,ourmod_RemovePalette,U'🗴',0);
+    laCreateOperatorType("OUR_pallette_new_color","New Color","New color in this pallette",0,0,0,ourinv_PaletteNewColor,0,L'⇊',0);
+    laCreateOperatorType("OUR_pallette_remove_color","Remove Color","Remove this color from the pallette",0,0,0,ourinv_PaletteRemoveColor,0,U'🗴',0);
 
 
     laCreateOperatorType("OUR_clear_empty_tiles","Clear Empty Tiles","Clear empty tiles in this image",0,0,0,ourinv_ClearEmptyTiles,0,U'🧹',0);
     laCreateOperatorType("OUR_clear_empty_tiles","Clear Empty Tiles","Clear empty tiles in this image",0,0,0,ourinv_ClearEmptyTiles,0,U'🧹',0);
 
 
@@ -4674,8 +4784,8 @@ void ourRegisterEverything(){
     laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0, GL_RGBA16F,0,0);
     laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0, GL_RGBA16F,0,0);
     laRegisterUiTemplate("panel_notes", "Notes", ourui_NotesPanel, 0, 0,0, 0,15,15);
     laRegisterUiTemplate("panel_notes", "Notes", ourui_NotesPanel, 0, 0,0, 0,15,15);
     laRegisterUiTemplate("panel_canvas_properties", "Canvas Properties", ourui_CanvasPropertiesPanel,0,0,"Customizations",0,15,15);
     laRegisterUiTemplate("panel_canvas_properties", "Canvas Properties", ourui_CanvasPropertiesPanel,0,0,"Customizations",0,15,15);
-    laRegisterUiTemplate("panel_pigments", "Pigments", ourui_PigmentsPreviewPanel, 0, 0,0, GL_RGBA16F,20,25);
-    laRegisterUiTemplate("panel_pallettes", "Pallettes", ourui_PallettesPanel, 0, 0,0, GL_RGBA16F,0,0);
+    laRegisterUiTemplate("panel_pigments", "Pigments", ourui_PigmentsPreviewPanel, 0, 0,0, GL_RGBA16F,20,27);
+    laRegisterUiTemplate("panel_pallettes", "Palettes", ourui_PalettesPanel, 0, 0,0, GL_RGBA16F,0,0);
     laRegisterUiTemplate("panel_brush_nodes", "Brush Nodes", ourui_BrushPage, 0, 0,0, 0,230,30);
     laRegisterUiTemplate("panel_brush_nodes", "Brush Nodes", ourui_BrushPage, 0, 0,0, 0,230,30);
     
     
     pc=laDefineRoot();
     pc=laDefineRoot();
@@ -4732,7 +4842,7 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"D65_P3","D65 P3","Convert pixels into non-linear D65 P3",OUR_EXPORT_COLOR_MODE_D65_P3,0);
     laAddEnumItemAs(p,"D65_P3","D65 P3","Convert pixels into non-linear D65 P3",OUR_EXPORT_COLOR_MODE_D65_P3,0);
     laAddIntProperty(pc,"paint_undo_limit","Paint Undo Limit","Undo step limit for painting actions.",0,0," Steps",256,5,1,100,0,offsetof(OurPaint,PaintUndoLimit),0,0,0,0,0,0,0,0,0,0,0);
     laAddIntProperty(pc,"paint_undo_limit","Paint Undo Limit","Undo step limit for painting actions.",0,0," Steps",256,5,1,100,0,offsetof(OurPaint,PaintUndoLimit),0,0,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"canvas_default_scale","Canvas Default Scale","Default scale of the canvas",0,0,0,4,0.25,0.1,0.5,0,offsetof(OurPaint,DefaultScale),0,0,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"canvas_default_scale","Canvas Default Scale","Default scale of the canvas",0,0,0,4,0.25,0.1,0.5,0,offsetof(OurPaint,DefaultScale),0,0,0,0,0,0,0,0,0,0,0);
-    p=laAddEnumProperty(pc,"spectral_mode","Spectral Brush","Use spectral mixing in brush strokes",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,SpectralMode),0,0,0,0,0,0,0,0,0,0);
+    p=laAddEnumProperty(pc,"spectral_mode","Spectral Mixing","Use spectral mixing in brush strokes",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,SpectralMode),0,0,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"NONE","None","Use regular RGB mixing for brushes",0,0);
     laAddEnumItemAs(p,"NONE","None","Use regular RGB mixing for brushes",0,0);
     laAddEnumItemAs(p,"SPECTRAL","Spectral","Use spectral mixing for brushes",1,0);
     laAddEnumItemAs(p,"SPECTRAL","Spectral","Use spectral mixing for brushes",1,0);
     p=laAddEnumProperty(pc,"brush_numbers_on_header","Brush Numbers","Show brush numbers on header",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,BrushNumbersOnHeader),0,0,0,0,0,0,0,0,0,0);
     p=laAddEnumProperty(pc,"brush_numbers_on_header","Brush Numbers","Show brush numbers on header",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0,0,offsetof(OurPaint,BrushNumbersOnHeader),0,0,0,0,0,0,0,0,0,0);
@@ -4786,14 +4896,23 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"DEBAYER","Debayer","Interpolate channels from pigment canvas to display color at pixel level resolution",1,0);
     laAddEnumItemAs(p,"DEBAYER","Debayer","Interpolate channels from pigment canvas to display color at pixel level resolution",1,0);
     laAddEnumItemAs(p,"SHARP","Sharp","Using two times resolution for the view buffer to store converted color information",2,0);
     laAddEnumItemAs(p,"SHARP","Sharp","Using two times resolution for the view buffer to store converted color information",2,0);
     laAddEnumItemAs(p,"QUALITY","Quality","Using two times resolution for the view buffer and do 4x supersampled debayer average",3,0);
     laAddEnumItemAs(p,"QUALITY","Quality","Using two times resolution for the view buffer and do 4x supersampled debayer average",3,0);
+    p=laAddEnumProperty(pc,"reorder_pigments","Ordering Pigments","Reorder pigments (Only for UI state)",0,0,0,0,0,offsetof(OurPaint,ReorderPigmnets),0,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
+    laAddEnumItemAs(p,"NONE","None","Display pigments list",0,0);
+    laAddEnumItemAs(p,"REODERING","Reordering","Reordering pigments",1,0);
+    p=laAddEnumProperty(pc,"palette_in_colors_panel","Show Palette","Show palette in colors panel",0,0,0,0,0,offsetof(OurPaint,PaletteInColorsPanel),0,0,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"NONE","None","Don't display palette in colors panel",0,0);
+    laAddEnumItemAs(p,"SHOWN","Shown","Show palette in colors panel",1,0);
+    p=laAddEnumProperty(pc,"default_canvas_type","Default Canvas Type","Default canvas type",0,0,0,0,0,offsetof(OurPaint,DefaultCanvasType),0,0,0,0,0,0,0,0,0,0);
+    laAddEnumItemAs(p,"RGBA","RGBA","Use RGBA Canvas as default",0,0);
+    laAddEnumItemAs(p,"Pigment","Pigment","Use Pigment Canvas as default",1,0);
     
     
     pc=laAddPropertyContainer("our_tools","Our Tools","OurPaint tools",0,0,sizeof(OurPaint),0,0,1);
     pc=laAddPropertyContainer("our_tools","Our Tools","OurPaint tools",0,0,sizeof(OurPaint),0,0,1);
     laPropContainerExtraFunctions(pc,0,0,0,ourpropagate_Tools,0);
     laPropContainerExtraFunctions(pc,0,0,0,ourpropagate_Tools,0);
     sp=laAddSubGroup(pc,"brushes","Brushes","Brushes","our_brush",0,0,ourui_Brush,offsetof(OurPaint,CurrentBrush),0,0,0,ourset_CurrentBrush,ourgetstate_H2Modified,0,offsetof(OurPaint,Brushes),0);
     sp=laAddSubGroup(pc,"brushes","Brushes","Brushes","our_brush",0,0,ourui_Brush,offsetof(OurPaint,CurrentBrush),0,0,0,ourset_CurrentBrush,ourgetstate_H2Modified,0,offsetof(OurPaint,Brushes),0);
     sp->UiFilter=ourfilter_BrushInPage;
     sp->UiFilter=ourfilter_BrushInPage;
     laAddSubGroup(pc,"current_brush","Current Brush","Current brush","our_brush",0,0,0,offsetof(OurPaint,CurrentBrush),ourget_FirstBrush,0,laget_ListNext,ourset_CurrentBrush,0,0,0,LA_UDF_REFER);
     laAddSubGroup(pc,"current_brush","Current Brush","Current brush","our_brush",0,0,0,offsetof(OurPaint,CurrentBrush),ourget_FirstBrush,0,laget_ListNext,ourset_CurrentBrush,0,0,0,LA_UDF_REFER);
-    laAddSubGroup(pc,"pallettes","Pallettes","Pallettes","our_pallette",0,0,ourui_Pallette,offsetof(OurPaint,CurrentPallette),0,0,0,ourset_CurrentPallette,ourgetstate_Pallette,0,offsetof(OurPaint,Pallettes),0);
-    laAddSubGroup(pc,"current_pallette","Current Pallette","Current pallette","our_pallette",0,0,0,offsetof(OurPaint,CurrentPallette),ourget_FirstPallette,0,laget_ListNext,ourset_CurrentPallette,0,0,0,LA_UDF_REFER);
+    laAddSubGroup(pc,"pallettes","Palettes","Palettes","our_pallette",0,0,ourui_Palette,offsetof(OurPaint,CurrentPalette),0,0,0,ourset_CurrentPalette,ourgetstate_Palette,0,offsetof(OurPaint,Palettes),0);
+    laAddSubGroup(pc,"current_pallette","Current Palette","Current pallette","our_pallette",0,0,0,offsetof(OurPaint,CurrentPalette),ourget_FirstPalette,0,laget_ListNext,ourset_CurrentPalette,0,0,0,LA_UDF_REFER);
     laAddSubGroup(pc,"pigments","Pigments","Pigments","our_pigment",0,0,ourui_PigmentItem,offsetof(OurPaint,CurrentPigment),0,0,0,ourset_CurrentPigment,ourgetstate_H2Modified,0,offsetof(OurPaint,Pigments),0);
     laAddSubGroup(pc,"pigments","Pigments","Pigments","our_pigment",0,0,ourui_PigmentItem,offsetof(OurPaint,CurrentPigment),0,0,0,ourset_CurrentPigment,ourgetstate_H2Modified,0,offsetof(OurPaint,Pigments),0);
     laAddSubGroup(pc,"current_pigment","Current Pigment","Current pigment","our_pigment",0,0,ourui_PigmentDetails,offsetof(OurPaint,CurrentPigment),ourget_FirstPigment,0,laget_ListNext,ourset_CurrentPigment,0,0,0,LA_UDF_REFER);
     laAddSubGroup(pc,"current_pigment","Current Pigment","Current pigment","our_pigment",0,0,ourui_PigmentDetails,offsetof(OurPaint,CurrentPigment),ourget_FirstPigment,0,laget_ListNext,ourset_CurrentPigment,0,0,0,LA_UDF_REFER);
     laAddSubGroup(pc,"lights","Lights","Lights","our_light",0,0,ourui_LightItem,-1,0,0,0,0,ourgetstate_H2Modified,0,offsetof(OurPaint,Lights),0);
     laAddSubGroup(pc,"lights","Lights","Lights","our_light",0,0,ourui_LightItem,-1,0,0,0,0,ourgetstate_H2Modified,0,offsetof(OurPaint,Lights),0);
@@ -4807,7 +4926,6 @@ void ourRegisterEverything(){
     laAddFloatProperty(pc,"absorption","Absorption","Spectral absorption of the pigment",0,wavelengths,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Absorption),0,0,OUR_SPECTRAL_SLICES,0,0,0,0,ourset_Absorption,0,0,0);
     laAddFloatProperty(pc,"absorption","Absorption","Spectral absorption of the pigment",0,wavelengths,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Absorption),0,0,OUR_SPECTRAL_SLICES,0,0,0,0,ourset_Absorption,0,0,0);
     laAddFloatProperty(pc,"reflectance_density","Density","Spectral reflectance of the pigment",0,0,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Reflectance[15]),0,ourset_ReflectanceDensity,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"reflectance_density","Density","Spectral reflectance of the pigment",0,0,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Reflectance[15]),0,ourset_ReflectanceDensity,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"absorption_density","Density","Spectral absorption of the pigment",0,0,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Absorption[15]),0,ourset_AbsorptionDensity,0,0,0,0,0,0,0,0,0);
     laAddFloatProperty(pc,"absorption_density","Density","Spectral absorption of the pigment",0,0,0,1,0,0.05,0.5,0,offsetof(OurPigmentData,Absorption[15]),0,ourset_AbsorptionDensity,0,0,0,0,0,0,0,0,0);
-    //laAddFloatProperty(pc,"display_color","Display Color","Color to display on the interface",0,0,0,1,0,0.05,0.8,0,offsetof(OurPigmentData,DisplayColor),0,0,3,0,0,0,0,0,0,0,LA_READ_ONLY);
     laAddStringProperty(pc,"info","Info","Information of this pigment",0,0,0,0,0,0,0,ourget_PigmentInfo,0,0,LA_UDF_IGNORE|LA_READ_ONLY);
     laAddStringProperty(pc,"info","Info","Information of this pigment",0,0,0,0,0,0,0,ourget_PigmentInfo,0,0,LA_UDF_IGNORE|LA_READ_ONLY);
 
 
     pc=laAddPropertyContainer("our_pigment","Our Pigment","OurPaint pigment",0,0,sizeof(OurPigment),0,0,2);
     pc=laAddPropertyContainer("our_pigment","Our Pigment","OurPaint pigment",0,0,sizeof(OurPigment),0,0,2);
@@ -4820,6 +4938,7 @@ void ourRegisterEverything(){
     pc=laAddPropertyContainer("our_use_pigment","Our Use Pigment","OurPaint Use Pigment",0,0,sizeof(OurUsePigment),0,0,1);
     pc=laAddPropertyContainer("our_use_pigment","Our Use Pigment","OurPaint Use Pigment",0,0,sizeof(OurUsePigment),0,0,1);
     laAddSubGroup(pc,"pigment","Pigment","Referencing Pigment","our_pigment",0,0,0,offsetof(OurUsePigment,pigment),ourget_FirstPigment,0,laget_ListNext,ourset_UsePigmentPigment,0,0,0,LA_UDF_REFER);
     laAddSubGroup(pc,"pigment","Pigment","Referencing Pigment","our_pigment",0,0,0,offsetof(OurUsePigment,pigment),ourget_FirstPigment,0,laget_ListNext,ourset_UsePigmentPigment,0,0,0,LA_UDF_REFER);
     laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,ourset_UsePigmentMove,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
     laAddIntProperty(pc,"__move","Move Slider","Move Slider",LA_WIDGET_HEIGHT_ADJUSTER,0,0,0,0,0,0,0,0,0,ourset_UsePigmentMove,0,0,0,0,0,0,0,0,LA_UDF_IGNORE);
+    laAddOperatorProperty(pc,"remove","Remove","Stop using this pigment","OUR_remove_use_pigment",U'🗴',0);
 
 
     pc=laAddPropertyContainer("our_light","Our Light","OurPaint light",0,0,sizeof(OurLight),0,0,2);
     pc=laAddPropertyContainer("our_light","Our Light","OurPaint light",0,0,sizeof(OurLight),0,0,2);
     laAddStringProperty(pc,"name","Name","Name of the light",0,0,0,0,1,offsetof(OurLight,Name),0,0,0,0,LA_AS_IDENTIFIER);
     laAddStringProperty(pc,"name","Name","Name of the light",0,0,0,0,1,offsetof(OurLight,Name),0,0,0,0,LA_AS_IDENTIFIER);
@@ -4890,13 +5009,17 @@ void ourRegisterEverything(){
     laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",U'🗴',0);
     laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",U'🗴',0);
     laAddOperatorProperty(pc,"duplicate","Duplicate","Duplicate brush","OUR_duplicate_brush",U'⎘',0);
     laAddOperatorProperty(pc,"duplicate","Duplicate","Duplicate brush","OUR_duplicate_brush",U'⎘',0);
 
 
-    pc=laAddPropertyContainer("our_pallette","Our Pallette","OurPaint pallette",0,0,sizeof(OurColorPallette),0,0,2);
-    laAddStringProperty(pc,"name","Name","Name of this pallette",0,0,0,0,1,offsetof(OurColorPallette,Name),0,0,0,0,LA_AS_IDENTIFIER);
-    laAddSubGroup(pc,"colors","Colors","Colors in this pallette","our_color_item",0,0,0,-1,0,0,0,ourset_PalletteColor,0,0,offsetof(OurColorPallette,Colors),0);
+    pc=laAddPropertyContainer("our_pallette","Our Palette","OurPaint pallette",0,0,sizeof(OurColorPalette),0,0,2);
+    laAddStringProperty(pc,"name","Name","Name of this pallette",0,0,0,0,1,offsetof(OurColorPalette,Name),0,0,0,0,LA_AS_IDENTIFIER);
+    sp=laAddSubGroup(pc,"colors","Colors","Colors in this pallette","our_color_item",0,0,0,-1,0,0,0,ourset_PaletteColor,0,0,offsetof(OurColorPalette,Colors),0);
+        sp->UiFilter=ourfilter_PaletteColorItem;
 
 
     pc=laAddPropertyContainer("our_color_item","Our Color Item","OurPaint pallette color item",0,0,sizeof(OurColorItem),0,0,1);
     pc=laAddPropertyContainer("our_color_item","Our Color Item","OurPaint pallette color item",0,0,sizeof(OurColorItem),0,0,1);
-    laAddFloatProperty(pc,"color","Color","Color",LA_WIDGET_FLOAT_COLOR,0,0,0,0,0,0,0,offsetof(OurColorItem,Color),0,0,3,0,0,0,0,0,0,0,LA_PROP_IS_LINEAR_SRGB);
+        pc->UndoTouched=ourundotouched_PaletteColorItem;
+    laAddSubGroup(pc,"pigment","Pigment","Pigment info","our_pigment_data",0,0,0,offsetof(OurColorItem,Pigment),0,0,0,0,0,0,0,LA_UDF_LOCAL);
+    laAddFloatProperty(pc,"color","Color","Color",LA_WIDGET_FLOAT_COLOR,0,0,0,0,0,0,0,offsetof(OurColorItem,Pigment.PreviewColor[0]),0,0,3,0,0,0,0,0,0,0,LA_PROP_IS_LINEAR_SRGB);
     laAddSubGroup(pc,"parent","Parent","Parent pallette","our_pallette",0,0,0,offsetof(OurColorItem,Parent),0,0,0,0,0,0,0,LA_UDF_REFER|LA_READ_ONLY);
     laAddSubGroup(pc,"parent","Parent","Parent pallette","our_pallette",0,0,0,offsetof(OurColorItem,Parent),0,0,0,0,0,0,0,LA_UDF_REFER|LA_READ_ONLY);
+    laAddIntProperty(pc,"is_pigment","Is Pigment","Is this a pigment color",0,0,0,0,0,0,0,0,offsetof(OurColorItem,IsPigment),0,0,0,0,0,0,0,0,0,0,LA_READ_ONLY);
     laAddOperatorProperty(pc,"remove","Remove","Remove this color item","OUR_pallette_remove_color",U'🗴',0);
     laAddOperatorProperty(pc,"remove","Remove","Remove this color item","OUR_pallette_remove_color",U'🗴',0);
 
 
     pc=laAddPropertyContainer("our_canvas","Our Canvas","OurPaint canvas",0,0,sizeof(OurPaint),ourpost_Canvas,0,1);
     pc=laAddPropertyContainer("our_canvas","Our Canvas","OurPaint canvas",0,0,sizeof(OurPaint),ourpost_Canvas,0,1);
@@ -4960,6 +5083,10 @@ void ourRegisterEverything(){
     laAddEnumItemAs(p,"FULL","Full","Show sketch layers in full opacity",1,0);
     laAddEnumItemAs(p,"FULL","Full","Show sketch layers in full opacity",1,0);
     laAddEnumItemAs(p,"NONE","None","Show double page spread",2,0);
     laAddEnumItemAs(p,"NONE","None","Show double page spread",2,0);
     laAddSubGroup(pc,"use_pigments","Use Pigments","Pigments that are referenced in this canvas for color picker","our_use_pigment",0,0,0,-1,0,0,0,0,0,0,offsetof(OurPaint,UsePigments),0);
     laAddSubGroup(pc,"use_pigments","Use Pigments","Pigments that are referenced in this canvas for color picker","our_use_pigment",0,0,0,-1,0,0,0,0,0,0,offsetof(OurPaint,UsePigments),0);
+    laAddSubGroup(pc,"use_white","Use White","Preferred white pigment for color picker","our_pigment",0,0,ourui_PigmentItem,offsetof(OurPaint,UseWhite),ourget_FirstPigment,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
+    laAddSubGroup(pc,"use_black","Use Black","Preferred black pigment for color picker","our_pigment",0,0,ourui_PigmentItem,offsetof(OurPaint,UseBlack),ourget_FirstPigment,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
+    laAddSubGroup(pc,"set_use_white","Set Use White","Preferred white pigment for color picker","our_pigment",0,0,0,offsetof(OurPaint,UseWhite),0,0,0,0,0,0,0,LA_UDF_REFER|LA_UDF_IGNORE);
+    laAddSubGroup(pc,"set_use_black","Set Use Black","Preferred black pigment for color picker","our_pigment",0,0,0,offsetof(OurPaint,UseBlack),0,0,0,0,0,0,0,LA_UDF_REFER|LA_UDF_IGNORE);
     p=laAddEnumProperty(pc,"alpha_mode","Alpha Mode","How to associate alpha channel with color in RGBA canvas",0,0,0,0,0,offsetof(OurPaint,AlphaMode),0,ourset_AlphaMode,0,0,0,0,0,0,0,0);
     p=laAddEnumProperty(pc,"alpha_mode","Alpha Mode","How to associate alpha channel with color in RGBA canvas",0,0,0,0,0,offsetof(OurPaint,AlphaMode),0,ourset_AlphaMode,0,0,0,0,0,0,0,0);
     laAddEnumItemAs(p,"PREMULT","Premultiplied","Color values on canvas are pre-multiplied with alpha channel",0,0);
     laAddEnumItemAs(p,"PREMULT","Premultiplied","Color values on canvas are pre-multiplied with alpha channel",0,0);
     laAddEnumItemAs(p,"STRAIGHT","Straight","Color values are not associative with alpha values on canvas",1,0);
     laAddEnumItemAs(p,"STRAIGHT","Straight","Color values are not associative with alpha values on canvas",1,0);
@@ -5153,8 +5280,7 @@ static void android_ensure_asset_to_public_dir(char* asset_file){
 }
 }
 #endif
 #endif
 
 
-void ourGetUniforms(int CanvasProgram, int CompositionProgram){
-    if(CanvasProgram<0 || CompositionProgram<0) return;
+void ourGetUniforms(int CanvasProgram, int DisplayProgram, int CompositionProgram){
     OURU->uCanvasType=glGetUniformLocation(CanvasProgram,"uCanvasType");
     OURU->uCanvasType=glGetUniformLocation(CanvasProgram,"uCanvasType");
     OURU->uCanvasRandom=glGetUniformLocation(CanvasProgram,"uCanvasRandom");
     OURU->uCanvasRandom=glGetUniformLocation(CanvasProgram,"uCanvasRandom");
     OURU->uCanvasFactor=glGetUniformLocation(CanvasProgram,"uCanvasFactor");
     OURU->uCanvasFactor=glGetUniformLocation(CanvasProgram,"uCanvasFactor");
@@ -5190,13 +5316,19 @@ void ourGetUniforms(int CanvasProgram, int CompositionProgram){
     OURU->RoutineDoMixSpectral=glGetSubroutineIndex(CanvasProgram, GL_COMPUTE_SHADER, "DoMixSpectral");
     OURU->RoutineDoMixSpectral=glGetSubroutineIndex(CanvasProgram, GL_COMPUTE_SHADER, "DoMixSpectral");
 #endif
 #endif
 
 
-    OURU->uBlendMode=glGetUniformLocation(CompositionProgram,"uBlendMode");
-    OURU->uAlphaTop=glGetUniformLocation(CompositionProgram,"uAlphaTop");
-    OURU->uAlphaBottom=glGetUniformLocation(CompositionProgram,"uAlphaBottom");
-
 #ifndef LA_USE_GLES
 #ifndef LA_USE_GLES
     glGetProgramStageiv(CanvasProgram,GL_COMPUTE_SHADER,GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &OURU->SubroutineUniformLocations);
     glGetProgramStageiv(CanvasProgram,GL_COMPUTE_SHADER,GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS, &OURU->SubroutineUniformLocations);
 #endif
 #endif
+
+    if(DisplayProgram>=0){
+        OURU->uMixingTop=glGetUniformLocation(DisplayProgram,"MixingTop");
+    }
+
+    if(CompositionProgram>=0){
+        OURU->uBlendMode=glGetUniformLocation(CompositionProgram,"uBlendMode");
+        OURU->uAlphaTop=glGetUniformLocation(CompositionProgram,"uAlphaTop");
+        OURU->uAlphaBottom=glGetUniformLocation(CompositionProgram,"uAlphaBottom");
+    }
 }
 }
 
 
 int ourInit(){
 int ourInit(){
@@ -5247,23 +5379,31 @@ int ourInit(){
     glUniformBlockBinding(Our->CanvasPigmentProgram, Our->uboBrushPigmentLocation, 0);
     glUniformBlockBinding(Our->CanvasPigmentProgram, Our->uboBrushPigmentLocation, 0);
 
 
 
 
-    Our->CompositionShader = glCreateShader(GL_COMPUTE_SHADER);
+    Our->CompositionShader =         glCreateShader(GL_COMPUTE_SHADER);
     Our->CompositionStraightShader = glCreateShader(GL_COMPUTE_SHADER);
     Our->CompositionStraightShader = glCreateShader(GL_COMPUTE_SHADER);
-    const GLchar* source2 = strSub(OUR_COMPOSITION_SHADER,"#with OUR_SHADER_COMMON",OUR_SHADER_COMMON);
-    const GLchar* sources2[]= {versionstr, source2};
-    const GLchar* sources2a[]={versionstr, "#define OUR_STRAIGHT_ALPHA", source2};
+    Our->PigmentCompositionShader  = glCreateShader(GL_COMPUTE_SHADER);
+    const GLchar* source2 =  strSub(OUR_COMPOSITION_SHADER,"#with OUR_SHADER_COMMON",OUR_SHADER_COMMON);
+    const GLchar* source2p = strSub(OUR_PIGMENT_COMPOSITION_SHADER,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
+    const GLchar* sources2[]=  {versionstr, source2};
+    const GLchar* sources2a[]= {versionstr, "#define OUR_STRAIGHT_ALPHA", source2};
+    const GLchar* sources2p[]= {versionstr, source2p};
     glShaderSource(Our->CompositionShader, 2, sources2, NULL);          glCompileShader(Our->CompositionShader);
     glShaderSource(Our->CompositionShader, 2, sources2, NULL);          glCompileShader(Our->CompositionShader);
     glShaderSource(Our->CompositionStraightShader, 3, sources2a, NULL); glCompileShader(Our->CompositionStraightShader);
     glShaderSource(Our->CompositionStraightShader, 3, sources2a, NULL); glCompileShader(Our->CompositionStraightShader);
+    glShaderSource(Our->PigmentCompositionShader,  2, sources2p, NULL); glCompileShader(Our->PigmentCompositionShader);
     tnsCheckShaderCompileStatus(Our->CompositionShader,"Composition");
     tnsCheckShaderCompileStatus(Our->CompositionShader,"Composition");
     tnsCheckShaderCompileStatus(Our->CompositionStraightShader,"Composition Straight");
     tnsCheckShaderCompileStatus(Our->CompositionStraightShader,"Composition Straight");
-    if(source2) free(source2);
+    tnsCheckShaderCompileStatus(Our->PigmentCompositionShader,"Pigment Composition");
+    if(source2) free(source2); if(source2p) free(source2p);
 
 
     Our->CompositionProgram =         glCreateProgram();
     Our->CompositionProgram =         glCreateProgram();
     Our->CompositionStraightProgram = glCreateProgram();
     Our->CompositionStraightProgram = glCreateProgram();
+    Our->PigmentCompositionProgram  = glCreateProgram();
     glAttachShader(Our->CompositionProgram, Our->CompositionShader);                 glLinkProgram(Our->CompositionProgram);
     glAttachShader(Our->CompositionProgram, Our->CompositionShader);                 glLinkProgram(Our->CompositionProgram);
     glAttachShader(Our->CompositionStraightProgram, Our->CompositionStraightShader); glLinkProgram(Our->CompositionStraightProgram);
     glAttachShader(Our->CompositionStraightProgram, Our->CompositionStraightShader); glLinkProgram(Our->CompositionStraightProgram);
+    glAttachShader(Our->PigmentCompositionProgram, Our->PigmentCompositionShader);   glLinkProgram(Our->PigmentCompositionProgram);
     tnsCheckProgramLinkStatus(Our->CompositionProgram,"Composition");
     tnsCheckProgramLinkStatus(Our->CompositionProgram,"Composition");
     tnsCheckProgramLinkStatus(Our->CompositionStraightProgram,"Composition Straight");
     tnsCheckProgramLinkStatus(Our->CompositionStraightProgram,"Composition Straight");
+    tnsCheckProgramLinkStatus(Our->PigmentCompositionProgram,"Pigment Composition");
 
 
     Our->PigmentLayeringShader = glCreateShader(GL_FRAGMENT_SHADER);
     Our->PigmentLayeringShader = glCreateShader(GL_FRAGMENT_SHADER);
     const GLchar* source3 = strSub(OUR_PIGMENT_TEXTURE_MIX_SHADER,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
     const GLchar* source3 = strSub(OUR_PIGMENT_TEXTURE_MIX_SHADER,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
@@ -5274,7 +5414,6 @@ int ourInit(){
 
 
     Our->PigmentLayeringProgramT = tnsNewShaderProgram(T->immShader->vtShaderID,Our->PigmentLayeringShader,-1);
     Our->PigmentLayeringProgramT = tnsNewShaderProgram(T->immShader->vtShaderID,Our->PigmentLayeringShader,-1);
 
 
-
     Our->PigmentDisplayShader = glCreateShader(GL_FRAGMENT_SHADER);
     Our->PigmentDisplayShader = glCreateShader(GL_FRAGMENT_SHADER);
     const GLchar* source4 = strSub(OUR_PIGMENT_TEXTURE_DISPLAY_SHADER,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
     const GLchar* source4 = strSub(OUR_PIGMENT_TEXTURE_DISPLAY_SHADER,"#with OUR_PIGMENT_COMMON",OUR_PIGMENT_COMMON);
     const GLchar* sources4[]={versionstr, source4};
     const GLchar* sources4[]={versionstr, source4};
@@ -5300,11 +5439,11 @@ int ourInit(){
     glBindBuffer(GL_UNIFORM_BUFFER, 0);
     glBindBuffer(GL_UNIFORM_BUFFER, 0);
 
 
     Our->u = &Our->uRGBA;
     Our->u = &Our->uRGBA;
-    ourGetUniforms(Our->CanvasProgram,Our->CompositionProgram);
+    ourGetUniforms(Our->CanvasProgram,-1,Our->CompositionProgram);
     Our->u = &Our->uRGBStraightA;
     Our->u = &Our->uRGBStraightA;
-    ourGetUniforms(Our->CanvasStraightProgram,Our->CompositionProgram);
+    ourGetUniforms(Our->CanvasStraightProgram,-1,Our->CompositionStraightProgram);
     Our->u = &Our->uPigment;
     Our->u = &Our->uPigment;
-    ourGetUniforms(Our->CanvasPigmentProgram,Our->PigmentLayeringProgramT->glProgramID); // XXXXX  (?)
+    ourGetUniforms(Our->CanvasPigmentProgram,Our->PigmentLayeringProgramT->glProgramID,Our->PigmentCompositionProgram); // XXXXX  (?)
 
 
     Our->X=-2800/2; Our->W=2800;
     Our->X=-2800/2; Our->W=2800;
     Our->Y=2400/2;  Our->H=2400;
     Our->Y=2400/2;  Our->H=2400;
@@ -5359,6 +5498,10 @@ int ourInit(){
     Our->CanvasLight=memAcquireHyper(sizeof(OurLight));
     Our->CanvasLight=memAcquireHyper(sizeof(OurLight));
     Our->CanvasSurface=memAcquireHyper(sizeof(OurCanvasSurface));
     Our->CanvasSurface=memAcquireHyper(sizeof(OurCanvasSurface));
 
 
+    Our->PigmentMode=Our->DefaultCanvasType;
+
+    for(int i=0;i<5;i++) our_NewUsePigment(0);
+
 #ifdef LAGUI_ANDROID
 #ifdef LAGUI_ANDROID
     android_ensure_asset_to_public_dir("default_brushes.udf");
     android_ensure_asset_to_public_dir("default_brushes.udf");
     android_ensure_asset_to_public_dir("default_pallettes.udf");
     android_ensure_asset_to_public_dir("default_pallettes.udf");

+ 17 - 6
ourpaint.h

@@ -42,6 +42,7 @@ extern const char OUR_MIME[];
 extern const char OUR_THUMBNAILER[];
 extern const char OUR_THUMBNAILER[];
 extern const char OUR_DESKTOP[];
 extern const char OUR_DESKTOP[];
 extern const char OUR_PIGMENT_TEXTURE_MIX_SHADER[];
 extern const char OUR_PIGMENT_TEXTURE_MIX_SHADER[];
+extern const char OUR_PIGMENT_COMPOSITION_SHADER[];
 extern const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[];
 extern const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[];
 extern const char OUR_PIGMENT_COMMON[];
 extern const char OUR_PIGMENT_COMMON[];
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -99,6 +100,8 @@ extern const char OUR_PIGMENT_COMMON[];
 extern laWidget* OUR_WIDGET_PIGMENT;
 extern laWidget* OUR_WIDGET_PIGMENT;
 extern laUiType* _OUR_UI_PIGMENT;
 extern laUiType* _OUR_UI_PIGMENT;
 
 
+#define OUR_COLOR_PAD_PIGMENT_DATA LA_UI_FLAGS_KNOB
+
 #define OURU Our->u
 #define OURU Our->u
 
 
 STRUCTURE(OurCanvasDraw){
 STRUCTURE(OurCanvasDraw){
@@ -325,13 +328,14 @@ STRUCTURE(OurCanvasSurface){
     OurPigmentData Reflectance;
     OurPigmentData Reflectance;
 };
 };
 
 
-NEED_STRUCTURE(OurColorPallette);
+NEED_STRUCTURE(OurColorPalette);
 STRUCTURE(OurColorItem){
 STRUCTURE(OurColorItem){
     laListItem Item;
     laListItem Item;
-    tnsVector3d Color;
-    OurColorPallette* Parent;
+    OurPigmentData Pigment;
+    int IsPigment;
+    OurColorPalette* Parent;
 };
 };
-STRUCTURE(OurColorPallette){
+STRUCTURE(OurColorPalette){
     laListItem Item;
     laListItem Item;
     laSafeString* Name;
     laSafeString* Name;
     laListHandle Colors;
     laListHandle Colors;
@@ -468,6 +472,7 @@ STRUCTURE(BrushUniforms){
     GLint uAlphaTop;
     GLint uAlphaTop;
     GLint uAlphaBottom;
     GLint uAlphaBottom;
     GLsizei SubroutineUniformLocations;
     GLsizei SubroutineUniformLocations;
+    GLint uMixingTop;
 };
 };
 
 
 STRUCTURE(OurPaint){
 STRUCTURE(OurPaint){
@@ -481,8 +486,8 @@ STRUCTURE(OurPaint){
     tnsImage* SplashImage;
     tnsImage* SplashImage;
     tnsImage* SplashImageHigh;
     tnsImage* SplashImageHigh;
 
 
-    laListHandle Pallettes;
-    OurColorPallette* CurrentPallette;
+    laListHandle Palettes;
+    OurColorPalette* CurrentPalette;
 
 
     laListHandle Layers;
     laListHandle Layers;
     OurLayer*    CurrentLayer;
     OurLayer*    CurrentLayer;
@@ -539,6 +544,8 @@ STRUCTURE(OurPaint){
     int SketchMode;
     int SketchMode;
     int SegmentedWrite;
     int SegmentedWrite;
     int PigmentDisplayMethod;
     int PigmentDisplayMethod;
+    int PaletteInColorsPanel;
+    int DefaultCanvasType;
 
 
     tnsTexture* SmudgeTexture;
     tnsTexture* SmudgeTexture;
     GLuint CanvasShader;         GLuint CanvasProgram;
     GLuint CanvasShader;         GLuint CanvasProgram;
@@ -548,6 +555,7 @@ STRUCTURE(OurPaint){
     GLuint CompositionStraightShader; GLuint CompositionStraightProgram;
     GLuint CompositionStraightShader; GLuint CompositionStraightProgram;
     GLuint LayerShader;          GLuint LayerProgram;
     GLuint LayerShader;          GLuint LayerProgram;
     GLuint DisplayShader;        GLuint DisplayProgram;
     GLuint DisplayShader;        GLuint DisplayProgram;
+    GLuint PigmentCompositionShader; GLuint PigmentCompositionProgram;
     GLuint PigmentLayeringShader; tnsShader* PigmentLayeringProgramT;
     GLuint PigmentLayeringShader; tnsShader* PigmentLayeringProgramT;
     GLuint PigmentDisplayShader; tnsShader* PigmentDisplayProgramT;
     GLuint PigmentDisplayShader; tnsShader* PigmentDisplayProgramT;
     GLuint uPigmentFragOffset,uPigmentTextureScale,uPigmentDisplayMode;
     GLuint uPigmentFragOffset,uPigmentTextureScale,uPigmentDisplayMode;
@@ -556,12 +564,15 @@ STRUCTURE(OurPaint){
 
 
     BrushUniforms *u,uRGBA,uRGBStraightA,uPigment;
     BrushUniforms *u,uRGBA,uRGBStraightA,uPigment;
     int AlphaMode;
     int AlphaMode;
+    int ReorderPigmnets;
 
 
     OurCanvasSurface *CanvasSurface; // not ptr to list
     OurCanvasSurface *CanvasSurface; // not ptr to list
     OurLight         *CanvasLight;
     OurLight         *CanvasLight;
     OurPigmentData   PickedPigment;
     OurPigmentData   PickedPigment;
     OurPigmentData   MixedPigment;
     OurPigmentData   MixedPigment;
     laListHandle     UsePigments;
     laListHandle     UsePigments;
+    OurPigment*   UseWhite;
+    OurPigment*   UseBlack;
 
 
     real CurrentColor[3];
     real CurrentColor[3];
     real BackgroundColor[3];
     real BackgroundColor[3];

+ 54 - 18
ourshader.cpp

@@ -406,24 +406,6 @@ void DoSample(){
 R"(
 R"(
 #ifdef OUR_CANVAS_MODE_PIGMENT //========================================================================================
 #ifdef OUR_CANVAS_MODE_PIGMENT //========================================================================================
 
 
-#define GetImgPixel(tex, uv, p) \
-{ \
-    PixType c0=loadpix(tex,uv); \
-    PixType c1=loadpix(tex,ivec2(uv.x,uv.y+1)); \
-    PixType c2=loadpix(tex,ivec2(uv.x+1,uv.y)); \
-    PixType c3=loadpix(tex,ivec2(uv.x+1,uv.y+1)); \
-    setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p); \
-}
-
-#define WriteImgPixel(tex, uv, p) \
-{ \
-    PixType c0=getRL(p); PixType c1=getRH(p); PixType c2=getAL(p); PixType c3=getAH(p); \
-    imageStore(tex,uv,packpix(c0)); \
-    imageStore(tex,ivec2(uv.x,uv.y+1),packpix(c1)); \
-    imageStore(tex,ivec2(uv.x+1,uv.y),packpix(c2)); \
-    imageStore(tex,ivec2(uv.x+1,uv.y+1),packpix(c3)); \
-}
-
 int dab_pigment(float d, vec2 fpx, PigmentData color, float size, float hardness,
 int dab_pigment(float d, vec2 fpx, PigmentData color, float size, float hardness,
                 float smudge, PigmentData smudge_color, PigmentData last_color, out PigmentData final){
                 float smudge, PigmentData smudge_color, PigmentData last_color, out PigmentData final){
     PigmentData cc=(uBrushErasing!=0)?PIGMENT_BLANK:color;
     PigmentData cc=(uBrushErasing!=0)?PIGMENT_BLANK:color;
@@ -978,6 +960,24 @@ vec3 PigmentToRGB(PigmentData pd, PigmentData light){
     vec3 xyz=Spectral2XYZ(slices); vec3 rgb=XYZ2sRGB(xyz); return rgb;
     vec3 xyz=Spectral2XYZ(slices); vec3 rgb=XYZ2sRGB(xyz); return rgb;
 }
 }
 
 
+#define GetImgPixel(tex, uv, p) \
+{ \
+    PixType c0=loadpix(tex,uv); \
+    PixType c1=loadpix(tex,ivec2(uv.x,uv.y+1)); \
+    PixType c2=loadpix(tex,ivec2(uv.x+1,uv.y)); \
+    PixType c3=loadpix(tex,ivec2(uv.x+1,uv.y+1)); \
+    setRL(c0,p); setRH(c1,p); setAL(c2,p); setAH(c3,p); \
+}
+
+#define WriteImgPixel(tex, uv, p) \
+{ \
+    PixType c0=getRL(p); PixType c1=getRH(p); PixType c2=getAL(p); PixType c3=getAH(p); \
+    imageStore(tex,uv,packpix(c0)); \
+    imageStore(tex,ivec2(uv.x,uv.y+1),packpix(c1)); \
+    imageStore(tex,ivec2(uv.x+1,uv.y),packpix(c2)); \
+    imageStore(tex,ivec2(uv.x+1,uv.y+1),packpix(c3)); \
+}
+
 )";
 )";
 
 
 const char OUR_PIGMENT_TEXTURE_MIX_SHADER[]=R"(
 const char OUR_PIGMENT_TEXTURE_MIX_SHADER[]=R"(
@@ -988,6 +988,7 @@ precision highp float;
 precision highp int;
 precision highp int;
 layout (binding=2) uniform highp usampler2D TexColorUI0;
 layout (binding=2) uniform highp usampler2D TexColorUI0;
 layout (binding=5) uniform highp usampler2D TexColorUI1;
 layout (binding=5) uniform highp usampler2D TexColorUI1;
+uniform float MixingTop;
 
 
 in vec2 fUV;
 in vec2 fUV;
 
 
@@ -1001,6 +1002,7 @@ void main(){
 
 
     PigmentData p0 = GetPixel(TexColorUI0,iuv);
     PigmentData p0 = GetPixel(TexColorUI0,iuv);
     PigmentData p1 = GetPixel(TexColorUI1,iuvscr);
     PigmentData p1 = GetPixel(TexColorUI1,iuvscr);
+    p0.r[15]*=MixingTop; p0.a[15]*=MixingTop;
     PigmentData result = PigmentOver(p0,p1);
     PigmentData result = PigmentOver(p0,p1);
 
 
     int choose = xof*2+yof;
     int choose = xof*2+yof;
@@ -1009,6 +1011,40 @@ void main(){
 }
 }
 )";
 )";
 
 
+const char OUR_PIGMENT_COMPOSITION_SHADER[] = R"(
+layout(local_size_x = WORKGROUP_SIZE, local_size_y = WORKGROUP_SIZE, local_size_z = 1) in;
+#ifdef OUR_GLES
+precision highp uimage2D;
+precision highp float;
+precision highp int;
+layout(r32ui, binding = 0) uniform uimage2D top;
+layout(r32ui, binding = 1) uniform uimage2D bottom;
+#else
+layout(rgba16ui, binding = 0) uniform uimage2D top;
+layout(rgba16ui, binding = 1) uniform uimage2D bottom;
+#endif
+uniform float uAlphaTop;
+uniform float uAlphaBottom;
+
+#with OUR_PIGMENT_COMMON
+
+void main() {
+    ivec2 px=ivec2(gl_GlobalInvocationID.xy)*2;
+
+    PigmentData p0; GetImgPixel(top, px, p0);
+    PigmentData p1; GetImgPixel(bottom, px, p1);
+
+    float afac=uAlphaTop/uAlphaBottom;
+    if(afac==0.){ return; }
+
+    p0.r[15]*=afac; p0.a[15]*=afac;
+
+    PigmentData result=PigmentOver(p0,p1);
+
+    WriteImgPixel(bottom,px,result);
+}
+)";
+
 const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[]=R"(
 const char OUR_PIGMENT_TEXTURE_DISPLAY_SHADER[]=R"(
 #ifndef OUR_GLES
 #ifndef OUR_GLES
 #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding
 #extension GL_ARB_shading_language_420pack : enable // uniform sampler binding

+ 2 - 3
ourtranslations_es-ES.c

@@ -56,7 +56,7 @@ static const char *entries[]={
 "Inner","Interior",
 "Inner","Interior",
 "Outer","Exterior",
 "Outer","Exterior",
 "Cycle Sketches","Conmutar Bosquejos",
 "Cycle Sketches","Conmutar Bosquejos",
-"Remove Pallette", "Quitar Paleta",
+"Remove Palette", "Quitar Paleta",
 "New Color", "Nuevo Color",
 "New Color", "Nuevo Color",
 "Can't allocate memory for size", "No puedo asignar memoria para dicho tamaño",
 "Can't allocate memory for size", "No puedo asignar memoria para dicho tamaño",
 "Export Error","Error al exportar",
 "Export Error","Error al exportar",
@@ -65,7 +65,7 @@ static const char *entries[]={
 "Offset","Desviación",
 "Offset","Desviación",
 "Visual Offset:","Desviación visual:",
 "Visual Offset:","Desviación visual:",
 "Notes","Notas",
 "Notes","Notas",
-"Pallettes","Paletas",
+"Palettes","Paletas",
 "Thumbnail","Miniatura",
 "Thumbnail","Miniatura",
 "Factor","Factor",
 "Factor","Factor",
 "Paper","Papel",
 "Paper","Papel",
@@ -82,7 +82,6 @@ static const char *entries[]={
 "Credits to Sponsors","Créditos a los Patrocinantes",
 "Credits to Sponsors","Créditos a los Patrocinantes",
 "Ref Stripes","Bandas de referencia",
 "Ref Stripes","Bandas de referencia",
 "Release Notes","Notas de Lanzamiento",
 "Release Notes","Notas de Lanzamiento",
-"Spectral Brush","Pincel Espectral",
 "Spectral","Espectral",
 "Spectral","Espectral",
 "Canvas Default Scale","Escala por defecto del Lienzo",
 "Canvas Default Scale","Escala por defecto del Lienzo",
 "Help","Ayuda",
 "Help","Ayuda",

+ 3 - 3
ourtranslations_zh-hans.c

@@ -57,7 +57,7 @@ static const char *entries[]={
 "Inner","内边框",
 "Inner","内边框",
 "Outer","外边框",
 "Outer","外边框",
 "Cycle Sketches","切换草稿",
 "Cycle Sketches","切换草稿",
-"Remove Pallette", "删除调色板",
+"Remove Palette", "删除调色板",
 "New Color", "新颜色",
 "New Color", "新颜色",
 "Can't allocate memory for size", "无法为该尺寸分配内存",
 "Can't allocate memory for size", "无法为该尺寸分配内存",
 "Export Error","导出错误",
 "Export Error","导出错误",
@@ -66,7 +66,7 @@ static const char *entries[]={
 "Offset","偏移",
 "Offset","偏移",
 "Visual Offset:","视觉偏移:",
 "Visual Offset:","视觉偏移:",
 "Notes","笔记本",
 "Notes","笔记本",
-"Pallettes","调色板",
+"Palettes","调色板",
 "Thumbnail","缩略图",
 "Thumbnail","缩略图",
 "Factor","程度",
 "Factor","程度",
 "Paper","纸张",
 "Paper","纸张",
@@ -83,7 +83,7 @@ static const char *entries[]={
 "Credits to Sponsors","感谢赞助者",
 "Credits to Sponsors","感谢赞助者",
 "Ref Stripes","参考亮度带",
 "Ref Stripes","参考亮度带",
 "Release Notes","发行日志",
 "Release Notes","发行日志",
-"Spectral Brush","光谱笔刷",
+"Spectral Mixing","光谱混合",
 "Spectral","光谱",
 "Spectral","光谱",
 "Canvas Default Scale","画布默认比例",
 "Canvas Default Scale","画布默认比例",
 "Help","帮助",
 "Help","帮助",