sync on
sync rate 0
color backdrop 0
 
`Enabled use of constant for keys
keyConstants()
Dim LastKeyState(255) as boolean
 
 
#constant IMG_SIZE 256
make memblock 1, 12 + (IMG_SIZE * IMG_SIZE * 4)
write memblock dword 1, 0, IMG_SIZE
write memblock dword 1, 4, IMG_SIZE
write memblock dword 1, 8, 32
for i = 12 to get memblock size(1)-1 step 4
   write memblock dword 1, i, 0xFFFFFFFF
next i
make image from memblock 999, 1
delete memblock 1
 
 
 
 
 
 
 
 
 
 
 
position camera 0, 0, 3
point camera 0, 0, 0
 
 
 
Type Coord
   x as float
   y as float
EndType
 
 
 
 
 
Type WindowData
   Direction as integer
   Scale as float
   pos as Coord
   id as float
   lastDrawnCoord as Coord
EndType
 
Dim Windows() as WindowData
newWindow()
currentWindow = 0
 
 
Tool = 1
 
 
 
global W as WindowData
startTime = timer()
frameTime# = 1.0
repeat
   frameTime# = (0.5 * frameTime#) + (0.5 * (timer() - startTime))
   startTime = timer()
 
   W = Windows(currentWindow)
 
   text 0, 0, "FPS: " + str$(screen fps())
   text 0, 10, "SK: " + str$(sk) + ", Direction: " + str$(W.Direction) + ", Scale: " + str$(W.Scale)
 
 
 
   if KeyOnce(DIK_T)
      inc Tool
      if Tool > 3 then Tool = 1
   endif
   testForFunction(Tool)
 
 
 
 
   if KeyOnce(DIK_DELETE)
      make memblock from image 2, 999
      make image from memblock Windows(currentWindow).id, 2
      delete memblock 2
   endif
 
 
 
 
   `Sync changes to temp window "W" back into the typed array
   Windows(currentWindow) = W
 
   `Sync the window
   sync
until keystate(DIK_ESCAPE)
end
 
 
 
 
 
 
 
 
function KeyOnce(K as DWORD)
   r = 0
 
   if LastKeyState(K)
      if keystate(K) = 0 then LastKeyState(K) = 0
   else
      if keystate(K)
         LastKeyState(K) = 1
         r = 1
      endif
   endif
endfunction r
 
 
 
 
 
 
 
remstart
function minimiseWindow()
   if spacekey()
      if sk = 0 AND W.Direction = 0
         sk = 1
         if W.Scale = 100
            W.Direction = -1
         else
            W.Direction = 1
         endif
      endif
   else
      if sk = 1 then sk = 0
   endif
 
 
   if W.Direction = -1
      W.Scale = curvevalue(10.0, W.Scale, 500.0 / frameTime#)
      W.pos.x = curvevalue(1.5, W.pos.x, 500.0 / frameTime#)
      W.pos.y = curvevalue(-1.25, W.pos.y, 500.0 / frameTime#)
 
      if W.Scale <= 10.2
         W.Direction = 0
         W.Scale = 10.0
      endif
 
      scale object 1, W.SCale, W.Scale, 100
      position object 1, W.x, W.y, 0.0
   else
      if W.Direction = 1
         W.Scale = curvevalue(100.0, W.Scale, 500.0 / frameTime#)
         W.x = curvevalue(0.0, W.x, 500.0 / frameTime#)
         W.y = curvevalue(0.0, W.y, 500.0 / frameTime#)
 
         if W.Scale >= 99.8
            W.Direction = 0
            W.Scale = 100.0
         endif
 
         scale object 1, W.SCale, W.Scale, 100
         position object 1, W.x, W.y, 0.0
      endif
   endif
endfunction
remend
 
 
function testForFunction(f)
   clicked as boolean : clicked = 0
   onCanvas as boolean : onCanvas = 0
   x as integer : x = -1
   y as integer : y = -1
 
   if W.Direction = 0
      if W.Scale = 100
         if pick object(mousex(), mousey(), W.id, W.id) = W.id
            onCanvas = 1
 
            if mouseclick() = 1
               x as double float
               y as double float
 
               x = int((0.5 - ((get pick vector x() - camera position x() - object position x(W.id)) / object size x(W.id))) * IMG_SIZE)
               y = int((0.0 - ((get pick vector y() - camera position y() - object position y(W.id)) / object size y(W.id))) * IMG_SIZE)
 
               clicked = 1
            endif
         endif
      endif
   endif
 
 
 
 
 
   select f
      case 1 : drawLineInWindow(x, y, clicked, onCanvas) : endcase
      case 2 : drawFreehandInWindow(x, y, clicked, onCanvas) : endcase
      case 3 : fillAtCoord(x, y, clicked, onCanvas) : endcase
   endselect
 
endfunction
 
 
 
 
function fillAtCoord(x as word, y as word, clicked as boolean, onCanvas as boolean)
   PrintToolName("Fill In")
   if onCanvas
      if clicked
         `Used as a stack
         global ptr as DWORD : ptr = make memory(IMG_SIZE * IMG_SIZE * 4)
 
 
         `Create a memblock image
         make memblock from image 1, W.id
 
         `Get the match colour
         matchColor as dword : matchColor = memblock dword(1, getMemblockImagePos(x, y, IMG_SIZE))
 
         `Add to the queue...
         `writeMemory(ptr, getMemblockImagePos(x, y, IMG_SIZE))
         writeMemory(ptr, x)
         writeMemory(ptr+2, y)
         `Next point to write to
         i = 4
 
 
         repeat
            `"pop" the stack offset
            dec i, 4
            `If its not negative, grab it
            if i > -1
               `get the x and y coors from the memory section, +0 = 0, +2 = y.
               x = getMemory(ptr + i)
               y = getMemory(ptr + i + 2)
 
               `Clear the old bit
               fill memory ptr, i, 4
 
               `check left, up, right and down. If its within canvas boundaries - go into the fill test function below
               if x > 0            then i = FillTest(x-1, y, matchColor, i)
               if y > 0            then i = FillTest(x, y-1, matchColor, i)
               if x < IMG_SIZE - 1 then i = FillTest(x+1, y, matchColor, i)
               if y < IMG_SIZE - 1 then i = FillTest(x, y+1, matchColor, i)
 
               `Finally, fill this pixel black (after validation)
               pos = getMemblockImagePos(x, y, IMG_SIZE)
               if pos >= 12 AND pos <= get memblock size(1) -4 then write memblock dword 1, pos, 0xFF000000
 
               `Debug...
               make image from memblock W.id, 1
               sync
            endif
            `Keep going to till we exhaust the stack
         until i <= 0
 
         `turn it into an image and clean up.
         make image from memblock W.id, 1
         delete memblock 1
         delete memory ptr
      endif
   endif
 
