From cc9fcf4be00a99376a2083ddfbcf589f94ee6785 Mon Sep 17 00:00:00 2001 From: Mark Slee Date: Wed, 12 Jun 2013 22:38:41 -0700 Subject: [PATCH] APC40 is mapped, update UI to reflect that and use GLucose internals --- _Internals.pde | 35 ++++++++++++--- _Overlay.pde | 113 ++++++++--------------------------------------- code/GLucose.jar | Bin 14492 -> 18569 bytes code/HeronLX.jar | Bin 60851 -> 60903 bytes 4 files changed, 49 insertions(+), 99 deletions(-) diff --git a/_Internals.pde b/_Internals.pde index a103f13..46c3939 100644 --- a/_Internals.pde +++ b/_Internals.pde @@ -44,6 +44,8 @@ LXTransition[] transitions; LXEffect[] effects; OverlayUI ui; +boolean debugMode = false; + void setup() { startMillis = lastMillis = millis(); @@ -57,6 +59,7 @@ void setup() { // Create the GLucose engine to run the cubes glucose = new GLucose(this, new SCMapping()); lx = glucose.lx; + lx.enableKeyboardTempo(); logTime("Built GLucose engine"); // Set the patterns @@ -64,7 +67,7 @@ void setup() { logTime("Built patterns"); glucose.lx.addEffects(effects = effects(glucose)); logTime("Built effects"); - transitions = transitions(glucose); + glucose.setTransitions(transitions = transitions(glucose)); logTime("Built transitions"); // Build overlay UI @@ -72,12 +75,33 @@ void setup() { logTime("Built overlay UI"); // MIDI devices - SCMidiDevices.initializeStandardDevices(glucose, ui.patternKnobs, ui.transitionKnobs, ui.effectKnobs); + for (MidiInputDevice d : RWMidi.getInputDevices()) { + d.createInput(this); + } + SCMidiDevices.initializeStandardDevices(glucose); logTime("Setup MIDI devices"); println("Total setup: " + (millis() - startMillis) + "ms"); } +void controllerChangeReceived(rwmidi.Controller cc) { + if (debugMode) { + println("CC: " + cc.toString()); + } +} + +void noteOnReceived(Note note) { + if (debugMode) { + println("Note On: " + note.toString()); + } +} + +void noteOffReceived(Note note) { + if (debugMode) { + println("Note Off: " + note.toString()); + } +} + void logTime(String evt) { int now = millis(); println(evt + ": " + (now - lastMillis) + "ms"); @@ -102,12 +126,13 @@ boolean uiOn = true; boolean knobsOn = true; void keyPressed() { switch (key) { + case 'd': + debugMode = !debugMode; + println("Debug output: " + (debugMode ? "ON" : "OFF")); + break; case 'u': uiOn = !uiOn; break; - case 'k': - knobsOn = !knobsOn; - break; } } diff --git a/_Overlay.pde b/_Overlay.pde index c08e185..793d313 100644 --- a/_Overlay.pde +++ b/_Overlay.pde @@ -49,17 +49,6 @@ class OverlayUI { private Method patternStateMethod; private Method transitionStateMethod; private Method effectStateMethod; - - private final int NUM_PATTERN_KNOBS = 8; - private final int NUM_TRANSITION_KNOBS = 4; - private final int NUM_EFFECT_KNOBS = 4; - - private int activeTransitionIndex = 0; - private int activeEffectIndex = 0; - - public final VirtualPatternKnob[] patternKnobs; - public final VirtualTransitionKnob[] transitionKnobs; - public final VirtualEffectKnob[] effectKnobs; OverlayUI() { leftPos = width - w; @@ -70,21 +59,6 @@ class OverlayUI { transitionNames = classNameArray(transitions, "Transition"); effectNames = classNameArray(effects, "Effect"); - patternKnobs = new VirtualPatternKnob[NUM_PATTERN_KNOBS]; - for (int i = 0; i < patternKnobs.length; ++i) { - patternKnobs[i] = new VirtualPatternKnob(i); - } - - transitionKnobs = new VirtualTransitionKnob[NUM_TRANSITION_KNOBS]; - for (int i = 0; i < transitionKnobs.length; ++i) { - transitionKnobs[i] = new VirtualTransitionKnob(i); - } - - effectKnobs = new VirtualEffectKnob[NUM_EFFECT_KNOBS]; - for (int i = 0; i < effectKnobs.length; ++i) { - effectKnobs[i] = new VirtualEffectKnob(i); - } - try { patternStateMethod = getClass().getMethod("getState", LXPattern.class); effectStateMethod = getClass().getMethod("getState", LXEffect.class); @@ -114,9 +88,9 @@ class OverlayUI { yPos += controlSpacing; firstPatternKnobY = yPos; int xPos = leftTextPos; - for (int i = 0; i < NUM_PATTERN_KNOBS/2; ++i) { - drawKnob(xPos, yPos, knobSize, patternKnobs[i]); - drawKnob(xPos, yPos + knobSize + knobSpacing + knobLabelHeight, knobSize, patternKnobs[NUM_PATTERN_KNOBS/2 + i]); + for (int i = 0; i < glucose.NUM_PATTERN_KNOBS/2; ++i) { + drawKnob(xPos, yPos, knobSize, glucose.patternKnobs.get(i)); + drawKnob(xPos, yPos + knobSize + knobSpacing + knobLabelHeight, knobSize, glucose.patternKnobs.get(glucose.NUM_PATTERN_KNOBS/2 + i)); xPos += knobSize + knobSpacing; } yPos += 2*(knobSize + knobLabelHeight) + knobSpacing; @@ -127,8 +101,8 @@ class OverlayUI { yPos += controlSpacing; firstTransitionKnobY = yPos; xPos = leftTextPos; - for (int i = 0; i < transitionKnobs.length; ++i) { - drawKnob(xPos, yPos, knobSize, transitionKnobs[i]); + for (VirtualTransitionKnob knob : glucose.transitionKnobs) { + drawKnob(xPos, yPos, knobSize, knob); xPos += knobSize + knobSpacing; } yPos += knobSize + knobLabelHeight; @@ -139,8 +113,8 @@ class OverlayUI { yPos += controlSpacing; firstEffectKnobY = yPos; xPos = leftTextPos; - for (int i = 0; i < effectKnobs.length; ++i) { - drawKnob(xPos, yPos, knobSize, effectKnobs[i]); + for (VirtualEffectKnob knob : glucose.effectKnobs) { + drawKnob(xPos, yPos, knobSize, knob); xPos += knobSize + knobSpacing; } yPos += knobSize + knobLabelHeight; @@ -193,7 +167,7 @@ class OverlayUI { public int getState(LXEffect e) { if (e.isEnabled()) { return STATE_PENDING; - } else if (effects[activeEffectIndex] == e) { + } else if (e == glucose.getSelectedEffect()) { return STATE_ACTIVE; } return STATE_DEFAULT; @@ -202,7 +176,7 @@ class OverlayUI { public int getState(LXTransition t) { if (t == lx.getTransition()) { return STATE_PENDING; - } else if (t == transitions[activeTransitionIndex]) { + } else if (t == glucose.getSelectedTransition()) { return STATE_ACTIVE; } return STATE_DEFAULT; @@ -324,54 +298,6 @@ class OverlayUI { } return s; } - - class VirtualPatternKnob extends LXVirtualParameter { - private final int index; - - VirtualPatternKnob(int index) { - this.index = index; - } - - public LXParameter getRealParameter() { - List parameters = glucose.getPattern().getParameters(); - if (index < parameters.size()) { - return parameters.get(index); - } - return null; - } - } - - class VirtualTransitionKnob extends LXVirtualParameter { - private final int index; - - VirtualTransitionKnob(int index) { - this.index = index; - } - - public LXParameter getRealParameter() { - List parameters = transitions[activeTransitionIndex].getParameters(); - if (index < parameters.size()) { - return parameters.get(index); - } - return null; - } - } - - class VirtualEffectKnob extends LXVirtualParameter { - private final int index; - - VirtualEffectKnob(int index) { - this.index = index; - } - - public LXParameter getRealParameter() { - List parameters = effects[activeEffectIndex].getParameters(); - if (index < parameters.size()) { - return parameters.get(index); - } - return null; - } - } private int patternKnobIndex = -1; private int transitionKnobIndex = -1; @@ -395,28 +321,27 @@ class OverlayUI { } else if (mouseY > firstEffectY) { int effectIndex = (mouseY - firstEffectY) / lineHeight; if (effectIndex < effects.length) { - if (activeEffectIndex == effectIndex) { + if (effects[effectIndex] == glucose.getSelectedEffect()) { effects[effectIndex].enable(); releaseEffect = effectIndex; } - activeEffectIndex = effectIndex; + glucose.setSelectedEffect(effectIndex); } } else if ((mouseY >= firstTransitionKnobY) && (mouseY < firstTransitionKnobY + knobSize + knobLabelHeight)) { transitionKnobIndex = (mouseX - leftTextPos) / (knobSize + knobSpacing); } else if (mouseY > firstTransitionY) { int transitionIndex = (mouseY - firstTransitionY) / lineHeight; if (transitionIndex < transitions.length) { - activeTransitionIndex = transitionIndex; + glucose.setSelectedTransition(transitionIndex); } } else if ((mouseY >= firstPatternKnobY) && (mouseY < firstPatternKnobY + 2*(knobSize+knobLabelHeight) + knobSpacing)) { patternKnobIndex = (mouseX - leftTextPos) / (knobSize + knobSpacing); if (mouseY >= firstPatternKnobY + knobSize + knobLabelHeight + knobSpacing) { - patternKnobIndex += NUM_PATTERN_KNOBS / 2; + patternKnobIndex += glucose.NUM_PATTERN_KNOBS / 2; } } else if (mouseY > firstPatternY) { int patternIndex = (mouseY - firstPatternY) / lineHeight; if (patternIndex < patterns.length) { - patterns[patternIndex].setTransition(transitions[activeTransitionIndex]); lx.goIndex(patternIndex); } } @@ -425,14 +350,14 @@ class OverlayUI { public void mouseDragged() { int dy = lastY - mouseY; lastY = mouseY; - if (patternKnobIndex >= 0 && patternKnobIndex < NUM_PATTERN_KNOBS) { - LXParameter p = patternKnobs[patternKnobIndex]; + if (patternKnobIndex >= 0 && patternKnobIndex < glucose.NUM_PATTERN_KNOBS) { + LXParameter p = glucose.patternKnobs.get(patternKnobIndex); p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); - } else if (effectKnobIndex >= 0 && effectKnobIndex < NUM_EFFECT_KNOBS) { - LXParameter p = effectKnobs[effectKnobIndex]; + } else if (effectKnobIndex >= 0 && effectKnobIndex < glucose.NUM_EFFECT_KNOBS) { + LXParameter p = glucose.effectKnobs.get(effectKnobIndex); p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); - } else if (transitionKnobIndex >= 0 && transitionKnobIndex < NUM_TRANSITION_KNOBS) { - LXParameter p = transitionKnobs[transitionKnobIndex]; + } else if (transitionKnobIndex >= 0 && transitionKnobIndex < glucose.NUM_TRANSITION_KNOBS) { + LXParameter p = glucose.transitionKnobs.get(transitionKnobIndex); p.setValue(constrain(p.getValuef() + dy*.01, 0, 1)); } } diff --git a/code/GLucose.jar b/code/GLucose.jar index 321f2a024daf58afa90f76d126ba1faf02ae471b..6f5463dfb6a0c6a0624cb6baad40cdf6c1be60db 100644 GIT binary patch delta 6571 zcma)B1yodP*B&}mVt^SCknRrY2Bo{3VWdME1qPH5h92n=knX4{qM%{}0GI$kc6ooy9Y&OQHy{vs z3q22RVVCA7APA6HZcze>`4%0Jm~JuYx4jFA?e_i@iTxHCk?C(y9eLpHjlWct6&GbJ z1^~c^hhRk^gGK0`!+;Y+*D5DmJ(m8omV{F4Of3UaAbGod)NCr$>2mLGb}l5MkOlK3 z&ZL>ae(LG>I(zjWXKh(d0)})9Wqahp<$erTpIka#`(F)TXY6f`jk@mli^VD{#j1X3 z+)UjU++1`W67>AKc)gg2HXPA3wd#l^Dqt8w<{WwF6jr(dp%yanaO@!2w>I2_Y+K+J+ieG|>hcRKK@~{GVy~f7YqbXA; zawFQzZP}SyOoTRri7PW*ok*ImLSeKDYo5hSwh1a!Y+IL=A2Wp-*b|;vi#$spIHzD2 zDJ?+fFq6zZ+9mr=3zAAS94nAL6Q4I*oCUIqdkG7F93I2VYXjw#mY|K{`)boS0vuFB zpLy)kGs18byuBUIlu?D+yQ5G}`(WDk5l>}h0Tf*&{hgrW6W*`P?P%lm)wV)HZ6in} z!u*~z(9BqnVjO1qv_Ylb#t$8`kVsq#$}Pog^t<=S#d&!f9)dHB@`;A~QS;h-rF*=> zUg*K%(a?A~XPU1rQ7)OHRLh3)iVJ2osK$gO4ebu7(>>j#X*eq_1@`s1v#pO4B6?N zye7ybd8jfC3L^uyj!jTKesWsSo`_rzHGW^z8-Mr8s<#f;`L8XTIC4ab-FP2rCmEG} z=B|M66~-9RZPFI`N31`MMBZH7ttH`hJV%bD}C@1T-RE)LzT~4*nKgfkW zcV9mRMusEpCg5AO4P=DtHA*yP^u=)nz3^8inz8uA%VWn#gJI9-sh}#{CPVp{vtW$- zM`=QuQ)YE5UP<5QE-{6%pxK1*K2WAsEbI{d3FwD1`1yf3*vUMeUynUPY))sW?1xzf z7E($AyK%6OVJFeWNOO; z(HM>*zz88AWCUJy4SR$B27pMzn|lz9__u%?Sf z?}ct_{(>6f6CE5xf#3mUUD;w|vus z56Lhd@d^0F`myM?#ccd8&vW`R=>{X=!Z560EeB8wDJgA16nz& zH1)V`!NTy7o}WZ_bJcM^>z?c7In8JMl%rux0g&+qPetW^*bDjeERf1560Ar>IKxwD zK|?N=+BjcPIc@iw*mqup;|IIUbmNY%EJ;8+<30$H@S4%svD7*Unm8@9R4sZuQAyx1 z9b|$zt*mutAfoWwSY1q&zL@6u1`nT2Wagt6L*wtx?r*x0iAlMR3{t%%BszXDBJKKF zZqhdNW87FssEW=o)7vPm;Vf9?n9zJM*J?PS716*h!!T__D+%(quaI=LnwTpqywKDA zX&#Rir>LmybX^9}^YK1QW!37*B#o8x;Kf2bE2U6fFkgZ=@wKnYB5`Vpl! zwPT&qIvd+tY?i?Q#0n)DUL;PH6y6HVc^XkdxGLlzSzK9M2*f@Pq%kiBCbvA(z*dF4 zECHUpmNK$gtJXtGVgKqsuL2=y)!nMa3aycDPos{6*TAVyDGSdzsO<-I*{;G~fA;+< zJ+H)rqcQN6X$+}3!L9~MlB&c@@E!L_0IwoJXwEybl&?FOC@W*$ zQ+z*WHGZVI%>9<{nBS9Fc{}l7|!LC+FM#aD%?ggPJ5DkNIGwbpZ?JXGW5_dkQADIl?nJ`$2Q7`RYv`KDtOfPC zvkBqQZHg}+ApDy%+h)lNFBf&H@3;?~c-atQnMf$=(vCN>%o8t~G<$GBuk=q!(fM@C z(9G+cBvE~h43Im%nQHmEk@}2#&aH+RGJj`Ap9x-r=r|`|g&{dBzU}STQT*N4|QRO*qgh$Mrh5s z5^964)9mZ!SmzXNbKm;=huM(g>Hw=?MDIv4YaE!1)SCP3`5Cq>>QdzImTjM{o?(^@ zHp8QYU#j+3?tDgx5;?;-Q$5>Fq48Og=TQqwu>831^WkV==<4LO`Io^ZBoO> zDqKPiE50~ZsD;ng>L{zSB_6|IbYRbs0fiO01Bfq1&8=mzCfjn%0I6Yok;@7CFs z69t(lRw+hA#E!4V*3V9ixw|rBqPQz$BrbiLckr#H(0VzFocX=f+jyW?Wx21X434~& zl&b)~6C4x!>EOjNbT~#kV8v%2Hc4$$xz$|$^@4-AVIxe}<}uD#T`3r+0$KWpU(uxN z@-krK{%+gR-SiGuVliiD;!W0mVS%W7TgfOSICqKFJxT+)Yh4fUmuj1>!7S@jEnWRa z?Q|FgHM`5$#X??4=WIT!%bJtE!GZxK&xy{}a}Ct9+@9EMv>zt1k43XF!#0zr4i)Zj z6eje>+0|v&l9P*eh1WBeZkCm!$$5Z^y1zZ4HCwMG&r;oI_C7Ei)zs)ijoesZfT%|9 zC1WZ(e-16fdPhnI?DREAw_Gw!uw_!aN>;HpF*C)}Sa%2KLk%cQdu%<0bDG|AZEgx~ zqSPzt7?@1o)xrz1e=?aR3#-lKEgO#|4-lIu65Raq1(nX6u|&RR)M!e7m_E@VFDFTP z(@M}Xesn%5syXvw8n$#!! z!JH*|dl!*P_Z&xD8W_&@4tvdzGb{*oOVP7MT;X+pW$hWMuRXg)5KI}A^4SoiYPLA? zm}}lOzV=94T&W<@G<}~fBmNJ^3AX`x-VV^hB1{uXWr7jb~JpX#Oi|4n{+dC zh4%pOpUGP?B+$BZle~pDuirGkk{7|x_W%~BHRnPmizf<^r!bzZUY)+{LQRc9KszHt zADEH~BIp5SPSC}dtp&~*81(HFdUV(l;c7P=5{gJ3u0FyJb0Lt*_S#^`U1jk{4oQ!* zhZ4b=Pt2cGZ}tl=h>BkBw5Ub_j9M8aWw=P%;WZ!`>?6MhAnj3~pV8e_T$95!Z5US* zar2H>Ta+6fPEG4mzE}9H=m+$R*ej&PA<>dLxQh3k;Eho6Mf^FzNY9Sc&1gYvNu{iA z^;Je5T+~&FDPu)=hLo)w=j)86?{x1BElz zQ-zfVsHT#i%s9w$u<$&R=`Gc8M62=ahWt?FSgi&jzs}rx+LK0ETb@ z91ae7+J*q|;0feD)YI+tAk134FcyDHAph+_q>HZnR+zeK9KYwQw6HHH8Ru4sLVjHx znq_PQxjf;*In_m5dH3lQ%aq~06^f1X#a1Xkc~h__dSE={=r zYdPfwHV5^jjyH>{>+{8aljRfWqCyqQ0jeGc$w|zF(>XNxqYru!U9d#?T&62Gi2rc% zE6W3Ef|zk!H~pQF$6Y_yRfxL%&L+)wIz(_h@ldsMa1it9eZ z*uIHIm=@Ftx=hPR8iDO9E~1<-BFSL-6xUy(1#>DLMVy0TttgGZvC0kkz_VvQXIDO4 zT?k>=gP(QUtdRXc&#Jsn+*d+HN3(do{5%WEZ+$ay;{kcdo<5YjOVZ-la7OZv zx&V_Z)m;_)fCK#h;-jHq8yiAM^S5{tkk04hTwgT{<%U43%I05$xp)o z8Yo+W@294p+^w`J*+AwtDr04HKX9Kzy`TSMCUg_FX87G(vl>EoFf0p(vv)4nfw}^l zX-E|Hh!2c-mq}jH>lhWTa+$BtV@q91oymH#^tzdLmQ;Vxe$*sC%5VN%9D+V9o};|m z&B6V7=hd8gF;=ye52NYRkRqrezg9mm|G7$sZOOB@Vd#WuG}BSD?!MLV_a^y0Sla1l zAE?t|>b+Sd`D&fI)<<_;VMR!s@$wvAQ;S?~xkq+S&#?4!NxK9KNXOvfK8#8(h0c6! zRReZ2;^^N8r1kvv@J^8WyO^Er06r}eaNVJ6^c~D>8r-1N*#Saa!V@){ss4v4f*Dhb$^Lb#!?YX`2rmt6kX>ngY;PEc3?8US*p%MA5zYp`LOc+UQO_^Tl*g46zUw0oYr-D$Z{#eC)`%*`jJPe z7mK(a)qVVPoSseyHs)6fNP?MzMzAom7YY<<1yV3v)06>*{6dKlROq0P>H3I|1P3f9AfFH>4D{QGcWT!HxDT z|E|53i@Bq#jhl_r-{gzKrO461Rw^Xw3Q*IFH05lE!V(*i|>k_8+{4&;aW)0)4X9;eo`*r+J zj4WFfX?HZwDew1nE3IMiNX3Eu-oRp?$8ldu5{-Sebr6f$ui`_NkJ_BUf~ zin>sTOn2sjNE_`64fBAA@XJ!?$UKM;`{0tLFxt;JK>J%9p#JRaDwwh5k$w(pD?D%t zP;Mu+FT5n!gwbw>!q|ua9HI)Ddn#zR3*vzK=(iV#r0Ks_lF^u9CEmo(LsUct5Li)0 zQG|TEz?{nG*Tpi8=r8gIbYj0q%$Ws#SyEXv&{1xN&WJ-UfuBwYR&McIbmZo|#Y}FV zTa4r(Lwx1Fokb&vc!X|k8a#r(e-pmNejd?V#N`#cMP*+8TMXuX{O9m_o|g~yzdG8R z6uAAo3z)eXi2uL(TQx-_WFX4V@%gVN`Oo+4zbK>b{+$vb%13v*hd)%ZVYZwkgg>cwBQCB%Qx{=xdcs>d&4`oA7q z_YU$V{!Jxny!n#s(=oN z>d*sQS%4$ZK`}mBQa0^>YlT4|%DVt97@C^y9^y7Z5>FCC_eiMBWgTV*2(Uel#$3DBeJoO zRd$b^guY{8*(VPhaq*$r_D)@gI9005iTA)QS?9u%o;byRB+RN)UrGIuk6IX&byK)c z_ssLt%=hq~Ohj*U0^JX}Kyve{SR^1g>*duUzpg3@jaVm+@bJOn@=0%N{oN`; zauupgTY0z)>r~F3pZoNX!PI{1;j(ZaRto$Iixp-#lZOt!6VzYKtNU{a-*}C~lL$}K zH8eDBB_=9d^EvxNPY z0nYJ_i)q#^=SrjpM=sNXb_F-&Dz=IjK-cq(8#3vE3CxaT?iI`)YLhWTec!RhfR9a| z!~K5ODCd2$d3eyeFLqzm_>klPGSk!meD`ZajhS{TYE{UNA?h{J!=U%9@bF7M6 zZp&X-L}rHvBd&CW^hmf3h_)AsO}1uvRFNs;X8#Ks?M5Y%hDX)z?vq?Y$voi61tsp! zcoxi#KgPz>Ta*eISgLXz+cs7ju5v5i*xL2`Ud+Pq+yjbGWA6~xPK6k0)Rob>F`%>e ztBIY5&TL%%OX6SNj4$Pjs!q=x({;b;z~=^V25EMmPV$U$+16ilTP|o7HD^iF0zYf# zY)Ek{pJhi~q`O~dNHwN&N`wDcI+`P!Cjkq2IOm-cW8vqo0zWEBB78TKYh3IQJ0nYZ zYmKhp5TyMd+9Y_V<5x_2r=|l=BPB64UWJToHSaY>`dDc#x2goer6Anu27dZ~)!4mN zH7tW~+Ura~A&?{?phirCdehz8ZOlb{Q_LySVYjEKyr8zPcPP95=!Hs`{CRP&41#ZO z%}WxZI!KhrmYZ7JN4U3k135j1Fn_S*x27ihSYp-Xw&pbNq*83)>cYp>#j-$W>Q%%GgDG>Uor~RN@?0)`gu$C92Tyj=4<4)1xoq zSQ0e5gAp0Tr|u47sVY|+7w`U1YDrngnyFtj8-87BFwD~o9ZcBs=;=LwXRnfkwd9qT z!kV3mX@6GVp-AJBWZe&rwa4{~Ei_9Kx~U=(sFJKBOMNXT?uVE!E96Eg*u(D+;RDw% z)p_Y#C8>Gi&ilrasg0&isvkUMdc4lAv$*)-h-6Y-h3KM!j1eO|OP$h|gF`rVS`2eT zhu>-Ew$Og`!Nv;V%ns}MJI{XhZ>rlE2+%6&M+D&!shnb(giqjH(NJ#Sm|mB&xkp(2 z!w4&udao=z_PR#6fY!)q_Ivo9U*+X-WA^N`bCyxPdl!9xv{}tic z2Rfn9dXawWpR15|Oz}j6QAGW#>#hf^&iYNhJCPZ<+SJ&QvCyQ+n!8RV;U3BeNUl3I zr)pKm1>FskT9`cZOEL`K7UNURQ=iX5QtZgImdkXEhK*-*yc}25-jf~_%9FAtFr=P{ zhK=|#Q9s_NjR*2Jk<(<6pE{Ooeyx!!SV&uj4JuGea}sS+I3p(NAM)AQvO(!(x0KNR zhrTJXb9<#~uZ=`^QKh^ZZ(^~cjMG-WWQ_vUi@S|lRTKF!WsbJHVuI{Xk)nkL zwtxVCK?VE;sqRQ2i3O;ZQoy(Y6412Ue*4)8->5Y{DU<&@V0Vz+HGwWZ8Ev|EiwsU= dYKMmA;Q%5*QQCzp1mB{|@oxs-n$g?x{suz98fO3i diff --git a/code/HeronLX.jar b/code/HeronLX.jar index e6ac53e47ae04653ee7759bff74f262a8011fd44..dbe579cd5ab18eb756933a657b9581c92d00d345 100644 GIT binary patch delta 10142 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%0AlDq*!TP+=| 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 -- 2.34.1