From 90840bd0a0e76de1cd50e75e2061a80c9ba98daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucio=20Andr=C3=A9s=20Illanes=20Albornoz?= Date: Tue, 1 Oct 2019 21:34:42 +0200 Subject: [PATCH] Various bugfixes & usability improvements. 1) Canvas window: clear new canvases w/ [-1, -1] by default. 2) Canvas window: don't create new canvas on initialisation. 3) Canvas window: set default brush colours to [3, 9]. 4) Erase tool: correctly fill non-text cells w/ background colour. 5) GUI: correctly show current operator name in status bar whilst active. 6) GUI: {de,in}crease canvas {height,width} w/ & cursor keys. 7) GUI: disable tiling items unless current tool is object tool. 8) GUI: select tool w/ accelerators. --- assets/text/TODO | 2 +- assets/text/melp.txt | 14 +++++++++----- assets/text/roadmap.txt | 22 +++++++++++----------- libroar/RoarCanvasCommandsEdit.py | 12 ++++++------ libroar/RoarCanvasCommandsFile.py | 2 +- libroar/RoarCanvasCommandsOperators.py | 2 +- libroar/RoarCanvasCommandsTools.py | 26 +++++++++++++++----------- libroar/RoarCanvasWindow.py | 5 +++-- libroar/RoarClient.py | 2 -- libroar/RoarWindowMelp.py | 2 +- libtools/ToolErase.py | 5 ++++- roar.py | 4 ++++ 12 files changed, 56 insertions(+), 42 deletions(-) diff --git a/assets/text/TODO b/assets/text/TODO index 0d1a760..d233da0 100644 --- a/assets/text/TODO +++ b/assets/text/TODO @@ -15,6 +15,6 @@ c) https://material.io/resources/icons/?style=baseline d) replace logo w/ canvas panel in About dialogue, revisit melp? dialogue e) replace resize buttons w/ {-,edit box,+} buttons & lock button re: ratio (ty lol3) - f) Settings/Settings window (e.g. autosave, cursor opacity, hide cursor on leaving window, ...) + f) Settings window (e.g. autosave parameters, cursor opacity, default colours, hide cursor on leaving window, keyboard/mouse map, show cell position tooltip on mouse hover, ...) vim:ff=dos tw=0 diff --git a/assets/text/melp.txt b/assets/text/melp.txt index 035961c..b3158a3 100644 --- a/assets/text/melp.txt +++ b/assets/text/melp.txt @@ -2,21 +2,25 @@ Keys or mouse actions separated by forward slashes (`/') indicate alternatives. Keys or mouse actions separated by commas indicate separate commands. Global commands: - -, +/ Decrease/increase brush size height and width - Decrease/increase rendered cell size - -, +/ Decrease/increase canvas size height and width + -, +/ Decrease/increase brush height and width + Decrease/increase canvas height and width + , Decrease/increase canvas height + , Decrease/increase canvas width + Decrease/increase cell size + 0-9 Set foreground colour to #0-9 0-5, 6 Set foreground colour to #10-15 or transparent colour, resp. 0-9 Set background colour to #0-9 0-5, 6 Set background colour to #10-15 or transparent colour, resp. - C, U, E, F, L, P, R, E, T Switch to circle, cursor, erase, fill, line, pick colour, rectangle, object, text tool I Flip colours + View melp? + Switch to cursor, rectangle, circle, fill, line, text, object, erase, pick colour tool + N New canvas O Open mIRC art file S Save canvas as mIRC art file X Exit Y, Z Redo, undo last action - View melp? Break into Python debugger Canvas commands: diff --git a/assets/text/roadmap.txt b/assets/text/roadmap.txt index b2a78c0..fcb785b 100644 --- a/assets/text/roadmap.txt +++ b/assets/text/roadmap.txt @@ -1,13 +1,13 @@ -1) canvas: default to transparent background colour -2) GUI: disable tiling items unless current tool is object tool -3) GUI: edit asset in new canvas, import from {canvas,object} -4) GUI: implement GuiCanvasWxBackendFast.c{,c} -5) GUI: select all -6) GUI: show line numbers w/ either ruler or tooltip -7) operators: copy, cut, delete, insert from, paste -8) operators: crop, scale, shift, slice operators -9) tools: measure, triangle, unicode block elements tool -10) tools: text tool: finish Arabic/RTL text implementation -11) tools: text tool: implicitly draw (text) w/ bg -1, toggle drawing actual brushColours[1] mode w/ RMB +1) Backend: correctly refresh transparent cursor cells when drawing cursor patches +2) GUI: edit asset in new canvas, import from {canvas,object} +3) GUI: implement GuiCanvasWxBackendFast.c{,c} +4) GUI: select all +5) GUI: show line numbers w/ tooltip on accelerator +6) Operators: copy, cut, delete, insert from, paste +7) Operators: crop, scale, shift, slice operators +8) Tools: measure, triangle, unicode block elements tool +9) Tools: object tool: reimplement cloning correctly outside of object tool +10) Tools: text tool: finish Arabic/RTL text implementation +11) Tools: text tool: implicitly draw (text) w/ bg -1, toggle drawing actual brushColours[1] mode w/ RMB vim:ff=dos tw=0 diff --git a/libroar/RoarCanvasCommandsEdit.py b/libroar/RoarCanvasCommandsEdit.py index d785606..21e6945 100644 --- a/libroar/RoarCanvasCommandsEdit.py +++ b/libroar/RoarCanvasCommandsEdit.py @@ -59,12 +59,12 @@ class RoarCanvasCommandsEdit(): setattr(canvasBrushSize_, "attrDict", f.attrList[dimension + (0 if not incrFlag else 3)]) return canvasBrushSize_ - @GuiCommandListDecorator(0, "Decrease canvas height", "Decrease canvas height", ["toolDecrCanvasH.png"], None, None) - @GuiCommandListDecorator(1, "Decrease canvas width", "Decrease canvas width", ["toolDecrCanvasW.png"], None, None) - @GuiCommandListDecorator(2, "Decrease canvas size", "Decrease canvas size", ["toolDecrCanvasHW.png"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("-")], None) - @GuiCommandListDecorator(3, "Increase canvas height", "Increase canvas height", ["toolIncrCanvasH.png"], None, None) - @GuiCommandListDecorator(4, "Increase canvas width", "Increase canvas width", ["toolIncrCanvasW.png"], None, None) - @GuiCommandListDecorator(5, "Increase canvas size", "Increase canvas size", ["toolIncrCanvasHW.png"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("+")], None) + @GuiCommandListDecorator(0, "Decrease canvas height", "Decrease canvas height", ["toolDecrCanvasH.png"], [wx.ACCEL_CTRL, wx.WXK_UP], None) + @GuiCommandListDecorator(1, "Decrease canvas width", "Decrease canvas width", ["toolDecrCanvasW.png"], [wx.ACCEL_CTRL, wx.WXK_LEFT], None) + @GuiCommandListDecorator(2, "Decrease canvas size", "Decrease canvas size", ["toolDecrCanvasHW.png"], None, None) + @GuiCommandListDecorator(3, "Increase canvas height", "Increase canvas height", ["toolIncrCanvasH.png"], [wx.ACCEL_CTRL, wx.WXK_DOWN], None) + @GuiCommandListDecorator(4, "Increase canvas width", "Increase canvas width", ["toolIncrCanvasW.png"], [wx.ACCEL_CTRL, wx.WXK_RIGHT], None) + @GuiCommandListDecorator(5, "Increase canvas size", "Increase canvas size", ["toolIncrCanvasHW.png"], None, None) def canvasCanvasSize(self, f, dimension, incrFlag): def canvasCanvasSize_(event): if (dimension < 2) and not incrFlag: diff --git a/libroar/RoarCanvasCommandsFile.py b/libroar/RoarCanvasCommandsFile.py index 4bd97e4..446ac34 100644 --- a/libroar/RoarCanvasCommandsFile.py +++ b/libroar/RoarCanvasCommandsFile.py @@ -261,7 +261,7 @@ class RoarCanvasCommandsFile(): nonlocal newCanvasSize if newCanvasSize == None: newCanvasSize = list(self.parentCanvas.canvas.size) - newMap = [[[1, 1, 0, " "] for x in range(newCanvasSize[0])] for y in range(newCanvasSize[1])] + newMap = [[[-1, -1, 0, " "] for x in range(newCanvasSize[0])] for y in range(newCanvasSize[1])] return (True, "", newMap, None, newCanvasSize) if self._promptSaveChanges(): self._import(canvasImportEmpty, False, None) diff --git a/libroar/RoarCanvasCommandsOperators.py b/libroar/RoarCanvasCommandsOperators.py index 6890a10..b9113fc 100644 --- a/libroar/RoarCanvasCommandsOperators.py +++ b/libroar/RoarCanvasCommandsOperators.py @@ -18,7 +18,7 @@ class RoarCanvasCommandsOperators(): @GuiCommandListDecorator(1, "Flip horizontally", "Flip &horizontally", None, None, None) @GuiCommandListDecorator(2, "Invert colours", "&Invert colours", None, None, None) @GuiCommandListDecorator(3, "Rotate", "&Rotate", None, None, None) - @GuiCommandListDecorator(4, "Tile", "&Tile", None, None, None) + @GuiCommandListDecorator(4, "Tile", "&Tile", None, None, False) def canvasOperator(self, f, idx): def canvasOperator_(event): self.currentOperator = [OperatorFlipVertical, OperatorFlipHorizontal, OperatorInvert, OperatorRotate, OperatorTile][idx]() diff --git a/libroar/RoarCanvasCommandsTools.py b/libroar/RoarCanvasCommandsTools.py index 3b4cf4e..b6a40a1 100644 --- a/libroar/RoarCanvasCommandsTools.py +++ b/libroar/RoarCanvasCommandsTools.py @@ -16,15 +16,15 @@ from ToolText import ToolText import wx class RoarCanvasCommandsTools(): - @GuiSelectDecorator(0, "Circle", "&Circle", ["toolCircle.png"], [wx.ACCEL_CTRL, ord("C")], False) - @GuiSelectDecorator(1, "Cursor", "C&ursor", ["toolCursor.png"], [wx.ACCEL_CTRL, ord("U")], False) - @GuiSelectDecorator(2, "Erase", "&Erase", ["toolErase.png"], [wx.ACCEL_CTRL, ord("A")], False) - @GuiSelectDecorator(3, "Fill", "&Fill", ["toolFill.png"], [wx.ACCEL_CTRL, ord("F")], False) - @GuiSelectDecorator(4, "Line", "&Line", ["toolLine.png"], [wx.ACCEL_CTRL, ord("L")], False) - @GuiSelectDecorator(5, "Object", "&Object", ["toolObject.png"], [wx.ACCEL_CTRL, ord("E")], False) - @GuiSelectDecorator(6, "Pick colour", "&Pick colour", ["toolPickColour.png"], [wx.ACCEL_CTRL, ord("P")], False) - @GuiSelectDecorator(7, "Rectangle", "&Rectangle", ["toolRect.png"], [wx.ACCEL_CTRL, ord("R")], True) - @GuiSelectDecorator(8, "Text", "&Text", ["toolText.png"], [wx.ACCEL_CTRL, ord("T")], False) + @GuiSelectDecorator(0, "Circle", "&Circle", ["toolCircle.png"], [wx.MOD_NONE, wx.WXK_F4], False) + @GuiSelectDecorator(1, "Cursor", "C&ursor", ["toolCursor.png"], [wx.MOD_NONE, wx.WXK_F2], False) + @GuiSelectDecorator(2, "Erase", "&Erase", ["toolErase.png"], [wx.MOD_NONE, wx.WXK_F9], False) + @GuiSelectDecorator(3, "Fill", "&Fill", ["toolFill.png"], [wx.MOD_NONE, wx.WXK_F5], False) + @GuiSelectDecorator(4, "Line", "&Line", ["toolLine.png"], [wx.MOD_NONE, wx.WXK_F6], False) + @GuiSelectDecorator(5, "Object", "&Object", ["toolObject.png"], [wx.MOD_NONE, wx.WXK_F8], False) + @GuiSelectDecorator(6, "Pick colour", "&Pick colour", ["toolPickColour.png"], [wx.MOD_NONE, wx.WXK_F10], False) + @GuiSelectDecorator(7, "Rectangle", "&Rectangle", ["toolRect.png"], [wx.MOD_NONE, wx.WXK_F3], True) + @GuiSelectDecorator(8, "Text", "&Text", ["toolText.png"], [wx.MOD_NONE, wx.WXK_F7], False) def canvasTool(self, f, idx): def canvasTool_(event): if (self.currentTool.__class__ == ToolObject) \ @@ -36,12 +36,16 @@ class RoarCanvasCommandsTools(): self.currentTool = self.currentTool() self.currentOperator, self.operatorState = None, None self.parentFrame.menuItemsById[self.canvasTool.attrList[idx]["id"]].Check(True) + if self.currentTool.__class__ == ToolObject: + self.parentFrame.menuItemsById[self.canvasOperator.attrList[4]["id"]].Enable(True) + else: + self.parentFrame.menuItemsById[self.canvasOperator.attrList[4]["id"]].Enable(False) toolBar = self.parentFrame.toolBarItemsById[self.canvasTool.attrList[idx]["id"]][0] toolBar.ToggleTool(self.canvasTool.attrList[idx]["id"], True); toolBar.Refresh(); if self.currentTool != None: - self.update(toolName=self.currentTool.name) + self.update(operator=None, toolName=self.currentTool.name) else: - self.update(toolName="Cursor") + self.update(operator=None, toolName="Cursor") viewRect = self.parentCanvas.GetViewStart() eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True) diff --git a/libroar/RoarCanvasWindow.py b/libroar/RoarCanvasWindow.py index c7b5c5b..74ed680 100644 --- a/libroar/RoarCanvasWindow.py +++ b/libroar/RoarCanvasWindow.py @@ -27,6 +27,7 @@ class RoarCanvasWindowDropTarget(wx.TextDropTarget): viewRect = self.parent.GetViewStart(); mapPoint = [m + n for m, n in zip((mapX, mapY), viewRect)]; self.parent.commands.lastTool, self.parent.commands.currentTool = self.parent.commands.currentTool, ToolObject() self.parent.commands.currentTool.setRegion(self.parent.canvas, mapPoint, dropMap, dropSize, external=True) + self.parent.parentFrame.menuItemsById[self.parent.commands.canvasOperator.attrList[4]["id"]].Enable(True) self.parent.commands.update(toolName=self.parent.commands.currentTool.name) eventDc = self.parent.backend.getDeviceContext(self.parent.GetClientSize(), self.parent, viewRect) eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0); @@ -129,10 +130,10 @@ class RoarCanvasWindow(GuiWindow): else: region = self.canvas.map if hasattr(operator, "apply2"): + self.commands.update(operator=self.commands.currentOperator.name) if mouseLeftDown: self.commands.operatorState = True if self.commands.operatorState == None else self.commands.operatorState region = operator.apply2(mapPoint, mousePoint, region, copy.deepcopy(region)) - self.commands.update(operator=self.commands.currentOperator.name) elif self.commands.operatorState != None: self.commands.currentOperator = None; self.commands.update(operator=None); rc = False; else: @@ -359,7 +360,7 @@ class RoarCanvasWindow(GuiWindow): super().__init__(parent, pos) self.lastMouseState, self.size = [False, False, False], size self.backend, self.canvas, self.commands, self.parentFrame = backend(self.size), canvas, commands(self, parent), parent - self.brushColours, self.brushPos, self.brushSize, self.dirty, self.lastCellState = [4, 1], [0, 0], [1, 1], False, None + self.brushColours, self.brushPos, self.brushSize, self.dirty, self.lastCellState = [3, 9], [0, 0], [1, 1], False, None self.popupEventDc = None self.dropTarget = RoarCanvasWindowDropTarget(self) self.SetDropTarget(self.dropTarget) diff --git a/libroar/RoarClient.py b/libroar/RoarClient.py index af1ceac..54c8297 100644 --- a/libroar/RoarClient.py +++ b/libroar/RoarClient.py @@ -51,8 +51,6 @@ class RoarClient(GuiFrame): self._initToolBitmaps(self.canvasPanel.commands.toolBars) self.loadToolBars(self.canvasPanel.commands.toolBars) - self.canvasPanel.commands.canvasNew(None) - self.canvasPanel.commands.canvasTool(self.canvasPanel.commands.canvasTool, 1)(None) self.canvasPanel.commands.update(brushSize=self.canvasPanel.brushSize, colours=self.canvasPanel.brushColours) self.addWindow(self.canvasPanel) self.assetsWindow = RoarAssetsWindow(GuiCanvasWxBackend, self) diff --git a/libroar/RoarWindowMelp.py b/libroar/RoarWindowMelp.py index 5ef84aa..d2e84a6 100644 --- a/libroar/RoarWindowMelp.py +++ b/libroar/RoarWindowMelp.py @@ -23,7 +23,7 @@ class RoarWindowMelp(wx.Dialog): self.sizer.AddMany(((self.title, 1, wx.ALL | wx.CENTER | wx.EXPAND, 4), (self.buttonRoar, 0, wx.ALL | wx.CENTER, 4),)) self.panel.SetSizerAndFit(self.sizer) newSize = self.sizer.ComputeFittingWindowSize(self) - self.SetSize((newSize[0] + 64, newSize[1],)); self.Center(); + self.SetSize((newSize[0] + 128, newSize[1],)); self.Center(); self.SetTitle(title) self.ShowModal() diff --git a/libtools/ToolErase.py b/libtools/ToolErase.py index 78541a7..c0095a0 100644 --- a/libtools/ToolErase.py +++ b/libtools/ToolErase.py @@ -21,7 +21,10 @@ class ToolErase(Tool): and ((mapPoint[0] + brushCol) < canvas.size[0]) \ and ((mapPoint[1] + brushRow) < canvas.size[1]) \ and (canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][1] == brushColours[1]): - patches += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][0], brushColours[0], *canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][2:]]] + if canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][3] == " ": + patches += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, brushColours[0], brushColours[0], *canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][2:]]] + else: + patches += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][0], brushColours[0], *canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][2:]]] else: patchesCursor += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, brushColours[1], brushColours[1], 0, " "]] return True, patches if not isCursor else None, patchesCursor diff --git a/roar.py b/roar.py index 9fa1aaa..e306aa4 100755 --- a/roar.py +++ b/roar.py @@ -31,8 +31,12 @@ def main(*argv): roarClient.canvasPanel.update(roarClient.canvasPanel.canvas.importStore.inSize, False, roarClient.canvasPanel.canvas.importStore.outMap, dirty=False) roarClient.canvasPanel.commands.update(pathName=argv[0], undoLevel=-1) roarClient.canvasPanel.commands._pushRecent(argv[0]) + roarClient.canvasPanel.commands.canvasTool(roarClient.canvasPanel.commands.canvasTool, 1)(None) else: print("error: {}".format(error), file=sys.stderr) + else: + roarClient.canvasPanel.commands.canvasNew(None) + roarClient.canvasPanel.commands.canvasTool(roarClient.canvasPanel.commands.canvasTool, 1)(None) wxApp.MainLoop() if __name__ == "__main__": main(*sys.argv)