endfunction
 
 
 
function FillTest(x as word, y as word, matchColor as dword, i as DWORD)
   pos = getMemblockImagePos(x, y, IMG_SIZE)
   if pos <= get memblock size(1)-4
      if memblock dword(1, pos) = matchColor
         `Check its not already in the stack
         j = 0
         repeat
            if getMemory(ptr + j) = x then if getMemory(ptr + j + 2) = y then exitfunction
            inc j, 4
         until getMemory(ptr + j) = 0
 
 
         `Write the next coord to look at into the memory queue
         writeMemory(ptr + i, x)
         writeMemory(ptr + i + 2, y)
 
 
         `Forward the memory pointer on by 1
         inc i, 4
      endif
   endif
endfunction i
 
`Simple "get" function. returns value at pointer position
function getMemory(ptr as DWORD)
   r = *ptr
endfunction r
 
`Simple write function - sets a value at the pointer position
function writeMemory(ptr as DWORD, value as DWORD)
   *ptr = value
endfunction
 
 
 
 
 
 
 
 
function drawFreehandInWindow(x as integer, y as integer, clicked as boolean, onCanvas as boolean)
   PrintToolName("Freehand")
   if onCanvas
      if clicked = 1
         make memblock from image 1, W.id
 
         if W.lastDrawnCoord.x = -1
            MemblockLine(1, x, y, x, y)
         else
            MemblockLine(1, W.lastDrawnCoord.x, W.lastDrawnCoord.y, x, y)
         endif
 
         W.lastDrawnCoord.x = x
         W.lastDrawnCoord.y = y
 
         make image from memblock W.id, 1
         delete memblock 1
      else
         W.lastDrawnCoord.x = -1
         W.lastDrawnCoord.y = -1
         if memblock exist(1) then delete memblock 1
      endif
   else
      W.lastDrawnCoord.x = -1
      W.lastDrawnCoord.y = -1
      if memblock exist(1) then delete memblock 1
   endif
endfunction
 
 
 
 
 
 
 
function drawLineInWindow(x as integer, y as integer, clicked as boolean, onCanvas as boolean)
   PrintToolName("Line Tool")
   if onCanvas
      if clicked
         if W.lastDrawnCoord.x = -1
            W.lastDrawnCoord.x = x
            W.lastDrawnCoord.y = y
            make memblock from image 2, W.id
            make memblock from image 1, W.id
         endif
         copy memblock 2, 1, 0, 0, get memblock size(2)
 
         if W.lastDrawnCoord.x = -1
            MemblockLine(1, x, y, x, y)
         else
            MemblockLine(1, W.lastDrawnCoord.x, W.lastDrawnCoord.y, x, y)
         endif
 
         make image from memblock W.id, 1
      else
         W.lastDrawnCoord.x = -1
         W.lastDrawnCoord.y = -1
         if memblock exist(1) then delete memblock 1
         if memblock exist(2) then delete memblock 2
      endif
   endif
endfunction
 
 
 
 
 
 
 
 
function PrintToolName(tool as string)
   text screen width() - text width(tool), 0, tool
endfunction
 
 
 
 
 
 
 
 
 
 
 
function newWindow()
   array insert at bottom Windows()
   Windows().Direction = 0
   Windows().Scale = 100
   Windows().pos.x = 0
   Windows().pos.y = 0
   Windows().lastDrawnCoord.x = -1
   Windows().lastDrawnCoord.y = -1
   Windows().id = nextFreeObj()
 
   make memblock from image 2, 999
   make image from memblock Windows().id, 2
   delete memblock 2
 
 
   make object plain       Windows().id, 3, 3
   texture object          Windows().id, Windows().id
   set object transparency Windows().id, 3
   set object light        Windows().id, 0
 
 
   position object Windows().id, 0.0, 0.0, 0
   point object    Windows().id, 0.0, 0.0, 1
endfunction
 
 
 
 
 
 
 
function nextFreeObj()
   i = 1
   while object exist(i) : inc i : endwhile
endfunction i
 
 
 
 
 
 
 
 
function getMemblockImagePos(x, y, width)
   p = 12 + (x + (y * width)) * 4
endfunction p
 
 
 
 
 
 
function MemblockLine(mb, x1, y1, x2, y2)
   `Flip the image if going "up"
   if y2 < y1
      tx = x1
      ty = y1
 
      x1 = x2
      y1 = y2
 
      x2 = tx
      y2 = ty
   endif
 
 
   dx = abs(x1-x2)
   dy = abs(y1-y2)
 
   if dy > dx
     `More than 45 degrees, so flip the x and y angles but make a note for later checking.
      t = dx
      dx = dy
      dy = t
      t = 1
   else
      t = 0
   endif
 
 
   `dStart value
   d = (2 * dy) - dx
 
   `Check the x values to see if we draw from left to right
   if x1 > x2
      incX = -1
   else
      incX = 1
   endif
 
   x = x1
 
 
   `No need to check the y as we have flipped it earlier if we needed to
   y = y1
   incY = 1
 
 
   `Start the Loop
   do
      `Are we at the end yet? If so then exit
      if incx > 0
         if x >= x2
            if incy > 0
               if y >= y2 then exit
            else
               if y <= y2 then exit
            endif
         endif
      else
         if x <= x2
            if incy > 0
               if y >= y2 then exit
            else
               if y <= y2 then exit
            endif
         endif
      endif
 
 
      if d < 0
         `OPTION a
         d = d + (2 * dy)
 
         if t = 0
            inc x, incX
         else
            inc y, incY
         endif
      else
         `OPTION b
         d = d + (2 * dy) - (2 * dx)
         inc x, incX
         inc y, incY
      endif
 
      `Draw a dot (but check within memblock range first...
      pos = getMemblockImagePos(x, y, IMG_SIZE)
      if pos < get memblock size(mb)-5 AND pos > 0
         write memblock dword mb, pos, 0xFF000000
      endif
   loop
endfunction
 
 
 
function keyConstants()
  #constant    DIK_0              11
  #constant    DIK_1               2
  #constant    DIK_2               3
  #constant    DIK_3               4
  #constant    DIK_4               5
  #constant    DIK_5               6
  #constant    DIK_6               7
  #constant    DIK_7               8
  #constant    DIK_8               9
  #constant    DIK_9              10
  #constant    DIK_A              30
  #constant    DIK_ABNT_C1       115
  #constant    DIK_ABNT_C2       126
  #constant    DIK_ADD            78
  #constant    DIK_APOSTROPHE     40
  #constant    DIK_APPS          221
  #constant    DIK_AT            145
  #constant    DIK_AX            150
  #constant    DIK_B              48
  #constant    DIK_BACK           14
  #constant    DIK_BACKSLASH      43
  #constant    DIK_BACKSPACE      14
  #constant    DIK_C              46
  #constant    DIK_CALCULATOR    161
  #constant    DIK_CAPITAL        58
  #constant    DIK_CAPSLOCK       58
  #constant    DIK_CIRCUMFLEX    144
  #constant    DIK_COLON         146
  #constant    DIK_COMMA          51
  #constant    DIK_CONVERT       121
  #constant    DIK_D              32
  #constant    DIK_DECIMAL        83
  #constant    DIK_DELETE        211
  #constant    DIK_DIVIDE        181
  #constant    DIK_DOWN          208
  #constant    DIK_DOWNARROW     208
  #constant    DIK_E              18
  #constant    DIK_END           207
  #constant    DIK_EQUALS         13
  #constant    DIK_ESCAPE          1
  #constant    DIK_F              33
  #constant    DIK_F1             59
  #constant    DIK_F2             60
  #constant    DIK_F3             61
  #constant    DIK_F4             62
  #constant    DIK_F5             63
  #constant    DIK_F6             64
  #constant    DIK_F7             65
  #constant    DIK_F8             66
  #constant    DIK_F9             67
  #constant    DIK_F10            68
  #constant    DIK_F11            87
  #constant    DIK_F12            88
  #constant    DIK_F13           100
  #constant    DIK_F14           101
  #constant    DIK_F15           102
  #constant    DIK_G              34
  #constant    DIK_GRAVE          41
  #constant    DIK_H              35
  #constant    DIK_HOME          199
  #constant    DIK_I              23
  #constant    DIK_INSERT        210
  #constant    DIK_J              36
  #constant    DIK_K              37
  #constant    DIK_KANA          112
  #constant    DIK_KANJI         148
  #constant    DIK_L              38
  #constant    DIK_LALT           56
  #constant    DIK_LBRACKET       26
  #constant    DIK_LCONTROL       29
  #constant    DIK_LEFT          203
  #constant    DIK_LEFTARROW     203
  #constant    DIK_LMENU          56
  #constant    DIK_LSHIFT         42
  #constant    DIK_LWIN          219
  #constant    DIK_M              50
  #constant    DIK_MAIL          236
  #constant    DIK_MEDIASELECT   237
  #constant    DIK_MEDIASTOP     164
  #constant    DIK_MINUS          12
  #constant    DIK_MULTIPLY       55
  #constant    DIK_MUTE          160
  #constant    DIK_MYCOMPUTER    235
  #constant    DIK_N              49
  #constant    DIK_NEXT          209
  #constant    DIK_NEXTTRACK     153
  #constant    DIK_NOCONVERT     123
  #constant    DIK_NUMLOCK        69
  #constant    DIK_NUMPAD0        82
  #constant    DIK_NUMPAD1        79
  #constant    DIK_NUMPAD2        80
  #constant    DIK_NUMPAD3        81
  #constant    DIK_NUMPAD4        75
  #constant    DIK_NUMPAD5        76
  #constant    DIK_NUMPAD6        77
  #constant    DIK_NUMPAD7        71
  #constant    DIK_NUMPAD8        72
  #constant    DIK_NUMPAD9        73
  #constant    DIK_NUMPADCOMMA   179
  #constant    DIK_NUMPADENTER   156
  #constant    DIK_NUMPADEQUALS  141
  #constant    DIK_NUMPADMINUS    74
  #constant    DIK_NUMPADPERIOD   83
  #constant    DIK_NUMPADPLUS     78
  #constant    DIK_NUMPADSLASH   181
  #constant    DIK_NUMPADSTAR     55
  #constant    DIK_O              24
  #constant    DIK_OEM_102        86
  #constant    DIK_P              25
  #constant    DIK_PAUSE         197
  #constant    DIK_PERIOD         52
  #constant    DIK_PGDN          209
  #constant    DIK_PGUP          201
  #constant    DIK_PLAYPAUSE     162
  #constant    DIK_POWER         222
  #constant    DIK_PREVTRACK     144
  #constant    DIK_PRIOR         201
  #constant    DIK_Q              16
  #constant    DIK_R              19
  #constant    DIK_RALT          184
  #constant    DIK_RBRACKET       27
  #constant    DIK_RCONTROL      157
  #constant    DIK_RETURN         28
  #constant    DIK_RIGHT         205
  #constant    DIK_RIGHTARROW    205
  #constant    DIK_RMENU         184
  #constant    DIK_RSHIFT         54
  #constant    DIK_RWIN          220
  #constant    DIK_S              31
  #constant    DIK_SCROLL         70
  #constant    DIK_SEMICOLON      39
  #constant    DIK_SLASH          53
  #constant    DIK_SLEEP         223
  #constant    DIK_SPACE          57
  #constant    DIK_STOP          149
  #constant    DIK_SUBTRACT       74
  #constant    DIK_SYSRQ         183
  #constant    DIK_T              20
  #constant    DIK_TAB            15
  #constant    DIK_U              22
  #constant    DIK_UNDERLINE     147
  #constant    DIK_UNLABELED     151
  #constant    DIK_UP            200
  #constant    DIK_UPARROW       200
  #constant    DIK_V              47
  #constant    DIK_VOLUMEDOWN    174
  #constant    DIK_VOLUMEUP      176
  #constant    DIK_W              17
  #constant    DIK_WAKE          227
  #constant    DIK_WEBBACK       234
  #constant    DIK_WEBFAVORITES  230
  #constant    DIK_WEBFORWARD    233
  #constant    DIK_WEBHOME       178
  #constant    DIK_WEBREFRESH    231
  #constant    DIK_WEBSEARCH     229
  #constant    DIK_WEBSTOP       232
  #constant    DIK_X              45
  #constant    DIK_Y              21
  #constant    DIK_YEN           125
  #constant    DIK_Z              44
endfunction