Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if OneOS then
- --running under OneOS
- OneOS.ToolBarColour = colours.grey
- OneOS.ToolBarTextColour = colours.white
- end
- colours.transparent = -1
- colors.transparent = -1
- --APIS--
- --This is my drawing API, is is pretty much identical to what drives OneOS, PearOS, etc.
- local _w, _h = term.getSize()
- local round = function(num, idp)
- local mult = 10^(idp or 0)
- return math.floor(num * mult + 0.5) / mult
- end
- Clipboard = {
- Content = nil,
- Type = nil,
- IsCut = false,
- Empty = function()
- Clipboard.Content = nil
- Clipboard.Type = nil
- Clipboard.IsCut = false
- end,
- isEmpty = function()
- return Clipboard.Content == nil
- end,
- Copy = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = false
- end,
- Cut = function(content, _type)
- Clipboard.Content = content
- Clipboard.Type = _type or 'generic'
- Clipboard.IsCut = true
- end,
- Paste = function()
- local c, t = Clipboard.Content, Clipboard.Type
- if Clipboard.IsCut then
- Clipboard.Empty()
- end
- return c, t
- end
- }
- if OneOS and OneOS.Clipboard then
- Clipboard = OneOS.Clipboard
- end
- Drawing = {
- Screen = {
- Width = _w,
- Height = _h
- },
- DrawCharacters = function (x, y, characters, textColour,bgColour)
- Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
- end,
- DrawBlankArea = function (x, y, w, h, colour)
- Drawing.DrawArea (x, y, w, h, " ", 1, colour)
- end,
- DrawArea = function (x, y, w, h, character, textColour, bgColour)
- --width must be greater than 1, other wise we get a stack overflow
- if w < 0 then
- w = w * -1
- elseif w == 0 then
- w = 1
- end
- for ix = 1, w do
- local currX = x + ix - 1
- for iy = 1, h do
- local currY = y + iy - 1
- Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
- end
- end
- end,
- DrawImage = function(_x,_y,tImage, w, h)
- if tImage then
- for y = 1, h do
- if not tImage[y] then
- break
- end
- for x = 1, w do
- if not tImage[y][x] then
- break
- end
- local bgColour = tImage[y][x]
- local textColour = tImage.textcol[y][x] or colours.white
- local char = tImage.text[y][x]
- Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
- end
- end
- elseif w and h then
- Drawing.DrawBlankArea(x, y, w, h, colours.green)
- end
- end,
- --using .nft
- LoadImage = function(path)
- local image = {
- text = {},
- textcol = {}
- }
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) then
- local _open = io.open
- if OneOS then
- _open = OneOS.IO.open
- end
- local file = _open(path, "r")
- local sLine = file:read()
- local num = 1
- while sLine do
- table.insert(image, num, {})
- table.insert(image.text, num, {})
- table.insert(image.textcol, num, {})
- --As we're no longer 1-1, we keep track of what index to write to
- local writeIndex = 1
- --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
- local bgNext, fgNext = false, false
- --The current background and foreground colours
- local currBG, currFG = nil,nil
- for i=1,#sLine do
- local nextChar = string.sub(sLine, i, i)
- if nextChar:byte() == 30 then
- bgNext = true
- elseif nextChar:byte() == 31 then
- fgNext = true
- elseif bgNext then
- currBG = Drawing.GetColour(nextChar)
- bgNext = false
- elseif fgNext then
- currFG = Drawing.GetColour(nextChar)
- fgNext = false
- else
- if nextChar ~= " " and currFG == nil then
- currFG = colours.white
- end
- image[num][writeIndex] = currBG
- image.textcol[num][writeIndex] = currFG
- image.text[num][writeIndex] = nextChar
- writeIndex = writeIndex + 1
- end
- end
- num = num+1
- sLine = file:read()
- end
- file:close()
- end
- return image
- end,
- DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
- w = w or Drawing.Screen.Width
- h = h or Drawing.Screen.Height
- x = x or 0
- y = y or 0
- x = math.ceil((w - #characters) / 2) + x
- y = math.floor(h / 2) + y
- Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
- end,
- GetColour = function(hex)
- if hex == ' ' then
- return colours.transparent
- end
- local value = tonumber(hex, 16)
- if not value then return nil end
- value = math.pow(2,value)
- return value
- end,
- Clear = function (_colour)
- _colour = _colour or colours.black
- Drawing.ClearBuffer()
- Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
- end,
- Buffer = {},
- BackBuffer = {},
- DrawBuffer = function()
- for y,row in pairs(Drawing.Buffer) do
- for x,pixel in pairs(row) do
- local shouldDraw = true
- local hasBackBuffer = true
- if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
- hasBackBuffer = false
- end
- if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
- shouldDraw = false
- end
- if shouldDraw then
- term.setBackgroundColour(pixel[3])
- term.setTextColour(pixel[2])
- term.setCursorPos(x, y)
- term.write(pixel[1])
- end
- end
- end
- Drawing.BackBuffer = Drawing.Buffer
- Drawing.Buffer = {}
- term.setCursorPos(1,1)
- end,
- ClearBuffer = function()
- Drawing.Buffer = {}
- end,
- WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
- for i = 1, #characters do
- local character = characters:sub(i,i)
- Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
- end
- end,
- WriteToBuffer = function(x, y, character, textColour,bgColour)
- x = round(x)
- y = round(y)
- if bgColour == colours.transparent then
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
- Drawing.Buffer[y][x][1] = character
- Drawing.Buffer[y][x][2] = textColour
- else
- Drawing.Buffer[y] = Drawing.Buffer[y] or {}
- Drawing.Buffer[y][x] = {character, textColour, bgColour}
- end
- end,
- }
- --Colour Deffitions--
- UIColours = {
- Toolbar = colours.grey,
- ToolbarText = colours.lightGrey,
- ToolbarSelected = colours.lightBlue,
- ControlText = colours.white,
- ToolbarItemTitle = colours.black,
- Background = colours.lightGrey,
- MenuBackground = colours.white,
- MenuText = colours.black,
- MenuSeparatorText = colours.grey,
- MenuDisabledText = colours.lightGrey,
- Shadow = colours.grey,
- TransparentBackgroundOne = colours.white,
- TransparentBackgroundTwo = colours.lightGrey,
- MenuBarActive = colours.white
- }
- --Lists--
- Current = {
- Artboard = nil,
- Layer = nil,
- Tool = nil,
- ToolSize = 1,
- Toolbar = nil,
- Colour = colours.lightBlue,
- Menu = nil,
- MenuBar = nil,
- Window = nil,
- Input = nil,
- CursorPos = {1,1},
- CursorColour = colours.black,
- InterfaceVisible = true,
- Selection = {},
- SelectionDrawTimer = nil,
- HandDragStart = {},
- Modified = false,
- }
- local isQuitting = false
- function PrintCentered(text, y)
- local w, h = term.getSize()
- x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
- term.setCursorPos(x, y)
- print(text)
- end
- function DoVanillaClose()
- term.setBackgroundColour(colours.black)
- term.setTextColour(colours.white)
- term.clear()
- term.setCursorPos(1, 1)
- PrintCentered("Thanks for using Sketch!", (Drawing.Screen.Height/2)-1)
- term.setTextColour(colours.lightGrey)
- PrintCentered("Photoshop Inspired Image Editor for ComputerCraft", (Drawing.Screen.Height/2))
- term.setTextColour(colours.white)
- PrintCentered("(c) oeed 2013 - 2014", (Drawing.Screen.Height/2)+3)
- term.setCursorPos(1, Drawing.Screen.Height)
- error('', 0)
- end
- function Close()
- if isQuitting or not Current.Artboard or not Current.Modified then
- if not OneOS then
- DoVanillaClose()
- end
- return true
- else
- local _w = ButtonDialougeWindow:Initialise('Quit Sketch?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
- if success then
- if OneOS then
- OneOS.Close(true)
- else
- DoVanillaClose()
- end
- end
- window:Close()
- Draw()
- end):Show()
- --it's hacky but it works
- os.queueEvent('mouse_click', 1, _w.X, _w.Y)
- return false
- end
- end
- if OneOS then
- OneOS.CanClose = function()
- return Close()
- end
- end
- Lists = {
- Artboards = {},
- Interface = {
- Toolbars = {}
- }
- }
- Events = {
- }
- --Setters--
- function SetColour(colour)
- Current.Colour = colour
- Draw()
- end
- function SetTool(tool)
- if tool and tool.Select and tool:Select() then
- Current.Input = nil
- Current.Tool = tool
- return true
- end
- return false
- end
- function GetAbsolutePosition(object)
- local obj = object
- local i = 0
- local x = 1
- local y = 1
- while true do
- x = x + obj.X - 1
- y = y + obj.Y - 1
- if not obj.Parent then
- return {X = x, Y = y}
- end
- obj = obj.Parent
- if i > 32 then
- return {X = 1, Y = 1}
- end
- i = i + 1
- end
- end
- --Object Defintions--
- Pixel = {
- TextColour = colours.black,
- BackgroundColour = colours.white,
- Character = " ",
- Layer = nil,
- Draw = function(self, x, y)
- if self.BackgroundColour ~= colours.transparent or self.Character ~= ' ' then
- Drawing.WriteToBuffer(self.Layer.Artboard.X + x - 1, self.Layer.Artboard.Y + y - 1, self.Character, self.TextColour, self.BackgroundColour)
- end
- end,
- Initialise = function(self, textColour, backgroundColour, character, layer)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.TextColour = textColour or self.TextColour
- new.BackgroundColour = backgroundColour or self.BackgroundColour
- new.Character = character or self.Character
- new.Layer = layer
- return new
- end,
- Set = function(self, textColour, backgroundColour, character)
- self.TextColour = textColour or self.TextColour
- self.BackgroundColour = backgroundColour or self.BackgroundColour
- self.Character = character or self.Character
- end
- }
- Layer = {
- Name = "",
- Pixels = {
- },
- Artboard = nil,
- BackgroundColour = colours.white,
- Visible = true,
- Index = 1,
- Draw = function(self)
- if self.Visible then
- for x = 1, self.Artboard.Width do
- for y = 1, self.Artboard.Height do
- self.Pixels[x][y]:Draw(x, y)
- end
- end
- end
- end,
- Remove = function(self)
- for i, v in ipairs(self.Artboard.Layers) do
- if v == Current.Layer then
- Current.Artboard.Layers[i] = nil
- Current.Layer = Current.Artboard.Layers[1]
- ModuleNamed('Layers'):Update()
- end
- end
- end,
- Initialise = function(self, name, backgroundColour, artboard, index, pixels)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Name = name
- new.Pixels = {}
- new.BackgroundColour = backgroundColour
- new.Artboard = artboard
- new.Index = index or #artboard.Layers + 1
- if not pixels then
- new:MakeAllBlankPixels()
- else
- new:MakeAllBlankPixels()
- for x, col in ipairs(pixels) do
- for y, pixel in ipairs(col) do
- new:SetPixel(x, y, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
- end
- end
- end
- return new
- end,
- SetPixel = function(self, x, y, textColour, backgroundColour, character)
- textColour = textColour or Current.Colour
- backgroundColour = backgroundColour or Current.Colour
- character = character or " "
- if x < 1 or y < 1 or x > self.Artboard.Width or y > self.Artboard.Height then
- return
- end
- if self.Pixels[x][y] then
- self.Pixels[x][y]:Set(textColour, backgroundColour, character)
- self.Pixels[x][y]:Draw(x,y)
- end
- end,
- MakePixel = function(self, x, y, backgroundColour)
- backgroundColour = backgroundColour or self.BackgroundColour
- self.Pixels[x][y] = Pixel:Initialise(nil, backgroundColour, nil, self)
- end,
- MakeColumn = function(self, x)
- self.Pixels[x] = {}
- end,
- MakeAllBlankPixels = function(self)
- for x = 1, self.Artboard.Width do
- if not self.Pixels[x] then
- self:MakeColumn(x)
- end
- for y = 1, self.Artboard.Height do
- if not self.Pixels[x][y] then
- self:MakePixel(x, y)
- end
- end
- end
- end,
- PixelsInSelection = function(self, cut)
- local pixels = {}
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local cornerX = point1.x
- local cornerY = point1.y
- for x = 1, size.x + 1 do
- for y = 1, size.y + 1 do
- if not pixels[x] then
- pixels[x] = {}
- end
- if not self.Pixels[cornerX + x - 1] or not self.Pixels[cornerX + x - 1][cornerY + y - 1] then
- break
- end
- local pixel = self.Pixels[cornerX + x - 1][cornerY + y - 1]
- pixels[x][y] = Pixel:Initialise(pixel.TextColour, pixel.BackgroundColour, pixel.Character, Current.Layer)
- if cut then
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
- end
- end
- end
- end
- return pixels
- end,
- EraseSelection = function(self)
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local cornerX = point1.x
- local cornerY = point1.y
- for x = 1, size.x + 1 do
- for y = 1, size.y + 1 do
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, nil, Current.Layer.BackgroundColour, nil)
- end
- end
- end
- end,
- InsertPixels = function(self, pixels)
- local cornerX = Current.Selection[1].x
- local cornerY = Current.Selection[1].y
- for x, col in ipairs(pixels) do
- for y, pixel in ipairs(col) do
- Current.Layer:SetPixel(cornerX + x - 1, cornerY + y - 1, pixel.TextColour, pixel.BackgroundColour, pixel.Character)
- end
- end
- end
- }
- Artboard = {
- X = 0,
- Y = 0,
- Name = "",
- Path = "",
- Width = 1,
- Height = 1,
- Layers = {},
- Format = nil,
- SelectionIsBlack = true,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
- local odd
- for x = 1, self.Width do
- odd = x % 2
- if odd == 1 then
- odd = true
- else
- odd = false
- end
- for y = 1, self.Height do
- if odd then
- Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundTwo, UIColours.TransparentBackgroundOne)
- else
- Drawing.WriteToBuffer(self.X + x - 1, self.Y + y - 1, ":", UIColours.TransparentBackgroundOne, UIColours.TransparentBackgroundTwo)
- end
- odd = not odd
- end
- end
- for i, layer in ipairs(self.Layers) do
- layer:Draw()
- end
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- local point1 = Current.Selection[1]
- local point2 = Current.Selection[2]
- local size = point2 - point1
- local isBlack = self.SelectionIsBlack
- local function c()
- local c = colours.white
- if isBlack then
- c = colours.black
- end
- isBlack = not isBlack
- return c
- end
- function horizontal(y)
- Drawing.WriteToBuffer(self.X - 1 + point1.x, self.Y - 1 + y, '+', c(), colours.transparent)
- if size.x > 0 then
- for i = 1, size.x - 1 do
- Drawing.WriteToBuffer(self.X - 1 + point1.x + i, self.Y - 1 + y, '-', c(), colours.transparent)
- end
- else
- for i = 1, (-1 * size.x) - 1 do
- Drawing.WriteToBuffer(self.X - 1 + point1.x - i, self.Y - 1 + y, '-', c(), colours.transparent)
- end
- end
- Drawing.WriteToBuffer(self.X - 1 + point1.x + size.x, self.Y - 1 + y, '+', c(), colours.transparent)
- end
- function vertical(x)
- if size.y < 0 then
- for i = 1, (-1 * size.y) - 1 do
- Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y - i, '|', c(), colours.transparent)
- end
- else
- for i = 1, size.y - 1 do
- Drawing.WriteToBuffer(self.X - 1 + x, self.Y - 1 + point1.y + i, '|', c(), colours.transparent)
- end
- end
- end
- horizontal(point1.y)
- vertical(point1.x)
- horizontal(point1.y + size.y)
- vertical(point1.x + size.x)
- end
- end,
- Initialise = function(self, name, path, width, height, format, backgroundColour, layers)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Y = 3
- new.X = 2
- new.Name = name
- new.Path = path
- new.Width = width
- new.Height = height
- new.Format = format
- new.Layers = {}
- if not layers then
- new:MakeLayer('Background', backgroundColour)
- else
- for i, layer in ipairs(layers) do
- new:MakeLayer(layer.Name, layer.BackgroundColour, layer.Index, layer.Pixels)
- new.Layers[i].Visible = layer.Visible
- end
- Current.Layer = new.Layers[#new.Layers]
- end
- return new
- end,
- Resize = function(self, top, bottom, left, right)
- self.Height = self.Height + top + bottom
- self.Width = self.Width + left + right
- for i, layer in ipairs(self.Layers) do
- if left < 0 then
- for x = 1, -left do
- table.remove(layer.Pixels, 1)
- end
- end
- if right < 0 then
- for x = 1, -right do
- table.remove(layer.Pixels, #layer.Pixels)
- end
- end
- for x = 1, left do
- table.insert(layer.Pixels, 1, {})
- for y = 1, self.Height do
- layer:MakePixel(1, y)
- end
- end
- for x = 1, right do
- table.insert(layer.Pixels, {})
- for y = 1, self.Height do
- layer:MakePixel(#layer.Pixels, y)
- end
- end
- for y = 1, top do
- for x = 1, self.Width do
- table.insert(layer.Pixels[x], 1, {})
- layer:MakePixel(x, 1)
- end
- end
- for y = 1, bottom do
- for x = 1, self.Width do
- table.insert(layer.Pixels[x], {})
- layer:MakePixel(x, #layer.Pixels[x])
- end
- end
- if top < 0 then
- for y = 1, -top do
- for x = 1, self.Width do
- table.remove(layer.Pixels[x], 1)
- end
- end
- end
- if bottom < 0 then
- for y = 1, -bottom do
- for x = 1, self.Width do
- table.remove(layer.Pixels[x], #layer.Pixels[x])
- end
- end
- end
- end
- end,
- MakeLayer = function(self, name, backgroundColour, index, pixels)
- backgroundColour = backgroundColour or colours.white
- name = name or "Layer"
- local layer = Layer:Initialise(name, backgroundColour, self, index, pixels)
- table.insert(self.Layers, layer)
- Current.Layer = layer
- ModuleNamed('Layers'):Update()
- return layer
- end,
- New = function(self, name, path, width, height, format, backgroundColour, layers)
- local new = self:Initialise(name, path, width, height, format, backgroundColour, layers)
- table.insert(Lists.Artboards, new)
- Current.Artboard = new
- --new:Save()
- return new
- end,
- Save = function(self, path)
- Current.Artboard = self
- path = path or self.Path
- local _open = io.open
- if OneOS then
- _open = OneOS.IO.open
- end
- local file = _open(path, "w", true)
- if self.Format == '.skch' then
- file:write(textutils.serialize(SaveSKCH()))
- else
- local lines = {}
- if self.Format == '.nfp' then
- lines = SaveNFP()
- elseif self.Format == '.nft' then
- lines = SaveNFT()
- end
- for i, line in ipairs(lines) do
- file:write(line.."\n")
- end
- end
- file:close()
- Current.Modified = false
- end,
- Click = function(self, side, x, y, drag)
- if Current.Tool and Current.Layer and Current.Layer.Visible then
- Current.Tool:Use(x, y, side, drag)
- Current.Modified = true
- return true
- end
- end
- }
- Toolbar = {
- X = 0,
- Y = 0,
- Width = 0,
- ExpandedWidth = 14,
- ClosedWidth = 2,
- Height = 0,
- Expanded = true,
- ToolbarItems = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- self:CalculateToolbarItemPositions()
- --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
- --if not Current.Window then
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
- --else
- -- Drawing.DrawArea(self.X, self.Y, self.Width, self.Height, '|', colours.lightGrey, UIColours.Toolbar)
- --end
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem:Draw()
- end
- end,
- Initialise = function(self, side, expanded)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Expanded = expanded
- if expanded then
- new.Width = new.ExpandedWidth
- else
- new.Width = new.ClosedWidth
- end
- if side == 'right' then
- new.X = Drawing.Screen.Width - new.Width + 1
- end
- if side == 'right' or side == 'left' then
- new.Height = Drawing.Screen.Width
- end
- new.Y = 1
- return new
- end,
- AddToolbarItem = function(self, item)
- table.insert(self.ToolbarItems, item)
- self:CalculateToolbarItemPositions()
- end,
- CalculateToolbarItemPositions = function(self)
- local currY = 1
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem.Y = currY
- currY = currY + toolbarItem.Height
- end
- end,
- Update = function(self)
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- if toolbarItem.Module.Update then
- toolbarItem.Module:Update(toolbarItem)
- end
- end
- end,
- New = function(self, side, expanded)
- local new = self:Initialise(side, expanded)
- --new:AddToolbarItem(ToolbarItem:Initialise("Colours", nil, true, new))
- --new:AddToolbarItem(ToolbarItem:Initialise("IDK", true, new))
- table.insert(Lists.Interface.Toolbars, new)
- return new
- end,
- Click = function(self, side, x, y)
- return false
- end
- }
- ToolbarItem = {
- X = 0,
- Y = 0,
- Width = 0,
- Height = 0,
- ExpandedHeight = 5,
- Expanded = true,
- Toolbar = nil,
- Title = "",
- MenuIcon = "=",
- ExpandedIcon = "+",
- ContractIcon = "-",
- ContentView = nil,
- Module = nil,
- MenuItems = nil,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, UIColours.ToolbarItemTitle)
- Drawing.DrawCharacters(self.X + 1, self.Y, self.Title, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- Drawing.DrawCharacters(self.X + self.Width - 1, self.Y, self.MenuIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- local expandContractIcon = self.ContractIcon
- if not self.Expanded then
- expandContractIcon = self.ExpandedIcon
- end
- if self.Expanded and self.ContentView then
- self.ContentView:Draw()
- end
- Drawing.DrawCharacters(self.X + self.Width - 2, self.Y, expandContractIcon, UIColours.ToolbarText, UIColours.ToolbarItemTitle)
- end,
- Initialise = function(self, module, height, expanded, toolbar, menuItems)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Expanded = expanded
- new.Title = module.Title
- new.Width = toolbar.Width
- new.Height = height or 5
- new.Module = module
- new.MenuItems = menuItems or {}
- table.insert(new.MenuItems,
- {
- Title = 'Shrink',
- Click = function()
- new:ToggleExpanded()
- end
- })
- new.ExpandedHeight = height or 5
- new.Y = 1
- new.X = toolbar.X
- new.ContentView = ContentView:Initialise(1, 2, new.Width, new.Height - 1, nil, new)
- new.Toolbar = toolbar
- return new
- end,
- ToggleExpanded = function(self)
- self.Expanded = not self.Expanded
- if self.Expanded then
- self.Height = self.ExpandedHeight
- else
- self.Height = 1
- end
- end,
- Click = function(self, side, x, y)
- local pos = GetAbsolutePosition(self)
- if x == self.Width and y == 1 then
- local expandContract = "Shrink"
- if not self.Expanded then
- expandContract = "Expand"
- end
- self.MenuItems[#self.MenuItems].Title = expandContract
- Menu:New(pos.X + x, pos.Y + y, self.MenuItems, self)
- return true
- elseif x == self.Width - 1 and y == 1 then
- self:ToggleExpanded()
- return true
- elseif y ~= 1 then
- return self.ContentView:Click(side, x - self.ContentView.X + 1, y - self.ContentView.Y + 1)
- end
- return false
- end
- }
- ContentView = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- Parent = nil,
- Views = {},
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- for i, view in ipairs(self.Views) do
- view:Draw()
- end
- end,
- Initialise = function(self, x, y, width, height, views, parent)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = width
- new.Height = height
- new.Y = y
- new.X = x
- new.Views = views or {}
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- for k, view in pairs(self.Views) do
- if DoClick(view, side, x, y) then
- return true
- end
- end
- end
- }
- Button = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.white,
- ActiveBackgroundColour = colours.lightGrey,
- Text = "",
- Parent = nil,
- _Click = nil,
- Toggle = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local bg = self.BackgroundColour
- local tc = self.TextColour
- if type(bg) == 'function' then
- bg = bg()
- end
- if self.Toggle then
- tc = UIColours.MenuBarActive
- bg = self.ActiveBackgroundColour
- end
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
- Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
- end,
- Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.Text = text or ""
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.white
- new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
- new.Parent = parent
- new._Click = click
- new.Toggle = toggle
- return new
- end,
- Click = function(self, side, x, y)
- if self._Click then
- if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
- self.Toggle = not self.Toggle
- Draw()
- end
- return true
- else
- return false
- end
- end
- }
- TextBox = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- BackgroundColour = colours.lightGrey,
- TextColour = colours.black,
- Parent = nil,
- TextInput = nil,
- AbsolutePosition = function(self)
- return self.Parent:AbsolutePosition()
- end,
- Draw = function(self)
- local pos = GetAbsolutePosition(self)
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
- local text = self.TextInput.Value
- if #text > (self.Width - 2) then
- text = text:sub(#text-(self.Width - 3))
- if Current.Input == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
- end
- else
- if Current.Input == self.TextInput then
- Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
- end
- end
- Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
- term.setCursorBlink(true)
- Current.CursorColour = self.TextColour
- end,
- Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- height = height or 1
- new.Width = width or #text + 2
- new.Height = height
- new.Y = y
- new.X = x
- new.TextInput = TextInput:Initialise(text or '', function(key)
- if done then
- done(key)
- end
- Draw()
- end, numerical)
- new.BackgroundColour = backgroundColour or colours.lightGrey
- new.TextColour = textColour or colours.black
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- Current.Input = self.TextInput
- self:Draw()
- end
- }
- TextInput = {
- Value = "",
- Change = nil,
- CursorPos = nil,
- Numerical = false,
- Initialise = function(self, value, change, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Value = value
- new.Change = change
- new.CursorPos = #value
- new.Numerical = numerical
- return new
- end,
- Char = function(self, char)
- if self.Numerical then
- char = tostring(tonumber(char))
- end
- if char == 'nil' then
- return
- end
- self.Value = string.sub(self.Value, 1, self.CursorPos ) .. char .. string.sub( self.Value, self.CursorPos + 1 )
- self.CursorPos = self.CursorPos + 1
- self.Change(key)
- end,
- Key = function(self, key)
- if key == keys.enter then
- self.Change(key)
- elseif key == keys.left then
- -- Left
- if self.CursorPos > 0 then
- self.CursorPos = self.CursorPos - 1
- self.Change(key)
- end
- elseif key == keys.right then
- -- Right
- if self.CursorPos < string.len(self.Value) then
- self.CursorPos = self.CursorPos + 1
- self.Change(key)
- end
- elseif key == keys.backspace then
- -- Backspace
- if self.CursorPos > 0 then
- self.Value = string.sub( self.Value, 1, self.CursorPos - 1 ) .. string.sub( self.Value, self.CursorPos + 1 )
- self.CursorPos = self.CursorPos - 1
- end
- self.Change(key)
- elseif key == keys.home then
- -- Home
- self.CursorPos = 0
- self.Change(key)
- elseif key == keys.delete then
- if self.CursorPos < string.len(self.Value) then
- self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )
- self.Change(key)
- end
- elseif key == keys["end"] then
- -- End
- self.CursorPos = string.len(self.Value)
- self.Change(key)
- end
- end
- }
- LayerItem = {
- X = 1,
- Y = 1,
- Parent = nil,
- Layer = nil,
- Draw = function(self)
- self.Y = self.Layer.Index
- local pos = GetAbsolutePosition(self)
- local tc = colours.lightGrey
- if Current.Layer == self.Layer then
- tc = colours.white
- end
- Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, UIColours.Toolbar)
- Drawing.DrawCharacters(pos.X + 3, pos.Y, self.Layer.Name, tc, UIColours.Toolbar)
- if self.Layer.Visible then
- Drawing.DrawCharacters(pos.X + 1, pos.Y, "@", tc, UIColours.Toolbar)
- else
- Drawing.DrawCharacters(pos.X + 1, pos.Y, "X", tc, UIColours.Toolbar)
- end
- end,
- Initialise = function(self, layer, parent)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = parent.Width
- new.Height = 1
- new.Y = 1
- new.X = 1
- new.Layer = layer
- new.Parent = parent
- return new
- end,
- Click = function(self, side, x, y)
- if x == 2 then
- self.Layer.Visible = not self.Layer.Visible
- else
- Current.Layer = self.Layer
- end
- return true
- end
- }
- Menu = {
- X = 0,
- Y = 0,
- Width = 0,
- Height = 0,
- Owner = nil,
- Items = {},
- RemoveTop = false,
- Draw = function(self)
- Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
- if not self.RemoveTop then
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
- end
- end
- else
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
- for i, item in ipairs(self.Items) do
- if item.Separator then
- Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
- else
- local textColour = UIColours.MenuText
- if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
- textColour = UIColours.MenuDisabledText
- end
- Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
- Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
- end
- end
- end
- end,
- NameForKey = function(self, key)
- if key == keys.leftCtrl then
- return '^'
- elseif key == keys.tab then
- return 'Tab'
- elseif key == keys.delete then
- return 'Delete'
- elseif key == keys.n then
- return 'N'
- elseif key == keys.s then
- return 'S'
- elseif key == keys.o then
- return 'O'
- elseif key == keys.z then
- return 'Z'
- elseif key == keys.y then
- return 'Y'
- elseif key == keys.c then
- return 'C'
- elseif key == keys.x then
- return 'X'
- elseif key == keys.v then
- return 'V'
- elseif key == keys.r then
- return 'R'
- elseif key == keys.l then
- return 'L'
- elseif key == keys.t then
- return 'T'
- elseif key == keys.h then
- return 'H'
- elseif key == keys.e then
- return 'E'
- elseif key == keys.p then
- return 'P'
- elseif key == keys.f then
- return 'F'
- elseif key == keys.m then
- return 'M'
- else
- return '?'
- end
- end,
- Initialise = function(self, x, y, items, owner, removeTop)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- if not owner then
- return
- end
- local keyNames = {}
- for i, v in ipairs(items) do
- items[i].KeyName = ''
- if v.Keys then
- for _i, key in ipairs(v.Keys) do
- items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
- end
- end
- if items[i].KeyName ~= '' then
- table.insert(keyNames, items[i].KeyName)
- end
- end
- local keysLength = LongestString(keyNames)
- if keysLength > 0 then
- keysLength = keysLength + 2
- end
- new.Width = LongestString(items, 'Title') + 2 + keysLength
- if new.Width < 10 then
- new.Width = 10
- end
- new.Height = #items + 2
- new.RemoveTop = removeTop or false
- if removeTop then
- new.Height = new.Height - 1
- end
- if y < 1 then
- y = 1
- end
- if x < 1 then
- x = 1
- end
- if y + new.Height > Drawing.Screen.Height + 1 then
- y = Drawing.Screen.Height - new.Height
- end
- if x + new.Width > Drawing.Screen.Width + 1 then
- x = Drawing.Screen.Width - new.Width
- end
- new.Y = y
- new.X = x
- new.Items = items
- new.Owner = owner
- return new
- end,
- New = function(self, x, y, items, owner, removeTop)
- if Current.Menu and Current.Menu.Owner == owner then
- Current.Menu = nil
- return
- end
- local new = self:Initialise(x, y, items, owner, removeTop)
- Current.Menu = new
- return new
- end,
- Click = function(self, side, x, y)
- local i = y-1
- if self.RemoveTop then
- i = y
- end
- if i >= 1 and y < self.Height then
- if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
- self.Items[i]:Click()
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- self = nil
- end
- return true
- end
- end
- }
- MenuBar = {
- X = 1,
- Y = 1,
- Width = Drawing.Screen.Width,
- Height = 1,
- MenuBarItems = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.Toolbar)
- for i, button in ipairs(self.MenuBarItems) do
- button:Draw()
- end
- end,
- Initialise = function(self, items)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.X = 1
- new.Y = 1
- new.MenuBarItems = items
- return new
- end,
- AddToolbarItem = function(self, item)
- table.insert(self.ToolbarItems, item)
- self:CalculateToolbarItemPositions()
- end,
- CalculateToolbarItemPositions = function(self)
- local currY = 1
- for i, toolbarItem in ipairs(self.ToolbarItems) do
- toolbarItem.Y = currY
- currY = currY + toolbarItem.Height
- end
- end,
- Click = function(self, side, x, y)
- for i, item in ipairs(self.MenuBarItems) do
- if item.X <= x and item.X + item.Width > x then
- if item:Click(item, side, x - item.X + 1, 1) then
- break
- end
- end
- end
- return false
- end
- }
- --Modules--
- Modules = {
- {
- Title = "Colours",
- ToolbarItem = nil,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar)
- local buttons = {}
- local i = 0
- local coloursWidth = 8
- local _colours = {
- colours.brown,
- colours.yellow,
- colours.orange,
- colours.red,
- colours.green,
- colours.lime,
- colours.magenta,
- colours.pink,
- colours.purple,
- colours.blue,
- colours.cyan,
- colours.lightBlue,
- colours.lightGrey,
- colours.grey,
- colours.black,
- colours.white
- }
- for k, colour in pairs(_colours) do
- if type(colour) == 'number' and colour ~= -1 then
- i = i + 1
- local y = math.floor(i/(coloursWidth/2))
- local x = (i%(coloursWidth/2))
- if x == 0 then
- x = (coloursWidth/2)
- y = y -1
- end
- table.insert(buttons,
- {
- X = x*2 - 2 + self.ToolbarItem.Width - coloursWidth,
- Y = y+1,
- Width = 2,
- Height = 1,
- BackgroundColour = colour,
- Click = function(self, side, x, y)
- SetColour(self.BackgroundColour)
- end
- }
- )
- end
- end
- for i, button in ipairs(buttons) do
- table.insert(self.ToolbarItem.ContentView.Views,
- Button:Initialise(button.X, button.Y, button.Width, button.Height, button.BackgroundColour, self.ToolbarItem.ContentView, button.Click))
- end
- table.insert(self.ToolbarItem.ContentView.Views,
- Button:Initialise(1, 1, 4, 3, function()return Current.Colour end, self.ToolbarItem.ContentView, nil))
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- },
- {
- Title = "Tools",
- ToolbarItem = nil,
- Update = function(self)
- for i, view in ipairs(self.ToolbarItem.ContentView.Views) do
- if (Current.Tool and Current.Tool.Name == view.Text) then
- view.TextColour = colours.white
- else
- view.TextColour = colours.lightGrey
- end
- end
- self.ToolbarItem.ContentView.Views[1].Text = 'Size: '..Current.ToolSize
- end,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, #Tools+2, true, Current.Toolbar,
- {{
- Title = "Change Tool Size",
- Click = function()
- DisplayToolSizeWindow()
- end,
- }})
- table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, 1, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, DisplayToolSizeWindow, 'Size: '..Current.ToolSize))
- local y = 2
- for i, tool in ipairs(Tools) do
- table.insert(self.ToolbarItem.ContentView.Views, Button:Initialise(1, y, self.ToolbarItem.Width, 1, UIColours.Toolbar, self.ToolbarItem.ContentView, function() SetTool(tool) self:Update(self.ToolbarItem) end, tool.Name))
- y = y + 1
- end
- self:Update(self.ToolbarItem)
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- },
- {
- Title = "Layers",
- ToolbarItem = nil,
- Update = function(self)
- if Current.Artboard then
- self.ToolbarItem.ContentView.Views = {}
- for i = 1, #Current.Artboard.Layers do
- table.insert(self.ToolbarItem.ContentView.Views, LayerItem:Initialise(Current.Artboard.Layers[#Current.Artboard.Layers-i+1], self.ToolbarItem.ContentView))
- end
- end
- end,
- Initialise = function(self)
- self.ToolbarItem = ToolbarItem:Initialise(self, nil, true, Current.Toolbar,
- {{
- Title = "New Layer",
- Click = function()
- MakeNewLayer()
- end,
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = 'Delete Layer',
- Click = function()
- DeleteLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Title = 'Rename Layer...',
- Click = function()
- RenameLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- }})
- self:Update()
- Current.Toolbar:AddToolbarItem(self.ToolbarItem)
- end
- }
- }
- function ModuleNamed(name)
- for i, v in ipairs(Modules) do
- if v.Title == name then
- return v
- end
- end
- end
- --Tools--
- function ToolAffectedPixels(x, y)
- if not CheckSelectedLayer() then
- return {}
- end
- if Current.ToolSize == 1 then
- if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
- return {{Current.Layer.Pixels[x][y], x, y}}
- end
- else
- local pixels = {}
- local cornerX = x - math.ceil(Current.ToolSize/2)
- local cornerY = y - math.ceil(Current.ToolSize/2)
- for _x = 1, Current.ToolSize do
- for _y = 1, Current.ToolSize do
- if Current.Layer.Pixels[cornerX + _x] and Current.Layer.Pixels[cornerX + _x][cornerY + _y] then
- table.insert(pixels, {Current.Layer.Pixels[cornerX + _x][cornerY + _y], cornerX + _x, cornerY + _y})
- end
- end
- end
- return pixels
- end
- end
- local moveStartPoint = {}
- Tools = {
- {
- Name = "Hand",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if drag and Current.HandDragStart and Current.HandDragStart[1] and Current.HandDragStart[2] then
- local deltaX = x - Current.HandDragStart[1]
- local deltaY = y - Current.HandDragStart[2]
- Current.Artboard.X = Current.Artboard.X + deltaX
- Current.Artboard.Y = Current.Artboard.Y + deltaY
- else
- Current.HandDragStart = {x, y}
- end
- sleep(0)
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Pencil",
- Use = function(self, _x, _y, side, artboard)
- Current.Input = nil
- for i, pixel in ipairs(ToolAffectedPixels(_x, _y)) do
- if side == 1 then
- pixel[1].BackgroundColour = Current.Colour
- elseif side == 2 then
- pixel[1].TextColour = Current.Colour
- end
- pixel[1]:Draw(pixel[2], pixel[3])
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Eraser",
- Use = function(self, x, y, side)
- Current.Input = nil
- Current.Layer:SetPixel(x, y, nil, Current.Layer.BackgroundColour, nil)
- for i, pixel in ipairs(ToolAffectedPixels(x, y)) do
- Current.Layer:SetPixel(pixel[2], pixel[3], nil, Current.Layer.BackgroundColour, nil)
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Fill Bucket",
- Use = function(self, x, y, side)
- local replaceColour = Current.Layer.Pixels[x][y].BackgroundColour
- if side == 2 then
- replaceColour = Current.Layer.Pixels[x][y].TextColour
- end
- local nodes = {{X = x, Y = y}}
- while #nodes > 0 do
- local node = nodes[1]
- if Current.Layer.Pixels[node.X] and Current.Layer.Pixels[node.X][node.Y] then
- local replacing = Current.Layer.Pixels[node.X][node.Y].BackgroundColour
- if side == 2 then
- replacing = Current.Layer.Pixels[node.X][node.Y].TextColour
- end
- if replacing == replaceColour and replacing ~= Current.Colour then
- if side == 1 then
- Current.Layer.Pixels[node.X][node.Y].BackgroundColour = Current.Colour
- elseif side == 2 then
- Current.Layer.Pixels[node.X][node.Y].TextColour = Current.Colour
- end
- table.insert(nodes, {X = node.X, Y = node.Y + 1})
- table.insert(nodes, {X = node.X + 1, Y = node.Y})
- if x > 1 then
- table.insert(nodes, {X = node.X - 1, Y = node.Y})
- end
- if y > 1 then
- table.insert(nodes, {X = node.X, Y = node.Y - 1})
- end
- end
- end
- table.remove(nodes, 1)
- end
- Draw()
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Select",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if not drag then
- Current.Selection[1] = vector.new(x, y, 0)
- Current.Selection[2] = nil
- else
- Current.Selection[2] = vector.new(x, y, 0)
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Move",
- Use = function(self, x, y, side, drag)
- Current.Input = nil
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- if drag and moveStartPoint then
- local pixels = Current.Layer:PixelsInSelection(true)
- local size = Current.Selection[1] - Current.Selection[2]
- Current.Selection[1] = vector.new(x-moveStartPoint[1], y-moveStartPoint[2], 0)
- Current.Selection[2] = vector.new(x-moveStartPoint[1]-size.x, y-moveStartPoint[2]-size.y, 0)
- Current.Layer:InsertPixels(pixels)
- else
- moveStartPoint = {x-Current.Selection[1].x, y-Current.Selection[1].y}
- end
- end
- end,
- Select = function(self)
- return true
- end
- },
- {
- Name = "Text",
- Use = function(self, x, y)
- Current.Input = TextInput:Initialise('', function(key)
- if key == keys.delete or key == keys.backspace then
- if #Current.Input.Value == 0 then
- if Current.Layer.Pixels[x] and Current.Layer.Pixels[x][y] then
- Current.Layer.Pixels[x][y]:Set(nil, nil, ' ')
- local newPos = Current.CursorPos[1] - Current.Artboard.X
- if newPos < Current.Artboard.X - 1 then
- newPos = Current.Artboard.X - 1
- end
- Current.Tool:Use(newPos, Current.CursorPos[2] - Current.Artboard.Y + 1)
- Draw()
- end
- return
- else
- if Current.Layer.Pixels[x+#Current.Input.Value] and Current.Layer.Pixels[x+#Current.Input.Value][y] then
- Current.Layer.Pixels[x+#Current.Input.Value][y]:Set(nil, nil, ' ')
- end
- end
- else
- local i = #Current.Input.Value
- if Current.Layer.Pixels[x+i-1] then
- Current.Layer.Pixels[x+i-1][y]:Set(Current.Colour, nil, Current.Input.Value:sub(i,i))
- Current.Layer.Pixels[x+i-1][y]:Draw(x+i-1, y)
- end
- end
- local newPos = x+Current.Input.CursorPos
- if newPos > Current.Artboard.Width then
- Current.Input.CursorPos = Current.Input.CursorPos - 1
- end
- Current.CursorPos = {x+Current.Input.CursorPos + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
- Current.CursorColour = Current.Colour
- Draw()
- end)
- Current.CursorPos = {x + Current.Artboard.X - 1, y + Current.Artboard.Y - 1}
- Current.CursorColour = Current.Colour
- end,
- Select = function(self)
- if Current.Artboard.Format == '.nfp' then
- ButtonDialougeWindow:Initialise('NFP does not support text!', 'The format you are using, NFP, does not support text. Use NFT or SKCH to use text.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- return false
- else
- return true
- end
- end
- }
- }
- function ToolNamed(name)
- for i, v in ipairs(Tools) do
- if v.Name == name then
- return v
- end
- end
- end
- --Windows--
- NewDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OkButton = nil,
- Format = '.skch',
- ImageBackgroundColour = colours.white,
- NameLabelHighlight = false,
- SizeLabelHighlight = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- local nameLabelColour = colours.black
- if self.NameLabelHighlight then
- nameLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+2, "Name", nameLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+4, "Type", colours.black, colours.white)
- local sizeLabelColour = colours.black
- if self.SizeLabelHighlight then
- sizeLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+6, "Size", sizeLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+11, self.Y+6, "x", colours.black, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+8, "Background", colours.black, colours.white)
- self.OkButton:Draw()
- self.CancelButton:Draw()
- self.SKCHButton:Draw()
- self.NFTButton:Draw()
- self.NFPButton:Draw()
- self.PathTextBox:Draw()
- self.WidthTextBox:Draw()
- self.HeightTextBox:Draw()
- self.WhiteButton:Draw()
- self.BlackButton:Draw()
- self.TransparentButton:Draw()
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 13
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'New Document'
- new.Visible = true
- new.NameLabelHighlight = false
- new.SizeLabelHighlight = false
- new.Format = '.skch'
- new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local path = new.PathTextBox.TextInput.Value
- local ok = true
- new.NameLabelHighlight = false
- new.SizeLabelHighlight = false
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if path:sub(-1) == '/' or _fs.isDir(path) or #path == 0 then
- ok = false
- new.NameLabelHighlight = true
- end
- if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
- ok = false
- new.SizeLabelHighlight = true
- end
- if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
- ok = false
- new.SizeLabelHighlight = true
- end
- if ok then
- returnFunc(new, true, path, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.Format, new.ImageBackgroundColour)
- else
- Draw()
- end
- end, 'Ok', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 13, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)returnFunc(new, false)end, 'Cancel', colours.black)
- new.SKCHButton = Button:Initialise(7, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.NFTButton.Toggle = false
- new.NFPButton.Toggle = false
- self.Toggle = false
- new.Format = '.skch'
- end, '.skch', colours.black, true, colours.lightBlue)
- new.NFTButton = Button:Initialise(15, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.SKCHButton.Toggle = false
- new.NFPButton.Toggle = false
- self.Toggle = false
- new.Format = '.nft'
- end, '.nft', colours.black, false, colours.lightBlue)
- new.NFPButton = Button:Initialise(22, 5, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.SKCHButton.Toggle = false
- new.NFTButton.Toggle = false
- self.Toggle = false
- new.Format = '.nfp'
- end, '.nfp', colours.black, false, colours.lightBlue)
- local path = ''
- if OneOS then
- path = '/Desktop/'
- end
- new.PathTextBox = TextBox:Initialise(7, 3, new.Width - 7, 1, new, path, nil, nil, function(key)
- if key == keys.enter or key == keys.tab then
- Current.Input = new.WidthTextBox.TextInput
- end
- end)
- new.WidthTextBox = TextBox:Initialise(7, 7, 4, 1, new, tostring(15), nil, nil, function()
- if key == keys.enter or key == keys.tab then
- Current.Input = new.HeightTextBox.TextInput
- end
- end, true)
- new.HeightTextBox = TextBox:Initialise(14, 7, 4, 1, new, tostring(10), nil, nil, function()
- if key == keys.enter or key == keys.tab then
- Current.Input = new.PathTextBox.TextInput
- end
- end, true)
- Current.Input = new.PathTextBox.TextInput
- new.WhiteButton = Button:Initialise(2, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.TransparentButton.Toggle = false
- new.BlackButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.white
- end, 'White', colours.black, true, colours.lightBlue)
- new.BlackButton = Button:Initialise(10, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.TransparentButton.Toggle = false
- new.WhiteButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.black
- end, 'Black', colours.black, false, colours.lightBlue)
- new.TransparentButton = Button:Initialise(18, 10, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- new.WhiteButton.Toggle = false
- new.BlackButton.Toggle = false
- self.Toggle = false
- new.ImageBackgroundColour = colours.transparent
- end, 'Transparent', colours.black, false, colours.lightBlue)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- ButtonClick = function(self, button, x, y)
- if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
- button:Click()
- end
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton, self.SKCHButton, self.NFTButton, self.NFPButton, self.PathTextBox, self.WidthTextBox, self.HeightTextBox, self.WhiteButton, self.BlackButton, self.TransparentButton}
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- end
- end
- return true
- end
- }
- local TidyPath = function(path)
- path = '/'..path
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.isDir(path) then
- path = path .. '/'
- end
- path, n = path:gsub("//", "/")
- while n > 0 do
- path, n = path:gsub("//", "/")
- end
- return path
- end
- local WrapText = function(text, maxWidth)
- local lines = {''}
- for word, space in text:gmatch('(%S+)(%s*)') do
- local temp = lines[#lines] .. word .. space:gsub('\n','')
- if #temp > maxWidth then
- table.insert(lines, '')
- end
- if space:find('\n') then
- lines[#lines] = lines[#lines] .. word
- space = space:gsub('\n', function()
- table.insert(lines, '')
- return ''
- end)
- else
- lines[#lines] = lines[#lines] .. word .. space
- end
- end
- return lines
- end
- OpenDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OpenButton = nil,
- PathTextBox = nil,
- CurrentDirectory = '/',
- Scroll = 0,
- MaxScroll = 0,
- GoUpButton = nil,
- SelectedFile = '',
- Files = {},
- Typed = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
- self:DrawFiles()
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if (_fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and _fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
- self.OpenButton.TextColour = colours.black
- else
- self.OpenButton.TextColour = colours.lightGrey
- end
- self.PathTextBox:Draw()
- self.OpenButton:Draw()
- self.CancelButton:Draw()
- self.GoUpButton:Draw()
- end,
- DrawFiles = function(self)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- for i, file in ipairs(self.Files) do
- if i > self.Scroll and i - self.Scroll <= 11 then
- if file == self.SelectedFile then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
- elseif string.find(file, '%.skch') or string.find(file, '%.nft') or string.find(file, '%.nfp') or _fs.isDir(self.CurrentDirectory .. file) then
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
- else
- Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
- end
- end
- end
- self.MaxScroll = #self.Files - 11
- if self.MaxScroll < 0 then
- self.MaxScroll = 0
- end
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 32
- new.Height = 17
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Open Document'
- new.Visible = true
- new.CurrentDirectory = '/'
- new.SelectedFile = nil
- if OneOS then
- new.CurrentDirectory = '/Desktop/'
- end
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- if _fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not _fs.isDir(new.PathTextBox.TextInput.Value) then
- returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
- elseif new.SelectedFile and self.TextColour == colours.black and _fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
- new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
- elseif new.SelectedFile and self.TextColour == colours.black then
- returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
- end
- end, 'Open', colours.black)
- new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- returnFunc(new, false)
- end, 'Cancel', colours.black)
- new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
- local folderName = _fs.getName(new.CurrentDirectory)
- local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
- new:GoToDirectory(parentDirectory)
- end, 'Go Up', colours.black)
- new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
- new:GoToDirectory(new.CurrentDirectory)
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- GoToDirectory = function(self, path)
- path = TidyPath(path)
- self.CurrentDirectory = path
- self.Scroll = 0
- self.SelectedFile = nil
- self.Typed = false
- self.PathTextBox.TextInput.Value = path
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- self.Files = _fs.list(self.CurrentDirectory)
- Draw()
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- if not found then
- if y <= 12 then
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- self.SelectedFile = _fs.list(self.CurrentDirectory)[y-1]
- self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
- Draw()
- end
- end
- return true
- end
- }
- ButtonDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 5 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, true)
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- TextDialougeWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- CancelButton = nil,
- OkButton = nil,
- Lines = {},
- TextInput = nil,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- for i, text in ipairs(self.Lines) do
- Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
- Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
- Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
- Current.CursorColour = colours.black
- self.OkButton:Draw()
- if self.CancelButton then
- self.CancelButton:Draw()
- end
- end,
- Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 28
- new.Lines = WrapText(message, new.Width - 2)
- new.Height = 7 + #new.Lines
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = title
- new.Visible = true
- new.Visible = true
- new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
- if #new.TextInput.Value > 0 then
- returnFunc(new, true, new.TextInput.Value)
- end
- end, okText)
- if cancelText then
- new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
- returnFunc(new, false)
- end, cancelText)
- end
- new.TextInput = TextInput:Initialise('', function(enter)
- if enter then
- new.OkButton:Click()
- end
- Draw()
- end, numerical)
- Current.Input = new.TextInput
- return new
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Window = nil
- Current.Input = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.CancelButton}
- local found = false
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- found = true
- end
- end
- return true
- end
- }
- ResizeDocumentWindow = {
- X = 1,
- Y = 1,
- Width = 0,
- Height = 0,
- CursorPos = 1,
- Visible = true,
- Return = nil,
- OkButton = nil,
- AnchorPosition = 5,
- WidthLabelHighlight = false,
- HeightLabelHighlight = false,
- AbsolutePosition = function(self)
- return {X = self.X, Y = self.Y}
- end,
- Draw = function(self)
- if not self.Visible then
- return
- end
- Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
- Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
- Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
- Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
- Drawing.DrawCharacters(self.X+1, self.Y+2, "New Size", colours.lightGrey, colours.white)
- if (#self.WidthTextBox.TextInput.Value > 0 and tonumber(self.WidthTextBox.TextInput.Value) < Current.Artboard.Width) or (#self.HeightTextBox.TextInput.Value > 0 and tonumber(self.HeightTextBox.TextInput.Value) < Current.Artboard.Height) then
- Drawing.DrawCharacters(self.X+1, self.Y+8, "Clipping will occur!", colours.red, colours.white)
- end
- local widthLabelColour = colours.black
- if self.WidthLabelHighlight then
- widthLabelColour = colours.red
- end
- local heightLabelColour = colours.black
- if self.HeightLabelHighlight then
- heightLabelColour = colours.red
- end
- Drawing.DrawCharacters(self.X+1, self.Y+4, "Width", widthLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+1, self.Y+6, "Height", heightLabelColour, colours.white)
- Drawing.DrawCharacters(self.X+14, self.Y+2, "Anchor", colours.lightGrey, colours.white)
- self.WidthTextBox:Draw()
- self.HeightTextBox:Draw()
- self.OkButton:Draw()
- self.Anchor1:Draw()
- self.Anchor2:Draw()
- self.Anchor3:Draw()
- self.Anchor4:Draw()
- self.Anchor5:Draw()
- self.Anchor6:Draw()
- self.Anchor7:Draw()
- self.Anchor8:Draw()
- self.Anchor9:Draw()
- end,
- Initialise = function(self, returnFunc)
- local new = {} -- the new instance
- setmetatable( new, {__index = self} )
- new.Width = 27
- new.Height = 10
- new.Return = returnFunc
- new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
- new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
- new.Title = 'Resize Document'
- new.Visible = true
- new.WidthTextBox = TextBox:Initialise(9, 5, 4, 1, new, tostring(Current.Artboard.Width), nil, nil, function()
- new:UpdateAnchorButtons()
- end, true)
- new.HeightTextBox = TextBox:Initialise(9, 7, 4, 1, new, tostring(Current.Artboard.Height), nil, nil, function()
- new:UpdateAnchorButtons()
- end, true)
- new.OkButton = Button:Initialise(new.Width - 4, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
- local ok = true
- new.WidthLabelHighlight = false
- new.HeightLabelHighlight = false
- if #new.WidthTextBox.TextInput.Value == 0 or tonumber(new.WidthTextBox.TextInput.Value) <= 0 then
- ok = false
- new.WidthLabelHighlight = true
- end
- if #new.HeightTextBox.TextInput.Value == 0 or tonumber(new.HeightTextBox.TextInput.Value) <= 0 then
- ok = false
- new.HeightLabelHighlight = true
- end
- if ok then
- returnFunc(new, tonumber(new.WidthTextBox.TextInput.Value), tonumber(new.HeightTextBox.TextInput.Value), new.AnchorPosition)
- else
- Draw()
- end
- end, 'Ok', colours.black)
- local anchorX = 15
- local anchorY = 5
- new.Anchor1 = Button:Initialise(anchorX, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 1 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor2 = Button:Initialise(anchorX+1, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 2 new:UpdateAnchorButtons() end, '^', colours.black)
- new.Anchor3 = Button:Initialise(anchorX+2, anchorY, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 3 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor4 = Button:Initialise(anchorX, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 4 new:UpdateAnchorButtons() end, '<', colours.black)
- new.Anchor5 = Button:Initialise(anchorX+1, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 5 new:UpdateAnchorButtons() end, '#', colours.black)
- new.Anchor6 = Button:Initialise(anchorX+2, anchorY+1, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 6 new:UpdateAnchorButtons() end, '>', colours.black)
- new.Anchor7 = Button:Initialise(anchorX, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 7 new:UpdateAnchorButtons() end, ' ', colours.black)
- new.Anchor8 = Button:Initialise(anchorX+1, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 8 new:UpdateAnchorButtons() end, 'v', colours.black)
- new.Anchor9 = Button:Initialise(anchorX+2, anchorY+2, 1, 1, colours.lightGrey, new, function(self, side, x, y, toggle)new.AnchorPosition = 9 new:UpdateAnchorButtons() end, ' ', colours.black)
- return new
- end,
- UpdateAnchorButtons = function(self)
- local anchor1 = ' '
- local anchor2 = ' '
- local anchor3 = ' '
- local anchor4 = ' '
- local anchor5 = ' '
- local anchor6 = ' '
- local anchor7 = ' '
- local anchor8 = ' '
- local anchor9 = ' '
- self.AnchorPosition = self.AnchorPosition or 5
- if self.AnchorPosition == 1 then
- anchor1 = '#'
- anchor2 = '>'
- anchor4 = 'v'
- elseif self.AnchorPosition == 2 then
- anchor1 = '<'
- anchor2 = '#'
- anchor3 = '>'
- anchor5 = 'v'
- elseif self.AnchorPosition == 3 then
- anchor2 = '<'
- anchor3 = '#'
- anchor6 = 'v'
- elseif self.AnchorPosition == 4 then
- anchor1 = '^'
- anchor4 = '#'
- anchor5 = '>'
- anchor7 = 'v'
- elseif self.AnchorPosition == 5 then
- anchor2 = '^'
- anchor4 = '<'
- anchor5 = '#'
- anchor6 = '>'
- anchor8 = 'v'
- elseif self.AnchorPosition == 6 then
- anchor3 = '^'
- anchor6 = '#'
- anchor5 = '<'
- anchor9 = 'v'
- elseif self.AnchorPosition == 7 then
- anchor4 = '^'
- anchor7 = '#'
- anchor8 = '>'
- elseif self.AnchorPosition == 8 then
- anchor5 = '^'
- anchor8 = '#'
- anchor7 = '<'
- anchor9 = '>'
- elseif self.AnchorPosition == 9 then
- anchor6 = '^'
- anchor9 = '#'
- anchor8 = '<'
- end
- if #self.HeightTextBox.TextInput.Value > 0 and Current.Artboard.Height > tonumber(self.HeightTextBox.TextInput.Value) then
- local r = function(str)
- if string.find(str, "%^") then
- str = str:gsub('%^','v')
- elseif string.find(str, "v") then
- str = str:gsub('v','%^')
- end
- return str
- end
- anchor1 = r(anchor1)
- anchor2 = r(anchor2)
- anchor3 = r(anchor3)
- anchor4 = r(anchor4)
- anchor5 = r(anchor5)
- anchor6 = r(anchor6)
- anchor7 = r(anchor7)
- anchor8 = r(anchor8)
- anchor9 = r(anchor9)
- end
- if #self.WidthTextBox.TextInput.Value > 0 and Current.Artboard.Width > tonumber(self.WidthTextBox.TextInput.Value) then
- local r = function(str)
- if string.find(str, ">") then
- str = str:gsub('>','<')
- elseif string.find(str, "<") then
- str = str:gsub('<','>')
- end
- return str
- end
- anchor1 = r(anchor1)
- anchor2 = r(anchor2)
- anchor3 = r(anchor3)
- anchor4 = r(anchor4)
- anchor5 = r(anchor5)
- anchor6 = r(anchor6)
- anchor7 = r(anchor7)
- anchor8 = r(anchor8)
- anchor9 = r(anchor9)
- end
- self.Anchor1.Text = anchor1
- self.Anchor2.Text = anchor2
- self.Anchor3.Text = anchor3
- self.Anchor4.Text = anchor4
- self.Anchor5.Text = anchor5
- self.Anchor6.Text = anchor6
- self.Anchor7.Text = anchor7
- self.Anchor8.Text = anchor8
- self.Anchor9.Text = anchor9
- end,
- Show = function(self)
- Current.Window = self
- return self
- end,
- Close = function(self)
- Current.Input = nil
- Current.Window = nil
- self = nil
- end,
- Flash = function(self)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- sleep(0.15)
- self.Visible = false
- Draw()
- sleep(0.15)
- self.Visible = true
- Draw()
- end,
- ButtonClick = function(self, button, x, y)
- if button.X <= x and button.Y <= y and button.X + button.Width > x and button.Y + button.Height > y then
- button:Click()
- end
- end,
- Click = function(self, side, x, y)
- local items = {self.OkButton, self.WidthTextBox, self.HeightTextBox, self.Anchor1, self.Anchor2, self.Anchor3, self.Anchor4, self.Anchor5, self.Anchor6, self.Anchor7, self.Anchor8, self.Anchor9}
- for i, v in ipairs(items) do
- if CheckClick(v, x, y) then
- v:Click(side, x, y)
- end
- end
- return true
- end
- }
- ----------------------
- function CheckOpenArtboard()
- if Current.Artboard then
- return true
- else
- return false
- end
- end
- function CheckSelectedLayer()
- if Current.Artboard and Current.Layer then
- return true
- else
- return false
- end
- end
- function DisplayNewDocumentWindow()
- NewDocumentWindow:Initialise(function(self, success, path, width, height, format, backgroundColour)
- if success then
- if path:sub(-4) ~= format then
- path = path .. format
- end
- local oldWindow = self
- Current.Input = nil
- Current.Window = nil
- makeDocument = function()oldWindow:Close()NewDocument(path, width, height, format, backgroundColour)end
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) then
- ButtonDialougeWindow:Initialise('File Exists', path..' already exists! Use a different name and try again.', 'Ok', nil, function(window, ok)
- window:Close()
- oldWindow:Show()
- end):Show()
- elseif format == '.nfp' then
- Current.Window = nil
- ButtonDialougeWindow:Initialise('Use NFP?', 'The NFT format does not support text or layers, if you use it you will only be able to use 1 layer and not have any text.', 'Use NFP', 'Cancel', function(window, ok)
- window:Close()
- if ok then
- makeDocument()
- else
- oldWindow:Show()
- end
- end):Show()
- elseif format == '.nft' then
- ButtonDialougeWindow:Initialise('Use NFT?', 'The NFT format does not support layers, if you use it you will only be able to use 1 layer.', 'Use NFT', 'Cancel', function(window, ok)
- window:Close()
- if ok then
- makeDocument()
- else
- oldWindow:Show()
- end
- end):Show()
- else
- makeDocument()
- end
- else
- self:Close()
- end
- end):Show()
- end
- function NewDocument(path, width, height, format, backgroundColour)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- ab = Artboard:New(_fs.getName(path), path, width, height, format, backgroundColour)
- Current.Tool = Tools[2]
- Current.Toolbar:Update()
- Current.Modified = false
- Draw()
- end
- function DisplayToolSizeWindow()
- if not CheckOpenArtboard() then
- return
- end
- TextDialougeWindow:Initialise('Change Tool Size', 'Enter the new tool size you\'d like to use.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.ToolSize = math.ceil(tonumber(value))
- if Current.ToolSize < 1 then
- Current.ToolSize = 1
- elseif Current.ToolSize > 50 then
- Current.ToolSize = 50
- end
- ModuleNamed('Tools'):Update()
- end
- window:Close()
- end, true):Show()
- end
- --[[
- Attempt to figure out what format the image is if it doesn't have an extension
- ]]--
- function GetFormat(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local content = file.readAll()
- file.close()
- if type(textutils.unserialize(content)) == 'table' then
- -- It's a serlized table, asume sketch
- return '.skch'
- elseif string.find(content, string.char(30)) or string.find(content, string.char(31)) then
- -- Contains the characters that set colours, asume nft
- return '.nft'
- else
- -- Otherwise asume nfp
- return '.nfp'
- end
- end
- function DisplayOpenDocumentWindow()
- OpenDocumentWindow:Initialise(function(self, success, path)
- self:Close()
- if success then
- OpenDocument(path)
- end
- end):Show()
- end
- local function Extension(path, addDot)
- if not path then
- return nil
- elseif not string.find(fs.getName(path), '%.') then
- if not addDot then
- return fs.getName(path)
- else
- return ''
- end
- else
- local _path = path
- if path:sub(#path) == '/' then
- _path = path:sub(1,#path-1)
- end
- local extension = _path:gmatch('\.[0-9a-z]+$')()
- if extension then
- extension = extension:sub(2)
- else
- --extension = nil
- return ''
- end
- if addDot then
- extension = '.'..extension
- end
- return extension:lower()
- end
- end
- local RemoveExtension = function(path)
- if path:sub(1,1) == '.' then
- return path
- end
- local extension = Extension(path)
- if extension == path then
- return fs.getName(path)
- end
- return string.gsub(path, extension, ''):sub(1, -2)
- end
- --[[
- Open a documet at a given path
- ]]--
- function OpenDocument(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if _fs.exists(path) and not _fs.isDir(path) then
- local format = Extension(path, true)
- if (not format or format == '') and (format ~= '.nfp' and format ~= '.nft' and format ~= '.skch') then
- format = GetFormat(path)
- end
- local layers = {}
- if format == '.nfp' then
- layers = ReadNFP(path)
- elseif format == '.nft' then
- layers = ReadNFT(path)
- elseif format == '.skch' then
- layers = ReadSKCH(path)
- end
- for i, layer in ipairs(layers) do
- if layer.Visible == nil then
- layer.Visible = true
- end
- if layer.Index == nil then
- layer.Index = 1
- end
- if layer.Name == nil then
- if layer.Index == 1 then
- layer.Name = 'Background'
- else
- layer.Name = 'Layer'
- end
- end
- if layer.BackgroundColour == nil then
- layer.BackgroundColour = colours.white
- end
- end
- if not layers[1] then
- --log('File could not be read.')
- return
- end
- local width = #layers[1].Pixels
- local height = #layers[1].Pixels[1]
- Current.Artboard = nil
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- ab = Artboard:New(_fs.getName('Image'), path, width, height, format, nil, layers)
- Current.Tool = Tools[2]
- Current.Toolbar:Update()
- Current.Modified = false
- Draw()
- end
- end
- function MakeNewLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- TextDialougeWindow:Initialise('New Layer Name', 'Enter the name you want for the next layer.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.Artboard:MakeLayer(value, colours.transparent)
- end
- window:Close()
- end):Show()
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support multiple layers. Use SKCH to have more than one layer.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- function ResizeDocument()
- if not CheckOpenArtboard() then
- return
- end
- ResizeDocumentWindow:Initialise(function(window, width, height, anchor)
- window:Close()
- local topResize = 0
- local rightResize = 0
- local bottomResize = 0
- local leftResize = 0
- if anchor == 1 then
- rightResize = 1
- bottomResize = 1
- elseif anchor == 2 then
- rightResize = 0.5
- leftResize = 0.5
- bottomResize = 1
- elseif anchor == 3 then
- leftResize = 1
- bottomResize = 1
- elseif anchor == 4 then
- rightResize = 1
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 5 then
- rightResize = 0.5
- leftResize = 0.5
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 6 then
- leftResize = 1
- bottomResize = 0.5
- topResize = 0.5
- elseif anchor == 7 then
- rightResize = 1
- topResize = 1
- elseif anchor == 8 then
- rightResize = 0.5
- leftResize = 0.5
- topResize = 1
- elseif anchor == 9 then
- leftResize = 1
- topResize = 1
- end
- topResize = topResize * (height - Current.Artboard.Height)
- if topResize > 0 then
- topResize = math.floor(topResize)
- else
- topResize = math.ceil(topResize)
- end
- bottomResize = bottomResize * (height - Current.Artboard.Height)
- if bottomResize > 0 then
- bottomResize = math.ceil(bottomResize)
- else
- bottomResize = math.floor(bottomResize)
- end
- leftResize = leftResize * (width - Current.Artboard.Width)
- if leftResize > 0 then
- leftResize = math.floor(leftResize)
- else
- leftResize = math.ceil(leftResize)
- end
- rightResize = rightResize * (width - Current.Artboard.Width)
- if rightResize > 0 then
- rightResize = math.ceil(rightResize)
- else
- rightResize = math.floor(rightResize)
- end
- Current.Artboard:Resize(topResize, bottomResize, leftResize, rightResize)
- end):Show()
- end
- function RenameLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- TextDialougeWindow:Initialise("Rename Layer '"..Current.Layer.Name.."'", 'Enter the new name you want the layer to be called.', 'Ok', 'Cancel', function(window, success, value)
- if success then
- Current.Layer.Name = value
- end
- window:Close()
- end):Show()
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support renaming layers. Use SKCH to rename layers.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- function DeleteLayer()
- if not CheckOpenArtboard() then
- return
- end
- if Current.Artboard.Format == '.skch' then
- if #Current.Artboard.Layers > 1 then
- ButtonDialougeWindow:Initialise("Delete Layer '"..Current.Layer.Name.."'?", 'Are you sure you want delete the layer?', 'Ok', 'Cancel', function(window, success)
- if success then
- Current.Layer:Remove()
- end
- window:Close()
- end):Show()
- else
- ButtonDialougeWindow:Initialise('Can not delete layer!', 'You can not delete the last layer of an image! Make another layer to delete this one.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- else
- local format = 'NFP'
- if Current.Artboard.Format == '.nft' then
- format = 'NFT'
- end
- ButtonDialougeWindow:Initialise(format..' does not support layers!', 'The format you are using, '..format..', does not support deleting layers. Use SKCH to deleting layers.', 'Ok', nil, function(window)
- window:Close()
- end):Show()
- end
- end
- needsDraw = false
- isDrawing = false
- function Draw()
- if isDrawing then
- needsDraw = true
- return
- end
- needsDraw = false
- isDrawing = true
- if not Current.Window then
- Drawing.Clear(UIColours.Background)
- else
- Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
- end
- if Current.Artboard then
- ab:Draw()
- end
- if Current.InterfaceVisible then
- Current.MenuBar:Draw()
- Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
- Current.Toolbar:Draw()
- else
- Current.Toolbar.Width = Current.Toolbar.ExpandedWidth
- end
- if Current.InterfaceVisible and Current.Menu then
- Current.Menu:Draw()
- end
- if Current.Window then
- Current.Window:Draw()
- end
- if not Current.InterfaceVisible then
- ShowInterfaceButton:Draw()
- end
- Drawing.DrawBuffer()
- if Current.Input and not Current.Menu then
- term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
- term.setCursorBlink(true)
- term.setTextColour(Current.CursorColour)
- else
- term.setCursorBlink(false)
- end
- if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- Current.SelectionDrawTimer = os.startTimer(0.5)
- end
- isDrawing = false
- if needsDraw then
- Draw()
- end
- end
- function LoadMenuBar()
- Current.MenuBar = MenuBar:Initialise({
- Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(1, 2, {
- {
- Title = "New...",
- Click = function()
- DisplayNewDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.n
- }
- },
- {
- Title = 'Open...',
- Click = function()
- DisplayOpenDocumentWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.o
- }
- },
- {
- Separator = true
- },
- {
- Title = 'Save...',
- Click = function()
- Current.Artboard:Save()
- end,
- Keys = {
- keys.leftCtrl,
- keys.s
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Quit',
- Click = function()
- if Close() then
- OneOS.Close()
- end
- end
- },
- --[[
- {
- Title = 'Save As...',
- Click = function()
- end
- }
- ]]--
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'File', colours.lightGrey, false),
- Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if not self.Toggle then
- Menu:New(7, 2, {
- --[[
- {
- Title = "Undo",
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.z
- },
- Enabled = function()
- return false
- end
- },
- {
- Title = 'Redo',
- Click = function()
- end,
- Keys = {
- keys.leftCtrl,
- keys.y
- },
- Enabled = function()
- return false
- end
- },
- {
- Separator = true
- },
- ]]--
- {
- Title = 'Cut',
- Click = function()
- Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels')
- end,
- Keys = {
- keys.leftCtrl,
- keys.x
- },
- Enabled = function()
- return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Copy',
- Click = function()
- Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels')
- end,
- Keys = {
- keys.leftCtrl,
- keys.c
- },
- Enabled = function()
- return Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
- end
- },
- {
- Title = 'Paste',
- Click = function()
- Current.Layer:InsertPixels(Clipboard.Paste())
- end,
- Keys = {
- keys.leftCtrl,
- keys.v
- },
- Enabled = function()
- return (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels'
- end
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Edit', colours.lightGrey, false),
- Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- Menu:New(13, 2, {
- {
- Title = "Resize...",
- Click = function()
- ResizeDocument()
- end,
- Keys = {
- keys.leftCtrl,
- keys.r
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = "Crop",
- Click = function()
- local top = 0
- local left = 0
- local bottom = 0
- local right = 0
- if Current.Selection[1].x < Current.Selection[2].x then
- left = Current.Selection[1].x - 1
- right = Current.Artboard.Width - Current.Selection[2].x
- else
- left = Current.Selection[2].x - 1
- right = Current.Artboard.Width - Current.Selection[1].x
- end
- if Current.Selection[1].y < Current.Selection[2].y then
- top = Current.Selection[1].y - 1
- bottom = Current.Artboard.Height - Current.Selection[2].y
- else
- top = Current.Selection[2].y - 1
- bottom = Current.Artboard.Height - Current.Selection[1].y
- end
- Current.Artboard:Resize(-1*top, -1*bottom, -1*left, -1*right)
- Current.Selection[2] = nil
- end,
- Enabled = function()
- if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- return true
- else
- return false
- end
- end
- },
- {
- Separator = true
- },
- {
- Title = 'New Layer...',
- Click = function()
- MakeNewLayer()
- end,
- Keys = {
- keys.leftCtrl,
- keys.l
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- },
- {
- Title = 'Delete Layer',
- Click = function()
- DeleteLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Title = 'Rename Layer...',
- Click = function()
- RenameLayer()
- end,
- Enabled = function()
- return CheckSelectedLayer()
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Erase Selection',
- Click = function()
- Current.Layer:EraseSelection()
- end,
- Keys = {
- keys.delete
- },
- Enabled = function()
- if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
- return true
- else
- return false
- end
- end
- },
- {
- Separator = true
- },
- {
- Title = 'Hide Interface',
- Click = function()
- Current.InterfaceVisible = not Current.InterfaceVisible
- end,
- Keys = {
- keys.tab
- }
- }
- }, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Image', colours.lightGrey, false),
- Button:Initialise(20, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
- if toggle then
- local menuItems = {{
- Title = "Change Size",
- Click = function()
- DisplayToolSizeWindow()
- end,
- Keys = {
- keys.leftCtrl,
- keys.t
- }
- },
- {
- Separator = true
- }
- }
- local _keys = {'h','p','e','f','s','m','t'}
- for i, tool in ipairs(Tools) do
- table.insert(menuItems, {
- Title = tool.Name,
- Click = function()
- SetTool(tool)
- local m = ModuleNamed('Tools')
- m:Update(m.ToolbarItem)
- end,
- Keys = {
- keys[_keys[i]]
- },
- Enabled = function()
- return CheckOpenArtboard()
- end
- })
- end
- Menu:New(20, 2, menuItems, self, true)
- else
- Current.Menu = nil
- end
- return true
- end, 'Tools', colours.lightGrey, false),
- })
- end
- function Timer(event, timer)
- if timer == Current.ControlPressedTimer then
- Current.ControlPressedTimer = nil
- elseif timer == Current.SelectionDrawTimer then
- if Current.Artboard then
- Current.Artboard.SelectionIsBlack = not Current.Artboard.SelectionIsBlack
- Draw()
- end
- end
- end
- function Initialise(arg)
- if not OneOS then
- SplashScreen()
- end
- EventRegister('mouse_click', TryClick)
- EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
- EventRegister('mouse_scroll', Scroll)
- EventRegister('key', HandleKey)
- EventRegister('char', HandleKey)
- EventRegister('timer', Timer)
- EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
- Current.Toolbar = Toolbar:New('right', true)
- for k, v in pairs(Modules) do
- v:Initialise()
- end
- --term.setBackgroundColour(UIColours.Background)
- --term.clear()
- LoadMenuBar()
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- if arg and _fs.exists(arg) then
- OpenDocument(arg)
- else
- DisplayNewDocumentWindow()
- Current.Window.Visible = false
- end
- ShowInterfaceButton = Button:Initialise(Drawing.Screen.Width - 15, 1, nil, 1, colours.grey, nil, function(self)
- Current.InterfaceVisible = true
- Draw()
- end, 'Show Interface')
- Draw()
- if Current.Window then
- Current.Window.Visible = true
- Draw()
- end
- EventHandler()
- end
- function SplashScreen()
- local splashIcon = {{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},{1,256,256,8,8,8,8,8,8,8,8,256,256,1,},{256,8,8,8,8,8,8,8,8,8,8,8,8,256,},{256,256,256,8,8,8,8,8,8,8,8,256,256,256,},{256,256,256,256,256,256,256,256,256,256,256,256,256,256,},{2048,2048,256,256,256,256,256,256,256,256,256,256,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,},{256,256,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,256,256,},{1,256,256,256,256,256,256,256,256,256,256,256,256,1,},{1,1,1,256,256,256,256,256,256,256,256,1,1,1,},["text"]={{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","S","k","e","t","c","h"," "," "," "," ",},{" "," "," "," "," "," ","b","y"," "," "," "," "," "," ",},{" "," "," "," "," ","o","e","e","d"," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," "," "," "," ",},},["textcol"]={{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,256,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,1,32768,32768,32768,32768,},{32768,32768,32768,32768,8,8,8,8,8,8,8,32768,32768,32768,},{32768,32768,32768,32768,1,1,1,1,1,32768,8,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},{32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,},},}
- Drawing.Clear(colours.white)
- Drawing.DrawImage((Drawing.Screen.Width - 14)/2, (Drawing.Screen.Height - 13)/2, splashIcon, 14, 13)
- Drawing.DrawBuffer()
- parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
- end
- LongestString = function(input, key)
- local length = 0
- for i = 1, #input do
- local value = input[i]
- if key then
- if value[key] then
- value = value[key]
- else
- value = ''
- end
- end
- local titleLength = string.len(value)
- if titleLength > length then
- length = titleLength
- end
- end
- return length
- end
- function HandleKey(...)
- local args = {...}
- local event = args[1]
- local keychar = args[2]
- if event == 'key' and Current.Tool and Current.Tool.Name == 'Text' and Current.Input and (keychar == keys.up or keychar == keys.down or keychar == keys.left or keychar == keys.right) then
- local currentPos = {Current.CursorPos[1] - Current.Artboard.X + 1, Current.CursorPos[2] - Current.Artboard.Y + 1}
- if keychar == keys.up then
- currentPos[2] = currentPos[2] - 1
- elseif keychar == keys.down then
- currentPos[2] = currentPos[2] + 1
- elseif keychar == keys.left then
- currentPos[1] = currentPos[1] - 1
- elseif keychar == keys.right then
- currentPos[1] = currentPos[1] + 1
- end
- if currentPos[1] < 1 then
- currentPos[1] = 1
- end
- if currentPos[1] > Current.Artboard.Width then
- currentPos[1] = Current.Artboard.Width
- end
- if currentPos[2] < 1 then
- currentPos[2] = 1
- end
- if currentPos[2] > Current.Artboard.Height then
- currentPos[2] = Current.Artboard.Height
- end
- Current.Tool:Use(currentPos[1], currentPos[2])
- Current.Modified = true
- Draw()
- elseif Current.Input then
- if event == 'char' then
- Current.Input:Char(keychar)
- elseif event == 'key' then
- Current.Input:Key(keychar)
- end
- elseif event == 'key' then
- CheckKeyboardShortcut(keychar)
- end
- end
- function Scroll(event, direction, x, y)
- if Current.Window and Current.Window.OpenButton then
- Current.Window.Scroll = Current.Window.Scroll + direction
- if Current.Window.Scroll < 0 then
- Current.Window.Scroll = 0
- elseif Current.Window.Scroll > Current.Window.MaxScroll then
- Current.Window.Scroll = Current.Window.MaxScroll
- end
- end
- Draw()
- end
- function CheckKeyboardShortcut(key)
- local shortcuts = {}
- if key == keys.leftCtrl then
- Current.ControlPressedTimer = os.startTimer(0.5)
- return
- end
- if Current.ControlPressedTimer then
- shortcuts[keys.n] = function() DisplayNewDocumentWindow() end
- shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
- shortcuts[keys.s] = function() Current.Artboard:Save() end
- shortcuts[keys.x] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Cut(Current.Layer:PixelsInSelection(true), 'sketchpixels') end end
- shortcuts[keys.c] = function() if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Clipboard.Copy(Current.Layer:PixelsInSelection(), 'sketchpixels') end end
- shortcuts[keys.v] = function() if (not Clipboard.isEmpty()) and Clipboard.Type == 'sketchpixels' then Current.Layer:InsertPixels(Clipboard.Paste()) end end
- shortcuts[keys.r] = function() ResizeDocument() end
- shortcuts[keys.l] = function() MakeNewLayer() end
- end
- shortcuts[keys.delete] = function() if CheckSelectedLayer() and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then Current.Layer:EraseSelection() Draw() end end
- shortcuts[keys.backspace] = shortcuts[keys.delete]
- shortcuts[keys.tab] = function() Current.InterfaceVisible = not Current.InterfaceVisible Draw() end
- shortcuts[keys.h] = function() SetTool(ToolNamed('Hand')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.e] = function() SetTool(ToolNamed('Eraser')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.p] = function() SetTool(ToolNamed('Pencil')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.f] = function() SetTool(ToolNamed('Fill Bucket')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.m] = function() SetTool(ToolNamed('Move')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.s] = function() SetTool(ToolNamed('Select')) ModuleNamed('Tools'):Update() Draw() end
- shortcuts[keys.t] = function() SetTool(ToolNamed('Text')) ModuleNamed('Tools'):Update() Draw() end
- if shortcuts[key] then
- shortcuts[key]()
- return true
- else
- return false
- end
- end
- --[[
- Check if the given object falls under the click coordinates
- ]]--
- function CheckClick(object, x, y)
- if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
- return true
- end
- end
- --[[
- Attempt to clicka given object
- ]]--
- function DoClick(object, side, x, y, drag)
- if object and CheckClick(object, x, y) then
- return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
- end
- end
- --[[
- Try to click at the given coordinates
- ]]--
- function TryClick(event, side, x, y, drag)
- if Current.InterfaceVisible and Current.Menu then
- if DoClick(Current.Menu, side, x, y, drag) then
- Draw()
- return
- else
- if Current.Menu.Owner and Current.Menu.Owner.Toggle then
- Current.Menu.Owner.Toggle = false
- end
- Current.Menu = nil
- Draw()
- return
- end
- elseif Current.Window then
- if DoClick(Current.Window, side, x, y, drag) then
- Draw()
- return
- else
- Current.Window:Flash()
- return
- end
- end
- local interfaceElements = {}
- if Current.InterfaceVisible then
- table.insert(interfaceElements, Current.MenuBar)
- else
- table.insert(interfaceElements, ShowInterfaceButton)
- end
- for i, v in ipairs(Lists.Interface.Toolbars) do
- for i, v2 in ipairs(v.ToolbarItems) do
- table.insert(interfaceElements, v2)
- end
- table.insert(interfaceElements, v)
- end
- table.insert(interfaceElements, Current.Artboard)
- for i, object in ipairs(interfaceElements) do
- if DoClick(object, side, x, y, drag) then
- Draw()
- return
- end
- end
- Draw()
- end
- --[[
- Registers functions to run on certain events
- ]]--
- function EventRegister(event, func)
- if not Events[event] then
- Events[event] = {}
- end
- table.insert(Events[event], func)
- end
- --[[
- The main loop event handler, runs registered event functinos
- ]]--
- function EventHandler()
- while true do
- local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
- if Events[event] then
- for i, e in ipairs(Events[event]) do
- e(event, arg1, arg2, arg3, arg4)
- end
- end
- end
- end
- --[[
- Thanks to NitrogenFingers for the colour functions and NFT + NFP read/write functions
- ]]--
- --[[
- Gets the hex value from a colour
- ]]--
- local hexnums = { [10] = "a", [11] = "b", [12] = "c", [13] = "d", [14] = "e" , [15] = "f" }
- local function getHexOf(colour)
- if colour == colours.transparent or not colour or not tonumber(colour) then
- return " "
- end
- local value = math.log(colour)/math.log(2)
- if value > 9 then
- value = hexnums[value]
- end
- return value
- end
- --[[
- Gets the colour from a hex value
- ]]--
- local function getColourOf(hex)
- if hex == ' ' then
- return colours.transparent
- end
- local value = tonumber(hex, 16)
- if not value then return nil end
- value = math.pow(2,value)
- return value
- end
- --[[
- Saves the current artboard in .skch format
- ]]--
- function SaveSKCH()
- local layers = {}
- for i, l in ipairs(Current.Artboard.Layers) do
- local pixels = SaveNFT(i)
- local layer = {
- Name = l.Name,
- Pixels = pixels,
- BackgroundColour = l.BackgroundColour,
- Visible = l.Visible,
- Index = l.Index,
- }
- table.insert(layers, layer)
- end
- return layers
- end
- --[[
- Saves the current artboard in .nft format
- ]]--
- function SaveNFT(layer)
- layer = layer or 1
- local lines = {}
- local width = Current.Artboard.Width
- local height = Current.Artboard.Height
- for y = 1, height do
- local line = ''
- local currentBackgroundColour = nil
- local currentTextColour = nil
- for x = 1, width do
- local pixel = Current.Artboard.Layers[layer].Pixels[x][y]
- if pixel.BackgroundColour ~= currentBackgroundColour then
- line = line..string.char(30)..getHexOf(pixel.BackgroundColour)
- currentBackgroundColour = pixel.BackgroundColour
- end
- if pixel.TextColour ~= currentTextColour then
- line = line..string.char(31)..getHexOf(pixel.TextColour)
- currentTextColour = pixel.TextColour
- end
- line = line .. pixel.Character
- end
- table.insert(lines, line)
- end
- return lines
- end
- --[[
- Saves the current artboard in .nfp format
- ]]--
- function SaveNFP()
- local lines = {}
- local width = Current.Artboard.Width
- local height = Current.Artboard.Height
- for y = 1, height do
- local line = ''
- for x = 1, width do
- line = line .. getHexOf(Current.Artboard.Layers[1].Pixels[x][y].BackgroundColour)
- end
- table.insert(lines, line)
- end
- return lines
- end
- --[[
- Reads a .nfp file from the given path
- ]]--
- function ReadNFP(path)
- local pixels = {}
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local line = file.readLine()
- local y = 1
- while line do
- for x = 1, #line do
- if not pixels[x] then
- pixels[x] = {}
- end
- pixels[x][y] = {BackgroundColour = getColourOf(line:sub(x,x))}
- end
- y = y + 1
- line = file.readLine()
- end
- file.close()
- return {{Pixels = pixels}}
- end
- --[[
- Reads a .nft file from the given path
- ]]--
- function ReadNFT(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local line = file.readLine()
- local lines = {}
- while line do
- table.insert(lines, line)
- line = file.readLine()
- end
- file.close()
- return {{Pixels = ParseNFT(lines)}}
- end
- --[[
- Converts the lines of an .nft document to readble pixel data
- ]]--
- function ParseNFT(lines)
- local pixels = {}
- for y, line in ipairs(lines) do
- local bgNext, fgNext = false, false
- local currBG, currFG = nil,nil
- local writePosition = 1
- for x = 1, #line do
- if not pixels[writePosition] then
- pixels[writePosition] = {}
- end
- local nextChar = string.sub(line, x, x)
- if nextChar:byte() == 30 then
- bgNext = true
- elseif nextChar:byte() == 31 then
- fgNext = true
- elseif bgNext then
- currBG = getColourOf(nextChar)
- if currBG == nil then
- currBG = colours.transparent
- end
- bgNext = false
- elseif fgNext then
- currFG = getColourOf(nextChar)
- fgNext = false
- else
- if nextChar ~= " " and currFG == nil then
- currFG = colours.white
- end
- pixels[writePosition][y] = {BackgroundColour = currBG, TextColour = currFG, Character = nextChar}
- writePosition = writePosition + 1
- end
- end
- end
- return pixels
- end
- --[[
- Read a .skch file from the given path
- ]]--
- function ReadSKCH(path)
- local _fs = fs
- if OneOS then
- _fs = OneOS.FS
- end
- local file = _fs.open(path, 'r')
- local _layers = textutils.unserialize(file.readAll())
- file.close()
- local layers = {}
- for i, l in ipairs(_layers) do
- local layer = {
- Name = l.Name,
- Pixels = ParseNFT(l.Pixels),
- BackgroundColour = l.BackgroundColour,
- Visible = l.Visible,
- Index = l.Index,
- }
- table.insert(layers, layer)
- end
- return layers
- end
- --[[
- Start the program after all functions and tables are loaded
- ]]--
- if term.isColor and term.isColor() then
- Initialise(...)
- else
- print('Sorry, but Sketch only works on Advanced (gold) Computers')
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement