|
| 1 | +#!/usr/bin/env python3 |
| 2 | + |
| 3 | +# MIT License |
| 4 | +# |
| 5 | +# Copyright (c) 2024 Eugenio Parodi <ceccopierangiolieugenio AT googlemail DOT com> |
| 6 | +# |
| 7 | +# Permission is hereby granted, free of charge, to any person obtaining a copy |
| 8 | +# of this software and associated documentation files (the "Software"), to deal |
| 9 | +# in the Software without restriction, including without limitation the rights |
| 10 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 11 | +# copies of the Software, and to permit persons to whom the Software is |
| 12 | +# furnished to do so, subject to the following conditions: |
| 13 | +# |
| 14 | +# The above copyright notice and this permission notice shall be included in all |
| 15 | +# copies or substantial portions of the Software. |
| 16 | +# |
| 17 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 18 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 19 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 20 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 21 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 22 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 23 | +# SOFTWARE. |
| 24 | + |
| 25 | +import sys, os |
| 26 | +import time, math |
| 27 | + |
| 28 | +sys.path.append(os.path.join(sys.path[0],'../..')) |
| 29 | +import TermTk as ttk |
| 30 | + |
| 31 | +HouseBG_1_1 = ttk.TTkUtil.base64_deflate_2_obj( |
| 32 | + "eJxrYJmayM0ABrVTNHpYUhJLEqfETtEAoh5GhSkZLJiwh/nRtKYpIHIaVnkETAWagqaX5cP8te1TwFTLFAyZ6TAhNvxGgRSv2QMxpgtCNWJ3CxumgZiuwuJHkAX70I0U" + |
| 33 | + "IN4A4oNkCOhN7WFLzs/JLyqGpgw/v7YpxOIedmULUwsTS5Mp6BxSTEHHqQRcgcdWBI8KHJweIsmnuHyD2xc09BIqB6eXKAwfghFJQz9RHM/0sgc9nAY8GEYOZzS8R8N7" + |
| 34 | + "OHNGw5vO4Z1aqgcAL7yIzQ==") |
| 35 | + |
| 36 | +HouseBG_1_2 = ttk.TTkUtil.base64_deflate_2_obj( |
| 37 | + "eJxrYJn6lY8BDGqnaPSwpCSWJE6JnaIBRD2MClMyWHDBHuZH0xqngMgmPKoQMBVoIk6zWD7MX7toCprARLDpzVNAnDV7wdTaBpx2YTcfZML0KRlsQDYHFl2cGWxg0/dg" + |
| 38 | + "MRaHgSBXLCfKxzgM44AbM504Y/hAnpgGUcsG8VLLlAxR/EGKH4LMaJ2SIU7It6TDQWdOag9bcn5OflExNFX7+bVNIQf3sCtbmFqYWJpMQeeQayI6TiXDdagOQfDI4+D2" + |
| 39 | + "I/V8T6wv8dtIXX/TMKxoFiQD4mkqc8gIGyLDAHccDLyvaZfysAcSwfQJDuMB99aw5uCJAEqNHo29ocwZjb2hzBmNvaHMSU0t1QMAlN+srA==") |
| 40 | + |
| 41 | +HouseBG_2_1 = ttk.TTkUtil.base64_deflate_2_obj( |
| 42 | + "eJztl8FKw0AQhhXTFBHBYw4eBC89eRGiT9E38FA1kINQqHoUaoWqGPSybUEoBb3qG/g0PoGPYHYbjEs26e5mk9nAdFrKx6abf+ef2U2HzmTkr7HXDelEznnvqkdOSCd+" + |
| 43 | + "R+t7JHT0Itr4nt6SsEW/RyRyfhafQ+3J8iKIRcqKmSd3Z1IW/+FNoIsNzAn94bMh2dJi6a0fCIcz46nT0ucyMU9LO8dSmuilH19Fl7qGRUoHNTeuyW3BWHupil4xYUVw" + |
| 44 | + "R0IvbNWtkIutgrEdTVVeHKL1pzmiTj8K7WND9yw7L0bKU6Bx08C8K3PzFy5dy1SwFk4ZzZmB1cpErGf2TsLdhGjCX4vkFZWITsinThCVNYJ6eKlpVqjK+GSFqkygqsar" + |
| 45 | + "CiL3rH/RH1wmj3Td7pjU/Yna+/6hf3x0SuQBQqfKJzCYS37hKRVBbrJ0JjMLzTAV2kA5N0EM5MECr0z6Jrv/GM8beCuWr2xLLQVrBXBLle3RKXjI4xtLw+S+Df9sALKJ" + |
| 46 | + "6RSUTp0DOGuZowobArjWGp9/VhWdZS4ilNibwCWVrOtyZ7qo0iVmhM8GgnLhwCup8LjSbX+F/sBdHyFbROByLADdwwZeOQKCHVD+/yy2FwJCfnvxjVPtvVgvwq8aAQFB" + |
| 47 | + "BbBxERAaCNi4CAgNBGxcBIQGQhBcH/wCnyVIJQ==") |
| 48 | + |
| 49 | +HouseBG_2_2= ttk.TTkUtil.base64_deflate_2_obj( |
| 50 | + "eJxrYJm6hI8BDGqnaPSwpCSWJE6JnaIBRD2MClMyWNBhD/Ojab0QcVZMWUyYCjQJuylTp4DIbpBZ7BkcQDGWD/PXtk8BUWv2QW0Gc/ZMgWlpmZLBA6L7p+C1ghNoIFj9" + |
| 51 | + "BLAVnVOAIvwgVtcUqDWNUzIEYeav7ULzJliwbwp248GSi7AEDC4I1tCD3TRe4o0BQnEg5kYxgwcISTEBEjhgs7DHC2lw0JiR2sOWnJ+TX1QMTbp+fm1TiME97MpmxmYW" + |
| 52 | + "5klTCAlSilOJdBWK5RguoUSWeD8TZw6xviPXzSQ4ibCDUQURPGpz8IYWrlCil+OGJofkIMXUMOB+GGQc/BkIJWyJM2M0BVM9VohThj+ORjmDgTMaR4OfMxpHg5+Tmlqq" + |
| 53 | + "BwBHZ7KE") |
| 54 | + |
| 55 | +HouseBG_3_1 = ttk.TTkUtil.base64_deflate_2_obj( |
| 56 | + "eJztV81OGzEQLmpISzjApSeKRBSJRkqJIjZU4coD5A045GeRD5WQWnpEavmJetgW2k6qSqgFCYlTeYS+DE/AnQu2dzebdXaDN2uzTjWZON7vs/fbyXjGcT7m+ndbT/hr" + |
| 57 | + "H8pOrtvaa8E2lOnbmVkBkpMxJ3d7fv0ZWPf3n+Q9yc2mPknMm+Xe9Lg31wcw8O+Ly3wDks/At1nynMyNsAUyr9YbyRhpt4f8cJ7e/OzHZgobPVGaR9MSF7IQO7L4uPHg" + |
| 58 | + "xfIjchH40B/FdS63QvzRF24l/4IQe+my4aximUT3gCVBZ4nxn4B9HiX8HpJ+UuVLGEZnwnO4s9998sVgoBhilhU4NbrtTGTc4a8S0TKp1mjk4Zitc/8UyCvWX9F+YOXI" + |
| 59 | + "62h2FI0bjb5eNSk2bmKw3DwEUuH8S2qsr7iYjR0DeT3M8TnCPDrDNZET7xO0e0DWfI94ev0G7ljRnwBAany4JtHLcjI9s9LQYolfeM1z3Od9XPEsjhN14vR8PlisYoAz" + |
| 60 | + "sgIvKLZMSfdMDVY1qpIy94L6YTv5zu7b3XfvveN7s9kDlc15VrIsa91qgAhUP0l3sxVFJz4i4fAESACyAlPQ0sQ0dRzVgilfldTZ/UhhnggYEF/tFWBAmOVqI+uIYwWY" + |
| 61 | + "1bACTGlpK8Cw1ZiKmKuIe1MMt/zxQ/bclOxW2RzJ5pikN9zjiyLqdhVllMCFFILalmiSJTFst0GgAChPsIlqPfMwINALFCUW1WxsNOqbdZa3bau93qm5OYwsssgii6wx" + |
| 62 | + "LD8IDBMIECBQBLzTUGunZbc7/v+x6KnO4CBGr+pdZrEsquhUQb9RxWyVsfrBZpNs9+nazMQjQwSLKjpV0G9UMVslwe4jf1+w/73hr1gWVXSqoN+oYraK+n9eCBAgSPzb" + |
| 63 | + "jtWFAIGu6sreJQQI/keA1YUAgbbqsj9U7wEuEcBK") |
| 64 | + |
| 65 | +class Layer(): |
| 66 | + def __init__(self, imageData) -> None: |
| 67 | + self.processData(imageData) |
| 68 | + self._h = len(imageData['data']) |
| 69 | + self._w = len(imageData['data'][0]) |
| 70 | + |
| 71 | + def size(self): |
| 72 | + return self._w, self._h |
| 73 | + |
| 74 | + def processData(self, imageData): |
| 75 | + # Trying to extract for each line the slices that can be copied and the slices that are transparent (nobg is defined) |
| 76 | + data = imageData['data'] |
| 77 | + colors = imageData['colors'] |
| 78 | + opaques = [] |
| 79 | + transparents = [] |
| 80 | + for rowd,rowc in zip(data,colors): |
| 81 | + slicesOpaque = [] |
| 82 | + slicesTrans = [] |
| 83 | + pixOpaque = [] |
| 84 | + pixTrans = [] |
| 85 | + curSlice = [] |
| 86 | + transparent = False |
| 87 | + |
| 88 | + def _pushSlice(t, cs, so=slicesOpaque, st=slicesTrans, po=pixOpaque, pt=pixTrans): |
| 89 | + if not cs: return |
| 90 | + xa,xb = cs[0] |
| 91 | + if transparent: |
| 92 | + pix = pt |
| 93 | + sl = st |
| 94 | + else: |
| 95 | + pix = po |
| 96 | + sl = so |
| 97 | + if xa==xb: |
| 98 | + cs[0] = xa |
| 99 | + cs[1] = cs[1][0] |
| 100 | + cs[2] = cs[2][0] |
| 101 | + pix.append(tuple(cs)) |
| 102 | + else: |
| 103 | + # cs[0] = slice(xa,xb+1) |
| 104 | + cs[0] = (xa,xb+1) |
| 105 | + sl.append(tuple(cs)) |
| 106 | + cs.clear() |
| 107 | + |
| 108 | + for x, (ch,(fg,bg)) in enumerate(zip(rowd,rowc)): |
| 109 | + if ch == ' ' and fg==bg==None: # Fully transparent space |
| 110 | + _pushSlice(transparent,curSlice) |
| 111 | + continue |
| 112 | + if bg and transparent: |
| 113 | + _pushSlice(transparent,curSlice) |
| 114 | + transparent = False |
| 115 | + elif not bg and not transparent: |
| 116 | + _pushSlice(transparent,curSlice) |
| 117 | + transparent = True |
| 118 | + if not curSlice: |
| 119 | + curSlice = [[x,x],[],[]] |
| 120 | + curSlice[0][1]=x |
| 121 | + curSlice[1].append(ch) |
| 122 | + if fg and bg: |
| 123 | + curSlice[2].append(ttk.TTkColor.fg(fg)+ttk.TTkColor.bg(bg)) |
| 124 | + elif fg: |
| 125 | + curSlice[2].append(ttk.TTkColor.fg(fg)) |
| 126 | + elif bg: |
| 127 | + curSlice[2].append(ttk.TTkColor.bg(bg)) |
| 128 | + else: |
| 129 | + curSlice[2].append(ttk.TTkColor.RST) |
| 130 | + _pushSlice(transparent,curSlice) |
| 131 | + transparents.append(list([slicesTrans,pixTrans])) |
| 132 | + opaques.append(list([slicesOpaque,pixOpaque])) |
| 133 | + self._data = {'opaque': tuple(opaques), |
| 134 | + 'transparent':tuple(transparents)} |
| 135 | + |
| 136 | + def drawInCanvas(self, pos, canvas:ttk.TTkCanvas): |
| 137 | + x,y = pos |
| 138 | + w,h = canvas.size() |
| 139 | + if y>=h or x>=w: return |
| 140 | + for ly,sls in enumerate(self._data['opaque'][0:h-y],y): |
| 141 | + for sl in sls[0]: |
| 142 | + a,b = sl[0] |
| 143 | + if x+a>=w or x+b<0 : continue |
| 144 | + ca = max(0,min(w,x+a)) |
| 145 | + cb = max(0,min(w,x+b)) |
| 146 | + da = ca-(x+a) |
| 147 | + db = cb-ca+da |
| 148 | + # canvas._data[ ly][ca:cb] = ['X']*(cb-ca)# sl[1][da:db] |
| 149 | + canvas._data[ ly][ca:cb] = sl[1][da:db] |
| 150 | + canvas._colors[ly][ca:cb] = sl[2][da:db] |
| 151 | + for sl in sls[1]: |
| 152 | + a = sl[0] |
| 153 | + if not (0 <= x+a < w): continue |
| 154 | + canvas._data[ly][x+sl[0]] = sl[1] |
| 155 | + if type(sl[2]) != ttk.TTkColor: |
| 156 | + pass |
| 157 | + canvas._colors[ly][x+sl[0]] = sl[2] |
| 158 | + for ly,sls in enumerate(self._data['transparent'][0:h-y],y): |
| 159 | + for sl in sls[0]: |
| 160 | + a,b = sl[0] |
| 161 | + if x+a>=w or x+b<0 : continue |
| 162 | + ca = max(0,min(w,x+a)) |
| 163 | + cb = max(0,min(w,x+b)) |
| 164 | + da = ca-(x+a) |
| 165 | + db = cb-ca+da |
| 166 | + canvas._data[ ly][ca:cb] = sl[1][da:db] |
| 167 | + for mcx,mc in enumerate(zip(canvas._colors[ly][ca:cb],sl[2][da:db]),ca): |
| 168 | + canvas._colors[ly][mcx] = mc[0] + mc[1] |
| 169 | + for sl in sls[1]: |
| 170 | + a = sl[0] |
| 171 | + if not (0 <= x+a < w): continue |
| 172 | + canvas._data[ly][x+sl[0]] = sl[1] |
| 173 | + canCol = canvas._colors[ly][x+sl[0]] |
| 174 | + newCol = canCol + sl[2] |
| 175 | + canvas._colors[ly][x+sl[0]] = newCol |
| 176 | + |
| 177 | +class Parallax(ttk.TTkWidget): |
| 178 | + COLOR1 = ttk.TTkColor.fg("#FFFFFF")+ttk.TTkColor.bg("#AFAEBC") |
| 179 | + COLOR2 = ttk.TTkColor.fg("#FFFFFF")+ttk.TTkColor.bg("#858494") |
| 180 | + COLOR3 = ttk.TTkColor.fg("#FFFFFF")+ttk.TTkColor.bg("#63687B") |
| 181 | + COLOR4 = ttk.TTkColor.fg("#9694A1")+ttk.TTkColor.bg("#B3B2C0") |
| 182 | + COLOR5 = ttk.TTkColor.fg("#333238")+ttk.TTkColor.bg("#B3B2C0") |
| 183 | + COLOR6 = ttk.TTkColor.fg("#333238")+ttk.TTkColor.bg("#333238") |
| 184 | + |
| 185 | + def __init__(self, *args, **kwargs): |
| 186 | + self._baseTime = time.time() |
| 187 | + self._l11 = l11 = Layer(HouseBG_1_1) |
| 188 | + self._l12 = l12 = Layer(HouseBG_1_2) |
| 189 | + self._l21 = l21 = Layer(HouseBG_2_1) |
| 190 | + self._l22 = l22 = Layer(HouseBG_2_2) |
| 191 | + self._l31 = l31 = Layer(HouseBG_3_1) |
| 192 | + |
| 193 | + w11,h11 = l11.size() |
| 194 | + w12,h12 = l12.size() |
| 195 | + w21,h21 = l21.size() |
| 196 | + w22,h22 = l22.size() |
| 197 | + w31,h31 = l31.size() |
| 198 | + self._layer1 = {'size':w11+w12+w11+w11+w12,'layers':(l11,l12,l11,l11,l12),'off':(4,3,4,4,3)} |
| 199 | + self._layer2 = {'size':w21+w22+w21 ,'layers':(l21,l22,l21),'off':[4,8,4]} |
| 200 | + self._layer3 = {'size':w31+30 ,'layers':[l31] ,'off':[5]} |
| 201 | + |
| 202 | + super().__init__(*args, **kwargs) |
| 203 | + ttk.TTkHelper._rootWidget.paintExecuted.connect(self._refreshAnimation) |
| 204 | + self._refreshAnimation() |
| 205 | + |
| 206 | + @ttk.pyTTkSlot() |
| 207 | + def _refreshAnimation(self): |
| 208 | + self.update() |
| 209 | + |
| 210 | + # 1) 11 11 11 11-11 11 11 11-11 11 .. |
| 211 | + # 2) 22 11 11 11-22 11 11 11-22 11 .. |
| 212 | + # 3) 33 33 11 11-33 33 11 11-33 33 .. |
| 213 | + # 4) 44 44 44 11-44 44 44 11-44 44 .. |
| 214 | + # 5) 44 44 44 44-44 44 44 44-44 44 .. |
| 215 | + |
| 216 | + def paintEvent(self, canvas: ttk.TTkCanvas): |
| 217 | + w,h = self.size() |
| 218 | + diff = int(200*(time.time() - self._baseTime)) |
| 219 | + |
| 220 | + secH = h//5 |
| 221 | + # draw the bgColor |
| 222 | + canvas.fill(pos=(0,0), size=(w,secH*4), color=Parallax.COLOR1) |
| 223 | + # # draw the 2nd section |
| 224 | + # for x in range(0,w+8,16): |
| 225 | + # x += (diff%(32*4))//8 |
| 226 | + # canvas.fill(pos=(w-x, secH), size=(3,secH*3), color=Parallax.COLOR2) |
| 227 | + # canvas.fill(pos=(w-x-2,secH+2), size=(6,secH*3), color=Parallax.COLOR2) |
| 228 | + # canvas.fill(pos=(w-x, secH+3), size=(10,secH*3), color=Parallax.COLOR2) |
| 229 | + # canvas.fill( pos=(0,3*secH+3), size=(w,secH*3), color=Parallax.COLOR2) |
| 230 | + # # draw the 3nd section |
| 231 | + # for x in range(0,w+16,32): |
| 232 | + # x += (diff%(32*6))//6 |
| 233 | + # canvas.fill(pos=(w-x,2*secH), size=(12,secH*3), color=Parallax.COLOR3) |
| 234 | + # canvas.fill(pos=(w-x+12,5*secH//2), size=(4,secH*3), color=Parallax.COLOR3) |
| 235 | + |
| 236 | + # lw1,lh = self.l11.size() |
| 237 | + # lw2,lh = self.l12.size() |
| 238 | + # lw3,lh = self.l21.size() |
| 239 | + # lw=lw1 |
| 240 | + # self.l11.drawInCanvas(pos=(( (-diff)//8)%(w+lw)-lw,4),canvas=canvas) |
| 241 | + # self.l11.drawInCanvas(pos=((lw1+lw2+(-diff)//8)%(w+lw)-lw,4),canvas=canvas) |
| 242 | + # lw=lw2 |
| 243 | + # self.l12.drawInCanvas(pos=((lw1+ (-diff)//8)%(w+lw)-lw,3),canvas=canvas) |
| 244 | + # self.l12.drawInCanvas(pos=((2*lw1+lw2+(-diff)//8)%(w+lw)-lw,3),canvas=canvas) |
| 245 | + # canvas.fill(pos=(0,9), size=(w,h-9), color=Parallax.COLOR2) |
| 246 | + # lw=lw3 |
| 247 | + # self.l21.drawInCanvas(pos=(( (-diff)//4)%(w+lw)-lw,5),canvas=canvas) |
| 248 | + # self.l21.drawInCanvas(pos=((lw3+ (-diff)//4)%(w+lw)-lw,5),canvas=canvas) |
| 249 | + # self.l21.drawInCanvas(pos=((lw3+lw3+(-diff)//4)%(w+lw)-lw,5),canvas=canvas) |
| 250 | + |
| 251 | + # draw the Layers: |
| 252 | + def _drawLayer(_l,_d,canvas=canvas): |
| 253 | + _lw = _l['size'] |
| 254 | + _la = _l['layers'] |
| 255 | + _off = _l['off'] |
| 256 | + _x = _d |
| 257 | + for _ll,_lo in zip(_la,_off): |
| 258 | + __w,__h = _ll.size() |
| 259 | + _ll.drawInCanvas(pos=((_x )%(w+_lw)-_lw,_lo),canvas=canvas) |
| 260 | + _ll.drawInCanvas(pos=((_x+_lw)%(w+_lw)-_lw,_lo),canvas=canvas) |
| 261 | + _x += __w |
| 262 | + |
| 263 | + _drawLayer(self._layer1,(-diff)//8) |
| 264 | + canvas.fill(pos=(0,9), size=(w,h-9), color=Parallax.COLOR2) |
| 265 | + _drawLayer(self._layer2,(-diff)//4) |
| 266 | + canvas.fill(pos=(0,17), size=(w,h-17), color=Parallax.COLOR3) |
| 267 | + _drawLayer(self._layer3,(-diff)//2) |
| 268 | + |
| 269 | + # # draw the 4nd section |
| 270 | + # for x in range(0,w+20,50): |
| 271 | + # x += (diff%(50*2))//2 |
| 272 | + # canvas.fill( pos=(w-x+15,2*secH-3), color=Parallax.COLOR6, size=(1,secH*3) ) |
| 273 | + # canvas.fill( pos=(w-x+10,3*secH-4), color=Parallax.COLOR6, size=(10,secH*3) ) |
| 274 | + # canvas.drawText(pos=(w-x, 3*secH+0), color=Parallax.COLOR5, text='β'*43) |
| 275 | + # canvas.drawText(pos=(w-x, 3*secH+1), color=Parallax.COLOR4, text=f'β{"ββ₯"*20}ββ') |
| 276 | + # canvas.drawText(pos=(w-x, 3*secH+2), color=Parallax.COLOR4, text=f'β{"ββ¨"*20}ββ') |
| 277 | + # canvas.drawText(pos=(w-x, 3*secH+3), color=Parallax.COLOR5, text=f' {"βββ "*10} ') |
| 278 | + # canvas.drawText(pos=(w-x, 3*secH+4), color=Parallax.COLOR5, text=f' {"βββ "*10} ') |
| 279 | + # canvas.fill( pos=(w-x, 3*secH+5), color=Parallax.COLOR4, size=(43,secH) ) |
| 280 | + # # draw the 5nd section |
| 281 | + # canvas.fill(pos=(0,4*secH+2), size=(w,secH), color=Parallax.COLOR4) |
| 282 | + |
| 283 | + |
| 284 | +root = ttk.TTk(title="TTKanabalt") |
| 285 | +Parallax(parent=root, pos=(5,2), size=(100,25)) |
| 286 | +root.mainloop() |
| 287 | + |
0 commit comments