From dc1134d6d713b96a3f3b4b2ef219d37ad1015ee8 Mon Sep 17 00:00:00 2001 From: Allanis <allanis@saracraft.net> Date: Sat, 13 Apr 2013 18:50:11 +0100 Subject: [PATCH] [Add] resedit: Space is drawn, you can move systems around etc. --- utils/resedit/space.glade | 167 ++++++++++++++++++++++++++------------ utils/resedit/space.py | 147 +++++++++++++++++++++++++++++++-- utils/resedit/space.pyc | Bin 6104 -> 10248 bytes 3 files changed, 255 insertions(+), 59 deletions(-) diff --git a/utils/resedit/space.glade b/utils/resedit/space.glade index d05f1dd..ddffb44 100644 --- a/utils/resedit/space.glade +++ b/utils/resedit/space.glade @@ -2,10 +2,10 @@ <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd"> <glade-interface> <widget class="GtkWindow" id="winSystems"> + <property name="width_request">750</property> + <property name="height_request">450</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> <property name="title" translatable="yes">Systems</property> - <property name="default_width">600</property> - <property name="default_height">420</property> <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property> <child> <widget class="GtkVBox" id="vbox1"> @@ -42,8 +42,8 @@ <property name="label" translatable="yes">Name:</property> </widget> <packing> - <property name="x">31</property> - <property name="y">25</property> + <property name="x">114</property> + <property name="y">21</property> </packing> </child> <child> @@ -56,8 +56,8 @@ <property name="truncate_multiline">True</property> </widget> <packing> - <property name="x">95</property> - <property name="y">30</property> + <property name="x">184</property> + <property name="y">26</property> </packing> </child> <child> @@ -69,24 +69,8 @@ <property name="label" translatable="yes">X,Y</property> </widget> <packing> - <property name="x">242</property> - <property name="y">28</property> - </packing> - </child> - <child> - <widget class="GtkButton" id="butRepos"> - <property name="width_request">75</property> - <property name="height_request">33</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - <property name="label" translatable="yes">Reposition</property> - <property name="response_id">0</property> - </widget> - <packing> - <property name="x">319</property> - <property name="y">23</property> + <property name="x">371</property> + <property name="y">26</property> </packing> </child> <child> @@ -104,7 +88,7 @@ </child> <child> <widget class="GtkHSeparator" id="hseparator1"> - <property name="width_request">402</property> + <property name="width_request">525</property> <property name="height_request">20</property> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> @@ -185,7 +169,7 @@ <child> <widget class="GtkVSeparator" id="vseparator1"> <property name="width_request">20</property> - <property name="height_request">259</property> + <property name="height_request">322</property> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> </widget> @@ -196,14 +180,14 @@ </child> <child> <widget class="GtkDrawingArea" id="draSpace"> - <property name="width_request">180</property> - <property name="height_request">171</property> + <property name="width_request">296</property> + <property name="height_request">248</property> <property name="visible">True</property> <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> </widget> <packing> - <property name="x">221</property> - <property name="y">88</property> + <property name="x">220</property> + <property name="y">97</property> </packing> </child> <child> @@ -229,7 +213,7 @@ </widget> <packing> <property name="x">10</property> - <property name="y">181</property> + <property name="y">180</property> </packing> </child> <child> @@ -244,8 +228,8 @@ <property name="response_id">0</property> </widget> <packing> - <property name="x">25</property> - <property name="y">300</property> + <property name="x">20</property> + <property name="y">296</property> </packing> </child> <child> @@ -260,8 +244,8 @@ <property name="response_id">0</property> </widget> <packing> - <property name="x">121</property> - <property name="y">300</property> + <property name="x">112</property> + <property name="y">295</property> </packing> </child> <child> @@ -273,20 +257,8 @@ <property name="label" translatable="yes">Space</property> </widget> <packing> - <property name="x">263</property> - <property name="y">69</property> - </packing> - </child> - <child> - <widget class="GtkHSeparator" id="hseparator3"> - <property name="width_request">190</property> - <property name="height_request">20</property> - <property name="visible">True</property> - <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> - </widget> - <packing> - <property name="x">218</property> - <property name="y">265</property> + <property name="x">215</property> + <property name="y">70</property> </packing> </child> <child> @@ -301,8 +273,8 @@ <property name="response_id">0</property> </widget> <packing> - <property name="x">227</property> - <property name="y">290</property> + <property name="x">14</property> + <property name="y">350</property> </packing> </child> <child> @@ -317,8 +289,97 @@ <property name="response_id">0</property> </widget> <packing> - <property name="x">322</property> - <property name="y">290</property> + <property name="x">115</property> + <property name="y">350</property> + </packing> + </child> + <child> + <widget class="GtkLabel" id="labCurPos"> + <property name="width_request">100</property> + <property name="height_request">20</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">X,Y</property> + </widget> + <packing> + <property name="x">333</property> + <property name="y">72</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="butNew"> + <property name="width_request">81</property> + <property name="height_request">37</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">New</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="x">20</property> + <property name="y">17</property> + </packing> + </child> + <child> + <widget class="GtkHSeparator" id="hseparator3"> + <property name="width_request">202</property> + <property name="height_request">20</property> + <property name="visible">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + </widget> + <packing> + <property name="x">5</property> + <property name="y">326</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="butZoomIn"> + <property name="width_request">35</property> + <property name="height_request">35</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">+</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="x">300</property> + <property name="y">350</property> + </packing> + </child> + <child> + <widget class="GtkButton" id="butZoomOut"> + <property name="width_request">35</property> + <property name="height_request">35</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">-</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="x">345</property> + <property name="y">350</property> + </packing> + </child> + <child> + <widget class="GtkToggleButton" id="butReposition"> + <property name="width_request">81</property> + <property name="height_request">37</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> + <property name="label" translatable="yes">Reposition</property> + <property name="response_id">0</property> + </widget> + <packing> + <property name="x">433</property> + <property name="y">18</property> </packing> </child> </widget> diff --git a/utils/resedit/space.py b/utils/resedit/space.py index 0ffc091..e8365a0 100644 --- a/utils/resedit/space.py +++ b/utils/resedit/space.py @@ -44,11 +44,16 @@ class space: self.swtree = gtk.glade.XML(self.glade, "winSystems") # Hook events and stuff. - self.__swidget("winSystems").connect("destroy", self.__done) - self.__swidget("treSystems").connect("row-activated", self.__update) - # Buttons. - self.__swidget("butDone").connect("clicked", self.__done) - self.__swidget("butSave").connect("clicked", self.saveSystems) + hooks = { + "winSystems":["destroy",self.__done], + "treSystems":["row-activated", self.__update], + "butDone":["clicked", self.__done], + "butSave":["clicked",self.saveSystems], + "butZoomIn":["clicked", self.__space_zoomin], + "butZoomOut":["clicked", self.__space_zoomout] + } + for key, val in hooks.items(): + self.__swidget(key).connect(val[0], val[1]) # Populate the tree. self.tree_systems = gtk.TreeStore(str) @@ -63,9 +68,22 @@ class space: col.add_attribute(cell, 'text', 0) self.__swidget("treSystems").set_model(self.tree_systems) + self.zoom = 1 + area = self.__swidget("draSpace") + area.set_events(gtk.gdk.EXPOSURE_MASK + | gtk.gdk.LEAVE_NOTIFY_MASK + | gtk.gdk.BUTTON_PRESS_MASK + | gtk.gdk.POINTER_MOTION_MASK + | gtk.gdk.POINTER_MOTION_HINT_MASK) + area.connect("expose-event", self.__space_draw) + area.connect("button-press-event", self.__space_down) + area.connect("motion-notify-event", self.__space_drag) + # Display the window and such. self.__swidget("winSystems").show_all() self.cur_system = "" + self.x = self.y = 0 + self.lx = self.ly = 0 # ---------------- PLANETS -------------------- @@ -117,12 +135,32 @@ class space: col.add_attribute(cell, 'text', 0) wgt.set_model(jumps) + self.__space_draw() + def __store(self): sys_name = self.__swidget("inpName").get_text() # Renamed the current system. if sys_name != self.cur_system: - self.systems[sys_name] = self.systems[self.cur_systems] # Copy it over. + self.systems[sys_name] = self.systems[self.cur_system] # Copy it over. + model = self.__swidget("treSystems").get_model() + + # Must rename the node in the treeview. + for i in model: + if i[0] == self.cur_system: + i[0] = sys_name + break + + # Update the jump paths. + for key, value in self.systems.items(): + i = 0 + for jump in value["jumps"]: + if jump == self.cur_system: + self.systems[key]["jumps"].pop(i) + self.systems[key]["Jumps"].append(sys_name) + i = i+1 + + # Delete the old system and change current to it. del self.systems[self.cur_system] # Get rid of the old one. self.cur_system = sys_name # Now use self.cur_system again. @@ -161,6 +199,103 @@ class space: """ gtk.main_quit() + def __space_down(self, wgt, event): + if event.button == 1: + x = event.x + y = event.y + + # Modify the current position. + if self.__swidget("butReposition").get_active() and self.cur_system != "": + wx, wy, ww, wh = self.__swidget("draSpace").get_allocation() + + mx = x - (self.x*self.zoom + ww/2) + my = y - (self.y*self.zoom + wh/2) + + system = self.systems[self.cur_system] + system["pos"]["x"] = str(mx) + system["pos"]["y"] = str(-my) + + self.__space_draw() + + self.__swidget("butReposition").set_active(False) + + self.lx = x + self.ly = y + return True + + def __space_drag(self, wgt, event): + x = event.x + y = event.y + state = event.state + + wx, wy, ww, wh = self.__swidget("draSpace").get_allocation() + + mx = x - (self.x*self.zoom + ww/2) + my = y - (self.y*self.zoom + wh/2) + + self.__swidget("labCurPos").set_text("%d%d" % (mx, my)) + + if state & gtk.gdk.BUTTON1_MASK: + xrel = x - self.lx + yrel = y - self.ly + self.x = self.x + xrel/self.zoom + self.y = self.y + yrel/self.zoom + self.lx = x + self.ly = y + + self.__space_draw() + + return True + + def __space_zoomout(self, wgt=None, event=None): + self.zoom = self.zoom/2 + if self.zoom < 0.1: + self.zoom = 0.1 + self.__space_draw() + + def __space_zoomin(self, wgt=None, event=None): + self.zoom = self.zoom*2 + if self.zoom > 4: + self.zoom = 4 + self.__space_draw() + + def __space_draw(self, wgt=None, event=None): + area = self.__swidget("draSpace") + style = area.get_syle() + gc = style.fg_gc[gtk.STATE_NORMAL] + bg_gc = style.bg_gc[gtk.STATE_NORMAL] + wx, wy, ww, wh = area.get_allocation() + cx = self.x*self.zoom + ww/2 + cy = sefl.y*self.zoom + wh/2 + r = 15 + + # Cleanup. + area.window.draw_rectangle(bg_gc, True, 0, 0, ww, wh) + area.window.draw_rectangle(gc, False, 0, 0, ww-1, wh-1) + + for sys_name, system in self.systems.items(): + sx = float(system["pos"]["x"]) + sy = -float(system["pos"]["y"]) + dx = cx+sx*self.zoom + dy = cy+sy*self.zoom + + # Draw jumps. + for jump in system["jumps"]: + jsx = float(self.systems[jump]["pos"]["x"]) + jsy = -float(self.systems[jump]["pos"]["y"]) + jdx = cx+jsx*self.zoom + jdy = cy+jsy*self.zoom + + area.window.draw_line(gc, dx, dy, jdx, jdy) + + # Draw circle. + area.window.draw_arc(gc, True, dx-r/2, dy-r/2, r, r, 0, 360*64) + area.window.draw_arc(bg_gc, True, dxr/2+2, dy-r/2+2, r-4, r-4, 0, 360*64) + + # Draw name. + layout = area.create_pango_layout(sys_name) + area.window.draw_layout(gc, dx+r/2+2, dy-r/2, layout) + def debug(self): print "SYSTEMS LOADED:" print self.systems diff --git a/utils/resedit/space.pyc b/utils/resedit/space.pyc index d996ec3b61c5e0b9f3b9661611409703f0c81068..a00d68baf56f2c025728ccdd99e57fc13a6a8f1d 100644 GIT binary patch literal 10248 zcmcgyO>-OBb$tzh-=C5wk(`ld;2CKI&x}Mn$;ioAj)#)yk!%T)8ys^aOYT7ECfN{( z2GLECaL7%lDwiv<lQ_vD-ei+~s<KIWpH&uFWtT;&@)xp5l{d*b=QaS2N2#R3NeK4C zd-r|cckj9P-A3`>W+vlb#NTVU{I7`bkMN{TB)y6YoeMqJa_%uQmiJEN3+{2jZL}{s z&-229`}j^+WKu#B72O|ruI;%`^L{1wxa7hS7mm4b)V*}>*ttiKQTAM|GLGru|G-~0 zT}Ad$vR4k1ay!Y&+w~Vwxzo$GlXiJ4dtQDPx5K!-mA+q2y5(N7ccmMZcj7b!t-RH$ zhf%o|KTFdUjIy4T_tL0*FY0W^X_j0`%iSoA!Z>5U^3GnGmE(4r)myD{wjJ%HXVGUn z%Q_#ftaN&q>sr#?S}A8EAg7&rBN}k21j<cP{}D+9=6GZdwghfqJIoXv_`wYJTvP@- zEh#ffF0iW4h{xkDJlp>tb1#eT@uUmK)n-cc3HK6gpLXG-h%^1hQ|={>VAh4xqR+W- zMw$73gIP5=(=X1cIGAf*#d9t^qh1TnuT{=rOAQYRp8}p+c+zhn!Ojky3y>)&gH0Ee zQL(9f({sn3^U$tYVqLSKa_DfzC5%x`r#KwBc}=G!reC|Zg8#6dt)yu$y>_tEN*B;< zNba=i?I>eKg{Pq-QTJ?;!}Zb($M@;|dn#IE6**ZesfRUdk@d?DHC|fb9y6{hjar)( zd^;uS*N|J;PIjUd2uHmgrz>f<vC<c$mAx!(r7O8Gt=MiLq7>pFh}&@%1oOzJT%7YJ z^qKb><R+gnJmM-R%fKWs7R>Zq2Jyi^WT)h|itbn}3{WKdxbdnjmK$cVxwq3vvr*(W zTTzsy8Ar~yFLtXr_*z$noKR-HyBDc#&bbO#<#QZS!RF1l6`htJJ{h}+C*|;Nxc>>1 zwEy2m#`bTr1!=MUXGIr_3(%D7Knq~TbtptQ;jSN#I#2u{bE_$N-WM7zK0j)o71}JB z<a0`~OpNl`S9~*O`IHMW%%AReOMyH797_HyD+e6%d9tTvjRcW1<g0xhW2R)6^OlBu z;t`8aZz1z}IoX1)eMUlxXjb*9IU2u_?Cc~!yEsaRd-G>dtu5K6zu0~GT=JWE{>vkO zm#dS=zv9TD1TqoBL#9ktrAKyBga93LuEDljo^F4)J)a_XV#DWA)L#Ej4>DiR+n8*4 zkc1bC+Tb9&V7KiaqE2{}+8-O9LgpdqMu+~(lw3E6ZH}m1f)<RZpVf~J%A=~MmRS9m z%HxCbxXMtUBhMXtgK*QFaL3NwetOkCDYzs28-7o^LqT?P${j)jC*3l?rra_X>Fxf^ zZE*S1E}J2)(;UpYgCA%~a~SNQJ2Kdxbxqiy1$T&rLQFCIh&x!x+kv<Yi?w|F=|y)m zDx%sSV(r+7+IzcG-p1}f+k7xsn(t^#+&jmWAC0Rc3}uN+X=1K1vpr+3dEOn4yX*od z_CRhfvK+!rPP*fwnWsU=rF;RjTi7V~wA>$hjw2pTxWft8d`)w|?wS|-nJ>AU<OWD@ z403M{a%FduL$WK3_`HVvvaQHSXGD7IB<ZY3ZyO0iW0Bwnc6W(e_QG?l4=!^bCFb5y z`O2VNQTZ!c;Jemk0j7g0kP>4i%lK<_qk0z6<tgvOnM(FWmFYw|M<gj(7^PV^>7~Ss zZnA&1-pJw?=o_kW*6qWW8aG;T<2kBmgP!eWw-Z?GJYNISWmHnoA1BGq-L?kEOAla9 zQRiZ+i)rc^<OJSXbdbrehTVFNUPDTNjt)9W8eNTEMD0ut1V+k|_SFtda+;Ir$Lu6o z3^Lrvc(Z4892gL#@*Ywc8Ry{U`SJo-pa((3N%yh0DC1Otta}iI+zu^4pRm_~U5)$; zAY}_D=+^#6*k#<#$oPJTVMT(~5)xv1Eg5ahpv`_9Zbg~#GikS@Mkc<kV>z`f=|);J z4n=F@B7@w7%T#Ic^-d>ho1L%r7tQ|PkE8utNo#MXozaBdidron4Wn+<T_=}$$ksP# zSTjNwc>X+qkKD}!pVlf2gL;;AW3b)MHI1?WwkB%n(71UWFv)gE#_RC8`mcTZ@Imbp ze=WGbTKjIsv%a^s`u(+_`e6O;w;v6uH$Pcle^3n``fIhCQF*8jAKb03uld1!v_`GQ zSo%Eu4q90y-TDE8DMJB-X+L`fIoWT&irlSlNe0vHWIupIsJ%7zx;gJN%Flt)9y~aB zoCo&R6E}A1al1lRnuEoI-%gU}saWzn>goGMy=9UoM^&@&blc#mnK+6kjzuFjaCFMl zp~<IqMJVuw16PnsZz6FcuNRBn{NQu0u<Ttfo<(^HpEtZYZ`!+n(m8LrFoDu&=>z2P zDV~F`i+&>w@}d9S;<%JKKvom~a(97hHTmD^yQmQaLGsIWU=mfJyxC25`WTgCk{X#O z#$D?e&@`|fLl;fzv%i(K>pQ1*Vx@jTklGwS<W9IPS8C8*qs|PB`%fVUw!>p!HFLmj zk%E&qq=H+9k&Mkwn~{e>gxy~bi+Et;`^6CyVdDG6F%)UhVUExqmYHU`pM^QyEVv7> zlh<i#zv^I2aRtNtx1YWx6F=%;KDjDcSsE3XUNf1ye-1kfGYOjsuK*Tr+#OufEVH!I zOEQ7uG)J&zw9jZV>309gdcnGxot)zJ0nPy?J(|v^g5hIp9eES?)-x=2Z+i4VX61+U ziJ*IJunQG)?r@6jJbb~AIE24}ezfH%!$#sF43_{T+H$mqSsb_a*xmx?r>U$}h|5E} z_lXd@FH-}%M;jHlJ5>ma1ZOL1M_s5R(H{^VbvFT#?M5V^PCGG-*N{e|R>$qLo5W$N zE@-hjAW$|4o~hwSC$6!Ol6*OR|FU5KY?*%t6#p&~p+Kwt>>-F8T!!L1y626v*o{<> z!Svq-r7G(#TpfU%ECq43PXSn&4*4I0YS)^p%w0obYl9xq*!u5~!kO<OW+I#8^ET}N zCX)}CTt_m{z1&pDLx^^g7g26J{I9bqFL-v@_#NgxWO55hh3yRwi^xG&%^<=Y9SGTA z8oT~OR0$o!xZzh>Amad)dy#nK6T<!PG4YwykenJ0$>kt0>mDJWeiexuoh;0G^8m$3 zz#TuA0Ew@a=DafiLc$?w%ifGYai-9qN#ICaFgKk3cmNK$M<;ABy`WMS-1DOAz9rZ& zPaJ^23KTqdgE<9WpcSUpaM|fl7ogu)<h;X82Y%#Z6<l|N9qGIm-HnI48xH>)2QQ_T zMS{RFp&=DCl<1zL9qs@JKO}Mhg`oGoymNEVu|ACX?|FBi4v}h^5K<gy9+pZvV5<qF z5ll#<v4&B%h{1RN#%=8W+->Ch(zd_JRf6RO2j%a<i?=<iZW)NR(H>WH5h0LISqHZt zaWniY9Dob3SY}j3&47xZr2;L`78eM#Rpek62U7JPA@#q6#B_-w?>AWF+4;Z61VK;d zBjDxyCrp08geJg$ilm|*0|lZXk^&7hOj<;;JR_g_CTZ>@9chz1pT347e%X<>DHLj| zK>>n$7toGL^v%WM`eNyWpCD^mKwUYt>=O!M>j)ozgsh3acfL61Eh3$Pg`f1six<67 zi2WQqf!DpWpiUQx-hx;3MoJf;3=N7reF`eJME@gXcydVXYH6YmGXyi{Bv;ocbSADh z+As_K0?peEof$V>t#C|XmcPr~Zy~90F7Zov;Xg-FY|e784SsmiML}qJY8Ek41QzvA z>u*t149a=ufdaYalLdqAcTlkHo95@X(3k+n016GZNa~T&58ze2pa80Li&yFar=F-v zY6pddO{}pg%4lI_v8#kht0vtN7ZhEE$7|f{A}5nU@kHzs_Y7Q=WWR<K+~v4iLUGW6 ztJ%)P@PSwhh!vJJapjzJTKyNCXNM)u-T8ueKCofG#Gom4*a4I2h%%ioG{|v2ob(nR zwZVPQ+%ON^ugOPDd0UV#xuNTCIZpAip&f}-H8*l#1?jy9yL)kFvPWT)i8g;w;lfkz zkAvC`^Y6Lr+`r^j=z|PQ$T@6`hpk9F(Rj{d5#E)_3xX^bd;#8?qRId3{z~E}fTxYI zBHCEoWR$Y^L>2(C7yvE<D;Q9GV>;#*h`1x}{NfTrAvTA3w5$WRS{=MYG)HfwumMMK z2NgMi$%5Yo6R-@}zCqfgn>s-pH}i(jOzt)h){hb3P3C@~))dU-3qafn_5waxO*mW? zYD=VXDfJ`xR0w<~ZT~Vj=wCt-ldXQ8$sHzlkyPf9=r}EaFszZ944fRrJtFx|iUCkZ za1Trxb<Ob&j;BzuJSEDWy7KyKU4`D?uD8<2{|*~}mkC9<!V@<15^(Xbbz>ebMR&=4 zyHf7k1#^Gjh}-(wvAUg}0Pxh($Q1$M?4pbt@jsxPzJbI+(eN&#c**;6;i7l3Fb~u} zUzjZL4mj;e{kSE<09laE4dgW!P)I6-2O_I*AjJeHEjPhj8cJbb1Sx4Ig@&FZCTRsp zAtcSDP_6@nZ2|WZ$UG%f5j+kIGz7FFqKc;IFy(kZqA<a_*kuPH(2u%PUOvyHTjH(7 z2A)CzqJ|}6`u<(!{2~Z&2S~=uR!`X{83dEi{^9~#iLOI*gCLywOPrxR3QOVb-`eZK z;aA}Ja(FqckdG%MfKq{L1j0?%Sn(4k61pwsh*kbKkqEynX!13MK28W5PsAinV-s>@ zDt#LI;Z*)#u=rCZKV$O8O#Xz)pECJ568Yx`-8|OQL*|PWIYe9j71N|;B>Bs;f(cw1 zA~%E2B0dnr0<3KjZTL{RC3L)J*s(#f&JWK^mK7@2eUE}-^mhL!k1<imcWfN0Dx}!@ z#b5I8m)|mbAZ~Mlp&1ym@6`KO2rySU2G0;6{1xWP9gBGxxc_FW3%|bA(*Jm?F*Wx8 zW1Ez`KC)PVl(zcwyL=7p=y~Wse}tnQ94OS6Sc3bDxld5m65#|6A0T8Iw-}b8-+5Vn z5-<P<`~=`4;|63w@Pb2HIAnZ?9%ix_=0Gj!xKI#PfD3>V0s_WG2m*jGN__^j5M5-^ z_+D~YjV0i1L%$jZa*1Q%i_H%HT6dN?#x}6B+fV<@djd$Dbw_gybR6O}z8TA9?sxtq zZ5%IRJU4ZOR)80Ksepwp9w{nvXs;ARIOh(2tf3}&mHT~nw4iaYF+^7uV2e*oasCxm z{h2OkCcIEFmMk9OT?+OOa-V<~D8?470SAB-@ffsPa>pZhXSC{V<n<tfFW@4YfO+8T z5}Wq3s4$k|s)jq?u#<R=AUk{DSv=86Mf92mgYAn<pB)T<b)x_-;+2jq5(~FQ+O&(m zHsIm1<2`ZrU)+WefvQ;@0(Q)Dj3>V)e%7B*R3hGnP{$v!2^A~m&t;TU_+ru=i*e-S zX!lxnv)kMXwi*_Dq5Z9`udXv5?%!X%C*R?j>IM9FI12GdK%7RKE%`G3CnQnD7~KxK zaOvyqtyW~=mp^1DuHCMoG$@<+Ie@)gP={8G7aUxdO7(6-m#FZdn=$Ba?~HH_Xm2G! ztB&8#WV#$!SCuPN+o3CChGiWzZ6M9KRl+p(`B!ZD3L~TXhPgA1o^B6ae~*oMy;W^$ zwW&Emp_Rg(F2P!H6D^8p-9!_8qm6y{^4J;|e`?77jF$w4j}pm#1M|{L!gT~6#>$tx z(c+ul75Gc=m2hi5Q#^xP^F`(g<>Ck4D(=<|bk(JW-?#9{^uc_6e1|&b@O|eF#MFu; z4{cS-Gp#+Ut*_m$mG3=Ry}fq(L(v}ITdl6G4`>GO5&$Br0`EGjQ!|316h_bXw%#KL z$QI{~c;om%n1}B?I!U<-6vqexxyAv5B73bU2z=d2sVRDwre6^F5+w?>IXt}Q`|mP| znBY$5{7oibVRD<v8k6^#yvKxW^#2aYaDU4E?|#|iV<1P>N-rT9Eli9}l=9ElC&tcR znRsV<Y+`C|bYf{@X>Jss%QmgNEV^fQXT~qe>_<!7@>cS!$=7?6$Xjf7?I6x{q11F= d$ik)2H;mQ4OD)jb(jvrio&g(uCJWPr{{%d&)3N{n delta 1504 zcmZ8gOK%%h6h6medpsV$AF<t9rB&k82_$J~R3)WCqzRx(m0PYsDWSzOo>4SzY^R<{ z;z+h4ksyIo3DLV}LnU^ts!B-k17ORJsvEZK*&!C3b0<y#+4J4=yytnpy!~P!to<2} zp8x7u_$uPpausjraj^I=zroxkA`Cc2*o=V{g=2ut6D?RK90y=C0ai@OlOXEV#PeL> zR_HJc03rI;=yM+-fCtb<Xa``Z2n*pz(G5*Wg1{0o2!Z9>gxLVunsnM&7gW~zzjdLp zF06FQ?{Mr$mj0!_GNK$g7X!Q~>nK3Oguy4uHwNqXZo^1P+a|PCr9*@*mF*}1gM|}2 z5|*q8l-BQ+VdR&f?1z-R23v>90U!JZ8xOvR4Gx&(K2pF@Q1v1OM*yRcy6&{VGz^1m zgLJerFbsj0^-Co_$2^UI+J2<{uQPdd4=LD}f>lrZIl*y|Cd7pnROq5FiUUnc{$afR z8g+sO)VJ#gu4i{#H%@H7w?EfxdCp$blOII0ms{IT>%MJyI_W;!_3F(%TbM+PH2Ve_ z?1AUd$uR(G)sp-xIwg<I^YWZIBOjYj<ZQg0Vara_=~j6|1cQ7SpO>hwE;F<5bgkb0 zMWWnk0tlVe%2*E2r)4mOMf#n?B*t)pxGa{mEE@7oqKOsxQ(_Nq%Ee?EkDk|(pQC)4 zdJ^+!^<bdzKt4*(=@*EvRde#^^cy#>5G|4f9<QpywF{2wMF?EmYj8<ok|hSgO~>`> zUaxP9*NGEz3=0gG<dsY%zsTg93<-wI3`=r1Gm~2;($femr=`yO_JMqw$(t)|bCuyO z`RmzrS<}L?-5smx*>w`S^Rkj%%(b`#_C9@2KZ4xOPL)1XLm$7N63?9&gllp?H+vX> zjcx=G(E_O7VI?hFfL|BACX3cA=&y<|rOhHKy`BF^btR=oLsGt`%5A8LcL>G%466+9 zF|09MXLy%keTmSY@o7i5#vOgtciy1ZZolFBn<q#4LXk^Vi{X#qz-@G!9a}7`4kahd z^neW9A^~7tOJV`#+C+ba!-%^K^8~NfOK|taM+B<%UUN&`+i|+RJ~83~-<#q@8V%R! z?x+brl-CQ-GAeT}nKSS7EPGr2U0A|-xmcWvshv?mu_5mkKSn8kD7J7?o+<5_-;$FX zAb_C!qVh}eG4nCzF@zBs3es7trld8!GINc@YVTC$Vuslo!>0_l7^)0A^7m;mdxpqx dz|f80$**GQnTnB%>4upMv*AhclhVHU-9H3k4dVa+