|
@@ -6,8 +6,8 @@ extern tnsMain* T;
|
|
|
|
|
|
const char OUR_CANVAS_SHADER[]="#version 430\n\
|
|
|
layout(local_size_x = 32, local_size_y = 32, local_size_z = 1) in;\n\
|
|
|
-layout(rgba8, binding = 0) uniform image2D img;\n\
|
|
|
-layout(rgba8, binding = 1) coherent uniform image2D smudge_buckets;\n\
|
|
|
+layout(rgba16, binding = 0) uniform image2D img;\n\
|
|
|
+layout(rgba16, binding = 1) coherent uniform image2D smudge_buckets;\n\
|
|
|
uniform ivec2 uBrushCorner;\n\
|
|
|
uniform vec2 uBrushCenter;\n\
|
|
|
uniform float uBrushSize;\n\
|
|
@@ -23,12 +23,16 @@ vec4 mix_over(vec4 colora, vec4 colorb){\n\
|
|
|
float erase(float a, float target_a, float eraser_a){\n\
|
|
|
return mix(a,target_a,eraser_a);\n\
|
|
|
}\n\
|
|
|
+vec4 alpha_mix(vec4 c1, vec4 c2, float fac){\n\
|
|
|
+ return vec4(mix(c1.rgb*c1.a,c2.rgb*c2.a,fac)/(c1.a*(1-fac)+c2.a*fac+1e-3),mix(c1.a,c2.a,fac));\n\
|
|
|
+}\n\
|
|
|
int dab(float d, vec4 color, float size, float hardness, float smudge, vec4 smudge_color, vec4 last_color, out vec4 final){\n\
|
|
|
- vec4 cc; cc.rgb=mix(color,smudge_color,smudge*smudge_color.a).rgb;\n\
|
|
|
+ vec4 cc=color;\n\
|
|
|
float fac=(1-pow(d/size,1+1/(1-hardness)));\n\
|
|
|
- cc.a=clamp(mix(color.a,smudge_color.a,smudge)*fac,0,1);\n\
|
|
|
- final=mix_over(cc,last_color);\n\
|
|
|
- final.a=erase(final.a,mix(color.a,smudge_color.a,smudge),fac*smudge*(1-color.a));\n\
|
|
|
+ cc.a=color.a*fac*(1-smudge+1e-5);\n\
|
|
|
+ vec4 c1=mix_over(cc,last_color);\n\
|
|
|
+ vec4 c2=alpha_mix(c1,smudge_color,smudge*fac*color.a);\n\
|
|
|
+ final=c2;\n\
|
|
|
return 1;\n\
|
|
|
}\n\
|
|
|
subroutine void BrushRoutines();\n\
|
|
@@ -110,26 +114,40 @@ void ourui_Brush(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laC
|
|
|
laEndRow(uil,b);
|
|
|
}laEndCondition(uil,b1);
|
|
|
}
|
|
|
-void ourui_BrushesPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
|
|
|
- laColumn* c=laFirstColumn(uil);
|
|
|
+void ourui_ToolsPanel(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,0);cr=laRightColumn(c,0);
|
|
|
laUiItem* b1;
|
|
|
#define OUR_BR b1=laBeginRow(uil,c,0,0);
|
|
|
#define OUR_ER laEndRow(uil,b1);
|
|
|
|
|
|
- laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.current_brush"));{
|
|
|
- laShowItem(uil,c,0,"our.current_brush.name");
|
|
|
- OUR_BR laShowItem(uil,c,0,"our.current_brush.size")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_size",0,"text=P",0,0); OUR_ER
|
|
|
- OUR_BR laShowItem(uil,c,0,"our.current_brush.transparency")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_transparency",0,"text=P",0,0); OUR_ER
|
|
|
- OUR_BR laShowItem(uil,c,0,"our.current_brush.hardness")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_hardness",0,"text=P",0,0); OUR_ER
|
|
|
- OUR_BR laShowItem(uil,c,0,"our.current_brush.smudge")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_smudge",0,"text=P",0,0); OUR_ER
|
|
|
- laShowItem(uil,c,0,"our.current_brush.dabs_per_size");
|
|
|
- laShowItem(uil,c,0,"our.current_brush.smudge_resample_length");
|
|
|
- }laEndCondition(uil,b);
|
|
|
-
|
|
|
- laShowLabel(uil,c,"Select a brush:",0,0);
|
|
|
-
|
|
|
- laShowItemFull(uil,c,0,"our.brushes",0,0,0,0);
|
|
|
- laShowItem(uil,c,0,"OUR_new_brush");
|
|
|
+ laShowItem(uil,c,0,"our.tool")->Flags|=LA_UI_FLAGS_EXPAND;
|
|
|
+ laUiItem* bt=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.tool"),laIntExpression(OUR_TOOL_PAINT)));{
|
|
|
+ laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.current_brush"));{
|
|
|
+ laShowItem(uil,c,0,"our.current_brush.name");
|
|
|
+ OUR_BR laShowItem(uil,c,0,"our.current_brush.size")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_size",0,"text=P",0,0); OUR_ER
|
|
|
+ OUR_BR laShowItem(uil,c,0,"our.current_brush.transparency")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_transparency",0,"text=P",0,0); OUR_ER
|
|
|
+ OUR_BR laShowItem(uil,c,0,"our.current_brush.hardness")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_hardness",0,"text=P",0,0); OUR_ER
|
|
|
+ OUR_BR laShowItem(uil,c,0,"our.current_brush.smudge")->Expand=1; laShowItemFull(uil,c,0,"our.current_brush.pressure_smudge",0,"text=P",0,0); OUR_ER
|
|
|
+ laShowItem(uil,c,0,"our.current_brush.dabs_per_size");
|
|
|
+ laShowItem(uil,c,0,"our.current_brush.smudge_resample_length");
|
|
|
+ }laEndCondition(uil,b);
|
|
|
+
|
|
|
+ laShowLabel(uil,c,"Select a brush:",0,0);
|
|
|
+
|
|
|
+ laShowItemFull(uil,c,0,"our.brushes",0,0,0,0);
|
|
|
+ laShowItem(uil,c,0,"OUR_new_brush");
|
|
|
+ }laEndCondition(uil,bt);
|
|
|
+
|
|
|
+ bt=laOnConditionThat(uil,c,laEqual(laPropExpression(0,"our.tool"),laIntExpression(OUR_TOOL_CROP)));{
|
|
|
+ laShowItemFull(uil,c,0,"our.show_border",LA_WIDGET_ENUM_HIGHLIGHT,0,0,0);
|
|
|
+ laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"our.show_border"));{
|
|
|
+ laShowLabel(uil,cl,"Position:",0,0); laShowItem(uil,cr,0,"our.canvas.position")->Flags|=LA_UI_FLAGS_TRANSPOSE;
|
|
|
+ laShowSeparator(uil,c);
|
|
|
+ laShowLabel(uil,cl,"Size:",0,0); laShowItem(uil,cr,0,"our.canvas.size")->Flags|=LA_UI_FLAGS_TRANSPOSE;
|
|
|
+ laShowSeparator(uil,c);
|
|
|
+ laShowItem(uil,c,0,"our.border_alpha");
|
|
|
+ }laEndCondition(uil,b);
|
|
|
+ }laEndCondition(uil,bt);
|
|
|
}
|
|
|
void ourui_ColorPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps, laColumn *UNUSED, int context){
|
|
|
laColumn* c=laFirstColumn(uil);
|
|
@@ -137,7 +155,6 @@ void ourui_ColorPanel(laUiList *uil, laPropPack *This, laPropPack *DetachedProps
|
|
|
laShowItemFull(uil,c,0,"our.current_color",LA_WIDGET_FLOAT_COLOR_HCY,0,0,0);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
void our_CanvasDrawTextures(){
|
|
|
tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0); tnsUseNoTexture();
|
|
|
for(OurLayer* l=Our->Layers.pLast;l;l=l->Item.pPrev){
|
|
@@ -154,7 +171,6 @@ void our_CanvasDrawTextures(){
|
|
|
if(any) tnsFlush();
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
void our_CanvasDrawTiles(){
|
|
|
OurLayer* l=Our->CurrentLayer; if(!l) return;
|
|
|
tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0); tnsUseNoTexture();
|
|
@@ -175,7 +191,21 @@ void our_CanvasDrawTiles(){
|
|
|
}
|
|
|
}
|
|
|
if(any) tnsFlush();
|
|
|
-
|
|
|
+}
|
|
|
+void our_CanvasDrawCropping(OurCanvasDraw* ocd){
|
|
|
+ tnsUseImmShader; tnsEnableShaderv(T->immShader); tnsUniformUseTexture(T->immShader,0,0); tnsUseNoTexture();
|
|
|
+ tnsColor4d(0,0,0,Our->BorderAlpha);
|
|
|
+ tnsVertex2d(-1e6,Our->Y); tnsVertex2d(1e6,Our->Y); tnsVertex2d(-1e6,1e6); tnsVertex2d(1e6,1e6); tnsPackAs(GL_TRIANGLE_FAN);
|
|
|
+ tnsVertex2d(-1e6,Our->Y); tnsVertex2d(Our->X,Our->Y); tnsVertex2d(Our->X,Our->Y-Our->H); tnsVertex2d(-1e6,Our->Y-Our->H); tnsPackAs(GL_TRIANGLE_FAN);
|
|
|
+ tnsVertex2d(1e6,Our->Y); tnsVertex2d(Our->X+Our->W,Our->Y); tnsVertex2d(Our->X+Our->W,Our->Y-Our->H); tnsVertex2d(1e6,Our->Y-Our->H); tnsPackAs(GL_TRIANGLE_FAN);
|
|
|
+ tnsVertex2d(-1e6,Our->Y-Our->H); tnsVertex2d(1e6,Our->Y-Our->H); tnsVertex2d(-1e6,-1e6); tnsVertex2d(1e6,-1e6); tnsPackAs(GL_TRIANGLE_FAN);
|
|
|
+
|
|
|
+ if(Our->Tool==OUR_TOOL_CROP){
|
|
|
+ tnsColor4dv(laAccentColor(LA_BT_TEXT));
|
|
|
+ tnsVertex2d(Our->X,Our->Y); tnsVertex2d(Our->X+Our->W,Our->Y); tnsVertex2d(Our->X+Our->W,Our->Y-Our->H); tnsVertex2d(Our->X,Our->Y-Our->H);
|
|
|
+ tnsPackAs(GL_LINE_LOOP);
|
|
|
+ glLineWidth(3); tnsFlush(); glLineWidth(1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
@@ -230,6 +260,7 @@ void our_CanvasDrawCanvas(laBoxedTheme *bt, OurPaint *unused_c, laUiItem* ui){
|
|
|
tnsClearColor(LA_COLOR3(Our->BackgroundColor),1); tnsClearAll();
|
|
|
//if(ocd->ShowTiles){ our_CanvasDrawTiles(); }
|
|
|
our_CanvasDrawTextures();
|
|
|
+ if(Our->ShowBorder){ our_CanvasDrawCropping(ocd); }
|
|
|
|
|
|
//glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
|
|
|
}
|
|
@@ -270,9 +301,9 @@ void our_LayerEnsureTiles(OurLayer* ol, real xmin,real xmax, real ymin,real ymax
|
|
|
for(int col=l;col<=r;col++){
|
|
|
if(ol->TexTiles[row][col]) continue;
|
|
|
ol->TexTiles[row][col]=memAcquireSimple(sizeof(OurTexTile));
|
|
|
- ol->TexTiles[row][col]->Texture=tnsCreate2DTexture(GL_RGBA8,OUR_TEX_TILE_W,OUR_TEX_TILE_W,0);
|
|
|
- float initColor[]={0,0,0,0};
|
|
|
- glClearTexImage(ol->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_BGRA, GL_UNSIGNED_BYTE, &initColor);
|
|
|
+ ol->TexTiles[row][col]->Texture=tnsCreate2DTexture(GL_RGBA16,OUR_TEX_TILE_W,OUR_TEX_TILE_W,0);
|
|
|
+ uint16_t initColor[]={0,0,0,0};
|
|
|
+ glClearTexImage(ol->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_RGBA, GL_UNSIGNED_SHORT, 0);
|
|
|
}
|
|
|
}
|
|
|
*tl=l; *tr=r; *tu=u; *tb=b;
|
|
@@ -341,7 +372,7 @@ void our_PaintDoDabs(OurLayer* l,int tl, int tr, int tu, int tb, int Start, int
|
|
|
for(int row=tb;row<=tu;row++){
|
|
|
for(int col=tl;col<=tr;col++){
|
|
|
OurTexTile* ott=l->TexTiles[row][col];
|
|
|
- glBindImageTexture(0, ott->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
|
|
+ glBindImageTexture(0, ott->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16);
|
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
|
for(int i=Start;i<End;i++){
|
|
|
our_PaintDoDab(&Our->Dabs[i],sx,sx+OUR_TEX_TILE_W,sy,sy+OUR_TEX_TILE_W);
|
|
@@ -371,9 +402,9 @@ void our_PaintDoDabsWithSmudgeSegments(OurLayer* l,int tl, int tr, int tu, int t
|
|
|
float x=Our->Dabs[oss->Start].X, y=Our->Dabs[oss->Start].Y;
|
|
|
int col=(int)(floor(OUR_TEX_TILE_CTR+x/OUR_TEX_TILE_W_USE+0.5)); TNS_CLAMP(col,0,OUR_TEX_TILES_PER_ROW-1);
|
|
|
int row=(int)(floor(OUR_TEX_TILE_CTR+y/OUR_TEX_TILE_W_USE+0.5)); TNS_CLAMP(row,0,OUR_TEX_TILES_PER_ROW-1);
|
|
|
- glBindImageTexture(0, l->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
|
|
+ glBindImageTexture(0, l->TexTiles[row][col]->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16);
|
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
|
- glBindImageTexture(1, Our->SmudgeTexture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
|
|
+ glBindImageTexture(1, Our->SmudgeTexture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16);
|
|
|
our_PaintDoSample(x,y,sx,sy);
|
|
|
Our->CurrentBrush->SmudgeRestart=0;
|
|
|
}
|
|
@@ -383,7 +414,7 @@ void our_PaintDoDabsWithSmudgeSegments(OurLayer* l,int tl, int tr, int tu, int t
|
|
|
for(int row=tb;row<=tu;row++){
|
|
|
for(int col=tl;col<=tr;col++){
|
|
|
OurTexTile* ott=l->TexTiles[row][col];
|
|
|
- tnsBindTexture(ott->Texture); glBindImageTexture(0, ott->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA8);
|
|
|
+ tnsBindTexture(ott->Texture); glBindImageTexture(0, ott->Texture->GLTexHandle, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA16);
|
|
|
int sx=((real)col-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM,sy=((real)row-OUR_TEX_TILE_CTR-0.5)*OUR_TEX_TILE_W_USE-OUR_TEX_TILE_SEAM;
|
|
|
for(int i=oss->Start;i<oss->End;i++){
|
|
|
our_PaintDoDab(&Our->Dabs[i],sx,sx+OUR_TEX_TILE_W,sy,sy+OUR_TEX_TILE_W);
|
|
@@ -405,6 +436,32 @@ void our_ReadWidgetColor(laCanvasExtra*e,int x,int y){
|
|
|
Our->CurrentColor[2]=(real)color[2]/255*a;
|
|
|
}
|
|
|
|
|
|
+void our_StartCropping(OurCanvasDraw* cd){
|
|
|
+ if(cd->CanvasDownX<Our->X){
|
|
|
+ if(cd->CanvasDownY<Our->Y-Our->H){ cd->AtCrop=OUR_AT_CROP_BL; }
|
|
|
+ elif(cd->CanvasDownY>=Our->Y-Our->H&&cd->CanvasDownY<=Our->Y){ cd->AtCrop=OUR_AT_CROP_L; }
|
|
|
+ elif(cd->CanvasDownY>Our->Y){ cd->AtCrop=OUR_AT_CROP_UL; }
|
|
|
+ }elif(cd->CanvasDownX>=Our->X&&cd->CanvasDownX<=Our->X+Our->W){
|
|
|
+ if(cd->CanvasDownY<Our->Y-Our->H){ cd->AtCrop=OUR_AT_CROP_B; }
|
|
|
+ elif(cd->CanvasDownY>=Our->Y-Our->H&&cd->CanvasDownY<=Our->Y){ cd->AtCrop=OUR_AT_CROP_CENTER; }
|
|
|
+ elif(cd->CanvasDownY>Our->Y){ cd->AtCrop=OUR_AT_CROP_U; }
|
|
|
+ }elif(cd->CanvasDownX>Our->X+Our->W){
|
|
|
+ if(cd->CanvasDownY<Our->Y-Our->H){ cd->AtCrop=OUR_AT_CROP_BR; }
|
|
|
+ elif(cd->CanvasDownY>=Our->Y-Our->H&&cd->CanvasDownY<=Our->Y){ cd->AtCrop=OUR_AT_CROP_R; }
|
|
|
+ elif(cd->CanvasDownY>Our->Y){ cd->AtCrop=OUR_AT_CROP_UR; }
|
|
|
+ }
|
|
|
+}
|
|
|
+void our_DoCropping(OurCanvasDraw* cd, real x, real y){
|
|
|
+ int dx=x-cd->CanvasLastX, dy=y-cd->CanvasLastY;
|
|
|
+ if(cd->AtCrop==OUR_AT_CROP_B||cd->AtCrop==OUR_AT_CROP_BL||cd->AtCrop==OUR_AT_CROP_BR){ Our->H-=dy; }
|
|
|
+ if(cd->AtCrop==OUR_AT_CROP_U||cd->AtCrop==OUR_AT_CROP_UL||cd->AtCrop==OUR_AT_CROP_UR){ Our->Y+=dy; Our->H+=dy; }
|
|
|
+ if(cd->AtCrop==OUR_AT_CROP_L||cd->AtCrop==OUR_AT_CROP_BL||cd->AtCrop==OUR_AT_CROP_UL){ Our->X+=dx; Our->W-=dx; }
|
|
|
+ if(cd->AtCrop==OUR_AT_CROP_R||cd->AtCrop==OUR_AT_CROP_BR||cd->AtCrop==OUR_AT_CROP_UR){ Our->W+=dx; }
|
|
|
+ if(cd->AtCrop==OUR_AT_CROP_CENTER){ Our->Y+=dy; Our->X+=dx; }
|
|
|
+ if(Our->W<32) Our->W=32; if(Our->H<32) Our->H=32;
|
|
|
+ cd->CanvasLastX+=dx; cd->CanvasLastY+=dy;
|
|
|
+}
|
|
|
+
|
|
|
int ourinv_NewLayer(laOperator* a, laEvent* e){
|
|
|
our_NewLayer("Our Layer"); laNotifyUsers("our.canvas.layers");
|
|
|
return LA_FINISHED;
|
|
@@ -438,15 +495,17 @@ int ourinv_MoveBrush(laOperator* a, laEvent* e){
|
|
|
return LA_FINISHED;
|
|
|
}
|
|
|
|
|
|
-int ourinv_Paint(laOperator* a, laEvent* e){
|
|
|
+int ourinv_Action(laOperator* a, laEvent* e){
|
|
|
OurLayer* l=Our->CurrentLayer; OurCanvasDraw *ex = a->This?a->This->EndInstance:0; OurBrush* ob=Our->CurrentBrush; if(!l||!ex||!ob) return LA_CANCELED;
|
|
|
our_PaintResetBrushState(ob);
|
|
|
real x,y; our_UiToCanvas(&ex->Base,e,&x,&y); ex->CanvasLastX=x;ex->CanvasLastY=y;ex->LastPressure=e->Pressure;
|
|
|
+ ex->CanvasDownX=x; ex->CanvasDownY=y;
|
|
|
+ Our->ActiveTool=Our->Tool;
|
|
|
+ if(Our->ActiveTool==OUR_TOOL_CROP){ if(!Our->ShowBorder) return LA_FINISHED; our_StartCropping(ex); }
|
|
|
return LA_RUNNING;
|
|
|
}
|
|
|
int ourmod_Paint(laOperator* a, laEvent* e){
|
|
|
OurLayer* l=Our->CurrentLayer; OurCanvasDraw *ex = a->This?a->This->EndInstance:0; OurBrush* ob=Our->CurrentBrush; if(!l||!ex||!ob) return LA_CANCELED;
|
|
|
-
|
|
|
if(e->Type==LA_L_MOUSE_UP || e->Type==LA_R_MOUSE_DOWN || e->Type==LA_ESCAPE_DOWN){ return LA_FINISHED; }
|
|
|
|
|
|
if(e->Type==LA_MOUSEMOVE||e->Type==LA_L_MOUSE_DOWN){
|
|
@@ -461,6 +520,29 @@ int ourmod_Paint(laOperator* a, laEvent* e){
|
|
|
|
|
|
return LA_RUNNING;
|
|
|
}
|
|
|
+int ourmod_Crop(laOperator* a, laEvent* e){
|
|
|
+ OurLayer* l=Our->CurrentLayer; OurCanvasDraw *ex = a->This?a->This->EndInstance:0; OurBrush* ob=Our->CurrentBrush; if(!l||!ex||!ob) return LA_CANCELED;
|
|
|
+ if(e->Type==LA_L_MOUSE_UP || e->Type==LA_R_MOUSE_DOWN || e->Type==LA_ESCAPE_DOWN){ return LA_FINISHED; }
|
|
|
+
|
|
|
+ if(e->Type==LA_MOUSEMOVE||e->Type==LA_L_MOUSE_DOWN){
|
|
|
+ real x,y; our_UiToCanvas(&ex->Base,e,&x,&y);
|
|
|
+ our_DoCropping(ex,x,y);
|
|
|
+ laNotifyUsers("our.canvas");
|
|
|
+ }
|
|
|
+
|
|
|
+ return LA_RUNNING;
|
|
|
+}
|
|
|
+int ourmod_Action(laOperator* a, laEvent* e){
|
|
|
+ OurCanvasDraw *ex = a->This?a->This->EndInstance:0; if(!ex) return LA_CANCELED;
|
|
|
+ switch(Our->ActiveTool){
|
|
|
+ case OUR_TOOL_PAINT: OurLayer* l=Our->CurrentLayer; OurBrush* ob=Our->CurrentBrush; if(!l||!ob) return LA_CANCELED;
|
|
|
+ return ourmod_Paint(a,e);
|
|
|
+ case OUR_TOOL_CROP:
|
|
|
+ return ourmod_Crop(a,e);
|
|
|
+ default: return LA_FINISHED;
|
|
|
+ }
|
|
|
+ return LA_RUNNING;
|
|
|
+}
|
|
|
int ourinv_PickColor(laOperator* a, laEvent* e){
|
|
|
OurLayer* l=Our->CurrentLayer; OurCanvasDraw *ex = a->This?a->This->EndInstance:0; OurBrush* ob=Our->CurrentBrush; if(!l||!ex||!ob) return LA_CANCELED;
|
|
|
laUiItem* ui=ex->Base.ParentUi;
|
|
@@ -499,8 +581,22 @@ void ourset_BrushMove(OurBrush* b, int move){
|
|
|
elif(move>0 && b->Item.pNext){ lstMoveDown(&Our->Brushes, b); laNotifyUsers("our.brushes"); }
|
|
|
}
|
|
|
void ourset_BackgroundColor(void* unused, real* arr){
|
|
|
- memcpy(Our->BackgroundColor, arr, sizeof(real)*3);
|
|
|
- laNotifyUsers("our.canvas");
|
|
|
+ memcpy(Our->BackgroundColor, arr, sizeof(real)*3); laNotifyUsers("our.canvas");
|
|
|
+}
|
|
|
+void ourset_BorderAlpha(void* unused, real a){
|
|
|
+ Our->BorderAlpha=a; laNotifyUsers("our.canvas");
|
|
|
+}
|
|
|
+void ourset_Tool(void* unused, int a){
|
|
|
+ Our->Tool=a; laNotifyUsers("our.canvas");
|
|
|
+}
|
|
|
+void ourset_ShowBorder(void* unused, int a){
|
|
|
+ Our->ShowBorder=a; laNotifyUsers("our.canvas");
|
|
|
+}
|
|
|
+void ourset_CanvasSize(void* unused, int* wh){
|
|
|
+ Our->W=wh[0]; Our->H=wh[1]; if(Our->W<32) Our->W=32; if(Our->H<32) Our->H=32; laNotifyUsers("our.canvas");
|
|
|
+}
|
|
|
+void ourset_CanvasPosition(void* unused, int* xy){
|
|
|
+ Our->X=xy[0]; Our->Y=xy[1]; laNotifyUsers("our.canvas");
|
|
|
}
|
|
|
|
|
|
#define OUR_ADD_PRESSURE_SWITCH(p)\
|
|
@@ -516,12 +612,12 @@ void ourRegisterEverything(){
|
|
|
laCreateOperatorType("OUR_new_brush","New Brush","Create a new brush",0,0,0,ourinv_NewBrush,0,'+',0);
|
|
|
laCreateOperatorType("OUR_remove_brush","Remove Brush","Remove this brush",0,0,0,ourinv_RemoveBrush,0,L'🗴',0);
|
|
|
laCreateOperatorType("OUR_move_brush","Move Brush","Remove this brush",0,0,0,ourinv_MoveBrush,0,0,0);
|
|
|
- laCreateOperatorType("OUR_paint","Paint","Paint on a layer",0,0,0,ourinv_Paint,ourmod_Paint,0,LA_EXTRA_TO_PANEL);
|
|
|
+ laCreateOperatorType("OUR_action","Action","Doing action on a layer",0,0,0,ourinv_Action,ourmod_Action,0,LA_EXTRA_TO_PANEL);
|
|
|
laCreateOperatorType("OUR_pick","Pick color","Pick color on the widget",0,0,0,ourinv_PickColor,ourmod_PickColor,0,LA_EXTRA_TO_PANEL);
|
|
|
|
|
|
laRegisterUiTemplate("panel_canvas", "Canvas", ourui_CanvasPanel, 0, 0,"Our Paint");
|
|
|
laRegisterUiTemplate("panel_layers", "Layers", ourui_LayersPanel, 0, 0,0);
|
|
|
- laRegisterUiTemplate("panel_brushes", "Brushes", ourui_BrushesPanel, 0, 0,0);
|
|
|
+ laRegisterUiTemplate("panel_tools", "Tools", ourui_ToolsPanel, 0, 0,0);
|
|
|
laRegisterUiTemplate("panel_color", "Color", ourui_ColorPanel, 0, 0,0);
|
|
|
|
|
|
pc=laDefineRoot();
|
|
@@ -533,6 +629,13 @@ void ourRegisterEverything(){
|
|
|
laAddSubGroup(pc,"current_brush","Current Brush","Current brush","our_brush",0,0,0,offsetof(OurPaint,CurrentBrush),ourget_FirstBrush,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
|
|
|
laAddFloatProperty(pc,"current_color","Current Color","Current color used to paint",0,0,0,1,0,0.05,0.8,0,offsetof(OurPaint,CurrentColor),0,0,4,0,0,0,0,0,0,0,0);
|
|
|
laAddFloatProperty(pc,"background_color","Background Color","Background color of the canvas",0,0,0,1,0,0.05,0.8,0,offsetof(OurPaint,BackgroundColor),0,0,3,0,0,0,0,ourset_BackgroundColor,0,0,0);
|
|
|
+ laAddFloatProperty(pc,"border_alpha","Border Alpha","Alpha of the border region around the canvas",0,0,0,1,0,0.05,0.5,0,offsetof(OurPaint,BorderAlpha),0,0,0,0,0,0,0,ourset_BorderAlpha,0,0,0);
|
|
|
+ p=laAddEnumProperty(pc,"tool","Tool","Tool to use on the canvas",0,0,0,0,0,offsetof(OurPaint,Tool),0,ourset_Tool,0,0,0,0,0,0,0,0);
|
|
|
+ laAddEnumItemAs(p,"PAINT","Paint","Paint stuff on the canvas",OUR_TOOL_PAINT,L'🖌');
|
|
|
+ laAddEnumItemAs(p,"CROP","Cropping","Crop the focused region",OUR_TOOL_CROP,L'🖼');
|
|
|
+ p=laAddEnumProperty(pc,"show_border","Show Border","Whether to show border on the canvas",0,0,0,0,0,offsetof(OurPaint,ShowBorder),0,ourset_ShowBorder,0,0,0,0,0,0,0,0);
|
|
|
+ laAddEnumItemAs(p,"FALSE","No","Dont' show border on the canvas",OUR_TOOL_PAINT,L'🖌');
|
|
|
+ laAddEnumItemAs(p,"TRUE","Yes","Show border on the canvas",OUR_TOOL_CROP,L'🖼');
|
|
|
|
|
|
pc=laAddPropertyContainer("our_brush","Our Brush","OurPaint brush",0,0,sizeof(OurBrush),0,0,2);
|
|
|
laAddStringProperty(pc,"name","Name","Name of the layer",0,0,0,0,1,offsetof(OurBrush,Name),0,0,0,0,LA_AS_IDENTIFIER);
|
|
@@ -557,6 +660,8 @@ void ourRegisterEverything(){
|
|
|
pc=laAddPropertyContainer("our_canvas","Our Canvas","OurPaint canvas",0,0,sizeof(OurPaint),0,0,1);
|
|
|
laAddSubGroup(pc,"layers","Layers","Layers","our_layer",0,0,ourui_Layer,offsetof(OurPaint,CurrentLayer),0,0,0,0,0,0,offsetof(OurPaint,Layers),0);
|
|
|
laAddSubGroup(pc,"current_layer","Current Layer","Current layer","our_layer",0,0,0,offsetof(OurPaint,CurrentLayer),ourget_FirstLayer,0,laget_ListNext,0,0,0,0,LA_UDF_REFER);
|
|
|
+ laAddIntProperty(pc,"size","Size","Size of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,W),0,0,2,0,0,0,0,ourset_CanvasSize,0,0,0);
|
|
|
+ laAddIntProperty(pc,"position","Position","Position of the cropping area",0,"X,Y","px",0,0,0,2400,0,offsetof(OurPaint,X),0,0,2,0,0,0,0,ourset_CanvasPosition,0,0,0);
|
|
|
|
|
|
pc=laAddPropertyContainer("our_layer","Our Layer","OurPaint layer",0,0,sizeof(OurLayer),0,0,1);
|
|
|
laAddStringProperty(pc,"name","Name","Name of the layer",0,0,0,0,1,offsetof(OurLayer,Name),0,0,0,0,LA_AS_IDENTIFIER);
|
|
@@ -572,7 +677,7 @@ void ourRegisterEverything(){
|
|
|
laAssignNewKey(km, 0, "LA_2d_view_zoom", LA_KM_SEL_UI_EXTRA, 0, LA_MOUSE_WHEEL_UP, 0, "direction=in");
|
|
|
laAssignNewKey(km, 0, "LA_2d_view_move", LA_KM_SEL_UI_EXTRA, LA_KEY_ALT, LA_L_MOUSE_DOWN, 0, 0);
|
|
|
laAssignNewKey(km, 0, "LA_2d_view_move", LA_KM_SEL_UI_EXTRA, 0, LA_M_MOUSE_DOWN, 0, 0);
|
|
|
- laAssignNewKey(km, 0, "OUR_paint", LA_KM_SEL_UI_EXTRA, 0, LA_L_MOUSE_DOWN, 0, 0);
|
|
|
+ laAssignNewKey(km, 0, "OUR_action", LA_KM_SEL_UI_EXTRA, 0, LA_L_MOUSE_DOWN, 0, 0);
|
|
|
laAssignNewKey(km, 0, "OUR_pick", LA_KM_SEL_UI_EXTRA, 0, LA_R_MOUSE_DOWN, 0, 0);
|
|
|
}
|
|
|
|
|
@@ -584,7 +689,7 @@ void ourInit(){
|
|
|
|
|
|
char error[1024]; int status;
|
|
|
|
|
|
- Our->SmudgeTexture=tnsCreate2DTexture(GL_RGBA,256,1,0);
|
|
|
+ Our->SmudgeTexture=tnsCreate2DTexture(GL_RGBA16,256,1,0);
|
|
|
|
|
|
Our->CanvasShader = glCreateShader(GL_COMPUTE_SHADER);
|
|
|
const GLchar* source = OUR_CANVAS_SHADER;
|
|
@@ -619,6 +724,10 @@ void ourInit(){
|
|
|
Our->RoutineDoDabs=glGetSubroutineIndex(Our->CanvasProgram, GL_COMPUTE_SHADER, "DoDabs");
|
|
|
Our->RoutineDoSample=glGetSubroutineIndex(Our->CanvasProgram, GL_COMPUTE_SHADER, "DoSample");
|
|
|
|
|
|
+ Our->X=-2800/2; Our->W=2800;
|
|
|
+ Our->Y=2400/2; Our->H=2400;
|
|
|
+ Our->BorderAlpha=0.6;
|
|
|
+
|
|
|
tnsEnableShaderv(T->immShader);
|
|
|
}
|
|
|
|