changeset 50:fef68d9650af

refactor TilePicker and GridCanvas (now ROMCanvas) into common superclass Also add a GridHolder class to more transparently iterate over variably-dimensioned arrays.
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Fri, 06 Sep 2019 08:32:35 -0400
parents 5ca986354475
children f2b46bee6c50
files img/checkerboard.png tilerswift
diffstat 2 files changed, 99 insertions(+), 78 deletions(-) [+]
line wrap: on
line diff
index 3d04e84950736555874defe921fb796f927cea12..089edf2f6fe31ae6ffc095f44736791b287e96b4
GIT binary patch
literal 3126
zc%1E4TToj?7~YfHNg%W&K+BzQla!(KoRbS7qjrD<I8<uNMQC42fD>{YLek`vi!*%y
z6<Ve<w0Q4>w$#?kLuXLyrK3}^wce@>tqN^@C|0HFIMXU>VVK5$6NoURSbcDGrknHc
z{=5J8{kz|8lCyhko6Dji5+e{oQEa)T3R(#^IaFxxfsrBHX(_5KLTGp(a?UP=zNm3i
znFaa#2F{*@p2AbU)rU}iCN`q;$i{XUBn7t8N?uV&qe;=F!_pcUN?|QUHS+PMhJ9Ug
z&si&`4Kb(A`+BRC{<Kdhgi1G%Nk8s-djKK1jH_oIESrn)8en0B1QFoj9<j(55n?2U
zwij#_Awp`rV6a3&8o)dYmNf4l1=9i^`<O!mUJ30nFb4csXitFgeZl;nfz1Zy!JiT@
zXBW6;O$RSHHDzq24Pl8Gx6tB24U<n(`6k3rbfKAo$DpB2W*u#&O@QegBvAq&FQcVp
zd2V?~F|LS3{(|BL@Wu0LWY`w@af?(Eq9E6Sx%2)(S#aK<GXI4CGK#J!WlLcqJO@<%
zOQ-}6K}O1?a*`w!3VDPwHcA;8sZ3DEtd31dOiN8kOitEh<>zQJ@-mZ?wFT?)C|a-A
zr{xshV`A>k*XbFYgit6H%1C8=R8%~Zo}AA7?c#qIspNP~Vj=^HRD@VX_)nuWSf`W-
zl!Z+sL}H0lM#>ctkpMUzjdw~cl8B{J34ED}T@XhSl~kQh7s+C_*vX6?u}t^=L-Nex
z;gPtiv1?hnMsJTIV$It4gv9K-a<uDm^#)^ssnA?vv6hyVvlZ1fwGY(QZ{60^%sE<|
z{DVGWXM0Cy*Fz6K@@Q}0?mhj3k3IgxlTSVU%z>f9&mTGZ!iz7x{K~7Z9e@3eH{Uw(
z-l@~?pZVa!k3K$k{_`)s9G|#waq{ac-+cSs)Yb2Qxc>7m)4%@q`;D1dtPAU0C}DM}
zK$l1&5lcv{ix72SfJ!1wr)BD*Eu?)%Oa{{}k1gJRXm~`CsjIpc*XSLKSd*on%)XAL
z1(e;Mu%3UUEF|ntT^Es3Ou*rZRcIrcx!JEhC|bc*pS(KMkF+b;jg{zkQv5$t{FVJT
zR(U7IznsE<L9a{W;eRkeu+|GDZkLN|6PCX*>$+F11yD8yHABeU6hH)C#Oo<|3^fd8
zrV7jyv!2qMDe9fnDc=%;%iYX7x^7K4Te5u=-z+eJ>*O8gVqWmsIB&Jx<!R-RDNlnR
z^-uTa04hC%vOw+{-o=Hx5^$qmjR80&1hztTzr*3<1b`dc`RXYM=Y+zn%ih9SIA4>O
z_XxbZZTU7tH=oM}ih3#KKCZ1ra3a%a>X|u+s+LCU_+}hT&$>Cdu+4#Bwc8<d*uC81
ziw(QiQVF1}5J+(DbTziw`PT5;p-Gyq27GcDJRGIR%lUj*hjE7U)B!Fv3~sRk#$dF0
zD15C+xfL>~27tR|v-n1*4FjyOS<Bcqf%7&w?QJbwsoU$a3rJ@$P4sr)tI>wr<;*XO
zHWnI%O*yqd%?(4fIo*QW#R*=%DUbnV3--YI8P#$9iNMl?VFfo5Z>f#%<XVw#a{SY6
zfE7a6S|8_K_(4#4ny`<tAWuWndZ;KmPg5A^8RvU61ppm`hYE4e5DMyp;{^aJ(18KX
UL=oG~MtmV*t(z^!iW_?V0LV$FmjD0&
--- a/tilerswift
+++ b/tilerswift
@@ -56,6 +56,10 @@
 
         self.set_palette(self.default_palette)
 
+    def __repr__(self):
+        num_to_ascii = {0: " ", 1: ".", 2: "o", 3: "#"}
+        return "\n".join([[num_to_ascii[val] for val in row] for row in self.tile])
+
     def palette_to_qt(self):
         return [QtGui.QColor(NES_PALETTE[color_idx]).rgb() for color_idx in self.palette]
 
@@ -66,26 +70,49 @@
         self.pixmap = QtGui.QPixmap(image)
 
 
-class GridCanvas(QtWidgets.QWidget):
+class GridHolder(object):
+    def __init__(self, things, numrows, numcols, fillvalue=None):
+        self.numrows = numrows
+        self.numcols = numcols
+        self.fillvalue = fillvalue
+        if things is None:
+            self.things = []
+            for i in range(self.numrows):
+                self.things.extend([fillvalue]*self.numcols)
+        else:
+            self.things = things
+
+    def __getitem__(self, idx):
+        i, j = idx
+        return self.things[i*self.numcols + j]
 
-    def __init__(self, filename):
+    def __setitem__(self, idx, value):
+        i, j = idx
+        self.things[i*self.numcols + j] = value
+
+    def __repr__(self):
+        return f"GridHolder(numrows={self.numrows}, numcols={self.numcols}, fillvalue={self.fillvalue})"
+
+    def __iter__(self):
+        for thing in self.things:
+            yield thing
+
+    def resize(self, numrows, numcols):
+        self.numrows = numrows
+        self.numcols = numcols
+
+
+class TileGrid(QtWidgets.QWidget):
+    def __init__(self, numrows, numcols, scalefactor, spacing):
         super().__init__()
 
-        self.file_name = filename
-        self.tiles = read_rom(self.file_name)
-
-        self.numcols = 16
-        self.numrows = len(self.tiles)//self.numcols
-
-        self.scalefactor = 5
-        self.spacing = 2
+        self.numcols = numcols
+        self.numrows = numrows
+        self.scalefactor = scalefactor
+        self.spacing = spacing
 
         self.setStyleSheet(CHECKERBOARD_CSS)
 
-        self.picked_tile = None
-
-        self.resize()
-
     def paintEvent(self, event):
         painter = QtGui.QPainter(self)
 
@@ -99,22 +126,26 @@
 
         for i in range(self.numrows):
             for j in range(self.numcols):
-                tile = self.tiles[i*self.numcols + j]
-                rect = QtCore.QRect(
-                    self.spacing + j*self.tilesize,
-                    self.spacing + i*self.tilesize,
-                    8*self.scalefactor, 8*self.scalefactor
-                )
-                painter.drawPixmap(rect, tile.pixmap)
+                tile = self.tiles[i, j]
+                if tile:
+                    rect = QtCore.QRect(
+                        self.spacing + j*self.tilesize,
+                        self.spacing + i*self.tilesize,
+                        self.tilesize - self.spacing,
+                        self.tilesize - self.spacing
+                    )
+                    flipx, flipy = self.flips[i, j]
+                    painter.drawPixmap(
+                        rect,
+                        tile.pixmap.transformed(QtGui.QTransform().scale(flipx, flipy))
+                    )
 
-    def mousePressEvent(self, event):
+    def mouseClickToIJ(self, event):
         j, i = (
             (event.x() - self.spacing)//self.tilesize,
             (event.y() - self.spacing)//self.tilesize,
         )
-        tile = self.tiles[i*self.numcols + j]
-
-        self.picked_tile = tile
+        return (i, j)
 
     def resize(self):
         self.tilesize = self.spacing + self.scalefactor*8
@@ -141,77 +172,67 @@
         self.resize()
 
 
-class TilePicker(QtWidgets.QWidget):
-
-    def __init__(self, grid_canvas):
-        super().__init__()
+class ROMCanvas(TileGrid):
+    def __init__(self, filename):
+        tiles = read_rom(filename)
 
-        self.grid_canvas = grid_canvas
-        self.setStyleSheet(CHECKERBOARD_CSS)
-        self.numrows = 20
-        self.numcols = 20
+        super().__init__(
+            numcols=16,
+            numrows=len(tiles)//16,
+            spacing=2,
+            scalefactor=5
+        )
 
-        self.picked_tiles = []
-        self.flips = []
-        for i in range(self.numrows):
-            self.picked_tiles.append([None]*self.numcols)
-            self.flips.append([(1, 1)]*self.numcols)
+        self.tiles = GridHolder(tiles, self.numrows, self.numcols)
+        self.flips = GridHolder(None, self.numrows, self.numcols, fillvalue=(1, 1))
+
+        self.filename = filename
+        self.picked_tile = None
 
         self.resize()
 
-    def resize(self):
-        self.tilesize = self.grid_canvas.scalefactor*8
-        self.setFixedSize(QtCore.QSize(
-            self.tilesize*self.numcols,
-            self.tilesize*self.numrows
-        ))
-        self.update()
+    def mousePressEvent(self, event):
+        i, j = self.mouseClickToIJ(event)
+        tile = self.tiles[i, j]
 
-    def paintEvent(self, event):
-        painter = QtGui.QPainter(self)
+        self.picked_tile = tile
+
+
+class TilePicker(TileGrid):
 
-        # I don't really know what this block of code means, but it's
-        # what I have to do in order to get this widget to obey CSS
-        # styles.
-        opt = QtWidgets.QStyleOption()
-        opt.initFrom(self)
-        style = self.style()
-        style.drawPrimitive(QtWidgets.QStyle.PE_Widget, opt, painter, self)
+    def __init__(self, rom_canvas):
+        super().__init__(
+            numcols=20,
+            numrows=20,
+            spacing=0,
+            scalefactor=5,
+        )
 
-        for i in range(self.numrows):
-            for j in range(self.numcols):
-                tile = self.picked_tiles[i][j]
-                if tile:
-                    rect = QtCore.QRect(
-                        j*self.tilesize,
-                        i*self.tilesize,
-                        8*self.grid_canvas.scalefactor,
-                        8*self.grid_canvas.scalefactor
-                    )
-                    flipx, flipy = self.flips[i][j]
-                    painter.drawPixmap(
-                        rect,
-                        tile.pixmap.transformed(QtGui.QTransform().scale(flipx, flipy))
-                    )
+        self.rom_canvas = rom_canvas
+        self.tiles = GridHolder(None, self.numrows, self.numcols)
+        self.flips = GridHolder(None, self.numcols, self.numcols, fillvalue=(1, 1))
+
+        self.resize()
 
     def mousePressEvent(self, event):
-        j, i = event.x()//self.tilesize, event.y()//self.tilesize
+        i, j = self.mouseClickToIJ(event)
+
         if event.button() == QtCore.Qt.LeftButton:
-            self.picked_tiles[i][j] = self.grid_canvas.picked_tile
+            self.tiles[i, j] = self.rom_canvas.picked_tile
         elif event.button() == QtCore.Qt.RightButton:
-            self.picked_tiles[i][j] = None
+            self.tiles[i, j] = None
         elif event.button() == QtCore.Qt.MidButton:
-            flipx, flipy = self.flips[i][j]
+            flipx, flipy = self.flips[i, j]
             if flipx == 1:
                 if flipy == 1:
-                    self.flips[i][j] = (1, -1)
+                    self.flips[i, j] = (1, -1)
                 else:
-                    self.flips[i][j] = (-1, 1)
+                    self.flips[i, j] = (-1, 1)
             else:
                 if flipy == 1:
-                    self.flips[i][j] = (-1, -1)
+                    self.flips[i, j] = (-1, -1)
                 else:
-                    self.flips[i][j] = (1, 1)
+                    self.flips[i, j] = (1, 1)
 
         self.update()
 
@@ -274,7 +295,7 @@
             "Open ROM", "", "NES Files (*.nes)"
         )
 
-        self.grid_widget = GridCanvas(filename[0])
+        self.grid_widget = ROMCanvas(filename[0])
 
         self.tile_picker = TilePicker(self.grid_widget)