set display mode 1024,768,32 #CONSTANT NULL = 0 #CONSTANT TRUE = 1 #CONSTANT FALSE = 0 #CONSTANT SLIDER_HORIZONTAL = 1 #CONSTANT SLIDER_VERTICAL = 2 #CONSTANT GUI_LAYERS_OFFSET = 400 #CONSTANT LAYER_HEIGHT = 25 REM should be a constant, but doing so gives a different result(?) TEXT_OFFSET = (LAYER_HEIGHT/2 - text height("A")/2) #CONSTANT ACTION_DRAW = 1 #CONSTANT ACTION_FILL = 2 #CONSTANT ACTION_LINE = 3 #CONSTANT ACTION_CIRCLE = 4 #CONSTANT ACTION_GRADIENT = 5 #CONSTANT ACTION_ADDLAYER = 6 #CONSTANT ACTION_DELETELAYER = 7 #CONSTANT ACTION_SPRAY = 8 GLOBAL _menuMouseFlag = 0 GLOBAL _menuFlag = 0 GLOBAL LAYER_INDEX = 0 GLOBAL CURRENT_LAYER = -1 GLOBAL CURRENT_ACTION = 1 rem type Vector2D x as integer y as integer endtype rem type Menu name as string active as boolean width as integer count as integer endtype rem type MenuItem parentID as integer item as string enabled as boolean check as integer endtype rem type toolButton x as integer y as integer size as integer active as boolean action as integer group as integer endtype rem isVisible = is the layer visible in the workspace rem parentLink = current drawing layer if this layer is told to link to it (-1 if no link) rem alpha = alpha transparency amount rem name = name of this layer type LAYER_UI isVisible as boolean parentLink as integer alpha as byte name as string order as byte memblock as byte endtype rem attributes for common values among all sliders of this type type sliderComponentUI trackWidth as float trackHeight as float trackColor as dword thumbWidth as float thumbHeight as float thumbColor as dword orientation as byte endtype rem attributes for unique values for each slider type sliderComponent x as integer y as integer min as float max as float value as float isDragging as boolean mOffsetX as float mOffsetY as float thumbX as float thumbY as float valueX as float valueY as float displayValue as boolean ui as sliderComponentUI endtype rem array to hold all sliders dim sliders(5) as SliderComponent sliderUI as sliderComponentUI sliderUI.trackWidth = 2 sliderUI.trackHeight = 256 sliderUI.trackColor = 0 sliderUI.thumbWidth = 10 sliderUI.thumbHeight = 4 sliderUI.thumbColor = rgb(128,128,128) sliderUI.orientation = SLIDER_VERTICAL brushSliderUI as sliderComponentUI brushSliderUI.trackWidth = 144 brushSliderUI.trackHeight = 2 brushSliderUI.trackColor = 0 brushSliderUI.thumbWidth = 4 brushSliderUI.thumbHeight = 10 brushSliderUI.thumbColor = rgb(128,128,128) brushSliderUI.orientation = SLIDER_HORIZONTAL slider as sliderComponent slider.x = 886 slider.y = 14 slider.min = 0 slider.max = 255 slider.value = 255 slider.thumbX = 956+56 slider.thumbY = slider.y slider.ui = sliderUI slider.displayValue = TRUE slider.valueX = 886 slider.valueY = 1 rem color sliders sliders(1) = slider : slider.x = 922 : slider.valueX = 922 sliders(2) = slider : slider.x = 958 : slider.valueX = 958 sliders(3) = slider : slider.x = 994 : slider.valueX = 994 sliders(4) = slider rem brush size slider slider.x = 876 slider.y = 326 slider.min = 1 slider.max = 10 slider.value = 1 slider.thumbX = slider.x slider.thumbY = slider.y slider.ui = brushSliderUI slider.valueX = 978 slider.valueY = 308 sliders(5) = slider rem array for drawing tools dim tools(8) as toolButton tempTool as toolButton tempTool.x = 876 tempTool.y = 340 tempTool.size = 20 tempTool.active = FALSE tempTool.action = ACTION_DRAW tempTool.group = 1 tools(1) = tempTool : tempTool.x = tempTool.x+tempTool.size+4 : tempTool.action = ACTION_LINE tools(2) = tempTool : tempTool.x = tempTool.x+tempTool.size+4 : tempTool.action = ACTION_CIRCLE tools(3) = tempTool : tempTool.x = tempTool.x+tempTool.size+4 : tempTool.action = ACTION_FILL tools(4) = tempTool : tempTool.x = tempTool.x+tempTool.size+4 : tempTool.action = ACTION_GRADIENT tools(5) = tempTool : tempTool.x = tempTool.x+tempTool.size+4 : tempTool.action = ACTION_SPRAY tools(6) = tempTool tools(1).active = TRUE tools(7).x = tools(5).x tools(7).y = 746 tools(7).size = 20 tools(7).group = -1 tools(7).action = ACTION_ADDLAYER tools(7).active = FALSE tools(8).x = tools(6).x tools(8).y = 746 tools(8).size = 20 tools(8).group = -1 tools(8).action = ACTION_DELETELAYER tools(8).active = FALSE rem for the menu system dim menus() as Menu dim menuItems() as MenuItem MENU_FILE = addMenu("File") MENU_EDIT = addMenu("Edit") MENU_FILTER = addMenu("Filter") addMenuItem(MENU_FILE,"New",1,-1) addMenuItem(MENU_FILE,"Open",1,-1) addMenuItem(MENU_FILE,"Save",1,-1) addMenuItem(MENU_FILE,"Exit",1,-1) addMenuItem(MENU_EDIT,"Resize",0,-1) addMenuItem(MENU_FILTER,"Noise",1,-1) addMenuItem(MENU_FILTER,"Blur",0,-1) addMenuItem(MENU_FILTER,"",1,-1) addMenuItem(MENU_FILTER,"",1,-1) rem array of drawing layers dim layerObjects(0) as LAYER_UI rem create a new document and add 2 more default(blank) layers new() addLayer(TRUE) addLayer(TRUE) sync on backdrop on color backdrop 0x808080 color as dword REPEAT if mouseclick() = 0 then drawFlag = 0 _mc = mouseclick() if _mc = 0 then _menuMouseFlag = 0 v$ = _handleMenus$(_mc) `if v$ <> "" then value$ = v$ if v$ <> "" then fireMenuAction(v$) : drawFlag = 0 if _menuFlag = 0 if mousex() > 874 gosub _handleGUI else if mouseclick() = 1 if drawFlag = 0 start = 0 oldmx = mousex() - sprite x(CURRENT_LAYER) oldmy = mousey() - sprite y(CURRENT_LAYER) endif drawFlag = 1 endif endif endif if drawFlag = 1 select CURRENT_ACTION case ACTION_DRAW : gosub _drawing : oldmx=mousex()-sprite x(CURRENT_LAYER) : oldmy=mousey()-sprite y(CURRENT_LAYER) : endcase case ACTION_FILL : gosub _flood : endcase case ACTION_LINE : gosub _line : endcase `case ACTION_CIRCLE : gosub _circle : endcase ` case ACTION_GRADIENT : gosub _gradient_fill : endcase case ACTION_SPRAY : gosub _spray : endcase endselect endif gosub _drawGUI _handleSliders(layerFlag) rem draw layers for i = 1 to array count(layerObjects()) img = layerObjects(i).memblock if _menuFlag = 1 `hide sprite img else if layerObjects(i).isVisible = TRUE show sprite img `sprite img,0,0,img set sprite alpha img, layerObjects(i).alpha `set sprite priority img, array count(layerObjects())-layerObjects(i).order set sprite priority img, layerObjects(i).order else hide sprite img endif endif next i sync UNTIL spacekey() end REM draw a line _line: if start = 0 start = 1 lx1 = mousex() ly1 = mousey() endif if start = 1 lx2 = mousex() ly2 = mousey() endif ink 0,0 line lx1,ly1,lx2,ly2 RETURN REM flood fill (paint bucket) _flood: color = rgb(sliders(1).value, sliders(2).value, sliders(3).value) floodFill(layerObjects(CURRENT_LAYER).memblock, mousex()-sprite x(CURRENT_LAYER), mousey()-sprite y(CURRENT_LAYER), color,sliders(4).value) make image from memblock layerObjects(CURRENT_LAYER).memblock, layerObjects(CURRENT_LAYER).memblock RETURN REM _spray: if mousex() >= sprite x(CURRENT_LAYER) and mousey() >= sprite y(CURRENT_LAYER) and mousex() <= sprite x(CURRENT_LAYER)+sprite width(CURRENT_LAYER) and mousey() <= sprite y(CURRENT_LAYER)+sprite height(CURRENT_LAYER) color = rgb(sliders(1).value, sliders(2).value, sliders(3).value) mx = mousex() - sprite x(CURRENT_LAYER) my = mousey() - sprite y(CURRENT_LAYER) spray(layerObjects(CURRENT_LAYER).memblock, mx, my, color, sliders(4).value, sliders(5).value*10) make image from memblock layerObjects(CURRENT_LAYER).memblock, layerObjects(CURRENT_LAYER).memblock endif RETURN REM handles drawing functions (with pencil tool) _drawing: if layerObjects(CURRENT_LAYER).isVisible = TRUE `if mousex() > 0 and mousey() > 0 and mousex() <= 874 and mousey() <= 1024 if mousex() >= sprite x(CURRENT_LAYER) and mousey() >= sprite y(CURRENT_LAYER) and mousex() <= sprite x(CURRENT_LAYER)+sprite width(CURRENT_LAYER) and mousey() <= sprite y(CURRENT_LAYER)+sprite height(CURRENT_LAYER) color = rgb(sliders(1).value, sliders(2).value, sliders(3).value) mx = mousex() - sprite x(CURRENT_LAYER) my = mousey() - sprite y(CURRENT_LAYER) bline(layerObjects(CURRENT_LAYER).memblock, oldmx,oldmy,mx,my, color, sliders(4).value,sliders(5).value-1) `oldmx = mx `oldmy = my make image from memblock layerObjects(CURRENT_LAYER).memblock, layerObjects(CURRENT_LAYER).memblock endif endif RETURN REM handles the GUI functions _handleGUI: REM handle reordering of the layers count = array count(layerObjects()) for i = 1 to array count(layerObjects()) t = count - layerObjects(i).order if mousex() > 898 or layerFlag > 0 if mouseclick() = 1 and layerFlag = 0 if mousex() > 898 and mousex() < 1024 and mousey() > (GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+2) and mousey() < (GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+LAYER_HEIGHT) if t < (count-1) then layerFlag = i CURRENT_LAYER = i loffsety = mousey() - (GUI_LAYERS_OFFSET+t*LAYER_HEIGHT+2) endif endif if t < (count-1) rem moving a layer with mouse (reording) if layerFlag > 0 if mouseclick() = 1 rem move layer above if mousey() < (GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+LAYER_HEIGHT) if layerObjects(layerFlag).order < layerObjects(i).order order = layerObjects(i).order layerObjects(i).order = layerObjects(layerFlag).order layerObjects(layerFlag).order = order endif endif rem move layer below if mousey() > GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+2 if layerObjects(layerFlag).order > layerObjects(i).order order = layerObjects(i).order layerObjects(i).order = layerObjects(layerFlag).order layerObjects(layerFlag).order = order endif endif endif endif endif endif if mousex() > 876 and mousex() < 896 and mousey() > (GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+3) and mousey() < (GUI_LAYERS_OFFSET+(t*LAYER_HEIGHT)+LAYER_HEIGHT)-1 if mouseclick() = 1 and visibleFlag = 0 visibleFlag = 1 if layerObjects(i).isVisible = TRUE : layerObjects(i).isVisible = FALSE : else : layerObjects(i).isVisible = TRUE : endif endif endif next i rem tools if mouseclick() = 1 and toolFlag = 0 and layerFlag = 0 toolFlag = 1 for i = 1 to array count(tools()) if mousex() > tools(i).x and mousex() < tools(i).x+tools(i).size and mousey() > tools(i).y and mousey() < tools(i).y+tools(i).size rem reset all tool states if tools(i).group > 0 for t = 1 to array count(tools()) if tools(t).group = tools(i).group then tools(t).active = FALSE next t tools(i).active = TRUE CURRENT_ACTION = tools(i).action else fireButtonAction(tools(i).action) endif break endif next i endif if mouseclick() <> 1 then layerFlag = 0 : visibleFlag = 0 : toolFlag = 0 RETURN REM handles component rendering _drawGUI: REM GUI ink rgb(192,192,192),0 box 872,0,1024,768 REM draw layers count = array count(layerObjects()) for t = 1 to count i = count - layerObjects(t).order rem if this layer is being moved by the user if t = layerFlag loy = mousey() - loffsety else loy = GUI_LAYERS_OFFSET+i*LAYER_HEIGHT endif if t = CURRENT_LAYER ink rgb(192,192,255),0 else ink rgb(255,255,255),0 endif box 874,loy+2,1024,loy+LAYER_HEIGHT ink 0,0 text 898,loy+2 + TEXT_OFFSET, layerObjects(t).name + " - " + str$(i) rem checkbox for showing/hiding layer ink rgb(128,128,128),0 box 876,loy+4,896,loy+LAYER_HEIGHT-2 t1 = loy+4 t2 = loy+LAYER_HEIGHT-2 if layerObjects(t).isVisible = TRUE ink rgb(0,255,0),0 line 877,t1+LAYER_HEIGHT/2,885,t2-1 line 885,t2-1, 895,t1+1 else ink rgb(255,0,0),0 line 877,t1+1,895,t2-1 line 877,t2-1,895,t1+1 endif next t rem Tools for i = 1 to array count(tools()) drawButton(tools(i).x, tools(i).y, tools(i).size, tools(i).active) drawIcon(tools(i).action, tools(i).x, tools(i).y) next i ink 0,0 rem labels for color sliders center text sliders(1).x, 270, "R" center text sliders(2).x, 270, "G" center text sliders(3).x, 270, "B" center text sliders(4).x, 270, "A" rem divider line under color sliders box 872,304,1024,305 ink rgb(255,255,255),0 box 872,305,1024,306 ink 0,0 text 876,308,"Brush Size - " rem color sample ink rgb(sliders(1).value, sliders(2).value, sliders(3).value), 0 box 874,286,1022,301 RETURN rem draws a square button function drawButton(x as integer, y as integer, size as integer, active as boolean) a as dword b as dword if active = FALSE a = 0xFFFFFF b = 0 else a = 0 b = 0xFFFFFF endif ink a,0 box x, y,x+size, y+1 box x, y,x+1, y+size ink b,0 box x, y+size-1,x+size, y+size box x+size-1, y,x+size,y+size endfunction REM Create a new blank layer REM if "blank" is false, it assumes the memblock used REM for drawing operations will be created in an load image REM routine. REM Should you not plan on creating a memblock from a loaded REM image after calling this, then "blank" must be TRUE function addLayer(blank as boolean) array insert at bottom layerObjects() inc LAYER_INDEX, 1 l as LAYER_UI l.isVisible = TRUE l.parentLink = -1 l.alpha = 255 l.name = "Layer "+str$(LAYER_INDEX) i = array count(layerObjects()) l.order = i l.memblock = i layerObjects(i) = l CURRENT_LAYER = i if blank = TRUE then makeLayerMemblock(i) endfunction i REM create a memblock for drawing routines function makeLayerMemblock(index as integer) `width = 872 `height = 752 width = 800 height = 600 size = width*height*4 + 12 make memblock index, size write memblock dword index, 0, width write memblock dword index, 4, height write memblock dword index, 8, 32 make image from memblock index, index `sprite index,0,16,index sprite index, 38,100,index endfunction REM Loads an image into a new layer function loadImage(imgPath as string) if path exist(imgPath) index = addLayer(0) load image imgPath,index,1 make memblock from image layerObjects(index).memblock, index sprite index, 38,100,index endif endfunction REM function spray(index as integer, x as integer, y as integer, color as dword, alpha as integer, size as integer) width = memblock dword(index, 0) height = memblock dword(index, 4) s = size/2 for px = x-size to x+size for py = y-size to y+size if px > 0 and px <= width and py > 0 and py <= height if ((px - x)^2 + (py-y)^2) <= size pos = ((py-1)*width + px - 1)*4 + 12 if rnd(1) = 1 write memblock dword index, pos, color write memblock byte index, pos+3, alpha endif endif endif next py next px endfunction REM draws a square for painting based on "size" function dotMemblockBrush(index as integer, x as integer, y as integer, color as dword, alpha as integer, size as integer) width = memblock dword(index, 0) height = memblock dword(index, 4) s = size/2 for px = x-size to x+size for py = y-size to y+size if px > 0 and px <= width and py > 0 and py <= height pos = ((py-1)*width + px - 1)*4 + 12 write memblock dword index, pos, color write memblock byte index, pos+3, alpha endif next py next px endfunction REM a single dot function dotMemblock(index as integer, x as integer, y as integer, color as dword, alpha as integer) width = memblock dword(index, 0) height = memblock dword(index, 4) if x > 0 and y > 0 and x <= width and y <= height pos = ((y-1)*width + x - 1)*4 + 12 write memblock dword index, pos, color write memblock byte index, pos+3, alpha endif endfunction REM determine how to handle each slider. function _handleSliders(lf) for t = 1 to array count(sliders()) if sliders(t).ui.orientation = SLIDER_HORIZONTAL then _handleSliderHorizontal(t, lf) if sliders(t).ui.orientation = SLIDER_VERTICAL then _handleSliderVERTICAL(t, lf) next t endfunction REM Horizontal Slider REM handles slider UI and renders the components function _handleSliderHorizontal(i as integer, lf as integer) local ui as sliderComponentUI ui = sliders(i).ui rem draw track ink ui.trackColor,0 y# = sliders(i).y - ui.trackHeight/2 box sliders(i).x, y#, sliders(i).x+ui.trackWidth, y#+ui.trackHeight rem draw thumb ink ui.thumbColor,0 y# = sliders(i).y - ui.thumbHeight/2 box sliders(i).thumbX, y#, sliders(i).thumbX+ui.thumbWidth, y#+ui.thumbHeight if lf = FALSE rem handle mouse events if mouseclick() = 1 and sliders(i).isDragging = 0 if mousex() >= sliders(i).thumbX and mousex() <= sliders(i).thumbX+ui.thumbWidth if mousey() >= y# and mousey() <= y#+ui.thumbHeight sliders(i).isDragging = 1 sliders(i).mOffsetX = sliders(i).thumbX - mousex() endif endif endif endif if sliders(i).isDragging = 1 sliders(i).thumbX = mousex() + sliders(i).mOffsetX if sliders(i).thumbX < sliders(i).x then sliders(i).thumbX = sliders(i).x if sliders(i).thumbX > (sliders(i).x+ui.trackWidth)-ui.thumbWidth then sliders(i).thumbX = (sliders(i).x+ui.trackWidth)-ui.thumbWidth rem set slider value sliders(i).value = (((sliders(i).max - sliders(i).min) * (sliders(i).thumbX-sliders(i).x)) / (ui.trackWidth-ui.thumbWidth)) + sliders(i).min endif rem display current value if sliders(i).displayValue = TRUE ink 0,0 `text 924, sliders(i).y-7, str$(int(sliders(i).value)) text sliders(i).valueX, sliders(i).valueY, str$(int(sliders(i).value)) endif if mouseclick() <> 1 then sliders(i).isDragging = 0 endfunction rem Vertical Slider function _handleSliderVertical(i as integer, lf as integer) local ui as sliderComponentUI ui = sliders(i).ui rem draw track ink ui.trackColor,0 x# = sliders(i).x - ui.trackWidth/2 box x#,sliders(i).y,x#+ui.trackWidth,sliders(i).y+ui.trackHeight rem draw thumb ink ui.thumbColor,0 x# = sliders(i).x - ui.thumbWidth/2 box x#,sliders(i).thumbY,x#+ui.thumbWidth,sliders(i).thumbY+ui.thumbHeight if lf = FALSE rem handle mouse events if mouseclick() = 1 and sliders(i).isDragging = 0 if mousex() >= x# and mousex() <= x#+ui.thumbWidth if mousey() >= sliders(i).thumbY and mousey() <= sliders(i).thumbY+ui.thumbHeight sliders(i).isDragging = 1 sliders(i).mOffsetY = sliders(i).thumbY - mousey() endif endif endif endif if sliders(i).isDragging = 1 sliders(i).thumbY = mousey() + sliders(i).mOffsetY if sliders(i).thumbY < sliders(i).y then sliders(i).thumbY = sliders(i).y if sliders(i).thumbY > (sliders(i).y+ui.trackHeight)-ui.thumbHeight then sliders(i).thumbY = (sliders(i).y+ui.trackHeight)-ui.thumbHeight rem set slider value sliders(i).value = sliders(i).max - (((sliders(i).max - sliders(i).min) * (sliders(i).thumbY-sliders(i).y)) / (ui.trackHeight-ui.thumbHeight)) + sliders(i).min endif rem display current value if sliders(i).displayValue = TRUE ink 0,0 center text sliders(i).valueX, sliders(i).valueY, str$(int(sliders(i).value)) endif if mouseclick() <> 1 then sliders(i).isDragging = 0 endfunction REM function fireButtonAction(action as integer) select action case ACTION_ADDLAYER : addLayer(TRUE) : endcase case ACTION_DELETELAYER : deleteLayer(CURRENT_LAYER) : endcase endselect endfunction REM function drawIcon(icon as integer, x as integer, y as integer) select icon case ACTION_DRAW : _draw_icon_draw(x,y) : endcase case ACTION_FILL : _draw_icon_fill(x,y) : endcase case ACTION_LINE : _draw_icon_line(x,y) : endcase case ACTION_CIRCLE : _draw_icon_circle(x,y) : endcase case ACTION_GRADIENT : _draw_icon_gradient(x,y) : endcase case ACTION_ADDLAYER : _draw_icon_add(x,y) : endcase case ACTION_DELETELAYER : _draw_icon_minus(x,y) : endcase case ACTION_SPRAY : _draw_icon_spray(x,y) : endcase endselect endfunction REM spray can icon function _draw_icon_spray(x,y) ink 0,0 dot x+10,y+8 dot x+5,y+10 dot x+15,y+10 dot x+7,y+5 dot x+10,y+5 dot x+13,y+5 dot x+7,y+15 dot x+10,y+17 dot x+13,y+15 endfunction REM + function _draw_icon_add(x,y) ink 0,0 box x+2,y+8,x+18,y+12 box x+8,y+2,x+12,y+18 endfunction REM - function _draw_icon_minus(x,y) ink 0,0 box x+4,y+8,x+16,y+12 endfunction REM function _draw_icon_draw(x,y) restore pencil for a = 0 to 19 for b = 0 to 19 read z if z <> -1 ink z,0 dot x+b,y+a endif next b next a endfunction REM function _draw_icon_gradient(x,y) box x+4,y+4,x+16,y+16,rgb(192,192,192),0xFFFFFF,0,rgb(192,192,192) endfunction REM function _draw_icon_fill(x,y) ink 0,0 box x+4,y+4,x+16,y+16 endfunction REM function _draw_icon_line(x,y) ink 0,0 line x+3,y+17,x+17,y+3 endfunction REM function _draw_icon_circle(x,y) ink 0,0 circle x+10,y+10,7 endfunction REM draws a line function bline(index,x1,y1,x2,y2,color as dword,alpha as integer,size as integer) dx = x2-x1 dy = y2-y1 dotMemblockBrush(index, x1, y1, color, alpha,size) if abs(dx) > abs(dy) m# = (0.0 + dy)/dx b# = y1 - m#*x1 if dx < 0 dx = -1 else dx = 1 endif while x1 <> x2 x1 = x1 + dx dotMemblockBrush(index, x1, m#*x1+b#, color, alpha,size) endwhile else if dy <> 0 m# = (0.0 + dx)/dy b# = x1 - m#*y1 if dy < 0 dy = -1 else dy = 1 endif while y1 <> y2 y1 = y1 + dy dotMemblockBrush(index, m#*y1+b#, y1, color, alpha,size) endwhile endif endif endfunction REM function floodFill(index as integer, x as integer, y as integer, color as dword, alpha as integer) width = memblock dword(index, 0) height = memblock dword(index, 4) if x > 0 and x <= width and y > 0 and y <= height pos = ((y-1)*width + x - 1)*4 + 12 tc as dword tc = memblock dword(index, pos) if tc <> color then _floodFill(index,x,y,x,y,tc,color,alpha,0) endif endfunction REM Recursive flood fill function _floodFill(index as integer, rx as integer, ry as integer,x as integer, y as integer, targetColor as dword, fillColor as dword, alpha as integer,count as integer) width = memblock dword(index, 0) height = memblock dword(index, 4) rem this limit prevents stack overflows that may occur from using this form of algorithm if count > 50000 then exitfunction rem check bounds if x > 0 and x <= width and y > 0 and y <= height pos = ((y-1)*width + x - 1)*4 + 12 temp as dword temp = memblock dword(index, pos) rem if this point's color equals the target color if temp <> targetColor exitfunction else rem color this pixel dotMemblock(index, x, y, fillColor,alpha) inc count rem branch off if x+1 <> rx then _floodFill(index,x,y,x+1,y,targetColor, fillColor,alpha,count) if x-1 <> rx then _floodFill(index,x,y,x-1,y,targetColor, fillColor,alpha,count) if y+1 <> ry then _floodFill(index,x,y,x,y+1,targetColor, fillColor,alpha,count) if y-1 <> ry then _floodFill(index,x,y,x,y-1,targetColor, fillColor,alpha,count) endif endif endfunction Function _open_save(filter As String,initdir As String,dtitle As String,defext As String,open As Boolean) `filter = "Text Documents ( *.txt )|*.txt|All Files ( *.* )|*.*|" `initdir = "C:" `dtitle = "Open ~ Test" `defext = "txt" `open = 1 For Open Dialogu, 0 for save dialogue `Get DLL numbers user32 As Integer comdlg32 As Integer `Load in required DLL's user32 = _find_fee_dll() Load DLL "user32.dll",user32 comdlg32 = _find_fee_dll() Load DLL "comdlg32.dll",comdlg32 `Get handle ( unique ID ) to the calling ( this ) window hwnd As DWord hwnd = Call DLL(user32,"GetActiveWindow") `Unload DLL as it is no longer needed Delete DLL user32 `Get the Memblock Number OPENFILENAME As Integer OPENFILENAME = _find_free_mem() `Make The Memblock containing the OPENFILENAME structure Make MemBlock OPENFILENAME,76 `Get the pointer to the just created Structure lpofn As DWord lpofn = Get MemBlock Ptr(OPENFILENAME) `Declare temp variables to hold data for OPENFILENAME structure size As Integer filebuffer As String filebufferptr As DWord flags As DWord filter = filter + "|" initdir = initdir + "|" dtitle = dtitle + "|" defext = defext + "|" filebuffer = "|" + Space$(255) + "|" filebufferptr = _get_str_ptr(filebuffer) flags = 0x00001000 || 0x00000004 || 0x00000002 size = 0 Write MemBlock DWord OPENFILENAME,0,76 : `lStructSize Write MemBlock DWord OPENFILENAME,4,hwnd : `hwndOwner `Write MemBlock DWord OPENFILENAME,8,NULL : `hInstance Write MemBlock DWord OPENFILENAME,12,_get_str_ptr(filter) : `lpstrFilter `Write MemBlock DWord OPENFILENAME,16,0 : `lpstrCustomFilter `Write MemBlock DWord OPENFILENAME,20,NULL : `nMaxCustFilter Write MemBlock DWord OPENFILENAME,24,1 : `nFilterIndex Write MemBlock DWord OPENFILENAME,28,filebufferptr : `lpstrFile Write MemBlock DWord OPENFILENAME,32,256 : `nMaxFile `Write MemBlock DWord OPENFILENAME,36,0 : `lpstrFileTitle `Write MemBlock DWord OPENFILENAME,40,NULL : `nMaxFileTitle Write MemBlock DWord OPENFILENAME,44,_get_str_ptr(initdir) : `lpstrInitialDir Write MemBlock DWord OPENFILENAME,48,_get_str_ptr(dtitle) : `lpstrTitle Write MemBlock DWord OPENFILENAME,52,flags : `Flags `Write MemBlock Word OPENFILENAME,56,NULL : `nFileOffset `Write MemBlock Word OPENFILENAME,58,NULL : `nFileExtension Write MemBlock DWord OPENFILENAME,60,_get_str_ptr(defext) : `lpstrDefExt `Write MemBlock DWord OPENFILENAME,64,NULL : `lCustData `Write MemBlock DWord OPENFILENAME,68,NULL : `lpfnHook `Write MemBlock DWord OPENFILENAME,72,0 : `lpTemplateName `Call the Command to open the dialouge retval As DWord If open retval = Call DLL(comdlg32,"GetOpenFileNameA",lpofn) Else retval = Call DLL(comdlg32,"GetSaveFileNameA",lpofn) EndIf `Check if it was sucecfull If retval <> 0 code$ = _get_str(filebufferptr,256) Else retval = Call DLL(comdlg32,"CommDlgExtendedError") Select retval Case 0xFFFF : code$ = "The dialog box could not be created. The common dialog box function's call to the DialogBox function failed. For example, this error occurs if the common dialog box call specifies an invalid window handle." : EndCase Case 0x0006 : code$ = "The common dialog box function failed to find a specified resource." : EndCase Case 0x0004 : code$ = "The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding instance handle." : EndCase Case 0x0002 : code$ = "The common dialog box function failed during initialization. This error often occurs when sufficient memory is not available." : EndCase Case 0x000B : code$ = "The ENABLEHOOK flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a pointer to a corresponding hook procedure." : EndCase Case 0x0008 : code$ = "The common dialog box function failed to lock a specified resource." : EndCase Case 0x0003 : code$ = "The ENABLETEMPLATE flag was set in the Flags member of the initialization structure for the corresponding common dialog box, but you failed to provide a corresponding template." : EndCase Case 0x0007 : code$ = "The common dialog box function failed to load a specified string." : EndCase Case 0x0001 : code$ = "The lStructSize member of the initialization structure for the corresponding common dialog box is invalid." : EndCase Case 0x0005 : code$ = "The common dialog box function failed to load a specified string." : EndCase Case 0x3003 : code$ = "The buffer pointed to by the lpstrFile member of the OPENFILENAME structure is too small for the file name specified by the user. The first two bytes of the lpstrFile buffer contain an integer value specifying the size, in TCHARs, required to receive the full name." : EndCase Case 0x0009 : code$ = "The common dialog box function was unable to allocate memory for internal structures." : EndCase Case 0x3002 : code$ = "A file name is invalid." : EndCase Case 0x000A : code$ = "The common dialog box function was unable to lock the memory associated with a handle." : EndCase Case 0x3001 : code$ = "An attempt to subclass a list box failed because sufficient memory was not available." : EndCase Case Default : code$ = "WHOOPS!" : EndCase EndSelect EndIF Delete DLL comdlg32 EndFunction code$ Function _get_str_ptr(pstr As String) `pstr$ should be a "|" ( NULL ) seperated string. memnum As Integer strlen As Integer char As Byte memptr As DWord strptr As DWord memnum = _find_free_mem() strlen = Len(pstr) Make MemBlock memnum,strlen For i = 1 To strlen If Mid$(pstr,i) = "|" char = 0 Else char = Asc(Mid$(pstr,i)) EndIf Write MemBlock Byte memnum,(i - 1),char Next i memptr = Get MemBlock Ptr(memnum) strptr = Make Memory(strlen) Copy Memory strptr,memptr,strlen Delete MemBlock memnum EndFunction strptr Function _get_str(strptr As DWord,strsize As Integer) `strptr is the pointer returned by _get_str_ptr() `strsize is the Integer length of the string specified by the pointer memnum As Integer memptr As DWord str As String char As String memnum = _find_free_mem() Make MemBlock memnum,strsize memptr = Get MemBlock Ptr(memnum) Copy Memory memptr,strptr,strsize For i = 1 To strsize str = str + Chr$(MemBlock Byte(memnum,i - 1)) Next i EndFunction str Function _find_fee_dll() retval = 0 Repeat Inc retval Until DLL Exist(retval) = 0 EndFunction retval Function _find_free_mem() retval = 50 Repeat Inc retval Until MemBlock Exist(retval) = 0 EndFunction retval REM add a new dropdown menu to the bar REM returns the index for referencing this menu function addMenu(name as string) m as Menu m.name = name array insert at bottom menus() count = array count(menus()) menus(count) = m endfunction count REM add a new menu item to an existing menu function addMenuItem(pid as integer, item as string, enabled as boolean, check as integer) m as MenuItem m.parentID = pid m.item = item m.enabled = enabled m.check = check array insert at bottom menuItems() menuItems(array count(menuItems())) = m rem make sure menu is drawn wide enough to handle this item's name width = text width(item)+6 if width > menus(pid).width then menus(pid).width = width menus(pid).count = menus(pid).count + 1 endfunction REM handle drawing and user-interaction of menus function _handleMenus$(mc as integer) v$ = "" offsetX = 0 active = -1 activeOffset = 0 rem text height, vertical spacing tw = 16 rem draw menu bar across top ink rgb(192,192,192),0 box 0,0,876,tw for i = 0 to array count(menus()) width = text width(menus(i).name) if mc = 1 if mousex() >= offsetX and mousex() <= offsetX+width+6 and mousey() >= 0 and mousey() <= tw if _menuMouseFlag = 0 _menuMouseFlag = 1 if menus(i).active = 0 menus(i).active = 1 else menus(i).active = 0 endif for t = 0 to array count(menus()) if t <> i then menus(t).active = 0 next t endif endif endif if menus(i).active = 1 active = i activeOffset = offsetX ink rgb(0,180,250),0 box offsetX,0,offsetX+width+6,tw `else `ink rgb(192,192,192),0 endif `box offsetX,0,offsetX+width+6,tw ink 0,0 text offsetX+3,0,menus(i).name offsetX = offsetX + width + 6 next i if active > -1 _menuFlag = 1 ink rgb(192,192,192),0 box activeOffset,tw,activeOffset+menus(active).width,tw+menus(active).count*tw offsetY = 0 ink 0,0 for i = 0 to array count(menuItems()) if menuItems(i).parentID = active inc offsetY if mousex() > activeOffset and mousex() < activeOffset+menus(active).width and mousey() > offsetY*tw and mousey() < (offsetY+1)*tw ink rgb(0,180,250),0 box activeOffset+1,offsetY*tw+1,activeOffset+menus(active).width-1,(offsetY+1)*tw-1 rem if this item was clicked if mc = 1 if _menuMouseFlag = 0 _menuMouseFlag = 1 if menuItems(i).enabled = 1 v$ = menus(active).name + "-" + menuItems(i).item menus(active).active = 0 exitfunction v$ endif endif endif endif if menuItems(i).enabled = 1 ink 0,0 else ink rgb(120,120,120),0 endif text activeOffset+3,offsetY*tw,menuItems(i).item endif next i else _menuFlag = 0 endif endfunction v$ REM function fireMenuAction(action as string) if action = "File-New" then new() if action = "File-Open" then open() if action = "File-Save" then save() if action = "File-Exit" then exitApp() if action = "Filter-Noise" then noise() endfunction REM function noise() width = memblock dword(CURRENT_LAYER, 0) height = memblock dword(CURRENT_LAYER, 4) white as dword white = rgb(255,255,255) for x = 0 to width-1 for y = 0 to height-1 pos = ((y*width)+x)*4 + 12 if rnd(1) = 0 white = rgb(1,1,1) else white = rgb(255,255,255) endif write memblock dword CURRENT_LAYER, pos,white next y next x make image from memblock CURRENT_LAYER,CURRENT_LAYER endfunction REM not finished REM need to fix adapt UDT to not use parrallel indices function deleteLayer(layer as integer) delete memblock layer delete sprite layer delete image layer dec LAYER_INDEX, 1 CURRENT_LAYER = 1 array delete element layerObjects(), layer endfunction rem new image, white as default background for 1st layer function new() for i = 1 to array count(layerObjects()) delete memblock i delete sprite i delete image i next i LAYER_INDEX = 0 CURRENT_LAYER = -1 undim layerObjects(0) dim layerObjects(0) as LAYER_UI addLayer(TRUE) width = memblock dword(CURRENT_LAYER, 0) height = memblock dword(CURRENT_LAYER, 4) rem make default background white for x = 0 to width-1 for y = 0 to height-1 pos = (y*width + x)*4 + 12 write memblock dword CURRENT_LAYER, pos, rgb(255,255,255) next y next x make image from memblock CURRENT_LAYER,CURRENT_LAYER endfunction rem open an image function open() for i = 1 to array count(layerObjects()) delete memblock i delete sprite i delete image i next i LAYER_INDEX = 0 CURRENT_LAYER = -1 `empty array layerObjects() undim layerObjects(0) dim layerObjects(0) as LAYER_UI loadImage(_open_save("All Files ( *.* )|*.*|","C:","Open File","jpg",1)) endfunction function save() file$ = _open_save("All Files ( *.* )|*.*|","C:","Save File","jpg",0) endfunction function exitApp() end endfunction pencil: data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,0,12517376,12517376,12517376,0,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,0,12517376,-1,-1,0,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,0,0,12517376,-1,0,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,0,12636233,0,0,0,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,0,12636233,11649842,10465069,0,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,0,12636233,11649842,0,0,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,0,12636233,11649842,10465069,0,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,0,11649842,10465069,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,12636233,11649842,10465069,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,0,10465069,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 data -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1