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/ <Ctrl> & cursor keys.
7) GUI: disable tiling items unless current tool is object tool.
8) GUI: select tool w/ <F2-F10> accelerators.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2019-10-01 21:34:42 +02:00
parent 3bb4fb0197
commit 89c555e2fd
12 changed files with 56 additions and 42 deletions

View File

@ -15,6 +15,6 @@
c) https://material.io/resources/icons/?style=baseline c) https://material.io/resources/icons/?style=baseline
d) replace logo w/ canvas panel in About dialogue, revisit melp? dialogue 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) 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 vim:ff=dos tw=0

View File

@ -2,21 +2,25 @@ Keys or mouse actions separated by forward slashes (`/') indicate alternatives.
Keys or mouse actions separated by commas indicate separate commands. Keys or mouse actions separated by commas indicate separate commands.
Global commands: Global commands:
<Ctrl> -, +/<Mouse wheel> Decrease/increase brush size height and width <Ctrl> -, +/<Mouse wheel> Decrease/increase brush height and width
<Ctrl> <Alt> <Mouse wheel> Decrease/increase rendered cell size <Ctrl> <Mouse wheel> Decrease/increase canvas height and width
<Ctrl> <Shift> -, +/<Mouse wheel> Decrease/increase canvas size height and width <Ctrl> <Up>, <Down> Decrease/increase canvas height
<Ctrl> <Left>, <Right> Decrease/increase canvas width
<Ctrl> <Alt> <Mouse wheel> Decrease/increase cell size
<Ctrl> 0-9 Set foreground colour to #0-9 <Ctrl> 0-9 Set foreground colour to #0-9
<Ctrl> <Shift> 0-5, 6 Set foreground colour to #10-15 or transparent colour, resp. <Ctrl> <Shift> 0-5, 6 Set foreground colour to #10-15 or transparent colour, resp.
<Ctrl> <Alt> 0-9 Set background colour to #0-9 <Ctrl> <Alt> 0-9 Set background colour to #0-9
<Ctrl> <Alt> <Shift> 0-5, 6 Set background colour to #10-15 or transparent colour, resp. <Ctrl> <Alt> <Shift> 0-5, 6 Set background colour to #10-15 or transparent colour, resp.
<Ctrl> C, U, E, F, L, P, R, E, T Switch to circle, cursor, erase, fill, line, pick colour, rectangle, object, text tool
<Ctrl> I Flip colours <Ctrl> I Flip colours
<F1> View melp?
<F2-F10> Switch to cursor, rectangle, circle, fill, line, text, object, erase, pick colour tool
<Ctrl> N New canvas <Ctrl> N New canvas
<Ctrl> O Open mIRC art file <Ctrl> O Open mIRC art file
<Ctrl> S Save canvas as mIRC art file <Ctrl> S Save canvas as mIRC art file
<Ctrl> X Exit <Ctrl> X Exit
<Ctrl> Y, Z Redo, undo last action <Ctrl> Y, Z Redo, undo last action
<F1> View melp?
<Shift> <Pause> Break into Python debugger <Shift> <Pause> Break into Python debugger
Canvas commands: Canvas commands:

View File

@ -1,13 +1,13 @@
1) canvas: default to transparent background colour 1) Backend: correctly refresh transparent cursor cells when drawing cursor patches
2) GUI: disable tiling items unless current tool is object tool 2) GUI: edit asset in new canvas, import from {canvas,object}
3) GUI: edit asset in new canvas, import from {canvas,object} 3) GUI: implement GuiCanvasWxBackendFast.c{,c}
4) GUI: implement GuiCanvasWxBackendFast.c{,c} 4) GUI: select all
5) GUI: select all 5) GUI: show line numbers w/ tooltip on accelerator
6) GUI: show line numbers w/ either ruler or tooltip 6) Operators: copy, cut, delete, insert from, paste
7) operators: copy, cut, delete, insert from, paste 7) Operators: crop, scale, shift, slice operators
8) operators: crop, scale, shift, slice operators 8) Tools: measure, triangle, unicode block elements tool
9) 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 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 11) Tools: text tool: implicitly draw (text) w/ bg -1, toggle drawing actual brushColours[1] mode w/ RMB
vim:ff=dos tw=0 vim:ff=dos tw=0

View File

@ -59,12 +59,12 @@ class RoarCanvasCommandsEdit():
setattr(canvasBrushSize_, "attrDict", f.attrList[dimension + (0 if not incrFlag else 3)]) setattr(canvasBrushSize_, "attrDict", f.attrList[dimension + (0 if not incrFlag else 3)])
return canvasBrushSize_ return canvasBrushSize_
@GuiCommandListDecorator(0, "Decrease canvas height", "Decrease canvas height", ["toolDecrCanvasH.png"], None, 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"], None, 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"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("-")], None) @GuiCommandListDecorator(2, "Decrease canvas size", "Decrease canvas size", ["toolDecrCanvasHW.png"], None, None)
@GuiCommandListDecorator(3, "Increase canvas height", "Increase canvas height", ["toolIncrCanvasH.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"], None, 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"], [wx.ACCEL_CTRL | wx.ACCEL_SHIFT, ord("+")], None) @GuiCommandListDecorator(5, "Increase canvas size", "Increase canvas size", ["toolIncrCanvasHW.png"], None, None)
def canvasCanvasSize(self, f, dimension, incrFlag): def canvasCanvasSize(self, f, dimension, incrFlag):
def canvasCanvasSize_(event): def canvasCanvasSize_(event):
if (dimension < 2) and not incrFlag: if (dimension < 2) and not incrFlag:

View File

@ -261,7 +261,7 @@ class RoarCanvasCommandsFile():
nonlocal newCanvasSize nonlocal newCanvasSize
if newCanvasSize == None: if newCanvasSize == None:
newCanvasSize = list(self.parentCanvas.canvas.size) 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) return (True, "", newMap, None, newCanvasSize)
if self._promptSaveChanges(): if self._promptSaveChanges():
self._import(canvasImportEmpty, False, None) self._import(canvasImportEmpty, False, None)

View File

@ -18,7 +18,7 @@ class RoarCanvasCommandsOperators():
@GuiCommandListDecorator(1, "Flip horizontally", "Flip &horizontally", None, None, None) @GuiCommandListDecorator(1, "Flip horizontally", "Flip &horizontally", None, None, None)
@GuiCommandListDecorator(2, "Invert colours", "&Invert colours", None, None, None) @GuiCommandListDecorator(2, "Invert colours", "&Invert colours", None, None, None)
@GuiCommandListDecorator(3, "Rotate", "&Rotate", 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(self, f, idx):
def canvasOperator_(event): def canvasOperator_(event):
self.currentOperator = [OperatorFlipVertical, OperatorFlipHorizontal, OperatorInvert, OperatorRotate, OperatorTile][idx]() self.currentOperator = [OperatorFlipVertical, OperatorFlipHorizontal, OperatorInvert, OperatorRotate, OperatorTile][idx]()

View File

@ -16,15 +16,15 @@ from ToolText import ToolText
import wx import wx
class RoarCanvasCommandsTools(): class RoarCanvasCommandsTools():
@GuiSelectDecorator(0, "Circle", "&Circle", ["toolCircle.png"], [wx.ACCEL_CTRL, ord("C")], False) @GuiSelectDecorator(0, "Circle", "&Circle", ["toolCircle.png"], [wx.MOD_NONE, wx.WXK_F4], False)
@GuiSelectDecorator(1, "Cursor", "C&ursor", ["toolCursor.png"], [wx.ACCEL_CTRL, ord("U")], False) @GuiSelectDecorator(1, "Cursor", "C&ursor", ["toolCursor.png"], [wx.MOD_NONE, wx.WXK_F2], False)
@GuiSelectDecorator(2, "Erase", "&Erase", ["toolErase.png"], [wx.ACCEL_CTRL, ord("A")], False) @GuiSelectDecorator(2, "Erase", "&Erase", ["toolErase.png"], [wx.MOD_NONE, wx.WXK_F9], False)
@GuiSelectDecorator(3, "Fill", "&Fill", ["toolFill.png"], [wx.ACCEL_CTRL, ord("F")], False) @GuiSelectDecorator(3, "Fill", "&Fill", ["toolFill.png"], [wx.MOD_NONE, wx.WXK_F5], False)
@GuiSelectDecorator(4, "Line", "&Line", ["toolLine.png"], [wx.ACCEL_CTRL, ord("L")], False) @GuiSelectDecorator(4, "Line", "&Line", ["toolLine.png"], [wx.MOD_NONE, wx.WXK_F6], False)
@GuiSelectDecorator(5, "Object", "&Object", ["toolObject.png"], [wx.ACCEL_CTRL, ord("E")], False) @GuiSelectDecorator(5, "Object", "&Object", ["toolObject.png"], [wx.MOD_NONE, wx.WXK_F8], False)
@GuiSelectDecorator(6, "Pick colour", "&Pick colour", ["toolPickColour.png"], [wx.ACCEL_CTRL, ord("P")], False) @GuiSelectDecorator(6, "Pick colour", "&Pick colour", ["toolPickColour.png"], [wx.MOD_NONE, wx.WXK_F10], False)
@GuiSelectDecorator(7, "Rectangle", "&Rectangle", ["toolRect.png"], [wx.ACCEL_CTRL, ord("R")], True) @GuiSelectDecorator(7, "Rectangle", "&Rectangle", ["toolRect.png"], [wx.MOD_NONE, wx.WXK_F3], True)
@GuiSelectDecorator(8, "Text", "&Text", ["toolText.png"], [wx.ACCEL_CTRL, ord("T")], False) @GuiSelectDecorator(8, "Text", "&Text", ["toolText.png"], [wx.MOD_NONE, wx.WXK_F7], False)
def canvasTool(self, f, idx): def canvasTool(self, f, idx):
def canvasTool_(event): def canvasTool_(event):
if (self.currentTool.__class__ == ToolObject) \ if (self.currentTool.__class__ == ToolObject) \
@ -36,12 +36,16 @@ class RoarCanvasCommandsTools():
self.currentTool = self.currentTool() self.currentTool = self.currentTool()
self.currentOperator, self.operatorState = None, None self.currentOperator, self.operatorState = None, None
self.parentFrame.menuItemsById[self.canvasTool.attrList[idx]["id"]].Check(True) 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 = self.parentFrame.toolBarItemsById[self.canvasTool.attrList[idx]["id"]][0]
toolBar.ToggleTool(self.canvasTool.attrList[idx]["id"], True); toolBar.Refresh(); toolBar.ToggleTool(self.canvasTool.attrList[idx]["id"], True); toolBar.Refresh();
if self.currentTool != None: if self.currentTool != None:
self.update(toolName=self.currentTool.name) self.update(operator=None, toolName=self.currentTool.name)
else: else:
self.update(toolName="Cursor") self.update(operator=None, toolName="Cursor")
viewRect = self.parentCanvas.GetViewStart() viewRect = self.parentCanvas.GetViewStart()
eventDc = self.parentCanvas.backend.getDeviceContext(self.parentCanvas.GetClientSize(), self.parentCanvas, viewRect) 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) self.parentCanvas.applyTool(eventDc, True, None, None, None, self.parentCanvas.brushPos, False, False, False, self.currentTool, viewRect, force=True)

View File

@ -27,6 +27,7 @@ class RoarCanvasWindowDropTarget(wx.TextDropTarget):
viewRect = self.parent.GetViewStart(); mapPoint = [m + n for m, n in zip((mapX, mapY), viewRect)]; 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.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.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) self.parent.commands.update(toolName=self.parent.commands.currentTool.name)
eventDc = self.parent.backend.getDeviceContext(self.parent.GetClientSize(), self.parent, viewRect) eventDc = self.parent.backend.getDeviceContext(self.parent.GetClientSize(), self.parent, viewRect)
eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0); eventDcOrigin = eventDc.GetDeviceOrigin(); eventDc.SetDeviceOrigin(0, 0);
@ -129,10 +130,10 @@ class RoarCanvasWindow(GuiWindow):
else: else:
region = self.canvas.map region = self.canvas.map
if hasattr(operator, "apply2"): if hasattr(operator, "apply2"):
self.commands.update(operator=self.commands.currentOperator.name)
if mouseLeftDown: if mouseLeftDown:
self.commands.operatorState = True if self.commands.operatorState == None else self.commands.operatorState self.commands.operatorState = True if self.commands.operatorState == None else self.commands.operatorState
region = operator.apply2(mapPoint, mousePoint, region, copy.deepcopy(region)) region = operator.apply2(mapPoint, mousePoint, region, copy.deepcopy(region))
self.commands.update(operator=self.commands.currentOperator.name)
elif self.commands.operatorState != None: elif self.commands.operatorState != None:
self.commands.currentOperator = None; self.commands.update(operator=None); rc = False; self.commands.currentOperator = None; self.commands.update(operator=None); rc = False;
else: else:
@ -359,7 +360,7 @@ class RoarCanvasWindow(GuiWindow):
super().__init__(parent, pos) super().__init__(parent, pos)
self.lastMouseState, self.size = [False, False, False], size 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.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.popupEventDc = None
self.dropTarget = RoarCanvasWindowDropTarget(self) self.dropTarget = RoarCanvasWindowDropTarget(self)
self.SetDropTarget(self.dropTarget) self.SetDropTarget(self.dropTarget)

View File

@ -51,8 +51,6 @@ class RoarClient(GuiFrame):
self._initToolBitmaps(self.canvasPanel.commands.toolBars) self._initToolBitmaps(self.canvasPanel.commands.toolBars)
self.loadToolBars(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.canvasPanel.commands.update(brushSize=self.canvasPanel.brushSize, colours=self.canvasPanel.brushColours)
self.addWindow(self.canvasPanel) self.addWindow(self.canvasPanel)
self.assetsWindow = RoarAssetsWindow(GuiCanvasWxBackend, self) self.assetsWindow = RoarAssetsWindow(GuiCanvasWxBackend, self)

View File

@ -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.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) self.panel.SetSizerAndFit(self.sizer)
newSize = self.sizer.ComputeFittingWindowSize(self) 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.SetTitle(title)
self.ShowModal() self.ShowModal()

View File

@ -21,7 +21,10 @@ class ToolErase(Tool):
and ((mapPoint[0] + brushCol) < canvas.size[0]) \ and ((mapPoint[0] + brushCol) < canvas.size[0]) \
and ((mapPoint[1] + brushRow) < canvas.size[1]) \ and ((mapPoint[1] + brushRow) < canvas.size[1]) \
and (canvas.map[mapPoint[1] + brushRow][mapPoint[0] + brushCol][1] == brushColours[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: else:
patchesCursor += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, brushColours[1], brushColours[1], 0, " "]] patchesCursor += [[mapPoint[0] + brushCol, mapPoint[1] + brushRow, brushColours[1], brushColours[1], 0, " "]]
return True, patches if not isCursor else None, patchesCursor return True, patches if not isCursor else None, patchesCursor

View File

@ -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.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.update(pathName=argv[0], undoLevel=-1)
roarClient.canvasPanel.commands._pushRecent(argv[0]) roarClient.canvasPanel.commands._pushRecent(argv[0])
roarClient.canvasPanel.commands.canvasTool(roarClient.canvasPanel.commands.canvasTool, 1)(None)
else: else:
print("error: {}".format(error), file=sys.stderr) 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() wxApp.MainLoop()
if __name__ == "__main__": if __name__ == "__main__":
main(*sys.argv) main(*sys.argv)