|  | @@ -19,6 +19,7 @@ uniform float uBrushSlender;\n\
 | 
											
												
													
														|  |  uniform float uBrushAngle;\n\
 |  |  uniform float uBrushAngle;\n\
 | 
											
												
													
														|  |  uniform vec4 uBrushColor;\n\
 |  |  uniform vec4 uBrushColor;\n\
 | 
											
												
													
														|  |  uniform vec4 uBackgroundColor;\n\
 |  |  uniform vec4 uBackgroundColor;\n\
 | 
											
												
													
														|  | 
 |  | +uniform int uBrushErasing;\n\
 | 
											
												
													
														|  |  float atan2(in float y, in float x){\n\
 |  |  float atan2(in float y, in float x){\n\
 | 
											
												
													
														|  |      bool s = (abs(x) > abs(y)); return mix(3.1415926535/2.0 - atan(x,y), atan(y,x), s);\n\
 |  |      bool s = (abs(x) > abs(y)); return mix(3.1415926535/2.0 - atan(x,y), atan(y,x), s);\n\
 | 
											
												
													
														|  |  }\n\
 |  |  }\n\
 | 
											
										
											
												
													
														|  | @@ -35,8 +36,11 @@ int dab(float d, vec4 color, float size, float hardness, float smudge, vec4 smud
 | 
											
												
													
														|  |      vec4 cc=color;\n\
 |  |      vec4 cc=color;\n\
 | 
											
												
													
														|  |      float fac=1-pow(d/size,1+1/(1-hardness+1e-4));\n\
 |  |      float fac=1-pow(d/size,1+1/(1-hardness+1e-4));\n\
 | 
											
												
													
														|  |      cc.a=color.a*fac*(1-smudge); cc.rgb=cc.rgb*cc.a;\n\
 |  |      cc.a=color.a*fac*(1-smudge); cc.rgb=cc.rgb*cc.a;\n\
 | 
											
												
													
														|  | 
 |  | +    float erasing=float(uBrushErasing);\n\
 | 
											
												
													
														|  | 
 |  | +    cc=cc*(1-erasing);\n\
 | 
											
												
													
														|  |      vec4 c1=mix_over(cc,last_color);\n\
 |  |      vec4 c1=mix_over(cc,last_color);\n\
 | 
											
												
													
														|  |      vec4 c2=mix(c1,smudge_color,smudge*fac*color.a);\n\
 |  |      vec4 c2=mix(c1,smudge_color,smudge*fac*color.a);\n\
 | 
											
												
													
														|  | 
 |  | +    c2=mix(c2,c2*(1-fac*color.a),erasing);\n\
 | 
											
												
													
														|  |      final=c2;\n\
 |  |      final=c2;\n\
 | 
											
												
													
														|  |      return 1;\n\
 |  |      return 1;\n\
 | 
											
												
													
														|  |  }\n\
 |  |  }\n\
 | 
											
										
											
												
													
														|  | @@ -171,9 +175,9 @@ void ourui_ToolsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps
 | 
											
												
													
														|  |      laEndCondition(uil,b2);
 |  |      laEndCondition(uil,b2);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      laShowItem(uil,c,0,"our.tool")->Flags|=LA_UI_FLAGS_EXPAND;
 |  |      laShowItem(uil,c,0,"our.tool")->Flags|=LA_UI_FLAGS_EXPAND;
 | 
											
												
													
														|  | -    laShowLabel(uil,c,"Brush settings:",0,0);
 |  | 
 | 
											
												
													
														|  |      laUiItem* bt=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.tool"),laIntExpression(OUR_TOOL_PAINT)));{
 |  |      laUiItem* bt=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.tool"),laIntExpression(OUR_TOOL_PAINT)));{
 | 
											
												
													
														|  |          laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.tools.current_brush"));{
 |  |          laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.tools.current_brush"));{
 | 
											
												
													
														|  | 
 |  | +            laShowLabel(uil,cl,"Mode:",0,0);laShowItem(uil,cr,0,"our.erasing");
 | 
											
												
													
														|  |              laShowItem(uil,c,0,"our.tools.current_brush.name");
 |  |              laShowItem(uil,c,0,"our.tools.current_brush.name");
 | 
											
												
													
														|  |              laShowItem(uil,cl,0,"our.tools.current_brush.use_nodes");
 |  |              laShowItem(uil,cl,0,"our.tools.current_brush.use_nodes");
 | 
											
												
													
														|  |  
 |  |  
 | 
											
										
											
												
													
														|  | @@ -190,6 +194,7 @@ void ourui_ToolsPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps
 | 
											
												
													
														|  |              laShowItem(uil,c,0,"our.tools.current_brush.dabs_per_size");
 |  |              laShowItem(uil,c,0,"our.tools.current_brush.dabs_per_size");
 | 
											
												
													
														|  |              laShowItem(uil,c,0,"our.tools.current_brush.smudge_resample_length");
 |  |              laShowItem(uil,c,0,"our.tools.current_brush.smudge_resample_length");
 | 
											
												
													
														|  |              laShowItem(uil,c,0,"our.tools.current_brush.smoothness");
 |  |              laShowItem(uil,c,0,"our.tools.current_brush.smoothness");
 | 
											
												
													
														|  | 
 |  | +            laShowItem(uil,c,0,"our.tools.current_brush.default_as_eraser");
 | 
											
												
													
														|  |          }laEndCondition(uil,b);
 |  |          }laEndCondition(uil,b);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |          laShowSeparator(uil,c);
 |  |          laShowSeparator(uil,c);
 | 
											
										
											
												
													
														|  | @@ -933,6 +938,7 @@ void our_PaintDoDabsWithSmudgeSegments(OurLayer* l,int tl, int tr, int tu, int t
 | 
											
												
													
														|  |      if(Our->Dabs[0].ResampleSmudge){ ((OurSmudgeSegement*)Segments.pFirst)->Resample=1; }
 |  |      if(Our->Dabs[0].ResampleSmudge){ ((OurSmudgeSegement*)Segments.pFirst)->Resample=1; }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      glUseProgram(Our->CanvasProgram);
 |  |      glUseProgram(Our->CanvasProgram);
 | 
											
												
													
														|  | 
 |  | +    glUniform1i(Our->uBrushErasing,Our->Erasing);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      while(oss=lstPopItem(&Segments)){
 |  |      while(oss=lstPopItem(&Segments)){
 | 
											
												
													
														|  |          if(oss->Resample || Our->CurrentBrush->SmudgeRestart){
 |  |          if(oss->Resample || Our->CurrentBrush->SmudgeRestart){
 | 
											
										
											
												
													
														|  | @@ -951,6 +957,23 @@ void our_PaintDoDabsWithSmudgeSegments(OurLayer* l,int tl, int tr, int tu, int t
 | 
											
												
													
														|  |          our_PaintDoDabs(l,tl,tr,tu,tb,oss->Start,oss->End);
 |  |          our_PaintDoDabs(l,tl,tr,tu,tb,oss->Start,oss->End);
 | 
											
												
													
														|  |      }
 |  |      }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  | 
 |  | +void our_EnsureEraser(int EventIsEraser){
 | 
											
												
													
														|  | 
 |  | +    if(EventIsEraser==Our->EventErasing){ return; }
 | 
											
												
													
														|  | 
 |  | +    printf("ev e %d %d\n", Our->EventErasing, Our->Erasing);
 | 
											
												
													
														|  | 
 |  | +    int erasing=Our->Erasing; int num=0;
 | 
											
												
													
														|  | 
 |  | +    if(EventIsEraser && (!Our->EventErasing)){ num=TNS_MAX2(Our->EraserID,num);
 | 
											
												
													
														|  | 
 |  | +        for(OurBrush* b=Our->Brushes.pFirst;b;b=b->Item.pNext){
 | 
											
												
													
														|  | 
 |  | +            if(b->Binding==num){ ourset_CurrentBrush(Our,b); laNotifyUsers("our.tools.brushes"); break; }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        Our->Erasing=1; Our->EventErasing=1; laNotifyUsers("our.erasing");
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +    elif((!EventIsEraser) && Our->EventErasing){ num=TNS_MAX2(Our->PenID,num);
 | 
											
												
													
														|  | 
 |  | +        for(OurBrush* b=Our->Brushes.pFirst;b;b=b->Item.pNext){
 | 
											
												
													
														|  | 
 |  | +            if(b->Binding==num){ ourset_CurrentBrush(Our,b); laNotifyUsers("our.tools.brushes"); break; }
 | 
											
												
													
														|  | 
 |  | +        }
 | 
											
												
													
														|  | 
 |  | +        Our->Erasing=0; Our->EventErasing=0; laNotifyUsers("our.erasing");
 | 
											
												
													
														|  | 
 |  | +    }
 | 
											
												
													
														|  | 
 |  | +}
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  void our_ReadWidgetColor(laCanvasExtra*e,int x,int y){
 |  |  void our_ReadWidgetColor(laCanvasExtra*e,int x,int y){
 | 
											
												
													
														|  |      uint8_t color[4];
 |  |      uint8_t color[4];
 | 
											
										
											
												
													
														|  | @@ -1118,6 +1141,7 @@ int ourinv_Action(laOperator* a, laEvent* e){
 | 
											
												
													
														|  |      Our->ActiveTool=Our->Tool; Our->CurrentScale = 1.0f/ex->Base.ZoomX;
 |  |      Our->ActiveTool=Our->Tool; Our->CurrentScale = 1.0f/ex->Base.ZoomX;
 | 
											
												
													
														|  |      Our->xmin=FLT_MAX;Our->xmax=-FLT_MAX;Our->ymin=FLT_MAX;Our->ymax=-FLT_MAX; Our->ResetBrush=1; ex->HideBrushCircle=1;
 |  |      Our->xmin=FLT_MAX;Our->xmax=-FLT_MAX;Our->ymin=FLT_MAX;Our->ymax=-FLT_MAX; Our->ResetBrush=1; ex->HideBrushCircle=1;
 | 
											
												
													
														|  |      if(Our->ActiveTool==OUR_TOOL_CROP){ if(!Our->ShowBorder) return LA_FINISHED; our_StartCropping(ex); }
 |  |      if(Our->ActiveTool==OUR_TOOL_CROP){ if(!Our->ShowBorder) return LA_FINISHED; our_StartCropping(ex); }
 | 
											
												
													
														|  | 
 |  | +    our_EnsureEraser(e->IsEraser);
 | 
											
												
													
														|  |      laHideCursor();
 |  |      laHideCursor();
 | 
											
												
													
														|  |      return LA_RUNNING;
 |  |      return LA_RUNNING;
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
										
											
												
													
														|  | @@ -1253,6 +1277,7 @@ void ourpropagate_Tools(OurPaint* p, laUDF* udf, int force){
 | 
											
												
													
														|  |  void ourset_CurrentBrush(void* unused, OurBrush* b){
 |  |  void ourset_CurrentBrush(void* unused, OurBrush* b){
 | 
											
												
													
														|  |      real r; if(Our->LockRadius) r=Our->CurrentBrush?Our->CurrentBrush->Size:15;
 |  |      real r; if(Our->LockRadius) r=Our->CurrentBrush?Our->CurrentBrush->Size:15;
 | 
											
												
													
														|  |      Our->CurrentBrush=b; if(b && Our->LockRadius) b->Size=r;
 |  |      Our->CurrentBrush=b; if(b && Our->LockRadius) b->Size=r;
 | 
											
												
													
														|  | 
 |  | +    if(b->DefaultAsEraser){ Our->Erasing=1; Our->EraserID=b->Binding; }else{ Our->Erasing=0; Our->PenID=b->Binding; }
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |  #define OUR_ADD_PRESSURE_SWITCH(p)\
 |  |  #define OUR_ADD_PRESSURE_SWITCH(p)\
 | 
											
										
											
												
													
														|  | @@ -1324,6 +1349,9 @@ void ourRegisterEverything(){
 | 
											
												
													
														|  |      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);
 |  |      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,"FALSE","No","Dont' show brush circle",0,0);
 | 
											
												
													
														|  |      laAddEnumItemAs(p,"TRUE","Yes","Show brush circle on hover",1,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);
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      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);
 | 
											
										
											
												
													
														|  | @@ -1357,6 +1385,9 @@ void ourRegisterEverything(){
 | 
											
												
													
														|  |      laAddEnumItemAs(p,"NONE","None","Not using nodes",0,0);
 |  |      laAddEnumItemAs(p,"NONE","None","Not using nodes",0,0);
 | 
											
												
													
														|  |      laAddEnumItemAs(p,"ENABLED","Enabled","Using nodes",1,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);
 | 
											
												
													
														|  | 
 |  | +    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);
 | 
											
												
													
														|  |      
 |  |      
 | 
											
												
													
														|  |      laAddOperatorProperty(pc,"move","Move","Move brush","OUR_move_brush",0,0);
 |  |      laAddOperatorProperty(pc,"move","Move","Move brush","OUR_move_brush",0,0);
 | 
											
												
													
														|  |      laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",L'🗴',0);
 |  |      laAddOperatorProperty(pc,"remove","Remove","Remove brush","OUR_remove_brush",L'🗴',0);
 | 
											
										
											
												
													
														|  | @@ -1455,6 +1486,7 @@ void ourInit(){
 | 
											
												
													
														|  |      Our->uBrushColor=glGetUniformLocation(Our->CanvasProgram,"uBrushColor");
 |  |      Our->uBrushColor=glGetUniformLocation(Our->CanvasProgram,"uBrushColor");
 | 
											
												
													
														|  |      Our->uBrushSlender=glGetUniformLocation(Our->CanvasProgram,"uBrushSlender");
 |  |      Our->uBrushSlender=glGetUniformLocation(Our->CanvasProgram,"uBrushSlender");
 | 
											
												
													
														|  |      Our->uBrushAngle=glGetUniformLocation(Our->CanvasProgram,"uBrushAngle");
 |  |      Our->uBrushAngle=glGetUniformLocation(Our->CanvasProgram,"uBrushAngle");
 | 
											
												
													
														|  | 
 |  | +    Our->uBrushErasing=glGetUniformLocation(Our->CanvasProgram,"uBrushErasing");
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      Our->uBrushRoutineSelection=glGetSubroutineUniformLocation(Our->CanvasProgram, GL_COMPUTE_SHADER, "uBrushRoutineSelection");
 |  |      Our->uBrushRoutineSelection=glGetSubroutineUniformLocation(Our->CanvasProgram, GL_COMPUTE_SHADER, "uBrushRoutineSelection");
 | 
											
												
													
														|  |      Our->RoutineDoDabs=glGetSubroutineIndex(Our->CanvasProgram, GL_COMPUTE_SHADER, "DoDabs");
 |  |      Our->RoutineDoDabs=glGetSubroutineIndex(Our->CanvasProgram, GL_COMPUTE_SHADER, "DoDabs");
 | 
											
										
											
												
													
														|  | @@ -1466,6 +1498,9 @@ void ourInit(){
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  |      Our->LockRadius=1;
 |  |      Our->LockRadius=1;
 | 
											
												
													
														|  |  
 |  |  
 | 
											
												
													
														|  | 
 |  | +    Our->PenID=-1;
 | 
											
												
													
														|  | 
 |  | +    Our->EraserID=-1;
 | 
											
												
													
														|  | 
 |  | +
 | 
											
												
													
														|  |      tnsEnableShaderv(T->immShader);
 |  |      tnsEnableShaderv(T->immShader);
 | 
											
												
													
														|  |  }
 |  |  }
 | 
											
												
													
														|  |  
 |  |  
 |