/* ----------------------------------------------------------------------------- This source file is part of OpenSpace3D For the latest info, see http://www.openspace3d.com Copyright (c) 2020 I-maginer This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA, or go to http://www.gnu.org/copyleft/lesser.txt ----------------------------------------------------------------------------- */ struct PlugDraw = [ DRW_instance : PInstance, DRW_bOnMaterial : I, DRW_Material : SO3_MATERIAL, DRW_iTechnique : I, DRW_iPass : I, DRW_iTexture : I, DRW_lPath : [[I [[[I I] r1] I I I I]] r1], DRW_lFullPaths : [[[[I I] r1] I I I I] r1], DRW_lUndoPaths : [[[[I I] r1] I I I I] r1], DRW_iBrushColor : [[I I] r1], DRW_iBrushSize : [[I I] r1], DRW_iBrushAlpha : [[I I] r1], DRW_win : SO3_WIDGET, DRW_AlphaBuffer : AlphaBitmap, DRW_iPosX : I, DRW_iPosY : I, DRW_iWidth : I, DRW_iHeight : I, DRW_tPercent : [I I I I I I I I], DRW_tAlign : [I I], DRW_bTransparency : I, DRW_iOpacity : I, DRW_sPath : S, DRW_bBackground : I, DRW_bMouseDrawing : I, DRW_iDrawMode : I, DRW_bShow : I ] MkPlugDraw;; var sDrawingPath = "tmp/draw/";; fun restoreTexture(drawstr)= V3DremoveWidgetControl (V3DgetDefaultViewport (V3DgetSessionView c3dXsession)) drawstr.DRW_win; SO3WidgetDestroy drawstr.DRW_win; set drawstr.DRW_win = nil; _DSalphaBitmap drawstr.DRW_AlphaBuffer; set drawstr.DRW_AlphaBuffer = nil; 0;; fun cbShow(inst, from, action, param, reply, drawstr)= SO3WidgetSetVisibility drawstr.DRW_win 1; set drawstr.DRW_bShow = 1; 0;; fun cbHide(inst, from, action, param, reply, drawstr)= SO3WidgetSetVisibility drawstr.DRW_win 0; set drawstr.DRW_bShow = 0; 0;; fun createBuffer(w, h, drawstr)= _DSalphaBitmap drawstr.DRW_AlphaBuffer; let _FILLbitmap _CRbitmap _channel w h 0xffffff -> bmp in let _FILLbitmap8 _CRbitmap8 _channel w h 0 -> alpha in let _CRalphaBitmap _channel bmp alpha nil nil -> abmp in ( _DSbitmap bmp; _DSbitmap8 alpha; set drawstr.DRW_AlphaBuffer = abmp; ); 0;; fun reDrawAll(drawstr)= let _GETalphaBitmaps drawstr.DRW_AlphaBuffer -> [buffer alpha] in ( _FILLbitmap buffer 0xffffff; _FILLbitmap8 alpha 0; let revertlist drawstr.DRW_lFullPaths -> l in while (l != nil) do ( let hd l -> [lpath color a thick mode] in ( if (mode == 0) then ( _BTDRAWpath buffer lpath color thick; _BTDRAWpath8 alpha lpath a thick; 0; ) else if (mode == 1) then ( let hd lpath -> [px py] in ( _BTDRAWfloodFill buffer [px py] color; _BTDRAWfloodFill8 alpha [px py] a; ); 0; ) else nil; ); set l = tl l; ); ); SO3BitmapWidgetBlitAlpha drawstr.DRW_win drawstr.DRW_AlphaBuffer; 0;; fun computePosSize(drawstr, vw, vh)= let drawstr.DRW_tPercent -> [px py pw ph xo yo wo ho] in let drawstr.DRW_tAlign -> [ax ay] in let if pw then (ftoi (((itof drawstr.DRW_iWidth) /. 100.0) *. (itof vw))) + wo else drawstr.DRW_iWidth -> pw in let if ph then (ftoi (((itof drawstr.DRW_iHeight) /. 100.0) *. (itof vh))) + ho else drawstr.DRW_iHeight -> ph in let if px then (ftoi (((itof drawstr.DRW_iPosX) /. 100.0) *. (itof vw))) + xo else drawstr.DRW_iPosX -> px in let if (ax == 1) then ((vw / 2) - (pw / 2)) + px else if (ax == 2) then (vw - pw) - px else px -> px in let if py then (ftoi (((itof drawstr.DRW_iPosY) /. 100.0) *. (itof vh))) + yo else drawstr.DRW_iPosY -> py in let if (ay == 1) then ((vh / 2) - (ph / 2)) + py else if (ay == 2) then (vh - ph) - py else py -> py in [px py pw ph];; fun cbResizeCtrl(inst, viewstr, vw, vh, drawstr)= if drawstr.DRW_win == nil || drawstr.DRW_bOnMaterial then nil else let computePosSize drawstr vw vh -> [px py pw ph] in ( SO3WidgetSetPosition drawstr.DRW_win px py; SO3WidgetSetSize drawstr.DRW_win pw ph; createBuffer pw ph drawstr; reDrawAll drawstr; ); 0;; fun drawNext(drawstr, id)= let if (id == nil) then 0 else id -> id in let switch drawstr.DRW_lPath id -> tpath in if (tpath == nil) then nil else ( set drawstr.DRW_lFullPaths = tpath::drawstr.DRW_lFullPaths; set drawstr.DRW_lPath = remove_idx_from_list drawstr.DRW_lPath id; ); 0;; fun drawBuffer(drawstr, x, y, id)= let _GETalphaBitmapSize drawstr.DRW_AlphaBuffer -> [bw bh] in if ((x == nil) || (y == nil) || (x <= 0) || (y <= 0) || (x >= bw) || (y >= bh)) then ( drawNext drawstr id; 0; ) else let if (id == nil) then 0 else id -> id in let _GETalphaBitmaps drawstr.DRW_AlphaBuffer -> [buffer alpha] in ( let switch drawstr.DRW_lPath id -> tpath in let switch drawstr.DRW_iBrushColor id -> color in let if (color == nil) then switch drawstr.DRW_iBrushColor 0 else color -> color in let switch drawstr.DRW_iBrushAlpha id -> acolor in let if (acolor == nil) then switch drawstr.DRW_iBrushAlpha 0 else acolor -> acolor in let switch drawstr.DRW_iBrushSize id -> thick in let if (thick == nil) then switch drawstr.DRW_iBrushSize 0 else thick -> thick in if (tpath == nil) then ( set drawstr.DRW_lPath = [id [[x y]::nil color acolor thick drawstr.DRW_iDrawMode]]::drawstr.DRW_lPath; 0; ) else ( let tpath -> [lpath _ _ _ _] in mutate tpath <- [[x y]::lpath _ _ _ _]; 0; ); let switch drawstr.DRW_lPath id -> [lpath color a thick mode] in let hd lpath -> fpt in let hd tl lpath -> npt in let fpt -> [px py] in let if (npt == nil) then fpt else npt -> [dx dy] in ( if (mode == 0) then ( _BTDRAWline buffer [px py] [dx dy] color thick; _BTDRAWline8 alpha [px py] [dx dy] a thick; 0; ) else if (mode == 1) then ( _BTDRAWfloodFill buffer [px py] color; _BTDRAWfloodFill8 alpha [px py] a; 0; ) else nil; SO3BitmapWidgetBlitAlpha drawstr.DRW_win drawstr.DRW_AlphaBuffer; ); 0; ); 0;; fun cbInputDown(widget, drawstr, id, x, y, btn)= if ((btn != 1) /*|| (drawstr.DRW_iDrawMode != 1)*/) then nil else ( drawNext drawstr id; if !(SO3WidgetHasFocus widget) then nil else drawBuffer drawstr x y id; ); 0;; fun cbInputUp(widget, drawstr, id, x, y, btn)= if (btn != 1) then nil else drawNext drawstr id; 0;; fun cbInputUpdate(widget, drawstr, id, x, y, btn)= if ((btn != 1) || !(SO3WidgetHasFocus widget)) then nil else drawBuffer drawstr x y id; 0;; fun cbInputOut(widget, drawstr, id)= drawNext drawstr id; 0;; fun createPicture(inst, drawstr)= let V3DgetSessionView c3dXsession -> viewstr in let V3DgetDefaultViewport viewstr -> viewportstr in if drawstr.DRW_win != nil then nil else ( V3DremoveWidgetControl viewportstr drawstr.DRW_win; SO3WidgetDestroy drawstr.DRW_win; if drawstr.DRW_bOnMaterial then ( set drawstr.DRW_win = SO3BitmapWidgetCreateOnMaterial (V3DgetSession c3dXsession) drawstr.DRW_Material (strcat (getPluginInstanceName inst) "_drawCtrl") drawstr.DRW_iWidth drawstr.DRW_iHeight drawstr.DRW_iTechnique drawstr.DRW_iPass drawstr.DRW_iTexture; createBuffer drawstr.DRW_iWidth drawstr.DRW_iHeight drawstr; 0; ) else if drawstr.DRW_bBackground then ( let V3DgetViewportSize viewstr viewportstr -> [_ _ vw vh] in let computePosSize drawstr vw vh -> [px py pw ph] in ( set drawstr.DRW_win = SO3BitmapWidgetCreateBackground (V3DgetSession c3dXsession) viewportstr.V3D_viewport (strcat (getPluginInstanceName inst) "_drawCtrl") px py pw ph; createBuffer pw ph drawstr; ); 0; ) else ( let V3DgetViewportSize viewstr viewportstr -> [_ _ vw vh] in let computePosSize drawstr vw vh -> [px py pw ph] in ( set drawstr.DRW_win = SO3BitmapWidgetCreate (V3DgetSession c3dXsession) viewportstr.V3D_viewport (strcat (getPluginInstanceName inst) "_drawCtrl") px py pw ph 100; createBuffer pw ph drawstr; ); SO3WidgetSetTopOnFocus drawstr.DRW_win 0; SO3WidgetSetForeground drawstr.DRW_win 0; 0; ); V3DaddWidgetControl viewportstr drawstr.DRW_win; SO3WidgetSetKeyboardEnable drawstr.DRW_win 0; SO3WidgetSetMouseEnable drawstr.DRW_win drawstr.DRW_bMouseDrawing; if (!drawstr.DRW_bMouseDrawing) then nil else ( SO3WidgetInputDownEventCb drawstr.DRW_win @cbInputDown drawstr; SO3WidgetInputUpEventCb drawstr.DRW_win @cbInputUp drawstr; SO3WidgetInputUpdateEventCb drawstr.DRW_win @cbInputUpdate drawstr; SO3WidgetExitEventExCb drawstr.DRW_win @cbInputOut drawstr; ); SO3WidgetSetTransparency drawstr.DRW_win drawstr.DRW_bTransparency; SO3WidgetSetOpacity drawstr.DRW_win (itof drawstr.DRW_iOpacity) *. 0.01; SO3WidgetSetVisibility drawstr.DRW_win 0; SO3BitmapWidgetBlitAlpha drawstr.DRW_win drawstr.DRW_AlphaBuffer; ); 0;; fun cbDraw(inst, from, action, param, reply, drawstr)= if (param == nil) then nil else let strextr param -> lp in let atoi hd (hd lp) -> x in let atoi (hd tl (hd lp)) -> y in let atoi (hd tl tl (hd lp)) -> id in let if (id == nil) then 0 else id -> id in drawBuffer drawstr x y id; 0;; fun cbClear(inst, from, action, param, reply, drawstr)= let _GETalphaBitmaps drawstr.DRW_AlphaBuffer -> [buffer alpha] in ( set drawstr.DRW_lPath = nil; set drawstr.DRW_lFullPaths = nil; set drawstr.DRW_lUndoPaths = nil; _FILLbitmap buffer 0xffffff; _FILLbitmap8 alpha 0; SO3BitmapWidgetBlitAlpha drawstr.DRW_win drawstr.DRW_AlphaBuffer; ); 0;; fun cbNewDraw(inst, from, action, param, reply, drawstr)= let atoi reply -> id in let if (id == nil) then if (param == nil) then 0 else atoi param else id -> id in drawNext drawstr id; 0;; fun cbSetBrushColor(inst, from, action, param, reply, drawstr)= let hd strextr param -> lp in let atoi hd lp -> pr in let atoi hd tl lp -> pg in let atoi hd tl tl lp -> pb in let atoi hd tl tl tl lp -> pa in let atoi reply -> id in let if (id == nil) then 0 else id -> id in if (pr == nil) || (pg == nil) || (pb == nil) then ( let atoi hd tl lp -> nid in if (nid == nil) then nil else set id = nid; let (htoi hd lp) -> color in let get_rgba color -> [r g b a] in ( set drawstr.DRW_iBrushColor = remove_idx_from_list drawstr.DRW_iBrushColor id; set drawstr.DRW_iBrushAlpha = remove_idx_from_list drawstr.DRW_iBrushAlpha id; set drawstr.DRW_iBrushColor = [id (make_rgb r g b)]::drawstr.DRW_iBrushColor; set drawstr.DRW_iBrushAlpha = [id (if a == nil then 255 else a)]::drawstr.DRW_iBrushAlpha; ); ) else ( let atoi hd tl tl tl tl lp -> nid in if (nid == nil) then nil else set id = nid; set drawstr.DRW_iBrushColor = remove_idx_from_list drawstr.DRW_iBrushColor id; set drawstr.DRW_iBrushAlpha = remove_idx_from_list drawstr.DRW_iBrushAlpha id; set drawstr.DRW_iBrushColor = [id (make_rgb pr pg pb)]::drawstr.DRW_iBrushColor; set drawstr.DRW_iBrushAlpha = [id (if pa == nil then 255 else pa)]::drawstr.DRW_iBrushAlpha; ); 0;; fun cbSetBrushSize(inst, from, action, param, reply, drawstr)= let hd strextr param -> lp in let atoi hd lp -> thick in if ((thick == nil) || (!strcmp param "")) then nil else let atoi reply -> id in let if (id == nil) then atoi hd tl lp else id -> id in let if (id == nil) then 0 else id -> id in ( set drawstr.DRW_iBrushSize = remove_idx_from_list drawstr.DRW_iBrushSize id; set drawstr.DRW_iBrushSize = [id thick]::nil; ); 0;; fun cbSetDrawMode(inst, from, action, param, reply, drawstr)= set drawstr.DRW_iDrawMode = if ((atoi param) == nil) then 0 else atoi param; 0;; fun saveDrawing(drawstr)= let XMLcreate drawstr.DRW_sPath nil -> xmlstr in let XMLaddMark xmlstr "drawing" nil nil nil -> drawmark in ( let revertlist drawstr.DRW_lFullPaths -> l in while (l != nil) do ( let hd l -> [lp color alpha thick mode] in let XMLaddMark xmlstr "line" drawmark ["color" (itoh color)]::["alpha" (itoa alpha)]::["thick" (itoa thick)]::["mode" (itoa mode)]::nil nil -> linemark in while (lp != nil) do ( let hd lp -> [x y] in XMLaddMark xmlstr "point" linemark ["x" (itoa x)]::["y" (itoa y)]::nil nil; set lp = tl lp; ); set l = tl l; ); XMLwriteZipped xmlstr nil; XMLclose xmlstr; ); 0;; fun cbSaveDrawing(inst, from, action, param, reply, drawstr)= saveDrawing drawstr; 0;; fun loadDrawing(drawstr)= set drawstr.DRW_lFullPaths = nil; set drawstr.DRW_lUndoPaths = nil; let XMLload drawstr.DRW_sPath -> xmlstr in let XMLgetMarkByValue xmlstr "drawing" -> drawmark in let XMLgetMarksByValueFromMarkSons drawmark "line" -> llines in while (llines != nil) do ( let hd llines -> linemark in let htoi (XMLgetParam linemark "color") -> color in let atoi (XMLgetParam linemark "alpha") -> alpha in let atoi (XMLgetParam linemark "thick") -> thick in let atoi (XMLgetParam linemark "mode") -> mode in let if (mode == nil) then 0 else mode -> mode in let XMLgetMarksByValueFromMarkSons linemark "point" -> lpointmarks in let nil -> lpoints in ( while (lpointmarks != nil) do ( let hd lpointmarks -> pointmark in let atoi (XMLgetParam pointmark "x") -> x in let atoi (XMLgetParam pointmark "y") -> y in set lpoints = [x y]::lpoints; set lpointmarks = tl lpointmarks; ); set drawstr.DRW_lFullPaths = [lpoints color alpha thick mode]::drawstr.DRW_lFullPaths; ); set llines = tl llines; ); reDrawAll drawstr; 0;; fun cbLoadDrawing(inst, from, action, param, reply, drawstr)= loadDrawing drawstr; 0;; fun exportDrawing(inst, from, action, param, reply, drawstr)= let (localtime time) -> [seconds minutes hours day month year wd yd] in let strcatn (itoa year)::(if month < 10 then "0" else "")::(itoa month)::(if day < 10 then "0" else "")::(itoa day)::"_"::(if hours < 10 then "0" else "")::(itoa hours)::(if minutes < 10 then "0" else "")::(itoa minutes)::(if seconds < 10 then "0" else "")::(itoa seconds)::nil -> formateddate in let strcatn "%pictures%/drawing/"::formateddate::(if drawstr.DRW_bTransparency then ".png" else ".jpg")::nil -> file in _BTSAVEalphaBitmap drawstr.DRW_AlphaBuffer (_getmodifypack file); 0;; fun UndoDraw(inst, from, action, param, reply, drawstr)= set drawstr.DRW_lUndoPaths = (hd drawstr.DRW_lFullPaths)::drawstr.DRW_lUndoPaths; set drawstr.DRW_lFullPaths = tl drawstr.DRW_lFullPaths; reDrawAll drawstr; 0;; fun RedoDraw(inst, from, action, param, reply, drawstr)= set drawstr.DRW_lFullPaths = (hd drawstr.DRW_lUndoPaths)::drawstr.DRW_lFullPaths; set drawstr.DRW_lUndoPaths = tl drawstr.DRW_lUndoPaths; reDrawAll drawstr; 0;; // Destroy instance fun deleteOb(inst, drawstr)= restoreTexture drawstr; 0;; fun cbNewOb(inst)= let (getPluginInstanceParam inst "object") -> objname in let (getPluginInstanceParam inst "material") -> matname in let atoi (getPluginInstanceParam inst "technique") -> technique in let if (technique == nil) || (technique < 0) then 0 else technique -> technique in let atoi (getPluginInstanceParam inst "pass") -> pass in let if (pass == nil) || (pass < 0) then 0 else pass -> pass in let atoi (getPluginInstanceParam inst "texture") -> texture in let if (texture == nil) || (texture < 0) then 0 else texture -> texture in let atoi (getPluginInstanceParam inst "istexture") -> istexture in let if istexture == nil then 0 else istexture -> istexture in let (getPluginInstanceParam inst "path") -> filepath in let if (filepath == nil) then strcatn sDrawingPath::(getShortName getPluginInstanceFullname inst)::".draw"::nil else filepath -> filepath in let atoi (getPluginInstanceParam inst "xpercent") -> xpercent in let if xpercent == nil then 0 else xpercent -> xpercent in let atoi (getPluginInstanceParam inst "xalign") -> xalign in let if xalign == nil then 0 else xalign -> xalign in let atoi (getPluginInstanceParam inst "posx") -> posx in let if posx == nil then 0 else posx -> posx in let atoi (getPluginInstanceParam inst "ypercent") -> ypercent in let if ypercent == nil then 0 else ypercent -> ypercent in let atoi (getPluginInstanceParam inst "yalign") -> yalign in let if yalign == nil then 0 else yalign -> yalign in let atoi (getPluginInstanceParam inst "posy") -> posy in let if posy == nil then 0 else posy -> posy in let atoi (getPluginInstanceParam inst "wpercent") -> wpercent in let if wpercent == nil then 1 else wpercent -> wpercent in let atoi (getPluginInstanceParam inst "width") -> width in let if width == nil then 100 else width -> width in let atoi (getPluginInstanceParam inst "hpercent") -> hpercent in let if hpercent == nil then 1 else hpercent -> hpercent in let atoi (getPluginInstanceParam inst "xoffset") -> xoffset in let if xoffset == nil then 0 else xoffset -> xoffset in let atoi (getPluginInstanceParam inst "yoffset") -> yoffset in let if yoffset == nil then 0 else yoffset -> yoffset in let atoi (getPluginInstanceParam inst "woffset") -> woffset in let if woffset == nil then 0 else woffset -> woffset in let atoi (getPluginInstanceParam inst "hoffset") -> hoffset in let if hoffset == nil then 0 else hoffset -> hoffset in let atoi (getPluginInstanceParam inst "height") -> height in let if height == nil then 100 else height -> height in let atoi (getPluginInstanceParam inst "brushcolor") -> brushcolor in let if brushcolor == nil then 0x000000FF else brushcolor -> brushcolor in let get_rgba brushcolor -> [r g b brushalpha] in let if (brushalpha == nil) then 255 else brushalpha * 2 -> brushalpha in let make_rgb r g b -> brushcolor in let atoi (getPluginInstanceParam inst "brushsize") -> brushsize in let if brushsize == nil then 2 else brushsize -> brushsize in let atoi (getPluginInstanceParam inst "mouse") -> mouse in let if (mouse == nil) then 1 else mouse -> mouse in let atoi (getPluginInstanceParam inst "load") -> load in let if (load == nil) then 1 else load -> load in let atoi (getPluginInstanceParam inst "background") -> background in let if (background == nil) then 1 else background -> background in let atoi (getPluginInstanceParam inst "opacity") -> opacity in let if opacity == nil then 100 else opacity -> opacity in let atoi (getPluginInstanceParam inst "transparency") -> trans in let if (trans == nil) then 0 else trans -> trans in let atoi (getPluginInstanceParam inst "show") -> show in let if (show == nil) then 1 else show -> show in let SO3SceneGetObject (V3DgetSession c3dXsession) objname -> obj in let if !istexture then nil else SO3SceneGetMaterial (V3DgetSession c3dXsession) (SO3EntityGetResourceGroup obj) matname -> mat in let MkPlugDraw [inst istexture mat technique pass texture nil nil nil [0 brushcolor]::nil [0 brushsize]::nil [0 brushalpha]::nil nil nil posx posy width height [xpercent ypercent wpercent hpercent xoffset yoffset woffset hoffset] [xalign yalign] trans opacity filepath background mouse 0 show] -> drawstr in ( createPicture inst drawstr; if drawstr.DRW_bOnMaterial then nil else setPluginInstanceCbResizeView inst mkfun5 @cbResizeCtrl drawstr; if drawstr.DRW_bShow then cbShow inst nil nil nil nil drawstr else cbHide inst nil nil nil nil drawstr; if (!load) then nil else loadDrawing drawstr; PluginRegisterAction inst "Show" mkfun6 @cbShow drawstr; PluginRegisterAction inst "Hide" mkfun6 @cbHide drawstr; PluginRegisterAction inst "Draw" mkfun6 @cbDraw drawstr; PluginRegisterAction inst "Clear" mkfun6 @cbClear drawstr; PluginRegisterAction inst "Save" mkfun6 @cbSaveDrawing drawstr; PluginRegisterAction inst "Load" mkfun6 @cbLoadDrawing drawstr; PluginRegisterAction inst "Export" mkfun6 @exportDrawing drawstr; PluginRegisterAction inst "Undo" mkfun6 @UndoDraw drawstr; PluginRegisterAction inst "Redo" mkfun6 @RedoDraw drawstr; PluginRegisterAction inst "New drawing" mkfun6 @cbNewDraw drawstr; PluginRegisterAction inst "Set brush color" mkfun6 @cbSetBrushColor drawstr; PluginRegisterAction inst "Set brush size" mkfun6 @cbSetBrushSize drawstr; PluginRegisterAction inst "Set draw mode" mkfun6 @cbSetDrawMode drawstr; setPluginInstanceCbDel inst mkfun2 @deleteOb drawstr; ); 0;; fun IniPlug(file) = PlugRegister @cbNewOb nil; setPluginEditor @dynamicedit; 0;;