libtuxcap-1.4.0/0000755000175000017500000000000011212652446013372 5ustar inniyahinniyahlibtuxcap-1.4.0/README0000644000175000017500000000333611062275772014265 0ustar inniyahinniyahThis is the GNU/Linux and Mac OSX port of PopCap's Games Framework It was ported by W.P. van Paassen in June 2007 ======================== "Lieve Sabine, 3 keer kracht * 3 keer hoop = 9 keer leven Heel veel sterkte, We zijn er voor je Je mannen" ======================== --HOW TO BUILD-- The library depends on CMake, SDL, SDL_mixer and Magick++ To build the library and the examples: cd tuxcap-build cmake .. make --INSTALL-- to install the shared library in /usr/local/lib make install ----------------- You can change the install directory by calling cmake -D CMAKE_INSTALL_PREFIX=/path/to/your/installdir .. On first startup of a TuxCap application, the framework tries to detect if the user's system is capable of doing 3D acceleration and runs it in either hardware or software mode accordingly. You can overrule the detected setting as follows: You can change the value of the Is3D attribute in the demo's ~/.PopCap_SexyAppFramework_*/*.ini file or add the gSexyAppBase->SwitchScreenMode(bool, bool) call to the Init function of GameApp.cpp. Some demo's like demo_5 and Hungarr come with an in-game dialog to enable/disable 3D acceleration. The particle system is based on HGE's particle system and excepts .psi files created with HGE's editor which is part of the HGE distribution. It also accepts .psi files created with James Poag's extended particle editor. I use wine to run the latest HGE (1.8) particle editor, it runs beautifully! The resource generator does also work with wine. Hack on! Cheers, W.P. libtuxcap-1.4.0/COPYRIGHT0000644000175000017500000002353411076657726014712 0ustar inniyahinniyahSat, 09 Feb 2008 12:06:40 +0100 The TuxCap Games Framework includes portions of the PopCap Games Framework (http://developer.popcap.com/). Copyright: PopCap Games Framework - Copyright (c) 2005-2008 PopCap Games. TuxCap Games Framework - Copyright (c) 2007-2008 W.P. van Paassen Chipmunk physics engine - Copyright (c) 2007 Scott Lembcke Pycap python bindings - Copyright (c) 2007 Jarrad Woods Hge particle engine - Copyright (c) 2003-2006 Relish Games License: PopCap Games Framework License Version 1.0 Copyright (c) 2005 PopCap Games. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code or derived libraries, whether source code or binary, must include a copy of this PopCap Games Framework License in its entirety. 2. The end-user documentation included with a work which contains any portion of the PopCap Games Framework must include the following acknowledgment: "This product includes portions of the PopCap Games Framework (http://developer.popcap.com/)." Alternatively, this acknowledgment may appear in the software itself, wherever such third-party acknowledgments normally appear. 3. The names "PopCap" and "PopCap Games" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact bizdev@popcap.com. 4. Products derived from this software may not be called "PopCap", nor may "PopCap" appear in their name, without prior written permission of PopCap Games. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGMENT AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL POPCAP GAMES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. License: TuxCap Games Framework License Copyright (c) 2007-2008 W.P. van Paassen Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License: Chipmunk Physics engine Copyright (c) 2007 Scott Lembcke Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. License: HGE Particle engine Copyright (c) 2003-2006 Relish Games This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. The following files are licensed under both the PopCap Games Framework license AND the TuxCap Games Framework license. This is not a dual license, both licenses apply at the same time. Buffer.cpp ButtonWidget.cpp Checkbox.cpp Color.cpp Common.cpp CursorWidget.cpp D3DInterface.cpp DDImage.cpp DDInterface.cpp DescParser.cpp DialogButton.cpp Dialog.cpp EditWidget.cpp Flags.cpp Font.cpp Graphics.cpp HyperlinkWidget.cpp Image.cpp ImageFont.cpp ImageLib.cpp Insets.cpp KeyCodes.cpp ListWidget.cpp MemoryImage.cpp MTRand.cpp MusicInterface.cpp NativeDisplay.cpp NaturalCubicSpline.cpp PropertiesParser.cpp Quantize.cpp Ratio.cpp ResourceManager.cpp ScrollbarWidget.cpp ScrollbuttonWidget.cpp SexyAppBase.cpp SexyMatrix.cpp SharedImage.cpp Slider.cpp SWTri.cpp SWTri_DrawTriangle.cpp SWTri_DrawTriangleInc1.cpp SWTri_DrawTriangleInc2.cpp SWTri_GetTexel.cpp SWTri_Loop.cpp SWTri_Pixel555.cpp SWTri_Pixel565.cpp SWTri_Pixel8888.cpp SWTri_Pixel888.cpp SWTri_TexelARGB.cpp TextWidget.cpp WidgetContainer.cpp Widget.cpp WidgetManager.cpp XMLParser.cpp XMLWriter.cpp BltRotatedHelper.inc Buffer.h ButtonListener.h ButtonWidget.h Checkbox.h CheckboxListener.h Color.h Common.h CursorWidget.h D3DInterface.h DDI_Additive.inc DDI_AlphaBlt.inc DDI_BltRotated_Additive.inc DDI_BltRotated.inc DDI_FastBlt_NoAlpha.inc DDI_FastStretch_Additive.inc DDI_FastStretch.inc DDImage.h DDI_NormalBlt_Volatile.inc DDInterface.h DescParser.h DialogButton.h Dialog.h DialogListener.h EditListener.h EditWidget.h Flags.h Font.h GENERIC_DrawLineAA.inc Graphics.h HyperlinkWidget.h ImageFont.h Image.h ImageLib.h Insets.h KeyCodes.h ListListener.h ListWidget.h MemoryImage.h MI_AdditiveBlt.inc MI_BltRotated_Additive.inc MI_BltRotated.inc MI_GetNativeAlphaData.inc MI_GetRLAlphaData.inc MI_NormalBlt.inc MTRand.h MusicInterface.h NativeDisplay.h NaturalCubicSpline.h Point.h PropertiesParser.h Quantize.h Ratio.h Rect.h ResourceManager.h ScrollbarWidget.h ScrollbuttonWidget.h ScrollListener.h SexyAppBase.h SexyMatrix.h SexyVector.h SharedImage.h Slider.h SliderListener.h SoundInstance.h SoundManager.h SWTri.h TextWidget.h TriVertex.h WidgetContainer.h Widget.h WidgetManager.h XMLParser.h XMLWriter.h PycapApp.cpp PycapApp.h PycapBoard.cpp PycapBoard.h PycapResources.cpp PycapResources.h The following files are licensed under the TuxCap Games Framework license: AudiereLoader.cpp AudiereMusicInterface.cpp AudiereSoundInstance.cpp AudiereSoundManager.cpp AudiereLoader.h AudiereMusicInterface.h AudiereSoundInstance.h AudiereSoundManager.h SDLMixerMusicInterface.cpp SDLMixerSoundInstance.cpp SDLMixerSoundManager.cpp SDLMixerMusicInterface.h SDLMixerSoundInstance.h SDLMixerSoundManager.h ParticlePhysicsSystem.cpp ParticlePhysicsSystem.h Physics.h Physics.cpp PhysicsListener.h The following files are licensed under the Chipmunk Physics engine license: chipmunk.c chipmunk.h cpArbiter.c cpArbiter.h cpArray.c cpArray.h cpBB.c cpBB.h cpBody.c cpBody.h cpCollision.c cpCollision.h cpHashSet.c cpHashSet.h cpJoint.c cpJoint.h cpPolyShape.c cpPolyShape.h cpShape.c cpShape.h cpSpace.c cpSpace.h cpSpaceHash.c cpSpaceHash.h cpVect.c cpVect.h prime.h The following files are licensed under the HGE Particle engine license: hgecolor.h hgeparticle.cpp hgeparticle.h hgepmanager.cpp hgeRandom.cpp hgeRandom.h hgerect.cpp hgerect.h hgevector.cpp hgevector.h libtuxcap-1.4.0/AUTHORS0000644000175000017500000000025011212535036014432 0ustar inniyahinniyahPopCap W.P. van Paassen James Poag Scott Lembcke Jarrad 'Farbs' Woods Pavel 'Haaf' Lebedev Nicolas A. Barriga Brian Hammond Kevin Lynx Rheenen Tony Oakden Miriam Ruiz libtuxcap-1.4.0/doc/0000755000175000017500000000000011330673043014134 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/0000755000175000017500000000000011212652246015771 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/images/0000755000175000017500000000000011330673043017235 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/images/atomicexplosion_.jpg0000644000175000017500000004076310641010422023313 0ustar inniyahinniyahJFIFHH.ExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:01 18:39:122(&HHPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMU2atomicexplosion_2nullboundsObjcRct1Top longLeftlongBtomlong2RghtlongslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong2RghtlongurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:8e421824-74c3-11d9-8a14-c426ef2c7c0c Adobed@      2^  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?v*UثWb]v*UثWb4i)׀U"4mqWbWrH@ A?dV_NmS$j Ue* BWnn3ShqT6*UV%8г78)|}|IiU[:ۇ+Y7IXN3#d^j|*6)"e4 qVf4QS6x+O"4*6,TW0r Gb6? (OF ~UVi#ݷ(J M>CE[y3].Nᛈ#b=:uD~c}ŦnKK_Kւ;6hO;b|m̚|fZ+qR؀zUWr>ȅ>Gu,'DDf5*!xi~jq[C%V>A#@^?8?ZZtbX!*]FXVp4JhՊC# P7y@S8y@CRUv*Uث47gcn]y(hk} y1-Ϙ.՞84a(NG^s#bPV$EI1VEae"8\UA鮍FwbQ- Uت v*UثWb]v*Uث0D4do5]E-%ӊbg-.EA?#=)!vT1ȄV Uf*U|q$ UMZ1%Z U>aBԵ&ྟ^05^W-O˅kl9S^LARA ЃE"E$EI8O :bfs]޷oNʣjՇZW*Fձ>s䋂ј ?H^ŏ4閷2v;``6^/)ኾti[-R;N*b[in"K<^ooO3htM&KۋlrU#e___3˧Cwj\Pw; -`;5*I^8Ǡ_꺏s`8W`eT Ul1CaSg?k]v*UثWb]"hk1D]^erkJbq}eyOq&d6%Xc#LUNyA]|jYi(1D|1W(9p,*:A^+eR'կYh:4'a?jtL NGn R~R~XK&~-#:uqWOɞSC"l(#|鰑4jTxU5kHu[=& :nX*Oʯ,KO/Αװ.y#_?S7ǗWomQ/ j]2;⯩B^4zq*rtZWYIMPPh)Oo-aX<[@5_3^mٵVZ'#}84=&Xogԑ\C|+\Uj"U @1VBZL 6*~տ3ot_CXӪF8 b<$W8fG۸5xlUK:ƧX޴i;b}*BKb bI_FU@T_tkz}b{QhGX.qW1Qs4#4W&;6N*ŮŘ:튿R h|nNH j.6%64 zoҞثO#>|s<=xŒ{ U[~l_>|׵Zc3-IJF (=QNث#3^2N*o*/,|3 (OM?]tH`_F4x^*y>h=M9Z|Mv?%?<۽}jxi\jF%KX~s~Q6'g|{u @}QBu(/, [+ȬN Di=%-Q SMK!%,4|U9([Y4,^P&&_?~x[u$Kvhw;Ta8Ʃ-/bG1C_/^>mߴP@xF⯠*7rV.ULH;r$ӽ_~<*J`_ Gኾ;=N*!4}ky=TK޻pP|/2 ]vh⯻ 8Y]t帖=*֎W3r/y&%E'~6~bZ.K=*UHV_wi$W*^?_?wnz=hzl!A_Q5UT0v@:ݕEY*lgŤ*.nFX Sܚ U~fi olOK!54_ԊYr^ *+Sk/iFU;Ƙ{oɠycN!%܇qƟg'_󖿞z>]Y[L,{廛p!ZUGثPKۉru; U?XWM_WǦZwI +ܑJ'sXܤt"B;|⯹u/9:hj <7܊U<5a\+7ꑴZ>D?^.RfY\I'>*<;4j1[YNʪ'}gi~]6>]ښ\HjFۓm<1Wڇ g˿mcۿ|/X5^νt]NpO~|F29ПՊU|qYb]-]ŕVNWWF[*k,Ƶw:e2]\mG>xJѰV#NypSG}U`XeH֞'}Ot+;31X 1VZRȃn4V*]KR8eħ~sI5&v*Uy3WpJLUֺՈP(x*UثWb]v*vw'$Z04*G˟h8@Q,d ;V#gi:(VI*U/5~8WGڍΙrVT~x sŚQԷ`qn4+$voxig6aث;~pjz-+3՟eS:fCV'Cb~pӘd 3ZrPӱbOƿ >AEʅ8P 8#be:YIB"MkJ b8/o:Fd Pz/̯?yR@; UqW]y_.=U8?9]})i>ghr$=JN]I䶲z"ͯK+] dgRwuTP*29XkNyO.h@*Кӹ=bѭ>v§o֧[-v_/ޣqSEbzZ~ϼ"/jfI)ʀ9ItdYy%"TG<\Us\ř|*kj~ZK[nH\?qW?_cLD?XӬuS3}~͞V<5r4R,rb@G_(y~oY0U\@*ibI\U93aqpKc_S~xO>ynx▫ɈCoWϷ4H`|*U~HZjnnt_)+gjT"}Wi__`rXi[IɎbV'U *20|I_+kjTPHnd|W<us-'#p88y$j~mJ U ʼnbw;^vkN^R3]`'*¼׫~yEm h$h*QW?$[s>qˉzƱNU9A9_͍r bqDRjrqW|.+O"kCQ_*Ϟ*p*Ǜ| >\G''`"$wPz˰}^LdX"E tS~m|x\򮒉&U@N=sc1U/-t/.e{mދs|3]:&I zlW|u#;K,bzWI5'^A ?yNNʵܜUzE+ :L<.Y,rv#WFZy̲鱺Z UUQ@*ϟoϖ5Լ4f=KXJGCv_pޡknynU$;$IqT~\j6dw {⯪eo[4E޹s7VH>Њ^!i<{fvX+}m(t& wf9Zi|$ ECG*X֩urČĒ{Wa튼v*&hPAi6(h{*1V W7ڬ1bQjE^KM:$X|u4:X[Gc1zYL1ZӶ*ծۄ"U=֫3r }ت[T%~m#LG*]v*UzWb]v*UثWbv*UثWb],ҢITT$jOSv*U3GL$ܴAT⬪ WW(fmX-KXvkx_HWbTRC)#YߗUe$S[#HA*1U`YJ#7/"OኼPn *5;GBzH'sZY=G@I&e+@{x|WC4[}ݩSX"MX ¦Wjki{5 4aK$^F,Y/%?jVeb%NWlUzf/&Z#3 Z׊.SjRΕ\Uk>f1gFqVqu=?"{R~t#kEO[ӯdY䏈eu^45?:b_ȯ3m."W"aPث/rg+̷ɮ!q@:1W^jƷ_ZPzq7B&JScU$]h?D?Mz;⯜?<??i|;⫱Wb}g8wU}~تeRngXzZ]zg{b2M/o8O>SWbUmQӯ\UŃu]1WybWbwUkي[]v*UثWb]v*UثWblibtuxcap-1.4.0/tuxcap-build/images/heroDamage_.jpg0000644000175000017500000000110210751375104022127 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C "(A!aq1Q ?ưE$$0| <"6ĸM:' ޭݔX~)ÈH`~ z.m-cwU B_c";C1 'T^eZ^?@tlibtuxcap-1.4.0/tuxcap-build/images/bigcanvas_.jpg0000644000175000017500000052614610751375104022054 0ustar inniyahinniyahJFIFHHExifMM*Created with The GIMPC  !"$"$CX "8!1A"Qaq2#$BRb%3C ? 9NٶFI|i,< !*4wh}K}6gTjbyɊI †$!5=<:J<2aX[br<UX(f2I@LWFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJg~&fț+M5np>{6HNN"P)Z _{iN*uQ[kLOP޵VDC2PL,$0! rG<Mq\䔊-i,|w8J6T͑(+e;Ab*"Ui8r/Pz9A o'w9uW$6BYszC e*6`Q M|q!c˰&c5z P4cq{wy:cU,O H##E}uqG1!1}$J5HRxF'ǷbdT|Z&_1EU4h^Q,4o'?PHoL|Ɇ#SƁ Ψy`XMtd"=v VlӠ3 7r#oBIboԗir<ݎ1%pJv܀wkG/N(f/tߍ+AT&-(_Ƈ#1@!efL̹tHƕ< ~k'g",Q7*@hI C f!Ȓů|p~5>*nryk.8PcyB*&[$йeIO1p }>2$Y +SRC^+m)%N 6mi⽾{~{֪ȖHr&S; 8}紐=T>Ѻbg eK{tȒY%A$lbDl@yA(i7Uv(_$wҷ&>rdȑ)@ˆ|w?TeJ,J&:d2CX;ǎqFC6Bn `߷OYsI!L1KKH^xHȍD Z%;n@l{5rʗlOQ|ƃMO`RTQ /CuVld2f _Bf\R$@Jځv?~5`c(rz 4 R!3Ib׀x>8?Ol|`C[f 79<5 (ImX\wfh\'Xظ|羃ddd,╩Щ!綔Pqն oq^==UdK$9)HP$sαIH"Ȗ1˼oW~81c}d3eOrfS"r.V!"8%yߏ7zay#gUrKcd(.\Eܟ7O0LfXrf 2H=V<Rn>?zY',^%@7qǓa4S68ǑVqueamGn+A+cdǻ71"r?ϲg7W|ތL\CL{/z=ΙK$#Yč,@Gna[{y{x&)HeHȍhU]@||V(1#FsA $VL`Y8Fxc<*?}PF⏛щ<2cKCc/eG""Idk8+o~O=o2 Mbh2YhN#5Uء$Jߐɓ "G Q+L(, E `{H;; @Mƭ 7Afn5G~m=g$3Ɠ$.ߩ.y!y#"7cJ+!h1ʏ*^Q<_!F, ; V36L[=+[EIQDP4FcǙY(C.Ι r&H+x";jaN uݬ ʢl3{@ 㚾u;nH@D2G=XYR߭Ud|]77 +&|ߍ&h^pM> ( 䊾?Slc$D:37U io#%UB}FEUJhy3z{H1ӝ`+/mld)gJekT}ua%JLxam׹mTPǁr6I7n1zJ#*(<'eFP "ׂynC<sDeL٬`iGOYUtF'(hڢI_4ʯtL93P.Fht9 7Z,h}Jo(-[ B;*cC0g6ak.|GI9biuؾl@m` edcel3ǿ$דG<ɚ0$;Vl o~<ILt R/ȳ۵ ,2ŞEĬ:j=w ia̠."Af dCBmBkk8CӜfTpO5<t(A}72ƱVGnY~ra>TMQcboh#@sWΧm(X`R2^q+*W\; >okRA&fx7D⯛ ю)GbR ;zslq~Et͗ "X̶ w[*s΢#cdBL4ͺ-B>uNCF&/_v2I]q\|w~EG}ATZO=֨g#.h)5, 0ctK"JE8_TI"KZ9UDrd Ƭ|LOVve(PI)lUO X"q X;O#Τ  oD`%}DΉ9&` %;Á.?AZEMRޘSpE4 q\ G~ڥLxf'n9GsO(BVrI=C⽼Z2u3"M";͈6ylc,9m1Z&s"x$#{hǙ3P&j̈́wǟA> X )!]E{vAuX]豘P-Qnz,=9Ut l!h^#PPIdV UYȢ< j$I~ҫG*(LVՏ: ۣج 8e#͊]A4 d@w.3KiyԁX!r Hh? 3;BĻyp9;h+@hI*[x PQHn8 HT9 xلmU r(tBVI'|Wk@NdQAGbѵ?"Ϫcp:0% <}06ܶ(] 9 $}%vqhm|Ҳ(lrMSk<7ZL2Ħlc z`4#F? ,a*K#YP_XmQ$/UhW%ɒߠwA2=[tayA' yVkKzcOs|j7I-!qWۿj1g!c0MXE5Ηq>HX Y$Mh̊14:_6 @6q΅r1Hh̊Uؒlkd@R6}7mxct$J:w)Yڇ}΍֖bYwcbV@Dvs4PUJ @t!xrBK6֡~~5!Lbx\*8': cX+#ʷ]?} 0l&(17 9SC, )pX/hs8Ո+HVI 5Q) q{`¼hqWBf  #RHu9&2AJ3uX8nU^'dYTv\QC7)@9޶ ":vfˆBFf[G9QF\tǏf{E |x:!dv$8>?mςzV\te Ib-x'T3ɑ4FX͚axL1|:AA%ZL%WIdbz" /$%JĢ92Y[V>O&Sn;bxO($ᔏ6*vӧ~,mܸ,R`7"0y@cDc0 aCu&ԩoL})@F".?jw#mR+?c@(fc"; W_9N pR(`uG<(66K.Lۯrڨt/T4lnbc$GwTQx9OJˎ7LEjy22Y/+5s'S2( #|؁hǟ<:2˓#g2)WbI9' y5aJ.HvA{hy +(ܤ_gj:7ZXe=eݎXu{ә@\EWI(І"5 ,Z@p91=r̨8ky$Nj*)P't2E%~x$y5E#JIux<}&I Y&6Y @W$_ȭY+|6S'"Hrh8;ↀ0nU͌I"C}i{ƨP{5ɝ#aGlr)j[|/4-o"tB*Q<`68oz#w7YѤF-ӟh͏c'YMr,O矝f4$FwaXh_54*9xVe~;h gMfUVAx>`iE] 5iAycr!L[[^f'MFD9R 9@$|bh*B {0꒮reaLoqlPTWݵ #4q:u?8߾$dDBeY;4/9fD.JJ-"cf}Wo'm6G2*lgf98FF;vbµ v# c9kj 9\ečtx|hJPHhUxNc-п? yf޹HTxWظqS,-9je/7۝*6("]ԭ oz3e4w]D?C<9 $["GI9nA<1Y [y^9=ǎup$ c$Hzaq]wqdITROdJI kƋG ,ExL*A,LLl&A  HZ*WlldNDq\w} a$ܫD8P<kE:G92`SԷ_o^h[wU2DU yT+lq4Rq2#F>ɻA$n!)H[>+۽} ,G rՏ5As(ˎ !n*&pJHgu[~I:ͽsd Cg/Y p+4NYL[rD_no:TmQdE42 #Zo50f%i=L W">57㑠>(xfD"I71H<?~uĒUɅbT!~Ǜ53"FY 8^<&CG!6!UYut( o< E!Ȇ1nƍmzEϝ6GHvz+ *8o rQƌ H(9÷Jɖ11%űARۅ]v(K`UXn~vr8Ui5 cdо8AL)+䴉Q \mTȩi@_ |+!X-#x=?k 1rSQC#6TM*A#cOU9PB)uzӆ-" Q5_^bViOl婖nt(ȊhetGR2,kA`͕Kzw+HE@|jo#A x.D=l&PT~Oh<gl2t^2N=mx9q`-"Ƶu;Ɓ&2m+0BmU/T73O"/& Qx7HC bݍ 7?:mB2%ʐVUqA#EP @QsهoTs,+bcKb UvQf7V7Ө9q'$&j(v|qփ2'șrRWi3>>;i~Ab>.8$F$m@U‚FƟcE*"s֡nS$6͐/ ZE Şj8d&6ÌҟM9e1nS-}QQE$hds|Xփ+O!3dV5_&OF\ z:Lr ьx"ddz^tڄdKӕ!0,4GF.&2 ߾*&XV(KnwP3A.́WnosPscO VIL&QB㛭dO2䤯&9Fg.5q| |vdyS"vcdci~++Xq(ib8NP88|}N9F\pI HwGƁQ4>ƊUWD;;B Im _N(G<|qzLmY>rbݳZ"s}ңh")IJ>;y6W,>CIguȭ jqM񩾟1Ð@$tCQ<EQx8޼xQM2DDeE*$H&hDqzi[| I0ίPx2K4"dP2vϞXfq6DIM~7PMʹ$Ho3pq `x&P93q#S(V=Ku%慷u_#!-NEP LM/W">n<4F"rZ4źsٱ@s2!IPA Ɨ~$L+ҡ &Uߝ6&G><ٯ4̼o|m!29 ɴ =TOGPޣ9cLJ!r$dH2-'xF1?a>qo+'xΣldL.5q}?n4 1ʊT"6I I_ $MwbҶ@a!^?hIeH%iD$U+VeJ<͔lȒ+o 9scHZg㱪MhrgHG"Q {Z:K nFB>4[ȝTA<5%w͎&^9D}y7|hX3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉG2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6B~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>G2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^9#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)o:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x> r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"tb:%\~KRFzyʍP/.V4rZ)鵏ߚ[:L#& %*#?Yp5j@QقV@Y+|=9LPGƄF@> :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΀ 2@aTd 9XƵG"9sY O"t3#" [lo(V;EWkd#"l7I6.5#Y:Y;$!@xjt*H`k|y:ĩ!Fum1=B[WozYDgyA0<5y5ssR(Hr%LrUߎ4 XY+S6D"6\Uz"8}紐=T>Ѻbg eK{tȒY%A$lbDl@yA(i7Uv(_$wҷ&>rdȑ)@ˆ|w?TeJ,J&:d2CX;ǎqFC6Bn `߷OYsI!L1KKH^xHȍD Z%;n@l{5rʗlOQ|ƃMO`RTQ /CuVld2f _Bf\R$@Jځv?~5`c(rz 4 R!3Ib׀x>8?Ol|`C[f 79<5 (ImX\wfh\'Xظ|羃ddd,╩Щ!綔Pqն oq^==UdK$9)HP$sαIH"Ȗ1˼oW~81c}d3eOrfS"r.V!"8%yߏ7zay#gUrKcd(.\Eܟ7O0LfXrf 2H=V<Rn>?zY',^%@7qǓa4S68ǑVqueamGn+A+cdǻ71"r?ϲg7W|ތL\CL{/z=ΙK$#Yč,@Gna[{y{x&)HeHȍhU]@||V(1#FsA $VL`Y8Fxc<*?}PF⏛щ<2cKCc/eG""Idk8+o~O=o2 Mbh2YhN#5Uء$Jߐɓ "G Q+L(, E `{H;; @Mƭ 7Afn5G~m=g$3Ɠ$.ߩ.y!y#"7cJ+!h1ʏ*^Q<_!F, ; V36L[=+[EIQDP4FcǙY(C.Ι r&H+x";jaN3dB#e NXȺZN#ĔPC[~w՞h\{|Qz13Lira o2_:dI,g6T"m@Y!#"6VWQUwZAFrU&ɋ~'zk`h*(x:6P2Eb`3{ٯ{y!3.D) qtGrm@;Lj1M9 d©r$k<j>Ds0!ʳEfFEˎ$Pv 34.FD_n l\v>kAGtvIBJT׊JuSBZbzoߞ%aa$y(k9kX$PmKLf7ޫh>WlDlAX3) V9BIÐDxkyoF&pɍ.Q !_ԽL%TFʖ #B70<=h$2sF4 *>>+Gfy9 WbG}+~Bc&L0,B4 ((WsuF[2ĢhC 5#x7M4o3d,ޝa}4ϏL~Kt(I)+S۸#\*~&fț+M5np>{6HNN"P)Z _{iN*uQ[kLOP޵VDC2PL,$0! rG<Mq\䔊-i,|w2u3"M";͈6ylc,9m1Z&s"x$#{hǙ3P&j̈́wǟA> X )!]E{vAuX]豘P-Qnz,=9Ut l!h^#PPIdV UYȢ< j$I~ҫG*(LVՏ: ۣج 8e#͊]A4 d@w.3KiyԁX!r Hh? 3;BĻyp9;h+@hI*[x PQHn8 HT9 xلmU r(tBVI'|Wk@NdQAGbѵ?"Ϫcp:0% <}06ܶ(] 9 $}%vqhm|Ҳ(lrMSk<7ZL2Ħlc z`4#F? ,a*K#YP_XmQ$/UhW%ɒߠwA2=[tayA' yVkKzcOs|j7I-!qWۿj1g!c0MXE5Ηq>HX Y$Mh̊14:_6 @6q΅r1Hh̊Uؒlkd@R6}7mxct$J:w)Yڇ}΍֖bYwcbV@Dvs4PUJ @t!xrBK6֡~~5!Lbx\*8': cX+#ʷ]?} 0l&(17 9SC, )pX/hs8Ո+HVI 5Q) q{`¼hqWBf  #RHu9&2AJ3uX8nU^'dYTv\QC7)@9޶ ":vfˆBFf[G9QF\tǏf{E |x:!dv$8>?mςzV\te Ib-x'T3ɑ4FX͚axL1|:AA%ZL%WIdbz" /$%JĢ92Y[V>O&Sn;bxO($ᔏ6*vӧ~,mܸ,R`7"0y@cDc0 aCu&ԩoL})@F".?jw#mR+?c@(fc"; W_9N pR(`uG<(66K.Lۯrڨt/T4lnbc$GwTQx9OJˎ7LEjy22Y/+5s'S2( #|؁hǟ<:2˓#g2)WbI9' y5aJ.HvA{hy +(ܤ_gj:7ZXe=eݎXu{ә@\EWI(І"5 ,Z@p91=r̨8ky Pnec*viu[U.|꜆Mی^dH 6> Yqє69&{P&F\bS6k1=0X`Ǒ#Ei0]%,(p/,D *reo@;X?O0Q5$hhAJ1Y獘O&[r"K$,Qhz{x&dfEDDv/ mX8ǁBY9Yrr$bLE*I6G52fL)E՛>m_?<}@:AS%eC,CgFK gc1+Z~;9Xzs( %A٠CY:м9DFzx%kPu&1 c|ȭ&1=EEExHAVUyQ,q't)շFYJ<'pGfiă?`h6Ȁ\fs@B` _p< ~Agv1ɘwN0s@ vVcFCT>?ƣyDm q5}߶S6r0+< ۺu@Q\w$<OPoց̝LȣHb k~x<[+'#.N[dVȥ^=&漞81L (!ڳakG?H2JdH`r~Eݨwlia,v:,f%a TAo۾`^3KNeq]$ 4k'B(/Omj_?7]'2x7,B#d=A(/M+o &Y?o&TX fdLA \"fT N&Ȝ!ɠØIW61$ q;@y֊&t9r*en߽жd#ED_W|idG܍}wƂHdBS+FN}W{6>>(xfD"I71H<?~uĒUɅbT!~Ǜ53"FY 8^<&CG!6!UYut( o< E!Ȇ1nƍmzEϝ6GHvz+ *8o rQƌ H(9÷Jɖ11%űARۅ]v(K`UXn~vr8Ui5 cdо8AL)+䴉Q \mTȩi@_ |+!X-#x=?k 1rSQC#6TM*A#cOU9PB)uzӆ-" Q5_^bViOl婖nt(ȊhetGR2,kA`͕Kzw+HE@|jo#A x.D=l&PT~Oh<gl2t^2N=mx9q`-"Ƶu;Ɓ&2m+0BmU/T73O"/& Qx7HC bݍ 7?:mB2%ʐVUqA#EP @QsهoTs,+bcKb UvQf7V7Ө9q'$&j(v|qփ2'șrRWi3>>;i~Ab>.8$F$m@U‚FƟcE*"s֡nS$6͐/ ZE Şj8d&6ÌҟM9e1nS-}QQE$hds|Xփ+O!3dV5_&OF\ z:Lr ьx"ddz^tڄdKӕ!0,4GF.&2 ߾*&XV(KnwP3A.́WnosPscO VIL&QB㛭dO2䤯&9Fg.5q| |vdyS"vcdci~++Xq(ib8NP88|}N9F\pI HwGƁQ4>ƊUWD;;B Im _N(G<|qzLmY>rbݳZ"s}ңh")IJ>;y6W,>CIguȭ jqM񩾟1Ð@$tCQ<EQx8޼xQM2DDeE*$H&hDqzi[| I0ίPx2K4"dP2vϞXfq6DIM~7PMʹ$Ho3pq `x&P93q#S(V=Ku%慷u_#!-NEP LM/W">n<4F"rZ4źsٱ@s2!IPA Ɨ~$L+ҡ &Uߝ6&G><ٯ4̼o|m!29 ɴ =TOGPޣ9cLJ!r$dH2-'xF1?a>qo+'xΣldL.5q}?n4 1ʊT"6I I_ $MwbҶ@a!^?hIeH%iD$U+VeJ<͔lȒ+o 9scHZg㱪MhrgHG"Q {Z:K nFB>4[ȝTA<5%w͎&^9D}y7|h$D 2it{wcXdB$s` $<Y.I%QV)Z=BMp.:lMʎ|y^3;n$iUx ߺ=.Bd4riYU{j.zGX9y~0WBl@@t^X`ShרYIj,?NTg¨G %,hʀP#;~aXs\[-U+mB6\AΝAŎg#>%Y&3PF0N n>D˒KH`.MLَN;ݤدa¼9B7@F c!8q$21#m8DҮ64)U^) t/ži'Yl}8b(pU,U!1.efi)vZhJ,WA$u+@  _İ:x '{"Q4Ʀ|r4ǏBIȑe[O5Gc~6'@}E$WOzG 6*\kW]~>hcŕDlǺ"<H<m$C :~C㾓$ʐK,,H B/Vʕ>ya)$94WqC@s 7*$!=cT(=@Α0EL9X-t||h:!Btxk0JM7Խ\s̈|nIAeh#ϴfEȄI&9BIx'γ]J;0R{J/ؚ]W~tؚffvHҫ2Au ǐz\h3&ҳ* Q<]Czs4"B`؁mg} 輱9-ѭP|#"XEaQ`>J1q4Xѕ G=vIW92°&7D(*[p\Wnڅ vl uc{: oNG}@JM"f2`,`h3"|%%|13>q]㶛#ʙ63w ##H _aZÏyD;Kroǵ5cd@.Cq2HdbFۺ

4 \($li4RR'1j_32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV# bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6B~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>G2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6Bo:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)o:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x> r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"tb:%\~KRFzyʍP/.V4rZ)鵏ߚ[:L#& %*#?Yp5j@QقV@Y+|=9LPGƄF@> :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x> r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ýH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}:R!3Ib׀x>8?Ol|`C[f 79<5 (ImX\wfh\'Xظ|羃ddd,╩Щ!綔Pqն oq^==UdK$9)HP$sαIH"Ȗ1˼oW~81c}d3eOrfS"r.V!"8%yߏ7zay#gUrKcd(.\Eܟ7O0LfXrf 2H=V<Rn>?zY',^%@7qǓa4S68ǑVqueamGn+A+cdǻ71"r?ϲg7W|ތL\CL{/z=ΙK$#Yč,@Gna[{y{x&)HeHȍhU]@||V(1#FsA $VL`Y8Fxc<*?}PF⏛щ<2cKCc/eG""Idk8+o~O=o2 Mbh2YhN#5Uء$Jߐɓ "G Q+L(, E `{H;; @Mƭ 7Afn5G~m=g$3Ɠ$.ߩ.y!y#"7cJ+!h1ʏ*^Q<_!F, ; V36L[=+[EIQDP4FcǙY(C.Ι r&H+x";jaN3dB#e NXȺZN#ĔPC[~w՞h\{|Qz13Lira o2_:dI,g6T"m@Y!#"6VWQUwZAFrU&ɋ~'zk`h*(x:6P2Eb`3{ٯ{y!3.D) qtGrm@;Lj1M9 d©r$k<j>Ds0!ʳEfFEˎ$Pv 34.FD_n l\v>kAGtvIBJT׊JuSBZbzoߞ%aa$y(k9kX$PmKLf7ޫh>WlDlAX3) V9BIÐDxkyoF&pɍ.Q !_ԽL%TFʖ #B70<=h$2sF4 *>>+Gfy9 WbG}+~Bc&L0,B4 ((WsuF[2ĢhC 5#x7M4o3d,ޝa}4ϏL~Kt(I)+S۸#\*~&fț+M5np>{6HNN"P)Z _{iN*uQ[kLOP޵VDC2PL,$0! rG<Mq\䔊-i,|w8J6T͑(+e;Ab*"Ui8r/Pz9A o'w9uW$6BYszC e*6`Q M|q!c˰&c5z P4cq{wy:cU,O H##E}uqG1!1}$J5HRxF'ǷbdT|Z&_1EU4h^Q,4o'?PHoL|Ɇ#SƁ Ψy`XMtd"=v VlӠ3 7r#oBIboԗir<ݎ1%pJv܀wkG/N(f/tߍ+AT&-(_Ƈ#1@!efL̹tHƕ< ~k'g",Q7*@hI C f!Ȓů|p~5>*nryk.8PcyB*&[$йeIO1p }>2$Y +SRC^+m)%N 6mi⽾{~{֪ȖHr&S; ?mςzV\te Ib-x'T3ɑ4FX͚axL1|:AA%ZL%WIdbz" /$%JĢ92Y[V>O&Sn;bxO($ᔏ6*vӧ~,mܸ,R`7"0y@cDc0 aCu&ԩoL})@F".?jw#mR+?c@(fc"; W_9N pR(`uG<(66K.Lۯrڨt/T4lnbc$GwTQx9OJˎ7LEjy22Y/+5s'S2( #|؁hǟ<:2˓#g2)WbI9' y5aJ.HvA{hy +(ܤ_gj:7ZXe=eݎXu{ә@\EWI(І"5 ,Z@p91=r̨8ky Pnec*viu[U.|꜆Mی^dH 6> Yqє69&{P&F\bS6k1=0X`Ǒ#Ei0]%,(p/,D *reo@;X?O0Q5$hhAJ1Y獘O&[r"K$,Qhz{x&dfEDDv/ mX8ǁBY9Yrr$bLE*I6G52fL)E՛>m_?<}@:AS%eC,CgFK gc1+Z~;9Xzs( %A٠CY:м9DFzx%kPu&1 c|ȭ&1=EEExHAVUyQ,q't)շFYJ<'pGfiă?`h6Ȁ\fs@B` _p< ~Agv1ɘwN0s@ vVcFCT>?ƣyDm q5}߶S6r0+< ۺu@Q\w$<OPoց̝LȣHb k~x<[+'#.N[dVȥ^=&漞81L (!ڳakG?H2JdH`r~Eݨwlia,v:,f%a TAo۾`^3KNeq]$ 4k'B(/Omj_?7]'2x7)B 鹖5> uݬ ʢl3{@ 㚾u;nH@D2G=XYR߭Ud|]77 +&|ߍ&h^pM> ( 䊾?Slc$D:37U io#%UB}FEUJhy3z{H1ӝ`+/mld)gJekT}ua%JLxam׹mTPǁr6I7n1zJ#*(<'eFP "ׂynC<sDeL٬`iGOYUtF'(hڢI_4ʯtL93P.Fht9 7Z,h}Jo(-[ B;*cC0g6ak.|GI9biuؾl@m` edcel3ǿ$דG<ɚ0$;Vl o~<ILt R/ȳ۵ ,2ŞEĬ:j=w ia̠."Af dCBmBkk8CӜfTpO5<t(A}72ƱVGnY~ra>TMQcboh#@sWΧm(X`R2^q+*W\; >okRA&fx7D⯛ ю)GbR ;zslq~Et͗ "X̶ w[*s΢#cdBL4ͺ-B>uNCF&/_v2I]q\|w~EG}ATZO=֨g#.h)5, 0ctK"JE8_TI"KZ9UDrd Ƭ|LOVve(PI)lUO X"q X;O#Τ  oD`%}DΉ9&` %;Á.?AZEMRޘSpE4 q\ G~ڥLxf'n9GsO(BVrI=C⽼Z2u3"M";͈6ylc,9m1Z&s"x$#{hǙ3P&j̈́wǟA> X )!]E{vAuX]豘P-Qnz,=9Ut l!h^#PtڄdKӕ!0,4GF.&2 ߾*&XV(KnwP3A.́WnosPscO VIL&QB㛭dO2䤯&9Fg.5q| |vdyS"vcdci~++Xq(ib8NP88|}N9F\pI HwGƁQ4>ƊUWD;;B Im _N(G<|qzLmY>rbݳZ"s}ңh")IJ>;y6W,>CIguȭ jqM񩾟1Ð@$tCQ<EQx8޼xQM2DDeE*$H&hDqzi[| I0ίPx2K4"dP2vϞXfq6DIM~7PMʹ$Ho3pq `x&P93q#S(V=Ku%慷u_#!-NEP LM/W">n<4F"rZ4źsٱ@s2!IPA Ɨ~$L+ҡ &Uߝ6&G><ٯ4̼o|m!29 ɴ =TOGPޣ9cLJ!r$dH2-'xF1?a>qo+'xΣldL.5q}?n4 1ʊT"6I I_ $MwbҶ@a!^?hIeH%iD$U+VeJ<͔lȒ+o 9scHZg㱪MhrgHG"Q {Z:K nFB>4[ȝTA<5%w͎&^9D}y7|h$D 2it{wcXdB$s` $<Y.I%QV)Z=BMp.:lMʎ|y^3;n$iUx ߺ=.Bd4riYU{j.zGX9y~0WBl@@t^X`ShרYIj,?NTg¨G %,hʀP#;~aXs\[-U+mB6\AΝAŎg#>%Y&3PF0N n>D˒KH`.MLَN;ݤدa¼9B7@F c!8q$21#m8DҮ64)U^) t/ži'Yl}8b(pU,U!1.efi)vZhJ,WA$u+@  _İ:x '{"Q4Ʀ|r4ǏBIȑe[O5Gc~6'@}E$WOzG 6*\kW]~>hcŕDlǺ"<H<m$C :~C㾓$ʐK,,H B/Vʕ>ya)$94WqC@s 7*$!=cT(=@Α0EL9X-t||h:!Btxk0JM7Խ\s̈|nIAeh#ϴfEȄI&9BIx'γ]J;0R{J/ؚ]W~tؚffvHҫ2Au ǐz\h3&ҳ* Q<]Czs4"B`؁mg} 輱9-ѭP|#"XEaQ`>J1q4Xѕ G=vIW92°&7D(*[p\Wnڅ vl uc{: oNG}@JM"f2`,`h3"|%%|13>q]㶛#ʙ63w ##H _aZÏyD;Kroǵ5cd@.Cq2HdbFۺ

4 \($li4RR'1j_`iE] 5iAycr!L[[^f'MFD9R 9@$|bh*B {0꒮reaLoqlPTWݵ #4q:u?8߾$dDBeY;4/9fD.JJ-"cf}Wo'm6G2*lgf98FF;vbµ v# c9kj 9\ečtx|hJPHhUxNc-п? yf޹HTxWظqS,-9je/7۝*6("]ԭ oz3e4w]D?C<9 $["GI9nA<1Y [y^9=ǎup$ c$Hzaq]wqdITROdJI kƋG ,ExL*A,LLl&A  HZ*WlldNDq\w} a$ܫD8P<kE:G92`SԷ_o^h[wU2DU yT+lq4Rq2#F>ɻA$n!)H[>+۽} ,G rՏ5As(ˎ !n*&pJHgu[~I:ͽsd Cg/Y p+4NYL[rD_no:TmQdE42 #Zo50f%i=L W">57㑠M\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PGC*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6B~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>G2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6B~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>79F!`^ .*o4T~ý٭-`cb3ɹ@t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)o:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)o:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I r$rb,4wqG.D vMx(&w)t޴'˒QI`InYT&Tsd%XntdI }aRDWՙ,%wʦhn:$QGv+$ʉw*O9S 1G4n r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"tb:%\~KRFzyʍP/.V4rZ)鵏ߚ[:L#& %*#?Yp5j@QقV@Y+|=9LPGƄF@> :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x> r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"t )"Bqmѱmh_d(-eH`; u}l8RM=uڸ9^~NR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5,z)u \`_9Hbߊ*ˆ%SŐ&A`,q!<\i)F'ڨ=+,~7YTbKGP"K A v4 ֞%K+况4ɄfA ͊$;: ~d;C,o!}/cn7$(;fMv&kHP$7PÅ.aٝS] 5Ɨ&(|Y$H3 8`W`<(@e!b9o_Chj^VybH&8 au2\ |2O$eH \9K>4[ XXQc_`y΂,'"R U9[Sd-bU>Yj" 2eƞ$jb~}R C~%A!$oh(RB2|@XP@#5@x҉gƉga(1Wp <8Ӿ$`d̋<{oHdfU#`=> v qeJD\.%1,x}L48}q W"!Btj$4&G Hq+{`8A81gS 𺞅-QE_:bE2WS.~/9?aY&twukSGwZdXxXgÒHb rE< a΃%HQ_ X>uLFBErC} ~43u$$8` Gc@i_I$T36`9ov7!|r|XC ;B8ƻcRQ;PL|Fdؠ1CmNR$ Xr#;Xܦg,a〦7S  γ+TKLvT0MÛZTE0 `ڕ)5$H@C%^kT}=#/G1 nU0/C022.\p%cUpMϟIr2&t`cb\ <|eHVBWǞSJBmV%{|U,Lw #yC\\W:9%"oG"Zd. 1_@Ŏ1͕>3dB#e NXȺZN#ĔPC[~w՞h\{|Qz13Lira o2_:dI,g6T"m@Y!#"6VWQUwZAFrU&ɋ~'zk`h*(x:6P2Eb`3{ٯ{y!3.D) qtGrm@;Lj1M9 d©r$k<j>Ds0!ʳEfFEˎ$Pv 34.FD_n l\v>kAGtvIBJT׊JuSBZbzoߞ%aa$y(k9kX$PmKLf7ޫh>WlDlAX3) V9BIÐDxkyoF&pɍ.Q !_ԽL%TFʖ #B70<=h$2sF4 *>>+Gfy9 WbG}+~Bc&L0,B4 ((WsuF[2ĢhC 5#x7M4o3d,ޝa}4ϏL~Kt(I)+S۸#\*~&fț+M5np>{6HNN"P)Z _{iN*uQ[kLOP޵VDC2PL,$0! rG<Mq\䔊-i,|w8J6T͑(+e;Ab*"Ui8r/Pz9A o'w9uW$6BYszC e*6`Q M|q!c˰&c5z P4cq{wy:cU,O H##E}uqG1!1}$J5HRxF'ǷbdT|Z&_1EU4h^Q,4o'?PHoL|Ɇ#SƁ Ψy`XMtd"=v VlӠ3 7r#oBIboԗir<ݎ1%pJv܀wkG/N(f/tߍ+AT&-(_Ƈ#1@!efL̹tHƕ< ~k'g",Q7*@hI C f!Ȓů|p~5>*nryk.8PcyB*&[$йeIO1p }>2$Y +SRC^+m)%N 6mi⽾{~{֪ȖHr&S; 8}紐=T>Ѻbg eK{tȒY%A$lbDl@yA(i7Uv(_$wҷ&>rdȑ)@ˆ|w?TeJ,J&:d2CX;ǎqFC6Bn `߷OYsI!L1KKH^xHȍD Z%;n@l{5rʗlOQ|ƃMO`RTQ /CuVld2f _Bf\R$@Jځv?~5`c(rz 4 R!3Ib׀x>8?Ol|`C[f 79<5 (ImX\wfh\'Xظ|羃ddd,╩Щ!綔Pqն oq^==UdK$9)HP$sαIH"Ȗ1˼oW~8'S2( #|؁hǟ<:2˓#g2)WbI9' y5aJ.HvA{hy +(ܤ_gj:7ZXe=eݎXu{ә@\EWI(І"5 ,Z@p91=r̨8ky Pnec*viu[U.|꜆Mی^dH 6> Yqє69&{P&F\bS6k1=0X`Ǒ#Ei0]%,(p/,D *reo@;X?O0Q5$hhAJ1Y獘O&[r"K$,Qhz{x&dfEDDv/ mX8ǁBY9Yrr$bLE*I6G52fL)E՛>m_?<}@:AS%eC,CgFK gc1+Z~;9Xzs( %A٠CY:м9DFzx%kPu&1 c|ȭ&1=EEExHAVUyQ,q't)շFYJ<'pGfiă?`h6Ȁ\fs@B` _p< ~Agv1ɘwN0s@ vVcFCT>?ƣyDm q5}߶S6r0+< ۺu@Q\w$<OPoց̝LȣHb k~x<[+'#.N[dVȥ^=&漞81L (!ڳakG?H2JdH`r~Eݨwlia,v:,f%a TAo۾`^3KNeq]$ 4k'B(/Omj_?7]'2x7)B 鹖5> uݬ ʢl3{@ 㚾u;nH@D2G=XYR߭Ud|]77 +&|ߍ&h^pM> ( 䊾?Slc$D:37U io#%UB}FEUJhy3z{H1ӝ`+/mld)gJekT}ua%JLxam׹mTPǁr6I7n1zJ#*(<'eFP "ׂynC<sDeL٬`iGOYUtF'(hڢI_4ʯtL93P.Fht9 7Z,h}Jo(-[ B;*cC0g6ak.|GI9biuؾl@m` edcel3ǿ$דG<ɚ0$;Vl o~<ILt R/ȳ۵ ,2ŞEĬ:j=w ia̠."Af dCBmBkk8CӜfTpO5<t(A}72ƱVGnY~ra>TMQcboh#@sWΧm(X`R2^q+*W\; >okRA&fx7D⯛ ю)GbR ;zslq~Et͗ "X̶ w[*s΢#cdBL4ͺ-B>uNCF&/_v2I]q\|w~EG}ATZO=֨g#.h)5, 0ctK"JE8_TI"KZ9UDrd Ƭ|LOVve(PI)lUO X"q X;O#Τ  oD`%}DΉ9&` %;Á.?AZEMRޘSpE4 q\ G~ڥLxf'n9GsO(BVrI=C⽼Z2u3"M";͈6ylc,9m1Z&s"x$#{hǙ3P&j̈́wǟA> X )!]E{vAuX]豘P-Qnz,=9Ut l!h^#PPIdV UYȢ< j$I~ҫG*(LVՏ: ۣج 8e#͊]A4 d@w.3KiyԁX!r Hh? 3;BĻyp9;h+@hI*[x PQHn8 HT9 xلmU r(tBVI'|Wk@NdQAGbѵ?"Ϫcp:0% <}06ܶ(] 9 $}%vqhm|Ҳ(lrMSk<7ZL2Ħlc z`4#F? ,a*K#YP_XmQ$/UhW%ɒߠwA2=[tayA' yVkKzcOs|j7I-!qWۿj1g!c0MXE5Ηq>HX Y$Mh̊14:_6 @6q΅r1Hh̊Uؒlkd@R6}7mxct$J:w)Yڇ}΍֖bYwcbV@Dvs4PUJ @t!xrBK6֡~~5!Lbx\*8':1ʊT"6I I_ $MwbҶ@a!^?hIeH%iD$U+VeJ<͔lȒ+o 9scHZg㱪MhrgHG"Q {Z:K nFB>4[ȝTA<5%w͎&^9D}y7|h$D 2it{wcXdB$s` $<Y.I%QV)Z=BMp.:lMʎ|y^3;n$iUx ߺ=.Bd4riYU{j.zGX9y~0WBl@@t^X`ShרYIj,?NTg¨G %,hʀP#;~aXs\[-U+mB6\AΝAŎg#>%Y&3PF0N n>D˒KH`.MLَN;ݤدa¼9B7@F c!8q$21#m8DҮ64)U^) t/ži'Yl}8b(pU,U!1.efi)vZhJ,WA$u+@  _İ:x '{"Q4Ʀ|r4ǏBIȑe[O5Gc~6'@}E$WOzG 6*\kW]~>hcŕDlǺ"<H<m$C :~C㾓$ʐK,,H B/Vʕ>ya)$94WqC@s 7*$!=cT(=@Α0EL9X-t||h:!Btxk0JM7Խ\s̈|nIAeh#ϴfEȄI&9BIx'γ]J;0R{J/ؚ]W~tؚffvHҫ2Au ǐz\h3&ҳ* Q<]Czs4"B`؁mg} 輱9-ѭP|#"XEaQ`>J1q4Xѕ G=vIW92°&7D(*[p\Wnڅ vl uc{: oNG}@JM"f2`,`h3"|%%|13>q]㶛#ʙ63w ##H _aZÏyD;Kroǵ5cd@.Cq2HdbFۺ

4 \($li4RR'1j_`iE] 5iAycr!L[[^f'MFD9R 9@$|bh*B {0꒮reaLoqlPTWݵ #4q:u?8߾$dDBeY;4/9fD.JJ-"cf}Wo'm6G2*lgf98FF;vbµ v# c9kj 9\ečtx|hJPHhUxNc-п? yf޹HTxWظqS,-9je/7۝*6("]ԭ oz3e4w]D?C<9 $["GI9nA<1Y [y^9=ǎup$ c$Hzaq]wqdITROdJI kƋG ,ExL*A,LLl&A  HZ*WlldNDq\w} a$ܫD8P<kE:G92`SԷ_o^h[wU2DU yT+lq4Rq2#F>ɻA$n!)H[>+۽} ,G rՏ5As(ˎ !n*&pJHgu[~I:ͽsd Cg/Y p+4NYL[rD_no:TmQdE42 #Zo50f%i=L W">57㑠>(xfD"I71H<?~uĒUɅbT!~Ǜ53"FY 8^<&CG!6!UYut( o< E!Ȇ1nƍmzEϝ6GHvz+ *8o rQƌ H(9÷Jɖ11%űARۅ]v(K`UXn~vr8Ui5 cdо8AL)+䴉Q \mTȩi@_ |+!X-#x=?k 1rSQC#6TM*A#cOU9PB)uzӆ-" Q5_^bViOl婖nt(ȊhetGR2,kA`͕Kzw+HE@|jo#A x.D=l&PT~Oh<gl2t^2N=mx9q`-"Ƶu;Ɓ&2m+0BmU/T73O"/& Qx7HC bݍ 7?:mB2%ʐVUqA#EP @QsهoTs,+bcKb UvQf7V7Ө9q'$&j(v|qփ2'șrRWi3>>;i~Ab>.8$F$m@U‚FƟcE*"s֡nS$6͐/ ZE Şj8d&6ÌҟM9e1nS-}QQE$hds|Xփ+O!3dV5_&OF\ z:Lr ьx"ddz^d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,'^5.B̿ȡExr|w=`,kY8*\^VJc]xhǔF]ătǟ +'-0BX{G{~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>G2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWy$y˻iw&tg뾧WsQE C*)WXWa|k~'"lr$xq 1ŠL8ń$+Q59*$Hkd#wǷyK Fd7V$uU6k͍2sڡ n(qR"G#HI^lz.Wuܙџs;h|i_4eGU6;wY*XF:)Sch5|kdS)8W-k #eYdwCG8p8*8llhQeǕጒg+lQˈ0H8@blY!j(c |sBBVVPľ$1浑E"0C:KdEq]cV ©U"6C< "bS;qXF:≻k1̘6c2*VѩMy$)\s"Cd)";K-&7i <&š6{L(GztaVp[QEq~|:1N@ꯊ^9@0B\Xn7i$ 6B~f1s$"!5X6MEXxHj͑^|cNۛ)a ҂; ZL@I ʝ;qXlPcdVW骘7' FW YYBP*7E;4Xa -ǑwƵ3X,ZW )T/΃8$LaC&]Λ2bُ0g/X˴[F4 4lYq̉ c,hߎ5<($ h;E0W[ceoFޑWd8t2U:!˪+xI sbHc޸a̐$2;/667G@NxԺ 23"рd?P⨩ryY*EvƷ}(f/RIw |(|ÌXBI bsQ`P1c"bMAVB8|{WI`CXbK7Q[#f<(: 5,.$xr4@1{~>G2ew]ɝcqR*A+8&UGyZ|$=D}S<ңfƎX\yQ.,|9;}A:!lS d#ś`F~̒Ʀx`7@J'IYby"bS&A6Eyκ V<|a;nl2(cJ܃i3A&H0f+#*t^k5Ɗ&cSa2Vr@PT",vɎ5Y_b0W=t)\t%ee ,KBCx<ߎkYX*c a3Hz$WE85`i\*R/o<ȿ:X&%3c(v:nnɋf bU.Go{ocL\$6hHs|x԰bdH$uWyH<9xD SfA ?l&GŏDE]E0p${oӿY:Y8xE$n&{]|i2e0O}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)o:x7݈[7L'0;K*˼K2@xT=[C8gy0^wK$Tp A˹`sSHz4 ynec` &6kƤ"Ic%'EU5h8r"j&Ea\HId ڬ6i*ne&F(9f&*|vsƁvG푑PPgηlˑD4 !{9c&$qcVi}@U}592ad>^ 83Mqζ_MHyUKȑ3E !VתED΁}P0@zg\ MdLᐪnGnJmث;X2Tа+7#xb  6EO;ݚ I 0X術m5kq+m gKIvpt>þ#D &|qT+C%yxww:)"Fddc~6s㹛%Q$M)9`H^tXDɀri_pwMiNLY$D" <\qDuqsR5An;{x"11r$LCfEU`Q?_T6 2?;}Ļ9C(/j4Jմ9|W3`ihwxK%K)"W<| U4'@p瑆V6lfjA* q$=bRqdU]]ZiƍӇ *K (vkYF.1dA @ݪ`VrRdb3bnB 7n(t&tǑQL$ *GtNN0"Qט>WyQlr+znf6v!l3HXt«p}/l..ƎF$ ھMRmnDa {k/A,Rr1È.$|UM#.,>\20ya(ٯJG?`$qXYWWG<֚Dqt ~QpKY#s%H7j< 嘛Mۊ5cAToFF?QA@wm΋$( 4y ~I3B)ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"tb:%\~KRFzyʍP/.V4rZ)鵏ߚ[:L#& %*#?Yp5j@QقV@Y+|=9LPGƄF@> :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;NZS"6e_l?Mr~e.IFr*6$Ct[l,=h>?~kl2d04f=}BӌIDf Yd [>E|Ӥg01@Q;3h6x> r?AL$MDW+R4O.s0K]!emR=7ŁTrT1Ƚܠ~^+n!W.!u}G߁}dt22rt2@\-NVn ?73!>O6oF'޴Rd*H&I+꣔:ADT15xKt[c"M;Ɋ #WodA4yࣜeܤ[s3zCԟ.IG&n'dSQ͒dec4{[{bOxU$rS %HVN_Vd1V3*!_sCGج*& >ۮXDN?;G,@ý8)cfXeΣd'_Rޤg(rbA9?K˕֊in:mcΓ&HɁ qOc ~l|-8Ĕ@6`B _?7m:Fsxh a,©ׯ 1dvQ]ZĠK}=x|4.SAyHc$Zj#4x GP`{$/GZ䂉oBHd_ }<shvn(NIҞXkbV?sz EŌ&h2ch,4y1_@K>Χ. v\EJbGPd+QP"_rx'^X֌L 9~YʙtpXe;Y7x̆8FMTʝL0!Y8jEY\pKʹX̪fl<|Α SREwbLp,na8<~@V"tb:%\~KRFzyʍP/.V4rZ)鵏ߚ[:L#& %*#?Yp5j@QقV@Y+|=9LPGƄF@> :T\G6:2bL60Rl񺁢>=NZL`_鱶ށPn.q) ^.`ƍ D_vJf)k p-Gehл;MQ`y!kjm{۝7RG*u0_XTd᪼QfK s/*c2;q>G:D1NIQ݊2n 5NTx Q[ ;( 9NٶFI|i,< !*4wh}K}6gTjbyɊI †$!5=<:J<2aX[br<UX(f2I@LWFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJgFP`I75|~AIf!"\Jl>>9li:Y<.KTlbWζXLzi˳~1OhhI`x֙!9!3$a\bsd2G78ūwVv>?S94\i_ @.D.*$skZxI,3͵Aݴ i\PoyDT,kj~@x&+6( @`O7i 3GlހJH_m4lAD"#h@¨@kGp[afuO]v(f /lן\d (bB]]ϓԣ-)(w)zY!"c$x) s49oU<Ó +Skpo֕,hn6aaDJm}: #|c,~H0%Wn?}NaʲTqd lX p4d9xJg~&fț+M5np>{6HNN"P)Z _{iN*uQ[kLOP޵VDC2PL,$0! rG<Mq\䔊-i,|w8J6T͑(+e;Ab*"Ui8r/Pz9A o'w9uW$6BYszC e*6`Q M|q!c˰&c5z P4cq{wy:cU,O H##E}uqG1!1}$J5HRxF'ǷbdT|Z&_1EU4h^Q,4o'?PHoL|Ɇ#SƁ Ψy`XMtd"=v VlӠ3 7r#oBIboԗir<ݎ1%pJv܀wkG/N(f/tߍ+AT&-(_Ƈ#1@!efL̹tHƕ< ~k'g",Q7*@hI C f!Ȓů|p~5>*nryk.8PcyB*&[$йeIO1p }>2$Y +SRC^+m)%N 6mi⽾{~{֪ȖHr&S; 8}紐=T>Ѻbg eK{tȒY%A$lbDl@yA(i7Uv(_$wҷ&>rdȑ)@ˆ|w?TeJ,J&:d2CX;ǎqFC6Bn `߷OYsI!L1KKH^xHȍD Z%;n@l{5rʗlOQ|ƃMO`RTQ /CuVld2f _Bf\R$@Jځv?~5`c(rz 4 R!3Ib׀x>8?Ol|`C[f 79<5 (ImX\wfh\'Xظ|羃ddd,╩Щ!綔Pqն oq^==UdK$9)HP$sαIH"Ȗ1˼oW~81c}d3eOrfS"r.V!"8%yߏ7zay#gUrKcd(.\Eܟ7O0LfXrf 2H=V<Rn>?zY',^%@7qǓa4S68ǑVqueamGn+A+cdǻ71"r?ϲg7W|ތL\CL{/z=ΙK$#Yč,@Gna[{y{x&)HeHȍhU]@||V(1#FsA $VL`Y8Fxc<*?}PF⏛щ<2cKCc/eG""Idk8+o~O=o2 Mbh2YhN#5Uء$Jߐɓ "G Q+L(, E `{H;; @Mƭ 7Afn5G~m=g$3Ɠ$.ߩ.y!y#"7cJ+!h1ʏ*^Q<_!F, ; V36L[=+[EIQDP4FcǙY(C.Ι r&H+x";jaN uݬ ʢl3{@ 㚾u;nH@D2G=XYR߭Ud|]77 +&|ߍ&h^pM> ( 䊾?Slc$D:37U io#%UB}FEUJhy3z{H1ӝ`+/mld)gJekT}ua%JLxam׹mTPǁr6I7n1zJ#*(<'eFP "ׂynC<sDeL٬`iGOYUtF'(hڢI_4ʯtL93P.Fht9 7Z,h}Jo(-[ B;*cC0g6ak.|GI9biuؾl@m` edcel3ǿ$דG<ɚ0$;Vl o~<ILt R/ȳ۵ ,2ŞEĬ:j=w ia̠."Af dCBmBkk8CӜfTpO5<t(A}72ƱVGnY~ra>TMQcboh#@sWΧm(X`R2^q+*W\; >okRA&fx7D⯛ ю)GbR ;zslq~Et͗ "X̶ w[*s΢#cdBL4ͺ-B>uNCF&/_v2I]q\|w~EG}ATZO=֨g#.h)5, 0ctK"JE8_TI"KZ9UDrd Ƭ|LOVve(PI)lUO X"q X;O#Τ  oD`%}DΉ9&` %;Á.?AZEMRޘSpE4 q\ G~ڥLxf'n9GsO(BVrI=C⽼Z2u3"M";͈6ylc,9m1Z&s"x$#{hǙ3P&j̈́wǟA> X )!]E{vAuX]豘P-Qnz,=9Ut l!h^#PPIdV UYȢ< j$I~ҫG*(LVՏ: ۣج 8e#͊]A4 d@w.3KiyԁX!r Hh? 3;BĻyp9;h+@hI*[x PQHn8 HT9 xلmU r(tBVI'|Wk@NdQAGbѵ?"Ϫcp:0% <}06ܶ(] 9 $}%vqhm|Ҳ(lrMSk<7ZL2Ħlc z`4#F? ,a*K#YP_XmQ$/UhW%ɒߠwA2=[tayA' yVkKzcOs|j7I-!qWۿj1g!c0MXE5Ηq>HX Y$Mh̊14:_6 @6q΅r1Hh̊Uؒlkd@R6}7mxct$J:w)Yڇ}΍֖bYwcbV@Dvs4PUJ @t!xrBK6֡~~5!Lbx\*8': cX+#ʷ]?} 0l&(17 9SC, )pX/hs8Ո+HVI 5Q) q{`¼hqWBf  #RHu9&2AJ3uX8nU^'dYTv\QC7)@9޶ ":vfˆBFf[G9QF\tǏf{E |x:!dv$8>?mςzV\te Ib-x'T3ɑ4FX͚axL1|:AA%ZL%WIdbz" /$%JĢ92Y[V>O&Sn;bxO($ᔏ6*vӧ~,mܸ,R`7"0y@cDc0 aCu&ԩoL})@F".?jw#mR+?c@(fc"; W_9N pR(`uG<(66K.Lۯrڨt/T4lnbc$GwTQx9OJˎ7LEjy22Y/+5s'S2( #|؁hǟ<:2˓#g2)WbI9' y5aJ.HvA{hy +(ܤ_gj:7ZXe=eݎXu{ә@\EWI(І"5 ,Z@p91=r̨8ky$Nj*)P't2E%~x$y5E#JIux<}&I Y&6Y @W$_ȭY+|6S'"Hrh8;ↀ0nU͌I"C}i{ƨP{5ɝ#aGlr)j[|/4-o"tB*Q<`68oz#w7YѤF-ӟh͏c'YMr,O矝f4$FwaXh_54*9xVe~;h gMfUVAx>`iE] 5iAycr!L[[^f'MFD9R 9@$|bh*B {0꒮reaLoqlPTWݵ #4q:u?8߾$dDBeY;4/9fD.JJ-"cf}Wo'm6G2*lgf98FF;vbµ v# c9kj 9\ečtx|hJPHhUxNc-п? yf޹HTxWظqS,-9je/7۝*6("]ԭ oz3e4w]D?C<9 $["GI9nA<1Y [y^9=ǎup$ c$Hzaq]wqdITROdJI kƋG ,ExL*A,LLl&A  HZ*WlldNDq\w} a$ܫD8P<kE:G92`SԷ_o^h[wU2DU yT+lq4Rq2#F>ɻA$n!)H[>+۽} ,G rՏ5As(ˎ !n*&pJHgu[~I:ͽsd Cg/Y p+4NYL[rD_no:TmQdE42 #Zo50f%i=L W">57㑠>(xfD"I71H<?~uĒUɅbT!~Ǜ53"FY 8^<&CG!6!UYut( o< E!Ȇ1nƍmzEϝ6GHvz+ *8o rQƌ H(9÷Jɖ11%űARۅ]v(K`UXn~vr8Ui5 cdо8AL)+䴉Q \mTȩi@_ |+!X-#x=?k 1rSQC#6TM*A#cOU9PB)uzӆ-" Q5_^bViOl婖nt(ȊhetGR2,kA`͕Kzw+HE@|jo#A x.D=l&PT~Oh<gl2t^2N=mx9q`-"Ƶu;Ɓ&2m+0BmU/T73O"/& Qx7HC bݍ 7?:mB2%ʐVUqA#EP @QsهoTs,+bcKb UvQf7V7Ө9q'$&j(v|qփ2'șrRWi3>>;i~Ab>.8$F$m@U‚FƟcE*"s֡nS$6͐/ ZE Şj8d&6ÌҟM9e1nS-}QQE$hds|Xփ+O!3dV5_&OF\ z:Lr ьx"ddz^tڄdKӕ!0,4GF.&2 ߾*&XV(KnwP3A.́WnosPscO VIL&QB㛭dO2䤯&9Fg.5q| |vdyS"vcdci~++Xq(ib8NP88|}N9F\pI HwGƁQ4>ƊUWD;;B Im _N(G<|qzLmY>rbݳZ"s}ңh")IJ>;y6W,>CIguȭ jqM񩾟1Ð@$tCQ<EQx8޼xQM2DDeE*$H&hDqzi[| I0ίPx2K4"dP2vϞXfq6DIM~7PMʹ$Ho3pq `x&P93q#S(V=Ku%慷u_#!-NEP LM/W">n<4F"rZ4źsٱ@s2!IPA Ɨ~$L+ҡ &Uߝ6&G><ٯ4̼o|m!29 ɴ =TOGPޣ9cLJ!r$dH2-'xF1?a>qo+'xΣldL.5q}?n4 1ʊT"6I I_ $MwbҶ@a!^?hIeH%iD$U+VeJ<͔lȒ+o 9scHZg㱪MhrgHG"Q {Z:K nFB>4[ȝTA<5%w͎&^9D}y7|hX3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉM\f 콸6@ߝ7%">^9z%\ # |qƁӶ1*{\K=jYi" \u@ʭ|>t!be)2# 8#y2!Nbw l6(hdt|4uDS,L̩ehYrڠC~ȕV#d4LK`w/t bXcǔ l<}HCXjmH@xOԱ32աfeW'jM$\"ʅ#"UX,-0Qi|ߛh:X3"2eeJ-|moQ̙5A X&ٖC0}깫PG,>o.G"$&!G|#hƁHaN @LCŋ?oΫʏ Ȁ2[i Am3D31/ I{Ecp!hjs:ǖbY*v#SQYύ#nO>42%O'6?% N@c&DI^im1Y1o/C&2< x󀮌,@R;X,o&9#Lr *v<|C8yy$KBoAlynjvC"C C2KףU-X.1aPN$01@"E"I AcƑRɶ^ #TK32z,`cgx[#ǂ ~5 sm7 R "`A>z%p!C,E/n+o97MHϗbe^W)H,yq@JFG,#oh|c9]x2q;8<cXqL&AN8?HtL`d49Bo#< ?"xa8)2,M,:*<@2`B"ʕn|k'*Iq̼&y+_bwC;XS;(2d؏NG}dGPG>7?`><@Ȗta>ė-9I%yff(ƉC*)WXWa|ksDUI2rGo^4A#ڌoIw^;{޻]tz.Wuܙџs;h|i_4eGU6;h,'ɕfőV IQk?4♱%ETK2K-C*)WXWa|ksDUI2rGo^4A#ڌoIw^;{޻]libtuxcap-1.4.0/tuxcap-build/images/explosion_.jpg0000644000175000017500000000214010751375104022116 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C@@" 0!1QA#aq"& ?Lj 1moXNy?5E\-+ 6WY\Ry#Lfgzc0ڇ(>RjSS{ؕyMp8;POUh +p8AV}1-J_AOZ ۥ*SKPRێNkO,W( {s[KHnd s,+q=EwYD)='Ua @5!v'sPNSzkͿ2KdԞ; Qӥ9k]r-))Q# adobe:docid:photoshop:b9008254-74c1-11d9-8a14-c426ef2c7c0c Adobed@      22  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?iڵZKJYY@G4UUN*4Xux4| ΋ .A긚^ʧ,lUYP̛=Bt[;ZZyGӭYXҏ('^2'楟ѥ2'R+h.,&uUk[*G4Ĕb[^m?-|1 m}ty;{aVn ԡ~bmVG][y4m&Aua)#N*.n}/?~gqsOiz3Aqq޸hՆ%j .A~V~Wg[|Kc2i;0K4CY,oO志tNcoYwՙR "/ӝ.njcr_\{xTuŕyb0|?{C+5ޛV@ ƽ9[7 !殡囏0iR<6{ kK;hCE 缕j^ S '#acdɖ8|؂q*|]>m>ylHVW#\-7 5#rty)G<2Y}'[:>觤I8" }A?Ϧ%~]~`hXgK2yfi䝣Hʘd6!"P-BXSڝ˦ŒX0b qGiLmzXH;Ӄڽ['f0LrQ_7̷Vjz=V{U2/9~MƍpO[?ɻ_ڏ|hX7Sߋ9 tAt"icv"$ !d]֡ϛ'`jej˝{O dj37q?XiLo/瑅}JT]FYg*`-;q"d'`15ݣ?hD4(9zd7]=}3k%Q8)Hm됯\'HЗ^[Z)[,ҕ||{ci1ko-WQ?Sn%2:.ޙmo"Сlibtuxcap-1.4.0/tuxcap-build/images/unicron_beam_down.jpg0000644000175000017500000004276410641010423023433 0ustar inniyahinniyahJFIFHHExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:03 13:23:38  (&HHJFIFHH Adobe_CMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?g}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mII]c.i4׻3imE^oK#}{ vPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMW unicron_beam_down  nullboundsObjcRct1Top longLeftlongBtomlong Rghtlong slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong Rghtlong urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM JFIFHH Adobe_CMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?g}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mI'}mId~?ӏg}mII]c.i4׻3imE^oK#}{8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:9faebe12-7629-11d9-b78b-819b7d52561c Adobed@         s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?xk >q#.nBC~?tgm8?/Wa?ʌ+xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_Og?ZRiCC9}Oxk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?Ճ!.__#ʜ?Sxk z<Tb_OgRiCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgYViChK?*sNxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgYRjC~~_S;xk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?փ!.__#ʌ?Sxk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?Ճ!.__#ʜ?Sxk z<2C1C~?Y?փ!.__#ʌ?Sxk z<Tb_Og?ZZjChK?)Nxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_Og?ZRiCC9}Oxk z<2C1C~?Y?Vԃ!._ڟ#?/?)Nxk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?vԃ!.__#=/~_S3xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<2C1C~?YOփ!._ڟ#|?Sxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_Og?ZRiCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgYViC~~_S+xk z<Tb_OgZNjCC9}Oxk z<Tb_OgRiCC9}Oxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?փ!.__#ʌ?Sxk z<Tb_OgRiCC9}Oxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?Y?Vԃ!._ڟ#?/?)Nxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?YOփ!._ڟ#|?Sxk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<2C1C~?Y?փ!.__#ʌ?Sxk z<Tb_Og?ZZjChK?)Nxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<Tb_OgRiCC9}Oxk z<2C1C~?YOԃ!.__#=/~_S3xk z<Tb_OgRiCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_OgYZiChK?*3Nxk z<Tb_OgYZiChK?*3Nxk z<2C1C~?Y?_ԃ!.__#=/~_S3xk z<2C1C~?Y?Ճ!.__#ʜ?Sxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZNjCC9}Oxk z<Tb_OgYRjC~~_S;xk z<Tbuty9(] K:K?*sNxk z<2C1C?tim8?7a?ʌ?Sxk z<2C1C~?YOփ!._ڟ#|?Sxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<2C1C~?YGvփM˙7a?9}Oxk z<2C1C~?YGӃ!._ڟ#=/~_S;xk z<Tb_OgZRjC~~_S+xk ?#.n??;GvփM˙7a?9}Oxk z<Tb_Og?Rڟ#=/z_S;xk z<Tb_OgZjC~~_S3xk z<2C1C~?YOփ!._ڟ#|?Sxk z<Tb_Og?Rڟ#=/z_S;xk z<2C1C?tim8?7a?ʌ?Sxk z<2C1C~?YOփ!._ڟ#|?Sxk z<2C1C?timh?7a?/~_S;xk z<Tb_OgZNjCC9}Oxk z<Tb_OgZNjCC9}Oxk z<Tb_Og?ZZjChK?)Nxk z<Tb_Og?Rڟ#=/z_S;xk z<Tb_OgYZiChK?*sNxk z<2C1C~?YGvՃ!.dv:?|?S?xk ?#.n??:Oփ!._ڟ#|?Sxk z<Tbuty9(]rGjC~z_S3xk ?#.n??;Gvփ!._ڟ#=/?*sLxk z|Tb_Oy9(] K7a?9}Oԯxk z<Tbuty9(]rGjC~z_S3xk z<2C1C~?YGӃ!._ڟ#=/~_S;xk ?#.n??;G_և!.dv:/ƄC9}Oxk ?#.n??;Oփ!._ڟ#|?S0ΨNxxO|1l[͓4l@7j! oqDO3͍2k%Z#RВeWKƦ8uayx$duW9džOՐ?t5Hb+3.x=#7G㯔a<$[Gxxr~>j^~xrwPJ6坷q8v?0u[EPQ(_|2pM_T[`c{?/;wݹ3ed= libtuxcap-1.4.0/tuxcap-build/images/unicron_beam_left.jpg0000644000175000017500000004021710641010423023405 0ustar inniyahinniyahJFIFHHExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:03 13:23:33  (&HHJFIFHH Adobe_CMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?j.ufzVձ݉n7ו=_5꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT `Photoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMW  unicron_beam_left nullboundsObjcRct1Top longLeftlongBtomlong Rghtlong slicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong Rghtlong urlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM JFIFHH Adobe_CMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?j.ufzVձ݉n7ו=_5꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT꛾M?4}_ΛRkK_GT8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:9faebe13-7629-11d9-b78b-819b7d52561c Adobed@        d  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?Q<ȶxxO|t$jڂ+n!j;kY'Tь'ҝ?lȰ١x_TG [v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb󧐴ax}1L{{Ya%W3 Yg7]q)?)Q톣$q2$}PYOuVX<$!el-?}'(԰7T8HKUr?ԇ9}c(?wT8HKUqH|b!W8OHKUqH|b?QBn?rGU:(bQMNSGQ>Q_!S7!/U:!'??Є7 uQGcBoB_uC'??Ѕ\?!/U:!'??Z oAW?ԇ'O oAW?ԇ/X8OBqS??_>q;&I\#R?ؿ}c(?wMNGQ>Q&GQ>GQUN\#R?؏>q:MN \#R?؟>q;&I\#R?ؿ}c(?o* ?GX8Ok&I\#R?؟>q;&I\#R?ؿ}c(?o*f%GQ>QMNGQ>QUN\#R?؏>q:'%GQ>QB?pGG B_uCOBqSW?ԇ'OЄ7 uQGc_!7:MH#GGcBn?tGU:!'??B?pGֿBn?tGU:!Gc!W8OHKUqH|b?QB?pGG B_uCOBqS??OX8OBqS??_>q;&I\#R?ؿ}c(?wMNGQ>QUN\#R?؏>q:MNGQ>?}c(?wMNGQ>QUN\#R?؏>q:MNGQ>?}c(?o* ?GX8Ok&I\#R?؟>q;&I\#R?ؿ}c(?wMNGQ>Q&UqH|b!7:MH#GGc!W8OHKUqH|b?QB?pGG B_uCO* ?_>q:MNGQ>?}c(?o* ?GX8Ok&I\#R?؟>q7BqSW?ԇ#OBqS??OX8OBqS??_>q;&I\#R?ؿ}c(?wMNGQ>Q&UqH|b'%GQ>}c(?u!W8OHKUqH|bֿBn?tGU:!GcBn?tGU:!'??B?pGЅ\?!/U:!'??Z oAW?ԇ'O oAW?ԇ/X8O B_uC'??]BqSW?ԇ/X8Ok&I\#R?؟>q7BqSW?ԇ#OBqS??OX8O B_uC'??Z oAW?ԇ'OЅ\?!/U:!G B_uCOBqS??OX8O B_uC'??Z oAW?ԇ'O oAW?ԇ/X8O B_uC'??]BqSW?ԇ/X8OwUN\#R?ؿ}c(?u&UqH|bQ&UqH|b!7:MH#GGc!W8OHKUqH|b?Q_!7:MH#G!37 uCOЅOS??_>q4;yoA_j!'??ޯ+.x}QKd?_L%2]*(gvqGO/:HEyz-,M' y~YjR᚟ǒf0WRƗjjMvhqC&&"ʚ|c&G?[CbտJ\?ʚ|by3Y5?W?؏2:C_"?SWOw?%"'LGV Up*j#t>g;ǫȈM_>뿝Kz|,OSWGt>=K=WD'U'LԷɟūȔ?ɑCo!?M_>뿝oɟɫȄ?5#·5CdB\5#t>=LMOD'USW_2:Cgj!??ʚ|bɑCCdտB\5#·5CdB\5#t>=>M=SD'U/w3Y5oW?ؿd{Cſ=K=[D'USWOw?=>K-SD'U#Ly/XoUSWOw?w?T Up*j#t>g5CdB\5?du·5CcտDW?؟2:CS=LMOD'U#Lz|,O?ؿd{Cƿz<,O?ؿdu·5Cb?B\5#t>w?T UqTCLG?S UqTCLy3Y5?WM_>뿝wG?S UqTCLy3Y5?WM_>뿝kɟǪȄ)j&G?kɿŪȄ)j#t>w??V UqRC&G?w??V UqRCLh:?&&"/wy,O?؟2:C3Y5OW-_>뿝[Cd?B\#t>wG?S UqTC&G]|cz<,O?ؿdu·7CdտB\5#·5CcտB\#·;ɟɩȄ*j&G]|cz<,O?ؿdu·;ɟɩȄ*j&G]|cz<,O?ؿdu·;ɟɩȄ*j&G]|c=>LM[D'USW_2=|c_=LMOD'USW_2:CW!??ʚ|bɑ:3gj!??ʚ|bɑ:?طɿŪȄ)j#t>w??V UqRC&G?wG?S UqTCLy3Y5?WM_>뿝[Cb?B\ɑ:?ػɟɩȄ*j#t>o%"2#t>g7CdB\5?du·;ɟɪȄ)j#t>=LMOD'USWGw3Y5oWM_>y3Y5?WM_>뿝wG?S UqTCLy3Y5?WM_>뿝wG?S UqTCLy3Y5?WM_>뿝wG?S UqTCLy3Y5?WM_>뿝[Cd?B\ɑ:?ػɟɩȄ*j#t>%"/?&&"'Ly3Y5?WM_>du·7CdտB\5#·5CcտB\#·5CcB\#·7CdB\5#t>g5CdB\5#t>=LMOD'USW_2:CCdB\5#t>&"/t>&&"/wy,O?؟2:Cg!??Z|b?y3Y5?WM_>뿝wO?T UqRC&G]|cz<,OOWGwoj!?zϟOwŗ<<:pF1u}.%HB<d)kZp(eQy;r-'<]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]I]libtuxcap-1.4.0/tuxcap-build/images/heroDamage.jpg0000644000175000017500000000124310751375104021776 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C " ,!Q"Abqr13s ?Lzm(JrN\CIn9`t\CviVר8̊~xc4pҤq#*>Z ,4r_u'pZ蚗S'GՓjY`)` I]HԺ{a;-hU9L3Y]F{F{49Npm'J#5M'~p=:̮*pA4AyKrESYfRt~FGϾlwјe*?[Kҙ➖ڌ0GW#bHGgvfv9f'$'Alibtuxcap-1.4.0/tuxcap-build/images/planets_small.jpg0000644000175000017500000001423610641010423022572 0ustar inniyahinniyahJFIFddDucky<Adobed       <!1A"Qa2qB#Rb3$!1Aa"Q2q#3Br ?DmKg"09IP~]*~Z|:kl$gbwvVy` \MEK@U\=,^ձl+3vM\29<9G/r;vBR_Xݿdžt\8 jP>e]}$.if]̯.[aRhf>@ {W %6`b%@#; T%qPWX=_6 V8gŭ i`d|kM}*"5xyO/=F#32H GO=_wI3{)y^slܧEm"hG.Rm S=9bܗ12䧫7EUcj(eU/lU[krVcyJ5QȈ bYֽ]8)5y8MHeXFM@]qZ֗~qȚ$|bk~@dp~!M\y|F<<".NjAKƌI(QI[]7'J5" qf3!4xGV:DpmZ䣵T5*`/9Kpv|l͓E,(8pP7YlRM T{;5Ɵljڴn^>? Zoui?l~G~k^d3GZ[$Mĭy;];}]z6ώַT_8Sb"XZ|3bYq6*a }LkyTWtĕTiJҼa86Ci}*ʤ&Wku3VZy۸J~?onpBh7ߏˤ\Ї NmH/iM}bKE6J=F6&jcuцi_5ɦZXIt.m"+q*Ҽ(zWµM_ Liaq<}]eoHSQJ"ڶ[UŅ60܋9|&I8Di'[7mj6$2=lhCSՌkE/+R󯿴]MXƊ:Xݹ"WA?e"lTW-?/OZ5g~_%ihd2O('Pzpɱ=u 6Swm zjEuNx(/[Z#ԣ]^G^gu5/#?ܤǡn cdkoٷ[ӯ~uQUSr5f?|uJس6[`1aE=y:֯]%EW{,V711%koxӮ><~.*<++RwLTȰqUދOc]s|VjҲG2´kV=~0bO^)޸os/'{hs1/@wqg_i[؇z36J֓ϦȝVJ6fw,m?Ӵҋ]Uty;|Dw`|w\ȷ{> 5SR*MU{IOqM1d B2$'դG,NhnHr*2Q5R$Z+ӭ5̓׏@t\I WBZkЉz2F:f2J*@*݅G#<{`.G)d!W hG(֕ ]fx)iգس)rݭ)]nѦlq0Wح՞:[ȑHOTkޭa[Ym;tz2 ׁ[K69&E6=E Y89`|MixO r4/J+%hi1y<$H̠v~g_F|;oZ}FMbA/MvbRI%oO@5 slG&ſ#gqm.:"ͽ>ygCG`1Glnl!];ӷuW3rbC+U|}3/3s{#ceK&xhg V|5^>[Wl~U~u~r({˺Г/ϴ?aEf=<ӸC5}Ηg4Ś*<SxLYMC+ GZcK##kR״#'!CJ;pӽ\?ɓrzLxV)yd R-PGVZeY=8{ڜt>ˏ#(.tqe8=G޲Q3EGo]Tꮹl^6mGa- L6SB֓axl/اwwmeD˻Y'ϳs{8F9 +!gv󮇂s^rZ_q /pL̃_@;=8-[=1XFSƊ_YKgx4j{ CG3Lx͸S^W-(X|51@VuoVm8ڝ *g'>q b8IZ} Pmugf^;%]#wy띒M3VL<RMg6j{{o$K@;G735Gvj/ ,31XgvyNSMuWT=?n7KXugo6g,;:ޝ!^{鯌ESM|B[?ĝٸHg"|MXցƠ(u|\٩X-%>k֨Jr{[H+Jɕ $n<=,EZzƾ̺8L(^Lꬕ~j^?>w"rL%T5BMOS Rt>+Tl+#Zf{m s ס:Rq%KD?;t%)Z5񧖻qIw'$gKėG"JCAڲf&]4לY瑀:ZS ~Eat.QB̬Em5!ř̹TXBC b T~#I#~Œs?m}ENS=w}lL_2juJA u$Y'iՁ )j]|oD9ݨ%R,MJa3qAYP0xBUчR5W1ύMh%nY>.r+j^?_gWǍS[Mmej(O'U[)Eld [) R QӦ>JLv/Jkڞ=)N6`Kn5_{]ier,tKjl{sYvPI?5$d\Ÿ6jک=I}ɒ0Dn\(iH @)xbY%͜99ݻ$?%>؄땼|uȨnrm^-3Ec&={M5Wl#2Pry4ػ G"VS@sf/㴷cx i kqvnc1%O^"lc;5M3#4+hIpd۽{S@yqk#=XN3~>&MtWr@јBƧ@/; ֚6GVɥX{]w-?M0Sb/L")?o- >(o9 ,cCF`*I>C@skx2RaGTvM4:u4_X$Hd$*ROA]z{n|bYJT )=::j9T]o0䜝細Cc!De-ԩ A03SR;{vO4)Y.E>`nd^IR'=Jz`~Gm4\d%vLFYcf`UV$&Zx3ܒF-aHg鼎IKq5wuP@]á>qK(n&ئ=eq_M+^!*II#bUMhN< rNE~ɏ̱4dԣe#o@dfd L']y|?9q(f0K}nUwf+L3K j,b*+H:-uVvE,Ah ˾Y/լVc6#1r2o4Ƶ:Ia}#1_/^3{[~n0WOȷcLM /(:qOUi"_>➚@D.|t;z֚ߧ]@Jsi!_>otwv+_uwmQݻՠ/c >Un~yw@}mfZݷxՠ7m-Z=W|4oVf[wϳ{Ϲ]libtuxcap-1.4.0/tuxcap-build/images/bomb_radial_death_.jpg0000644000175000017500000004315110641010423023471 0ustar inniyahinniyahJFIFHH.ExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:01 18:40:22X<(&HHPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMY<Xbomb_radial_death_X<nullboundsObjcRct1Top longLeftlongBtomlong<RghtlongXslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong<RghtlongXurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:8e421827-74c3-11d9-8a14-c426ef2c7c0c Adobed@      <XK  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?v*UثWb]v*UثWb]v*UثWb]f2ƯB%o:חM᭵+s "m*], u#kz埓l?Qƞ83~[$%Ew_!̂)d7%F 71Uy 7!oJEC~IGo~mQ'$MB{V4"bWbS-+Gյ}+D.NiPH|81W?z>y>Fm&R: '⿒? R;Q#]íL7Zvd>#Ν{Qhϕ-<1!<}_NR6Z<ݷ3olU׾kv*8(B8f'nN*@[iǩ)jrFMyT$wX1y`Jއr?n6 ס#}?,:nԧ֖(mm_ݥM>qUA"̋ՀS^= ?^ΩF*!]_៘Ϡ/tk~U!tm#HzM^>軿Ӽ-#Pߢ! ^x1hR|9U/]RDҼ-1֮,ܭXVEyKoi *-LLG*'v*U?$M /ы5RJYؕ"V|1 D8''ᷗqG Ss9U^CBYJ 0*^89 92y]ʽٮ%Dh@RW|?|˟0U?tIO^1D b^jz/8?<(-g-Y/{]HPXt

fXZ_B y\V+,_")WHRHcE`YmM&[c5eDb8GaqWbS7SiJ;YT<3z*:ŅC#ǥܹI,e><AV;]qWb]v*u1TL6W ok4ꢬѣ0*JeٔUn*UثWb)C*ӂq55A?~мQ F(FX*wc^C}_iodw^qzS9PXWbY<ytW;w޿;?1?/td󎕠j~\)3**WVBޘOʟ'oߓ#DcmIQ=IlBk*aLa*[&!$~#'z}/=#k>L]G障#/*_4lŒq^#˺ZEVNثߓ^MH7 pvIv銿+2!|qcMwwE.lBդ^⸫'Kq'p?{W-}rn!0W_ȟo5]Z>}{krj:B"I*Ow%cx'Sf $u/Ӧåkv畺HLAiEwQ'2+CM,(Vzwd+YiSSQJ=~EdykA󯗼qm*Bi, ##ԎһAW~C.Jc!Y[jzf9/n/n.xJ?WVSM9+g~iQ򅼐j>IDP"9*8A@c_?󅟛y(7Vո*A R;&T?qOj75귶*y$LO7]Yp2iUe.y?^r|W)e1IP\Um"yDT[~|!?^yWȞqԵʩ4}ZRH&$~wS/>ypgq˚5&Ԏ#feiFP?7d^sVڔKV&v#|Q>濘4k/nk$k%A2ٶ?B~N|mY}䈖ID@te^נ1W7/MWҬ9;{n?/mQc^RhƕqWroVZw&n21 b!Sr;͚uŴ^^α\mXʮ00qW'u{c֮xeoҐeRǀ!#jvY?ϟ?0+1|c=寚|vZHMo0VhGSU֋󐿗zG_ȭN_HGHQ5[%+=Vv`*^|=.Y]5|1Ťܼ:EXuI#a~qS/Z%S8hb;ʾL唐WVz- 桧1ej⯐?m-麷-Q: 8N~RbjSx]϶]QK3*R~U^k;uWhQUAHPWv}>|{O8ya^ɢ_s0Tb_.i)pcC%+WFGFث#=&ͬ:3*E,ЫHS~Zu¯!55.hvWZ^!" !V~.dW Ic/ɫ|_6w-ۊ4U~]i kKS=Q~<ũʏ!ږMB齱K$h<oS~bϚwu[,--(yVa߰_ߘJ>l hĞL*W䧓?8ܿzy˚<} KwYB/Ec{HtfKҥT2vspz^*__ߔ~X1?0Bn]ҹ {c?sW\v:v(UH&8bTm4MNG.[X-5;GdyTsBbRyG˷joeM]ο2@"b4*:8̟o9\~]и{k fXBk4v^[?>Kd>)!uV'b>kGt?2hGaO̹-sQ.dOG*it^dW"$|;v!U왊vf~Ϡ|16~Cr&p~t*\/_d֭h, i~ u)ǍX*oOyr&:լ͔,eNє =_IUHdP"SثͿ3.%5i#Azow:̓MہUaCj#;.!@#CgX WYP3pثW[Ƹ+IƧi;<fEEw;b7^Tty!\E5-"Iϧ\< *b] O"u5ek/:y,Pũ^H7UabOv*q'Iל"mN8} ;y2+./rpZ:&ȓJf(^ׄ%E#oKw_Vf~cfDcԁKVmqW} 89ͭ3cz/,/t}Ea|qJ@`}~o3kcD~[7l1b~e~h]˞_^h7Zg&ᣉkzUv*UR)dXSDM F*[r[^O/zOGWKw$Gu#S8ߗo-o+[Ը/%Cr@nbr^<ծiGGD`ҚGK(fRYf' W̘Wb?%?uO(p :9xX(,OQCDXKDXǗ.'ҔH)gJ(EE>G~; kH|q:yKKmK]6g8bf -x?ײjIF..Q9&&Y# 3#j5*:6fw֮RDnRW/mYN☫pCrwWɿy@xiۘ |3s}qWjW]v:w[FEcfOZ}Z?Qʺynmrޒ/*~q|!'Wϳ~Zh][yk#SԣDR" IتE8"_>~E:KoNX++|_3X.#pqFyX_55L8ȁ]#~XR*/ͻ+-,W+N"Dhq5?mZ\OB1WGpi^ӻzq}ZN݆*g?&/u*?i. *<([|T9& UD}sN73z}uǦƦ'V,#oyϕ7?(%/緑4+xM5='Gթb-:ަ/l.ei!;SMqV5|,|/}K#eWsj?On7y] uAZOEpN)V*WA'd-p$ʊUUbH~W~Uy{Om,kk(jUN5=qW+_gVw\6`O~~O^]_\+ZY58ff~s2__`*N*j/Z( ]F `*b^_Q*A: 5ŁW}9}:.gP^I.&!5PoJ U5ķSs;sw/+SqWv*UثWb]v*]yuu\KWE^HqWb]v*enNZܩw@0|1WKS󦥡ݽKֺ{hڑeA*O̝j:=ns6VڠUتcmj{k6qTH1wcVv5$U'gnnYhQȇ8?~.lu5yCPuyWDկ\cFUCHxRsBxѕ|Ig/ȅG4m[ژoMIGEF6=A*~^X7垁*DFhj}늿 1WF?熹7|"'/ݒhqPlvMڽh/{[sZ6c1[}Jg}OOk{~@HݜE^xo|CIog_W\ѷTWZl&f>D+1 O&G/)o4Ylg{KM qx*v5_V*šk{cj;F+ڧ~179H>.ğ׊ [ʓb3TM^w]jk̯G.|4'X5Q.zGW`])+-}(H߲WyZߞ<ϮwF[䗺8$QFʪ(`@hv֗o`76 _¦bP?̆bz6r`1Ӛ$BhH?;W7\ Nc^(db UCv*mb:.63<:)Zg.'~+cNwUbs]v*U݀_v*UثWb]v*UثWb]e:'<'QkXJR+Jᮯg3N\4P1WU~nfIq #&|Ik-֬h؊0SUuO]K\4>d U&]{TT z(mqWMIyN x-ۓD{{xOY⬟r]-u 8 ~hpJY#?cxdR=Ven}m(??-UijƬrIN*yVk8ӥ~@řXk_lլ&Zɲ}b;q)Bmv=X15>\Okiygo&iMz I,Hwf4UbS-Vak;+iPفw6ǯ*_/ܺOsʚ݌ŧPƊdjJZ^K43[ d$Rn1Te_q ) FMwTi:.$:֣<48 G5;^]-9(@l1T.*1Wmۧj]wNWv*UثWb]v*UثWb]v*UثWb]N|˟n5ኯvqU,UثWbYGOi?Crw*0 Rf|7KyxWbQZ|z<:g*>|CǗZ*Mc_*]v*ѧ|UZZ]v*UثgiZbE+>[]v*Uzs澗/SxWMVe+KЏ?pG‹χ-JVث~JuK֯ ϫڔ*DZWb]o|UPӇ-Ɵ1U,UثWlibtuxcap-1.4.0/tuxcap-build/images/dragonfly_.jpg0000644000175000017500000000135310751375104022070 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C "*!1A"Qa#q ?s{[QT`Q(XG 2N 98؛>[m:Fm;ݟ8TaT%u: zGn WG%dsĕ0AR܊:Oqڛ us3ReHXtꗸz{՗;* 3N*?=)D]cRRKJ % W8 ;rж' QUG\ģ[֞fdJXg}|'hϫ2˥\jf~Zi)T'\uàlibtuxcap-1.4.0/tuxcap-build/images/beam_opaque.jpg0000644000175000017500000000107510641010423022207 0ustar inniyahinniyahJFIFddDucky<Adobed       ,K ?@libtuxcap-1.4.0/tuxcap-build/images/sky_.jpg0000644000175000017500000005156010751375104020716 0ustar inniyahinniyahJFIFHHExifMM*Created with The GIMPC  !"$"$CX "1!1AQa"BRq2br# ?య2z  oQ +bH?XMܫЭ$E#C ]R`-[t blnjmlQP . 6;`ltyΪ d/5?,wS *>c^T@J~@ݍ@#Ĭ+b5bc^ NP}جb1شؔ= @%%:d@1ޒIu=L\U>8^q -F;ҌUz6a=kSf; +ki*Fugs}g@tK`(V;`3``1X P(vKm V]́΀/g~`|r?)Pg.?hэGGs_kᖻg%ye i,Ua~~[xtzx<+Xg; }G J}Xh@qWI V Ul]%NWYs>gT,$"~uc_@[B: O=['YQ^Se`( 9̊y4^Έo$o?L/}Nޅt#(J Vb8b1ش1(jJ'C:(b@KGr9H t5c#M3D3<4C4bіJtf^JD%c+14Vm|M(vU. )^ _f03<+ص횞h ƌu/fd&\K_܉)9OU=|lэT9L޺ Ÿ>^iv6#MIvB~[ˎ\EB]4/R@\+N]xa_}pRc[*סZ{8 %3UQ7Uf`#8- /VU)- 9W6%P)/"^H^o@Z5Oo$/$o"I2k~}0)Ie} C}RzfR `lVЮvvrrVQ&%r%@t^G #4<[fѧmO7(TVQ% 8,oQY)22REc̰X鉭-,U DhT_bmz h h0ya^ɪ `?'܏ ls^!{GsW_K>JBT/@/?L+ǜ?@"1IƗ)%4 82' Ve (FW'Yiw<"ם=ݜ_<ޙ%ql\F '^JN^,}e!hhe@O@IȼZ@3ZiB99'G@`hOiBx~fL籛/+z3ï,ϑoOF;}^93%Y :r+ *z@//-2ĽQ+yg8;K W~Jl 91 8Vw-PU46u;ackM}E@^^O1נ@/ T@//T6ɀ~tpHu ocJdu F8$M Ts]lt0l錙4ð*R!_cl/Ya4 w*/'sh $Ƚ{96`QO@ 5ܝZ_ltt 0;~Zn4zlRʫ sMk]#̗dg5m{9dמ:@LͰ=Z2cZiz]p8*!+*dwvV=?d%J=?H}(F>VctZº@q`G;KGҼ!x`_`FGUW04 s  KH:\ih*N[2 #%S\Z@D"2lJʾJ}F+dH93?H :@vX-u *.Ȥ 0t2N&4"2/K,l +Zߠ=>T#.<+nxe(ҐRg5R ];.E "0#}f-%)]@I[l@/PuAzvߣ\pQ\K&iR'cǴZ$b~J,eZjT'R];EH:Ap:=bkAl-pu^\ߓ:o7O]?ckq,J'햜6II'4c\pEl|7OZpBT;@"+[H/o@..cL‚3)z}@#u!gx׽ƻo%u [=2qo:?do~@Dm)%K{Ii`3ДOV Y^BPVaج^@α}OѦbW 2{/:T( 1OoLe3~E{<䖻yױDЭY[TF:.)uK@ y9%lOk-0=:$~'Զwo~6~ {Aa9m+)lRRDP:T%{>l%2-6=6'Npz#d <DiQje"Ԯ>#:[[ \Fg];"yr|́liF6e~LQZ]8H^mh( ;b錐R v] i c[5a> ߃TB^ Z~\*mI$5O 6i/qlv gF "r>P8+0!+_`|a-@/ܥyNm:ʶd }CUe`-aƻQ>^U LH?Ҏ]IՀ8|o5{KEk"D,™' =UKQ*_Ye2>㎛eϠ}> vuxJ*}k2`c>L='W<'ϒ2L'XN/1OߢzCOK^R zKVP3^?\:^7=SC7 V6ǜ?F+V!/T{7M#KM!(*@_C%ӰFZDr-ri ?BR5TVi%/,~Slv2x~ c~ 2crh ;RIRlyYBJRRY$/@I#^X_wO@gc(e`"A8;;h^&rvw1^^*Hˢ\=křioi1s['lTՂב{9 +:ceMyeF~z遧 e`<$cƞGDrqFx4X~8N] ~F r?boTE)9_S e'Y_-}1@Nj1hk"׆_KcOĽqF1$05aq"Ӓ_fN H>SC1cK2Ӆ~e+{)8װ$zBYcCr~_}4,r] ˣit^Ig|R3R>~YtgYxɒ`m9z&sa8`+bV^ķ }`Nbzmlб*Kɠ#rrPAHyǶ?Cy@TH*FH/d:R$uEO~Tg/&?#6\ gr"@O !Dt:Nd*)t:ʽyPlFɼV@v#v+l *QL *WB QC*9G{ s 'ϛdOЮ^F4صB Y1Kӥ-"{m}@\_FYpx~=ǓH*pf|nݞ(C02~nT[`+౮'\[ɝ|.5IV5+`y/я'\E'@fw唜TjRpW2,,y' E'pWTƼ2 xif鳱ƼPZKKH:k#^XXP1հ#,_` 945>hGѭ]]/ Owǣ;)3 \3½'WåqL̏;]'nY&jLptl+ zXD5vcoKuc{ƒFKon`28mm +<6<剿jɼɎ}a^4]2^*(/~x-W Z.=4N@`vt2|9)D2HD:6FlwZ@#yI)Ͱ:DYQAH & Rnơ%6:^@C`6`[)8c,m#PRpK4$L/@d\::ᾍFH ?~w9@ds^[z\M<μ9rIO ~2qy<^Em ~\tF0c턊)KY_sE! Fm5iܠ#yQ;ɰ/Y1w>n)-G%k`7UgWrdYq /!SogĞocs/`jm>~G89f2e~H^D2Wo})$ py?oFԺj9+RyG]eRz֒&BG/aY|+,6>;vɷӺ^U/ާ7ukT Mu4a}L*eį?caSu[)9aRז{[d0Puc=\}:ey>'>gٕK cO2e<:~Xǚɢ8 eeƀhr"hÍxC'*i4;@t `p;`lTJz)#ᐻ~5M@r]odQ?HB5p+}̽/t^Gh76~b_dD*@d|5 \,Ef^_dh`vN'|JVN_o6ܣF­O2V "}4:hƳ!! 9!$6 R% )IU!SN-@#w)nS~lыBkI8llPD3C~SD`*6׶GBLl{0;7>({2[ ʪZyrѫ)/Ϣu0<9uU_@<Ĥ$Adu'|߉_`z"%}.VIsJW<{<į#Yg{<92yK:g~`ǘe߄K~W~)p~y~SebFWDtGs;@-s7/+{z5,zѮ։dǑoD*^Px\噯~Gl&_ϓL$G'm@C'36N:\R3_ kN+#728|Y]倮6gs wN~«buw_@Q1$ɁdL(d,u)(RdFddI&uf*><@4rr3Ы9#K('~`+Ԝ^*[^K}2fi?p0JcI5Sf5G' Jg~f~쐵<PXG} -v7 Zĵ=BV4mȦ{dƿR`GGr-GJϰ-=&gP? O?`k;Sʲʲ? IKdW 哔AT S'i K@~)_`Q#ܵ . `sM v#d#uձ9i?_Q\ߦ+Q&Wy4i8wȳdEqO̰4,)A<>wdU% eȨNWU~˜9bay>7 <%./B=7V.͜ME =(Ӱn.}uå'iuC Ϝ+7uW<ѽDH?o^^a~ܨT/9a6P`~z;H ~$6%+H7:b4`PҷܴBI}΀cZ\WHvtoGt M#/OOshx hJ`%R R+CЭ bE (zJ'C:(1FVSL"X +ᑄV2IYD[]i̲K\ꌊM4QW}~cT2)vgi2KO}neH6/DVoh?*#ϰ!Z@z4rƊ5xcyO~ywMEf4Sc1+]>dKuBʘ8Y]0"ɦv#ih Aѩ kk,o`w2r{.Sk>ߣ'iATlػ8L=@IufluSb0~E~CN3HW:yb6gbd钺y^elwgCl vKa]@; 7)Lu)ws`t!]VV#+ 1F#@%J(D&Э9@)ܥ9B qYc@JQYC,hu,:?0dr,,uIV[*א(`ʆTE1~ 2>o,3t+^ LG;>f+}٥c2⢳KwqHa#;#ߐ6|q+<[~E[+&elV[o=4+tc;ݣb bYg?h PM3G*aT Эh@Frh)ͥ,Ѯ ފ9Ѝ;mkE71)΅lZi^vW"U-yFpշݏo2~3M1^îԋF5 N1ܬŸv;bsbج;8pQ))=3U#Z iFh ձ)?F"%'G/ѷbrfOr}gr?F+V7錡6AR !myAK :HРɀ(] ð+­ `^oDf)4smfw+N3|2hYytVƭxDnU ˧[ 0+65 ͯ=$2>YeQ:Ixi8t19wbg~g jlOzc],4&mbYYZ i}v +FX^ +ߖkoDrehWs쐙cTˎw6mʇț@JWv')JJi˲uTDbLP 9$I#glpqB98M3;@&AR1/Gr yN[p[p+$)G?bsAD^SI[9BQl c(6, 2C)~za*MtH+5h ˆA\<6T)9NEs|ZIL*ugdsu1+HUp1LIhדlœOO`dmsˁf_u:t45#$<fG{Ra.㦐 8VpP gh^ l+idEe=gC+Q1>Te~CNWS:}by!!޼߄ħL)BL˷?%˕ȴr>:}b^wMO Ϡ"W_}02Gr4vGfwi&GH GA%R .ὓ뱛-wlB>3eH7 T%$nЍ݅O62L*~RU#$,&ܫ~6w&E~3Leqז b`ANO*C 來]Hd-с3ԈH]2nd{l[BJlEvsIe"[@O$QB^;}Ƙ9M2Ӎ.㤐l Eettrcߑ#;`*ƗCw:H;@v 9&y:P62̅_@V2hǙ>9cKMЛ١dFHs+3NTbtߵ5Ɨ kT}y`\V5lP:_WYGk@v[%|m]DoIv=zr䝁 G,@y x%I7d5( ѢO4#mE9N24dC, (9:ȀK%9IȀY+6uIa%YT -HO+hޡ > ROJ}y7Pj/aXFJ풪Wj!yWUHJof:0&cL?c'^LeU/ yhd_.3M%n&'%z+9+&hōfq-wbbG/gD}`<`liů![l^FM/!ܠh}=ŽH)PRA輁B9H恰sy/1@2R@6+b+`uclVF+i OF\:i>'#F~z]c,#ʘUGC~ҟGR ~J9!i TlU쾁$Π* r?@C9c:# }t;e!-@C)PNHy@tQx^耒2Ăʽ+tF% J` duϒ~jՐY*^V%Y_b:&#Zл A@RhuDveC*A62l 蛠: .'tti^`EFUK~a~٣@?@xQaA<y+aD~򚣿1>^_2x_ a, ΀+8r-d7p1xEhegȻSf񇈞h)~#Z8Wg٢+7!eo xxm~FES,zccԲ2_٧~נ;3uDl+CcznyK¡k=.XKo!X``κ$z$ :O=(uա|ſVo߂xU/G8ck'xBK'XW<:bX{xH#_%ckIu t;Gmv#t& U LW:{hlDjW#.\*hFK++(J̽lV,ta dk }i XgH>Nx.<>LO\*_ukg~ N%ذk~&q/E'SC- J:ϲP@7ɿs/@na])r:k$[K4etp 1]͉Thh[F}Jz%yG&_6\`_/+ѓ7{2`[/~ 2o'^{~n_߸Oe}_+P*]/=?"5`>g&~Ly_crK$?aIyX@4<9Z+_q(m&+lz'Lkh :] hE7Տ;#Wv}k>Hs>=f+Iy׆%gSi Ytfy~y6gtf,ǶcLZ%ؙy˖^h ظ9U'̪SOs:W[^Y7tF2ͥAkمq ~]͵ZDLFߡ =5^^@fbR<cǗ5O/BrZbՌ#OK>9߶AЛo){;. W;="tC}*L[5p?z5b:1ya0?_ƗIGVBu/ ;􉹕!/$2qRP/80eyFlr= >:&J`z2k.o%? ~XOO*aKQeA@بuFe Vװ~+':ʑ߰GBuHd]! @.2&e%H)^P%#(2V$T\ހтCZy.zR=z_^mR+66sP5C+GX=k˜2#~Yy^LHe2'\T-E WMk}ٸ}uSyD9[@n_|/N\yW_GF{9Xw-|1R'CA?朘꞉./4??ҿlyqWZISʟ= w8T)\K{ⲻǧWԴScU׹|vJ²W%Z]&h ))|g|Wg|̲־ҳ4#&P_c 4V֞ "2^@`]:o@OV'< Wߊ^dk;S>K~"tw6*y{Kf\FOz*+7@qu͗6Wݳ >,.9@|K>c/bFS/ ٞ50 /=l%_n&P!]𶼁˜ Bz2zhc!,"  C$R2R:Ԏ )誁SKyN-w(m|\v wIˏ:KY hS+^,K2JyȺb`_heR1bAqMwHyy//o=ǽ`<`{܉f9SI#?=@VyalW@j^yF5v(b]6G-4ג ĻZ4ku njf#~g'ʽZ^Uװ=??)sl<-`;L A@:!$)0$Ri%cZ!`i2G [;f';~yW߶ɿa; `t|y߰4b:<uGs>w`S; S^Jy`=5O-ގs܍ةfU5i>pxf|/[g{oƻJBKɛ'>k^Z8|RJ2>z+HqtOQ6vJ ̓EV#&5дP2RdR<%&I& L9c0 e14nC <? 9Mr9Aˮ܁{@梮Eygs9Ŀ%FHME~@#,jH b?i#{^2mB-w@`hGחlx+&a;/ K؏zy%v>bZ!OIlyf &:?09Pʅa`71¹H89S l=Bq:g*Hnsvfqjw8zsl!888m{;{8^DyWuWUOuJ/ oĴw׍p#wuގ8 F+g~wq/%l)tޑz}Q1?GgIqRq8+838!4p+9W rq+&pI!qvHW#DqwȎȕk86\?@O]8 2u8&q^8U*{8;^libtuxcap-1.4.0/tuxcap-build/images/layer0.jpg0000644000175000017500000004455510641010423021137 0ustar inniyahinniyahJFIFHHC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?N)|ʣ.ǑrrjDj]A ) Ұ>e56Ӱ͊j7sN¹e= f5S\Zow+֌sM\m}]dZ 'ӵr桢\d%]R A3h)c`Tjhd oUrlP(iʵ-ڃk\v(BjejpJTqQkIT~XMPӚ>*ז) p3:@q֢"bFhت6jV bdA)3LD5b)ji& +rU5iэ5z[njZ)3b7 T%KEэՒ$i 8cf =".ުM>AjAT\s7&\'CdjEQ7,Pg&%UzV8D5lK)bTS0)P)m8m1YwǭR% a$Ԯ4l$ z08BOv95Bgi Td3y4aMfiwS[i4?5{LF' ¹h&꯾g}!zR@ZPNM;0H)pL )[*"$1v2⏊l]q*3'sYnkV}̫Qg$ջk=+DC$I2Roa7҇e0ֲا  ӳYEX[w.pLdfE 2AEE$[jPM(4 hj y樑yUE50jP1H+*`JT񚤼B*P½K(R1NI%JV*lTE[5b&cRY1P!JsQm W.VlA[I@VL{F!2hh.>CUdz| ǚGU OVN)5 El?&2L1TT9CoL5;y}5%bZ$TnjsLEznҐiX.]5Mf( i*UQ "ݱPfVɨCS"b`@Vnjd*=;R M`zB*l3Z*ʾk!& ?KC}zUY[?ʻs-:VS$ӸyzQJ=tݨ 3ڕl+},~P( `l  ⷴH)"KXJMM"RelVebˊ+c5vSUD36dkNqeu ̼!Z+dDC)T~i$ b$ iSƜQfv(5L#Մ.bITĔyi ۪zz+$ 9)*"o;4@jiCQ`-|}jcOY Ұ\Ӎ`Jù$"Y?hM+KV"b5vCLׅV5Jc =Ú-OJQ9p*GnD+@LEY CMDF)5 Q`n"c 6M)UȢ) e.sV&%֤2W5o.V75E&n֡:i'#.QR1֩S֨IrOgr%'HfyW5a98H$UjZfM2Kzʒ MK|ޛ{7i4+f{e^k\1`=^|\ޡAP6RAr;e11hE5"[VWbqCb(hj{VQJ 㱖-=nAZTmEQǎ&Lf˜"VaRuOM*B( 6)d HPM0,4@Lf5TSasR;M.M+@9Ƌ͑}Z = c (/tTyIQ44ĕ}i򜊧!H<IMvڡ&X9Ip(i1N(Ԋ3H0jdZPȔ NOZC% RD)TH ךJb<j@icB+i8lScJ*@ DRȵ-P n(bE'& 8-8)& Ff2DU"TE5(CRqUB┛) && Gp OCN9 l(RqO XGJWK&=E=:RY,TN`>>a%0'ԩ9`*;u nHv_Kv1V'$Tb[;Gr(f%^aeT,\Z RG$ ILW$y*|Kfi~sLcNA-Ԓc_54#B 1I"G(A4Tw:<8gb0 ;feSh4)&b'1iM_KsR|Rg4xmt6SQWYBNQUdSş8_atd֓L%v]""aiqY]-}ڸ8QJ"Y"/lWB$Ю"Z㝴慇AWVU#ȴ\,P5ԊYT\A#L\wrKI UL*7zFLS-vYL{Pj& S&CKSK1UbNaҭFjh} r"{SEgu+%HlcAjyÔRSGl}+p; oj9;zhl2EyjԼYR&IN*\u@fp4(]SS)i V'W{r"E!R7QJb<Q49+dR89Ʒ"ۜĖM:+Bd~:Tfj荆G a9KVڑڡ004T/jܱ[K='!e 6)~tRL QW)5Qt`A%8SDJ1WǞ !*:QqX&ھJзҙvaO?'mϦ0ys)!oJ [+8ʎ)s6Z2{Vm0 Nh9NlOjUbxǤǟZ4}\r6G*jMVGjdT^¥ifq*HlH9[a:qKeeO-rMA4EćXHŞ\5QӘHQ-Mjmljb!M41>35oˣʢWU8O jplVٚQZӂcE 8ҮhLFkMFW:֪*cړnjȌM4\ B#N1J8QEc'0[pE1VQpR*U߲dӾW JHPւ= ^Kf)ҘnO_QC-5 CsY=K/MW{-iX/ yTn I杅rqQ3 e=6XW- UYj/1G4r ^,S2;Q>Q[1tqX*i6<82)EsLcR$#y5GqRsMeqOYyr:TXw4J#.«D85v)u4M>Inii%cC)*\4ԗksLD tqV,VR0¥)D4bPuJw,w*(OzԖћԩUqG=jOLW`TF/ @0AHmKPcR;n5eΣ\G- y@Ck bX2jO'ֆQ⡓FU lYB)VPn2A,C>0 D2j[*[N68 vj/1`t2Q"\x9j]w,Vd;UbNTͩOYM$`qs88HMK Z3֠i3]cS Qi֛{Ӽ5 BqVQL2p\T[=i&*4aQ3SȤ\Ξh0$b|ҠJsҝ#8rcE=V+іȪa48}qOiֲK?!sEsAS5Td¹m0`եɮDnjݵĈFsM\#+ I8QYܗQW f\֤k@9lTREIW 65i5ZLEmzziVUj  rS|[g\]n)&ȸT݆zf=M ؛)aH ځCdVN=kn@(\QF{P+jpoS@\L怦bTjh({0N}iΠT-LW"cUF5ihU䚋a5<-G2ZZfCAB ؎*BJ_i42XJja8&2ǭ (;j in95Birx4͔9W8f9K7>P7TmsֱǹVPG&(sՈ"+J&(95&JZHhDR3ڀ%Y)r W!JL9+QDiZarB4M&9Ґ tPvqP<~ޝiZCڢf&xFTF&%"%ȧ,<`5 daiK 䣐wַ^QQ(K8g\o48l5D '5R{zg&EYA]4ְJU@a>R^E@QA[2UJi$vǵ_ wgTHJ$#2fUjTfaU@z|Q)5DKRX Nj)}tvQ]jA0w'"Djp(6S$mWblt~GlTdZbe#LҸdTMZh]x"̃JgJ1T/jZbԅڎEf_)Lh1\bMMO(T2;Svx4HS O(q3R#41ǵ,@̤VլXsֶdʳf_= j[fE)y"P-;X@JzaH8R .wZ{v.mEoUF*S?P*hM75BH5ͦ>J]069vVLkj{,UsQRiR:wj`4H@*DjpJUXJ5iEdt~1S39P;jQf[\ELkUehQp!c`EFAܚ R Ƥ\Ұ]ԆrjSwJrqB]ze9+F-ZVƠdsY| %8cEAVcګBմEC,qHiZ'N+Ud( pF={v˪=jdr:d7vcqȨ7SZb)zTRפu5ޞYf+*te'5- hc͚ jߒuW{Z&Sޣ(kV[\U N V*hJw0O1M0G{ҧZITmg93fh_JcHBE'V ;jDBNg򜩠7SSȠH"rQ<9W_Jw3 g*zE()Qq=(6L")?y+Qr9qTjRt҈I#=e ֣[x= i[O8CN+*#XPRlሒnX/zVrDCwhqMD ']ݳWSyæ* 71@K3fFmœsEhlW1HK$èڐ*ÆӧYC2l5(^®S7m ֋BL'O5{X bg4< ӎح:4Zq?J_$*6a-mxv Qڨ>s=E!ܱpP(xSSC˂W5}”Ul%hR@ S4b(iP) 0)=!'X=i\ dJ[U\f|h{0Uj ))\v V@4Ӆi˻WRmN4wOZ,ƃTFMUWSS#`Qړ^SR{EVǥ5 [HԢf84ژQUFAL$W9pSB$麫^sVY⳯$|-7pVubK7 4i ®-?C\[H<3!M#ȸP}+.p5"^?5jHYVqZPtQR$ Q! vz 91Lijierb$6}M{T2zmr?EY7 R?8A*# JcRhђT~U'[v\$%a6>IWAH4&'N[WnBU&Tf{)E?tӸ`xDêWۮ4'<*RAI wlϴ*6A@DTuU6QNI]]{ ))L F#=f_C@=qe@'48u  %>M4ʤY`IՋMAI}M]<>F[n]%*ZipBa}8O:Pis$"y4$dɁSlnxPOZ|yg>Ƥ@ ỡ@[ )3IZ?edp3BOKCH>ETj]kP) E]B/ANCԁ2#*=+4ƐJX|ƙ K9N3ց"VC& .iɞ͕h{ ajB4Q4OHŊYX9sӊA0IID))h\uh!UE9vz Jҁ\8sNhr.sRIl~ if>VE[L+泎sVom i\SOܷqz 2O%#)|)Jb'N(4Gq iX{VlMamqMkhX|M2[9{6jCI2ɰaҙ?ՅȢEVS>i/s֚<04]1\&f*պ(U\9NnKN-]3$VͬD݃XprvF5fI:瓓NmEp1Y'K݅hn9Ӳrɺc\k GUtE6K]h@? -c?*h*&E+b@r*U@wަ{^1L`5#\7tdI&zP34t%Xzԡ@RƘBzч=XTa/aJcɥ,Qxl5u#PRMV5#jCW=5 Czh+VS ǚmP [jW TҳW×oFORK >{j{^MEU[գ[c֪|c,dqDM#Fº; 0 (J-"t5JoXN0ƺ0qNK-p#N3Y-AqC7vm4 ->J=)oJBV1/P (h@* V1ERHaLiV=IueR: "MMsl򞴌*‘7$cҠe=Y-ҕ`V?=ajЍSh~z[~*/qW2E+٥Ԯ!Qҝ<3ZDҘLaJ{T/#zPChVړjwBĚm+,zӃҁiJRMH^)=y4yC֝.xj(**vZ.5ڤFRG8_Ҫ6Xu67d{(žɧv/m>IGMVJ)xw})A♦2FTPKQ!=;Sݽg=EZO"5bAڞ"_J ]D;Q|_3ޖxGzQ w2ƞNwfẑPTe9B)"\;TZ'q=XY0!tUyEh]T44T⭡F(,EYjR0",HPiJaqL4wRG@\ ۞en[g#㠧E4Y.݃ҳQcގf_&i50{FGSG3'Ϲpޏt*hH%~&VP(.ig܈ˁF*:&URhygf496SrO\=GyCҪ䙢3NGjPcSQR"1(ڔ9=i )n47JbSſ LGJ& n;^ԊoGM/J]NsJ) ;h=j55*jQiH*(WJSe#fBX 1iژȄ54wR):UP+ؔ(=)zpQ@_J \zai/cRFP.{TTڬ޼R)H3O HR7(─{J)f1iif2ܚ2iأM48TqJ)+ih֙wC3'֗> *i4@iDkR~tQarX1J2*Ež$S vF1ĸ/X>dit>aNϨFiy^J2wY0r }kH6*61+Ej A$Xj (#V:M(bBԛ*%7ˤEQFMP '3L2W Ji})q3ftQP"ýCpJhU7.RbP֗`N "-ҍҬ=)Urܩ{zOEA}E?'>SEB#o7E"'ދ!E4xQ*P{'7NT.ti}1tdfOT4B(#7S,~; N) [(IMz]aԦF:҂=*Q4}*\Qb qN3/e_ʣ2=}JǡG< CEa@4AdӁ4M h*3sFΕЪc#&WFGQOE-)eE1" ѱ_{Xɡ7QBH't.7RbS w҇}BѨ+FiBӶSvci86Q(Qu° <QRM"p=iv@փE5ؔJg`^xhPIKځKJ{P֞IM761 ֗}*UN)sG5g*W+Ti)JQd҂@gDJ`.BO,إ =.R}_R}):# dʕ++U)ܨ)Ӫ j(ɤq A*LvcQ\ &LE'6p,*z&eSLqܲM)-ܚ.2~aSdc"Yь#4,;"POr*"/TCtR"pcFsN? 8 b$=:S|V+"%֥T^(-E!J7Fڗpz=rGE?x,j.[`}iұHM֌ pҤ]5(RUX縧y~⒜ &ZK2;fI_ᩖ=b7ޥbңO)XŦ94}H<'.DlҒڧmOOփOdV1\4yC֧1!<'ؾZjpiGlQr(Gғ5pHCzS!EPҝlii/|moZ60Zt$)pިԘ>%ڟޤؾR4XwO-4O}8" RD}(Пg.EJc#4.z ڜn =1i~HQ@KvO ރlRNI FڔId8Xf(:=;)% L:.8+:I4(av?VݐuC_ʕ(Ԁ4ܷV|c4?+͕?xaUuɧA-YTuf=T; ,'o3vtV.уmQQE+>XBz)yOZY=AoASK hCMK2vZGR5F $U8=&\HnE/[z~Y4, >{gx4X9!ǭ46{Sϭ!ߛazT)6J8)J“KCLHUqцjEZ_JnMF\ƝC6Idڗa\񺣘Hf;Ql/( ~sG5.3~Tm~TW#+6HVE1܁XԀT? WjPA$4}i})@Z`>Hv=)dt;5"~ z\{EYtHjNx5g֌ZjV"TM!R;UzFюTUs\Rޥe2f&)@nƜ#pߕ&Pɩ2ϵ+GTI)_zp i}=haGI^{ޑV}moΣC a)RΙaHi|~tտ#I}JHi3FtT2uBM1X Z SFʬ;SG0I">{f*=)1qc33O?V3"a})8-a1SHaS= ֔z*|1G0(L+S#uPTp >b+(Gj? \9zQN֏ƝEKQH,7oiSP͔ Qǭ`P00=(jnG>hORr})`S>sN7Lw> S֎=M:u=RI3`4Ȇl:*&Qyq`zQf7p7pKEW܈`?5-\9GRcދ`qF?`zQqz;ъ`ȣ4`zQjC?E4h((tѴxʆϯN3e>w*٠iQpC1S>hFsҌRىGKKHviPQSʆm(rqKF)sI=)bw,?RQEQH(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((libtuxcap-1.4.0/tuxcap-build/images/smallShot_.JPG0000644000175000017500000000121510751375104021706 0ustar inniyahinniyahJFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ??ž}ysEPlibtuxcap-1.4.0/tuxcap-build/images/particle3.psi0000644000175000017500000000020010751375104021633 0ustar inniyahinniyahre9@@Jx?HBy>CId۶?=8>,˿r>o?5MS>zg?j&?{>A?!>libtuxcap-1.4.0/tuxcap-build/images/atomicexplosion.jpg0000644000175000017500000004745110641010423023156 0ustar inniyahinniyahJFIFHH.ExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:01 18:39:002(&HHPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMS2atomicexplosion2nullboundsObjcRct1Top longLeftlongBtomlong2RghtlongslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong2RghtlongurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:8e421822-74c3-11d9-8a14-c426ef2c7c0c Adobed@      2^  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?v*UثWb[N; EoL(v+N])c+4-0Kf *GΙI͎<2 K% 5ͻ2Fq#h02L]Llۻ(ҊM~&h[%?OV]¶fqٲ2Zu%I*~;f>.3Mya10ӘèQ`̸%؅N4QuHcf~)Ϫ.fNOPѿ,/oL\Eb9vӻšsЦu@ҕoBsV;vb[~9{'ʤsmd4\OfMk+2t4 r6{!mk5˅Ijd'1f8 L]d#z@~]}l={=!TbyRuc:\@ \kAiK/f:uO_$_6sG =]4;s늦vU8F;l ʥzidKy0"Lq:N|_]-g5ðEcbj~@uk͡>O?/_ 洶zEp ? ~@e<]P-Tӥx!u*AF*v43+Q6U0ܵ\&s%D%̔ 5zlp[1GGYhzs5#?@g,J<q}kƁ5nn,P+RHQMsqz3GαA<[ÏSLG(ćfg!ث`QZus43 OØm{#c J 5+LK`k6EoCOXZ cn yP6ؼ3>dOȟ_(ygɿ:tH>1̽,|JU!TU UgNɒ>GGj(zL&^M>w$GmLQg`&44bPVo^DϖtGD-% n-S` F}9"2 rZ|[RWdUث47gcn]i8{׶Bs|[&$?՚WҔ'1g"~U_$J_%IYas %(GH #=M30V+UHw c*Mq՜[w ĩ9\<ۛsPO ؁"/`s؀rB[E'YԚqڸ&L( irX[Ab]v*UثWb]ARmrYFF~]k:#ɰ +59_+.:ا俚4{t{IWȄ~#l{K.9z;Esm5Au4!"NU "يfh[0ỵOKW`L1DPB{ggwpC8#Zl%hQFq wQ?TIs0 fmapŪ+?4lT<2X;kQHret+\oQB!?dFtu8g]8']}?8)yu譣^\1B۰c4aq:t"Iw!ȿmr;#tԃ`N^1s~f6M6H{Yd4l;8ͣ\;㉞Qב4ΠnW0$PzNwU2&Ër?jy!Q! F>TZT; O)Nۼ[MY(+4 :׮KQM/ÿ'_@WwZk3 n\PV^]bQKɕY!7z( 1UQReAi>V5֩Ţ{\Ss&Gg"=[㟛C"+ҕ2d5Ƙ|CYvr7^fG}zҨ쭢dt~rp{OSƑmV$Ttr2Qydν?I?&,ouW VEV֣39ǯz$=jOt}mJ@iWaN IQ`Mz -b~Q[q8 b+\Zk2Yێ|)V+e>u= 87,iRNV1XϿ4 WRn$I'Ny@k=9|ZGQJf[s=#ŏ+YU)s%뗱b3oess&ȈLxK̋?%&mNR,u#~Hb/m>ygx`1$9!?\R*㊡5{9U調dq:~<ՅO)Wٮ^9*v*UثWb]v*UثrXDʍ2 NA֌Q6in'88=mw+y0Is-sip>,6.5_ }ye7[xb⏒,{,Ԇ.7D%ldz4{;.3xosO}>탗/5FdFR쥔V~㝏-V{E,;ᝣʻ3zp#$㟓*OyH &@QF^n"Reu90DL V_:RZA "q{;=fS/?O,s:ni}1JRO}yjhB z,HɸNZvƠN=G]C!6g?u ƀ"d@9sXcCi;V>FOI5E@ې(sKٚ,Z̤psNHz73"<""xOխ埛}Kp(RA>lz<:Nˌfr#CS"3JĪ(J>Ub+`;!u ;3ҁn':yDIK`WLs}w kMw[+V@Tz(;*7-M#@ hlYh^TlHZQ:[4 r‹Ǥ>>[-|ԯQ鄌=Q96r5b<>oZy+'Q@QBՎ-gួs?Z{}}U߂D[Y eU T\Aq?/=ռB:UlAeo7HԿ ebzmf̀&x.|嗔eE4d֯!42OeU&RÑ^YiY%9,A¯?)*n08RJہ d9>+&hTP \_y7W:ٍ9HF;,)1;[ɒz?ŚE:湌IYUukndgyk׮eBѿ!otJr̭ x>q;K,DP %/Ġ X}c"H| 5G@1CɪQ4$K1H(~QjpO /Qy#^tq,QgMǸ\S+K/+IqE%@Ɂ[jFA ? A"I]늳ʷZQ FBz1dn` y21bv*UثWb_@4p!/'<}u(7b(8[:A.ndp*TfZ= 򨓳Z)K!0?*WŬoj+/Кӷ4'\Do%T_?Ǘ7)k"xO8 =^s=9❊CZLex@FFߜxg<$}uǻSǖ5-6Stʰ K~y{)zm]T(.Wm$\wٲK%h*wL#1yD~RiqQk/[^H*Ѷv:x{.,x[nr?4KiӘ{=oD/W7p<]R3CKq*H>\Z|Jcef™ԃЇ$ hѵDVA*$@ /0˦92`Ⅺ(;碌1u/l,/ȮU7պQ _lnp"vq(S9Ekhҗ D×9>#ߗ{1Zwg7ې =r˛;qUH[$82Lی/ΫGZ6W995~ >Q stzj#q.ĂRPb3M8J[q@s2K]s͓ bfXNyt3t!"z"![^ގ|]EOPB|zXlYޥg<*$<_~ja+^ <󆺴(E|,o}6ĀpsfR BWcF%vzfj$ б4#fuPȝZydTA0RjU5Xzga{7p>o]&8lW4>G79?s$]o R"IW= UӐ2qzmSa pE9 (DN?˭@[pX0I Ob~d^Tf#qGzBQ'v5P|q9/hXHN$WC?2PKvv!7!=k$ʞk%yغA54ѩuv$q_̡b@A+A9h |^cXhE5tXKe T@kkv&] caaylR꿸(ՍZ4#zfX3r}Mc 3o_@PJ'm̽Z6x H*F߶k3%!G3m;1j:t=IJ2?k!w1Ty/ΛzsgQ=ϙഎYT{S "ۣ?ϖ4-e6"f.xziI̢dQDܚ.sQ%_m[ʱYO_7DཌྷӨשlHq>_z枷{ţ E(G!#E<0yg|/=Mʮ=M~j}A>C%Hi,^V&mQX4Uw$aco g:'svNB>ū-4ڵ6q_yV1k7d,ŀAþ@du6kwדb$N]8xovICUOQ }w^}R; 5]O]gLκen}dSn S_ZUثWb]v*6 9%OFO nÚX͇^Q״}F:Ū@RWN#DOIqH#0(oOSD $Mxپ伀S~-G7ow}3Hj+_ޓGM֫U,r-v*iދw圅%;5#&2[g#aޞI@yGg ڞZ>?&i{3U!#$u53Y*. |qj]K.Dy5[~͏L :}gk#<(j7ĝÄbe kC-0o|{"/ k խ v#5=٣TVqȿw?:,8#h \QPFreу$P/r2[]=eny fUKc#r1f3ok"@_`A1v\ܺsV:9xVa@Ŏ"DnO81;>y߹st/x,j觺9]w8"ah5B0/ïɟ#szvq' (Q'.?A&>-?gompJuûO˿RH"F$T5zˌ1Yc!r̯ cskԤ.+0GcLd]Ar! f=̡3!&OsYɜ8_~C뚄` +֤|Ѝ<L?ǰ5Xdv8q:vzu?? _ Ƴh$oNR+nE6s5亢5hcsHڊRXP~(d=c7n6X}vP*rrЉwWII H'<\qfED_1#o'꒳SM5?@ο{ pCVzPP=)X0_0?0k71sZH}OI!sGÞ1YVz8 ߑZkt4/-騲]ܒ [7 B@]ZXiyrtKûi͊la Qs~W7ē'ifD^O DkwS}roJ|G  AK&ܝ퐀STT3UP䓰9\VszWwAo^3*+DfK1\\]4LK^2DdsǙػ}59kҴV ;UKZ5wӑun5a(pxmZo51LC["lj4Իמ2m9W%/155_;j7%bMI &c#O;|rmn^ ]oQBcF[VIa[3a-jڌ^ծ$+!bEi ݱy mT~Iov5ȼMI=NMUZx;bNfQQ=V[_`+{$FF7ع#ub`{~p(&Njs;!].ڜ!vֵ$73I3N=!ϯnlAbX!]"l+22a،UNեvג~~Y0xv^8I_0UsK˗=aQ7bNmcܷKj~wBc 2'be2SfYuϚ/>q(Yw%,Wb̺\LPa K1f5'6Ny:PY|y^&|5!"/p^Ii!$'qg;giGMdLj~S@=y-f/ ,SCz6@uѿw7s]f,7p`(:Sܔ6MZjV%nl3Tqd06êFy6&qs7wf* 7އ'd.h·]mCC5ؚ0rvvNa]0y.$AsطAm /f7u;RFi6m1͞Yn\j#^D<.6^&(ephjwRLɂq0}&.y&ycv.}wbT4R?xv!~wOKwI%Ư!jYp0Ƶ/4__Fˡhɸc.Yر=dNR26[/r^y{YU|-tVUm,y#5H`sG(fxIh=~iI+.[j1Rhva5xnHT/@[ɯ̏1_k^a$[ ;SnŤ9mPO+Z&0y"zLQK>{$.ZPzW~ {o xd.> T8bc%'6sqRPo-]mٮc~|>#Ze`"IW_e͡mC^ϔV:|*E>SN2iG9|1[ԯٞᜱ%rNfPőҢjIkWΙaZFO&RG ۮcOՐry{qWneկ*ҙHql;< 'rO嵺ZpмM*c*sUyogI2@8S$Rz(v*ǻ ;@o8rr9O|7E}w}#ͷqkik+!Z(f^@Dx0mf_-SQG+QCƤ#)F-O7r]7S7>qu?_eO>y<7Wb_Y6W3ls 3za2|vlu͋Wb^g)5x2c9CR?gq++>SaPXUثUko.GN{de_K"k) 4R]1bk犳'9_rc_fJ'X]v*UثWb]v*UثWlibtuxcap-1.4.0/tuxcap-build/images/unicron_baby.bmp0000644000175000017500000000606611062275555022427 0ustar inniyahinniyahBM6 6(    *),=;?HDJIELQMTLHM748! # (&+PMSc`f[Y^DAFIFJ{b^cKILLKMa`bfchEBH,+.[Z^XW\0/3 KIMHDHjfjROQCAGVUY('* OLP  GEHfeh-+.a_dFEJ LJN  !geh?<>FDH,+-FCG  QNP;8:  JHN324   %)  dbe,+-:8<@>E %%"   ! "  dbfZY\ !,) %-. !( (      BACMJL:9=548 &%.-&04+ &&    lilPNU   +-8.<&1(%%!     FCGFCI/*/HFJ  ".:;J.9<6;JK[.;o$7v1h!-O$%.    b^eEDP,*.   "(6>: KLITGV|Kgo t H.v$+6     ^Z]$!$YTX   8jSW2#- .".F7Gan68c>cW5$$,  =OC 3JHN96:e]k  ,H Z!)Y $k_ E56E&\Fq~ûCzc0?fAF\$\S>*C4<8?LHMvry-*,   ) ?60'z !JICA?3K+F4HRs^SnB$W;!L3>*5$ '  GAG-+/GEI;<> d8Mal܋Ϳo%nm5v{qR1jF%_?"K1:(4 KMQ+((_\^ @"RGcvyݪ̹ݸд˵fj>].vM'_/N3=   PFQ  dcg "\3v[kzywuykU̇Fq=Z2rF%\8I*EDH.-1335[Z]  d8U̹gmvmnaSʄEi9N*j>"S'0  "RQT  a`d/.0 Y0pPYݰ`[ܴ`ṘHo:X0t>%U#.   JIM.-0!gfi+M-fk=u?wAc8T2sE'[)7?=BA@E769^]_"E:J!  &&'\[`444UTXIIJ 435GFJ778jik.-/ IGH  @>ERPV !edg\[_ $FDF 326a_cDBF  223feh^\^B?B$!$749^Z`95:)'+GFKb`gUTX +(,KGLd`fokrtowwq{~ysoukgl][a@?Clibtuxcap-1.4.0/tuxcap-build/images/loader_bar.jpg0000644000175000017500000001073110641010423022022 0ustar inniyahinniyahJFIFddDucky, XICC_PROFILE HLinomntrRGB XYZ  1acspMSFTIEC sRGB-HP cprtP3desclwtptbkptrXYZgXYZ,bXYZ@dmndTpdmddvuedLview$lumimeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ QXYZ XYZ o8XYZ bXYZ $descIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view_. \XYZ L VPWmeassig CRT curv #(-27;@EJOTY^chmrw| %+28>ELRY`gnu| &/8AKT]gqz !-8COZfr~ -;HUcq~ +:IXgw'7HYj{+=Oat 2FZn  % : O d y  ' = T j " 9 Q i  * C \ u & @ Z t .Id %A^z &Ca~1Om&Ed#Cc'Ij4Vx&IlAe@e Ek*Qw;c*R{Gp@j>i  A l !!H!u!!!"'"U"""# #8#f###$$M$|$$% %8%h%%%&'&W&&&''I'z''( (?(q(())8)k))**5*h**++6+i++,,9,n,,- -A-v--..L.../$/Z///050l0011J1112*2c223 3F3334+4e4455M555676r667$7`7788P8899B999:6:t::;-;k;;<' >`>>?!?a??@#@d@@A)AjAAB0BrBBC:C}CDDGDDEEUEEF"FgFFG5G{GHHKHHIIcIIJ7J}JK KSKKL*LrLMMJMMN%NnNOOIOOP'PqPQQPQQR1R|RSS_SSTBTTU(UuUVV\VVWDWWX/X}XYYiYZZVZZ[E[[\5\\]']x]^^l^__a_``W``aOaabIbbcCccd@dde=eef=ffg=ggh?hhiCiijHjjkOkklWlmm`mnnknooxop+ppq:qqrKrss]sttptu(uuv>vvwVwxxnxy*yyzFz{{c{|!||}A}~~b~#G k͂0WGrׇ;iΉ3dʋ0cʍ1fΏ6n֑?zM _ɖ4 uL$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)KmAdobed      "" .,,,.3333333333    ## ##,,),,3333333333T" SQ%!Rb1cAaq"CB3QR#%1"!q2bC ?ߧ>ƪ(Db_y\j"r=';i{juZVr*>*zw-Цt؋G1Ҿ ئX9%B+T3T/cx2g\>B ԶƥydՓͨAI_RLGxգ:5<_R8-GwՃ:5,`i1m&^wՆq}X3A:#Ac>LcɌNx-ߺ3A:#P-/m&^wՂ;AbcԷ^GwզwՃ:5,aRLcI`u'DjXc?/8cVLg\>tGyd͎AbcԶ/cDw}X\N }Ki31Ki>;a3A:#P-F0m'_GwՃp 0m&n2m 1&8ƬsA;P5m1m&^GwՆwՃ:5cRLceՓ33A;PU-_L[I]VfٌN GNO7Jt9VozKhʼj~JwKT[ދU ~_R76M'|5 _0GAG?Tz[F,ġ^=F,zrÖ0R}|(2. qfw__qҞ;0 ʀ=9&P7'q" sd5⁩zAn,@e=nI@@d%?%k;Q;PP?s8^( sS׊(-Ř qf׊'(J׊'(w p2~J2Đ\( $nQ[PPEnIFQ[PPA{rQ%kVAWܠ p2Or:{@e'"=<ߪ(1|GA_N@>zkyylibtuxcap-1.4.0/tuxcap-build/images/unicron_beam_right.jpg0000644000175000017500000001054210641010423023566 0ustar inniyahinniyahJFIFddDuckyFAdobed      SUAa!1QbSR!1B ?-S)L11ի3eݦB#G3OLTq!QI+dKTR|FSV'5jot5?cw:V+oENթxaq90չxaq91ung)$X\dNLM[/y : [/y : [/y : [.)$X\dNL5noxaq90չAoENVKoENVKoENV y : [/y : [.)$X\dNL5noxaq90չxaq90չAoENVKoENV y : [/y : [.)$X\dNL5noxaq90չxaq90չxaq90չAoENV y : [/y : [/y : [.)$X\dNL5noxaq90չxaq90չxaq90չxaq90չxaq90չxaq90չAoENVKoENV y : [/y : [.)$X\dNL5noxaq90չAoENV y : [/y : [/y : [/y : [/y : [/y : [.)$X\dNL5no)$X\dNL5noxaq90չxaq90չxaq90չAoENVKoENVKoENVKoENVKoENV y : [.)$X\dNL5noxaq90չxaq90չAoENVKoENVKoENV{+oENVKoENV y : [.)$X\dNL5noxaq90չAoENVKoENV+y : [/y : [/y : [.)$X\dNL5no)$X\dNL5no)$X\tNL5noxaq90չxaqө90չxaq90չxaq90չxaq90չxaq90չxaq90չAoENV+y : [쯯y : [쮄)$X\dNL5nwxaq'&;_^~,.2u'&7]yӗ ~qwٓ JcKLP?fډO%?] و>!/A~OEl;uM/:럶,znzs.c7TW?lX[Vzb٬s^* {LXl9uM/sŅg,]xn嫟,-=1ax 4UӞټw^Jbs&c7tW?lX[Vzbټw^+' {LXl;uM/Ņ,6oẦbs5pSKdao}97TY?lX[Nzbfix,-=1ax 4VOӞ6kỦb.c7tW?lX[Vzbfix,-=1ax 4VOӞټw^* {LXl9uM/Ņ+7SKdao}9fix,-=1b;uM/Ņ,6oẦbs7SKdao}9 xn~ذņ7TY?lX[Nzbfix,-=1ax 4VOӞټw^+' {LXl;uM/Ņ,6oẦbs7SKdao}9f ix,[{LW]xn~ر-=1bl;uM/sŅ,]xn~ذņ7TY?lX[Nzbfix,-=1bl;uM/sŅ,]xn~ذņc7TY?lX[Nzbx 4VOӞټw^+' {LXl;uM/Ņ,6oẦbs7SKdao}9 xn~ذņ7TY?lX[Nzbfix,-=1ax 4VO՞ټw^+' {LXl;uM/Ņ,M8n~ذŋx 4UӞ6kẦbs.7TY?lX[Nzbfix,-=1aX 4U՞6k຦bs5K\ao}Yfix,-=1ax 4VOӞټw^+' {LXl;uM/Ņ,6kẦbsf ix,-=1b;uM/Ņ,6oỦb7SKdao}9fiyk' {LW]xn䬟,-=1aX 4VO-+&7tO%+7p]SKdao}9 8n䬟,-=1_voỦb&7TOӞvoẦ~ذņ7tY?lX[Vzbfix,-=1ax 4VOӞټw^+' {LXl;wM/Ņg,Mxn嬟,-=1ax4Ņg,]8n嬟,-=1_ټw^Jb&7tOӞl9wM/%dao}9 x4ŋo}9 x 4VO%+.7TVOӞ6o໦~ذŋx 4Ņg,v rd%1i3Od7ӡ1LX޾/\*lS~SϣoW+ [6Z&*T#[Miߩ<Śy-EŦ?0brCOHYr lv@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1P*@b T1Pr5r&?jT0ե $)BXg"%u"̌abI-qD5ɳU5QR*v4M(libtuxcap-1.4.0/tuxcap-build/images/particle10.psi0000644000175000017500000000020010736754714021724 0ustar inniyahinniyah6e9@@Jx?HBy>CId۶?=8>,˿r>o?5MS>zg?j&?{>A?!>libtuxcap-1.4.0/tuxcap-build/images/spark.jpg0000644000175000017500000000163710641010423021055 0ustar inniyahinniyahJFIFddDuckyFAdobed    +,~ 1!2AQa3BR#!1QB" ?fjp] ʘ16$Ƃ?+K(Ѧ*ʓu5v6 o0$sKW3^G,|8j& `Z窬G,' 㦐/6ә@ԁi8q˝%m]mVD5#n5Y0cq]0: 5Jm!a!%VaF.)Lb6\tӒCp adobe:docid:photoshop:b9008253-74c1-11d9-8a14-c426ef2c7c0c Adobed@      22  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?iڵZKJYY@G4UUN*4Xux4| ΋ .A긚^ʧ,lUYP,m~m^Yk/t,si&iu%"Kܾ60a͋ h.nI>,cDɿ0?49-:yKGMϕm+Xn- B$$' ?_~&C: |H'*ܼ<"]&$Msɏv̓qeX*?ynPr9Jw;gAxox,򵎟;+H7]Hjl%U/jl/uGkm# -$Ss]BFYF{y 2$Ū$֧2NT8M=ck+g:Ceӵoy 4]oHX9MI&"j3HLuv>zXN\9τ-u;ak衡ɖ2$Wuc1Sq+"7Mچ4B[q,;qrV8c9*h=^~?Ã$1$#Db,vad_scHpxE_ʼߞ`;琕<ܺMp12I>I)W25/]L ΥeeXrf#T xe68/islwo&} ޟ1'?P֭FI-kr;nboTϘ0/khr=d^GG_q.6>OUOSy4Yy]zxBk>s4;Z}sKnfurn-v$vڴL3QϢ7@כ~=&=`b|j񵥫CsJsEPw 󭔞+.k!ZFEi 6 v"'2x֮{?| _30j~Y-}&F +QIvtuٔOWMy5 y;SU.[F٤"]ŔLf8YP<4'>DwȚżwmi3$YkJ4.5js#]Qk->",刏c|iŽ|]\yiUӥfK{9ѣP׃B8?9;bЌ_e<-&m=oP7T֓H1p~^SEqIJ4|So>/<}lSFth[}kȖfc;,Vc(%C_mI?tt;^/l~/Df?hOGGۋ)|__LοhP]libtuxcap-1.4.0/tuxcap-build/images/hero.JPG0000644000175000017500000000124310751375104020537 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C " ,!Q"Abqr13s ?Lzm(JrN\CIn9`t\CviVר8̊~xc4pҤq#*>Z ,4r_u'pZ蚗S'GՓjY`)` I]HԺ{a;-hU9L3Y]F{F{49Npm'J#5M'~p=:̮*pA4AyKrESYfRt~FGϾlwјe*?[Kҙ➖ڌ0GW#bHGgvfv9f'$'Alibtuxcap-1.4.0/tuxcap-build/images/unicron_baby_.GIF0000644000175000017500000000225510641010423022370 0ustar inniyahinniyahGIF89a}}}|||zzzyyyxxxwwwvvvtttqqqpppnnnmmmlllkkkiiihhhgggfffeeecccaaa```^^^YYYXXXWWWUUUOOOLLLIIIHHHGGGFFFEEEDDD@@@===:::999888777666555444333222111///...---,,,+++***((('''&&&%%%$$$###"""!!!  !,pƓB#S8(̎ @ IJU!8hG9#1b:إD#p@ s<Hb@*z9qI`8:aLI348~$G@1p.7cH"dΑI` 1P A_p@U @C@VPaa#xEDqB"#݁ q Ge 64P1B Nх mQ ,qcD h G4R@;libtuxcap-1.4.0/tuxcap-build/images/unicron_beam_up.jpg0000644000175000017500000001213610641010423023076 0ustar inniyahinniyahJFIFddDuckyFAdobed     r3t6!1Aaq#1q3r4!aQ"2Rb# ?iRՆa*?'}W߷}[ P8"DTsp'-pO)OSu6R>13MIR?Z᧗m  i.nm!ҥc%SJ)p[ma/(OOz"*[\Bp q/AWh|[槉B 1?џ= +ԦҬ1ş kO*sw |}?>v;Տ%o⯷"/\0sRq@+'?<s͸Ղ%p{٥)0XW(^ G?cvHs\}qiQb}蠿WU[)c*t 4!fh#b? cݢJccU1&=2U`NSG z,)v+ )TҳlU:^*PT6.o^3E1%a1*ޓ~yzVm#^+X*#FŽ~=ƻDƇczM{mYe{TG {׬z,)v+ oczM{MYe{TG z,)v+ )TҳlU:^+@X*Ao9XSVR7YfٗuҼWPT6.n^3E1%a1*ߓ~uzVm'^KX)#Fv(=$&64}?@mBBpێpێ%I @%I>캞A캞Ab?1 =4M?n۶>?5M>)">9c?%I>5MS>libtuxcap-1.4.0/tuxcap-build/images/particle4.psi0000644000175000017500000000020010751375104021634 0ustar inniyahinniyah /?)">8? Ҵ@x@yBHCpCIdIdII۶>%I?i>}}??y>%I?u]?8>>9=>libtuxcap-1.4.0/tuxcap-build/images/hero_.JPG0000644000175000017500000000132310751375104020675 0ustar inniyahinniyahJFIF``ExifMM*C  !"$"$C " ,1 !BaAQbq ?+n*kmjʩV K<`9x[5"jJVK luπ\\C@n#WFEmh w쉏]dvK-MSKbc6^ ](+mW*mʖjJYZJnbl~  ;| \yFIUysWS신޻MIJ?,1g7r,ZՠsEI$libtuxcap-1.4.0/tuxcap-build/images/particle_lightning.jpg0000644000175000017500000001307310641010423023600 0ustar inniyahinniyahJFIFddDuckydAdobed|    !1A Qa"B#qb 23S$!1Aa"Qq2B# ?`>ޛhlr[YJG &dD؆c2֪eƒ!% ;ԫuc%}%wSTC((2fKlSphr2Rr2CQhr7VDcPOңcHG-T6ڌB)s3xx ڊ N?wN6Q[ۡ4KOFۄȖ/Z11ܞeJRG cM ExMN=lq/uS, Us+bDiqS/khq>КB==kNmnj-Cy(6dg$}Km@4hqFW-iuۃbh%60-7ٷճTҜ9d%Nf[K테ͭIX9;r:f>FƇ$|brG;Ky|J{xӛݯphT^@I ڭW5}MlIqe4fDw N(At7 v8:'ACNii꒴{|`p:[imN,j %I4ŗ1ZdА;go2AM̴L,(^aa$}.% S9x'\^ټ6fԱǠ=} -卡k"sO<ե?;oUB۝~Cj+"i5+) S -$Tx)c)/{ko "IX W A,cS\4K_-R]>TĈVWqP1el3V1䱲kǴծiA*1\(kK5eɛU&>LJZTq4$ ,vsfZORPHU2)$B 8cqel9o Vl9ucf=Vw.MA`I!ICL|Q`PT_qO l:SBiR q ܭm2=#eE mP D̢O 21WpmպA_"KIy<ڒҊBTRi .8 H%D$x@> e$V՗X]|Lg!9hE\b)i)&3[M)RT ~x8TtI.7hlNW#,6]Tr F4V2LRMLtK^@* U(V$qiG!N xbԓ>2źBjhIW(!@!&87vcn\>`+N:Wҽ]֖ˊmĔ&B1:pdNu,FmN:T@ۄ5sr:n1UIpP|<! $DL:ZWcJc8XH[RT *3*MG8'B!E RMũ*eՑ+0VP q!h)$$b-Z"&qҔx IRJHЪmT$S c2@+QӺ4+9+LU#VЬRH<ĐRTh وLzw_GcosNͶױhzKnuN̺6V[ :r1_ͭxe(I ..}]Cjf-qmz:|rE5V8C+K08HO!10܆cqMjA4=vr2I٣ILioZWm5k7HfYv?D'uRdUh4E(\K˼c#˸&G%=XcnkNOAHN׼T=;)ݮ$~ٵݶ~j@aRflg\C)6PR@_5xӜ]Wpmpl<;dk!>;WAb~ʮy L`Y9>ESyj)vY:"d5mL82) %V&q7;p3#v\ϚG :4m tCUaVP*~`}˷{BoWs6_7QylAdD1xS-&B\k#xǏq8,cfVk懲6;j5pкiE].~RDퟹ{-imUWN29CJc!m;sj_ڝ=n.ܭXtkBHɄzb*!S?\(9kP8 |o4>MddQ2ɻZX> '_ƽ:+Y4m/߿a:;\ok$M;OS-vTx6%K88kWAcqx8,r/|kX^jMK[ iZH\FE_r^oVlܭ2$ۜ!J@eiCPM\Ck~. by[wmlpi{Ohn(s- s=+Vi]P-ii-Y 7ً ۊˊmRU|1?Ǽ~gy;5&H_]?;^gv|5skF-Vwn*:֔HB(t7{o)mݿksڶ;U]OXR|_,v6=s%t8AA>1<˼,m/{ úkkq̙:\#ٺ~o–30V۪JR!_ر7=Ծ-MtiƬa?2JX-,r ScSooxծ>6y$.kNI_E8HAUVz?NGרeF*CHu?!GM8<8yKd7,9ɥ\=:)MV7}aV fcmQ(|R wR RMc'* %oUGquE8:'jc=E9-!•eJh 8%Qd@*|0t2]haӡLu|ũ_\fA@RsOBQ5aHa- m!9Q'2S@an8Ԛ^߂d$c!$mnayN_KmmLWzk[o~ɖg SwgwuxεkxQOW~ >҇'wwnzΡ}w;̭x7^S%r_#E~>z''mBW}O'WJS”~U3^鵋RY !t.ztYS\1>ܦ{&e:=KgQ>o:ZI{mzo7̭E2Zv{!/_xr뾩ʜW;˜?Jk4xεkx$+y\姝rb|URd\y5x)DQ:r:>w:''6zRxv{!-?sr' s2˟o_m*K}_Ct~W3&^>4b|uTH9f9V׎,WbT0e7/s}5tv)VowXֶ?RA'S 4VvF[R)S$ajKS~nI[`GUBUT4QݵbZQ鑪Zsf;O>M#ӑOt y/%Ȭ\9}(Rn]:EzMlG.d4ҭ=K`S-Bi}Cb|RGQ^KW-3I4;_0X'JAdyl+qkk`t7U[0bEm1%q"~4E}]V Xc3sҪ4(ywXNS;3G&CvAPV[M @Fs A1_#*Ye߁@ \i@d۬Aht!(D d6ܭ}́g6C,p?:Or vנ̽]p?>3+:h:i3m];V7J= rjq625(3f/S/.\k[iБLIwO'eOwN|t~L#|+M:=ڭ֒6RT27qT~Ow  +S7ԏ9\V>YTBmܝ\&Ij6fUk뗌ަxJcV\6:T O1Q?PBbJQ3xH'H% ]HY 7k%0&P/_^]gMs_;Tj@2)_GPVx R}=}]wtEՏ)%.CVDw =HM4 XCyүnx\B.C]߬H91M [^4EZ/.b KvEVOȹG(Q4D҅JM(Q4D҅; 6#MvQV3TdSԫi: zB6h6KjHvwe&Ae] 1sRH?` Mw1ͤDc4_*?=7/lY5mN6*]TAs0^JRe;oawNTR0pHڎ'چB*{*|unRVTX'4L(fs7̒8ؤJn8TO骛|uBBRrbzy$CGEVcQ;VزiZF][pmQ52b/m|0jn3),Oh;E氒"U*5^.']E:Q>c|-C1bUVZ"{$T{elJ.>Qڽkyt9oCt"&nb"=WB U$(L5~chѩ!@B2{Ki2rUNY溹>$ r 0VdqDQ;蚖@L&Q]byOƷWMFW *=_l6 \N}GJ)RqFXs8b83nxnvQH*Eߦ i|4|Q뻵˿x!D-|(3?J㊋دWhs:H04Ē'yjv,M8]mIT0l~$'NvePXҍO:rRW|N?N~ ȭ8y4-g5lQ4m 8ANJHzBõ%112NP9 F=V]s[OGx%}{`T#oʮ)>TSCŴ~a1n# O+*H;*nUw"zuc&֑5`6Ll톨 OFgq=sWj Wһ ~Z(v-_& _"15 U$pA:7EEJuFSy*t$4Ԍ6- >1Wڥ^&VztШ Dڒw'^ԮV>P8qZBfR1;2pRX'ټEGhB*KҝV_R7saTjJg4C ~\;dw7Ȩ뭧Mi7iGNIk<=OkrHa*AH'+J- IBWV*VdpLn-2;0.Vy^q5"b-3.հ)LH^ W2HS^Gȝ;EzWIч R3|a$v)UtGSN2ACY[}˯ ݒT0Zzlg`wIھj>6DֹؿJ o!;JLGF(0/'(' M4YXrVK$] EKG%$20q'l}>)(P+4c„Fsm]6u4 G6V0}j~MSǬ.m"i@>6K(ӗB2|hU:;!Mf4,F.E MUDP!RZp}U T-c(ffIVg"q;nr,s #^Y(~[{AHU*FzjPSSA)?\liPdԅNt]ʐ"[WEUdV^$OO,㑞X `B?2fdW7PA.*QMThS%2VH 'gFSD2)m mȂc5n{!Y*[nvJ_ZJh'OV14(A!"5-b\&БhCET*/O G3_wXN JKc),3pݮ)(|=Q6=ޑqJ0 a)39w6JA R8;Ye(`q&]suw+$Z;œ)dB(뤽P=4> V+q4L'Hw[B5- 2g9GcqeG$-J. ) ;)Mù>*?"vmɤY|+>ݐ}p3jMf(+%#.U^ІvM !'̡@ nSs!3 oqG-"JuR:{=:'AC\T;cFPnƛXRABF1@Q1XqbنڔJ\( z8}#]U7(^$~,`JQQPǰl%mƟ(ոU$_EJ2+v$N<@sN="}PȜ%$f2+JPE)_[J>/teo%zcdudYlNPRITVrCZ:X# fV2{xoTӫ ,w򅹳H-~+䏯OyRІRČ;}=WAWn m|oѢk-9z  WWV6Rړ}NP-"Q3/b`R,LڤD@XJ` d($|^wǘBa9ꞬuUBYWsl1k 8Vlϻ$[DU#W:S\ͼd%yJri%#톛rn4z(7mN}J@O8P~.Gi d N=JkNV9wI21ʠoGZfQ_f?@jҕ|e+, SOʨ&e6mlW \ KiA% akj[t.Yk'nK}J (3o~X/Kphؑy1G &紵$>`UĬM*l׼~h)[QݦS1=d`AOriؚm2r@쎉ا\kV)$Gl{8HviN:#iB &(Pݬ2L8%>\&jrQEmwnM iZU1GVq򖒡5 J<`^]ek枰"{6+HPSJn}Xp8e ezH'i9{-Xi4?6᧿j.E)?|HۢQD{cIKwaz0K+PDW‰]t)RVRn% .& 09wrTv*X}͵Gۡ52O^b3kֳC@L‡Qǿg5:t_p{̋tPU$Rq/r} >rOPJ5b{Tk7ʔZ$М{sذR :wL'-<zٖmL T ꢘ܊Gm N3GF\`]\ڦu8:rE-Z-EL(4]1MI@ёRP'.T60ռ$=$!KEǷWM)K ܿv-rL|!Cj< ,)D%!t쾝CIRG>|g[ՂjFॣˆQ2: -ŊE ZnߒǍQ?*^L: XHN~mJYZRJ @2nEqJ솛 ȍHFԐ0OHj!I-rP YD6Q8(n&LΙ+١^JMB:tecqI#-ː<'!<>?(UE)b'MM\̪_>Ϯ+t `zmU3HP` n#چۨd ɯ |H:#mEZwNRTPR$q/lji`~c]q,3eBO:>ATҪjbN_kY8$ltܣ*-qe"߮q_H%-мN{ԩNִəE[y%V72V-:%sz>p~=֝7P:V伡XatKMɲn+RN=D Z3dM(Q4D҅JM(Q4D҅libtuxcap-1.4.0/tuxcap-build/images/particle1.psi0000644000175000017500000000020010751375104021631 0ustar inniyahinniyah&Q%@)"?@CCmDķmDHCJ2D%I @E>n۶>@"@"eY?*?9c=?>)">$I?1 >8>a?libtuxcap-1.4.0/tuxcap-build/images/backgroundbig_.jpg0000644000175000017500000007535310751375104022717 0ustar inniyahinniyahJFIFHHExifMM*Created with The GIMPC  !"$"$CX " C!1AQa"q2B#Rb3CrS$4DT ?#! "#b2$@ N\9r#"LdFD@DdHLR`@ >A L&D"$D"$m>@6A2 >`"/H  R""c,Lb`EY|l@FB/IԀ $ȀI>7"2,E"DdH#"DH1H0",Cb,Cb/ KdM b`&&L@DdY'D)`&EdD"DY",E"Ș 1X` @) DF dANKbAM|2 O,|!.@DY"2 Bc" "&6&X,Cb`ErbEl@B{%/6"dI2 &D"d `Y'Ed_$EDdE!Hb`DOȘ"|&1!ˑhYYl`' <\ȍ%'Ad@lD&XEb`F\l@El@)؁)nDȒ"I2$~ &E"DY&E `",LxoM?@"&K^Z~@0"؀0  'X%uoVoh<} ;*kjȗnʲYq*lUJp |X |B/2 `DRbDC|!0#! Hd2 @blM E=o o&`'ȀoqdX',"D_EHBc# &b ˑ0rdbL)'FV~OKGRi% ^=]kuRskOP^(ENg^uŽb^ цÔxM?ZY$qs.)xICz8SxIt4vQ,􅯇5>4כ7ڴ{~̩/i}hGim8ljλNIS4@2fh^iҥ' ZvZƱwu^u$Yբr[OytOh@cױMfV(4_ M(Щ."͖/ho @5XW.g̚7:TiwGJ@)lM~i2YuGI'E|dD晼[56<ƙMٝUIRKUzRԸۃY%2ʧM.(mOۃwmͼΓ{-rVYf*nOu+Rx[ÛK7ROV <~wt,FOvx%6?:ZE>pRլBJHU :P\iz^E0EݯBƳAG s MzQo7AbEqkȃ!`!Hb [ $ز1D$[&m 2 "FL&22b|Db2#Q9AI 2/2"l(N|OjVPըfR˧iv?[IhQԔ:w4 - RGש92t%̒j;?Lhvon(hZ}j&@ޥ?ex{JB_/kU]>2oKT 3JI^j%;c%@yuJ2q#)/VӺ?WÕ*u$dIQoxw(FPXW}?B*4#'7! gc3kRR>yKNӭRTc9JivСavejvTPt۹5/,Qy|l,$.=*cM~ Vk qmC߃xp(Zު9jx6Կ[8w3yt"Fy't͌mW-Ds/BާLƗ0=A{Ҵ-yyN _aMaAZFvCy˲4䷗B$p#_k XPػ5^/m1qMq荏[:UGגʋN4s:cO2~kSRUsg̱ g{c*o'=i~(SrO&az](Ԝm1ATR?Mm?ֺv4iVM?%z[aZJL햷LT%7[ȧNO~g4:Φ#O8~7՟t=^Mӟ0Ykr_),vx{FӇݚPm.klz:]_"ӡleYEe夋*S$/t*TrVeԫQWܹ+{:TUhԊqy cGX-9ɂJԧcº8b zr`8eZ}5WHһQ8޶ZӪ.U)Ujml4hGTҖ9}K:O~H귇JkMn=@Qԕi~LNxiWQJk9e?Ъvw][{ ^zcSk~Xh=r-$,UU@# ),#:t8FK-ՕyVSPA<Գ\TV)SQ![5 *ke%(p1rҩN|&XiX^R{,*P 'iem^l:cnl ұr' + (fls RK+)׌Q6B::YNMo[m椕[ɝr/3{Iap]EyN}$Zl+__,;yL4W\ziv4M5Z~iҧ~35ˋyЗ#JKv~\RLoiO8e4P2iՒڤ}ޘE|e> 5}΁)I=MMͦSۃMjNX:jPm&jn*-S@W9d:MW)JDZ]Z֡.zY˲~=Oc)4$Yk=^I0jsju644XdX$F@DRbc'<侤 w{@9& 6&Mȶ @310dF 2,2:yFݵ&{MBjN9IM^/hkm{8҄cuM^Zg%x3=;myVovf\2@ҳIWǫ/)}>.PkPcqVM22uP2֣wKn cS Ƴܗ5Jݿ$ҴrRY]t8vsyVKejUҚ riS<(wtK&qˣ,jW r䔠ZS,e _ԟhUWgkOnE~@uZ-nь{mu,я>f*O[Tʔb׹kL=TB˫ ֵӚ}8oCY%a/:V8?JΌ8SqIH Q,JN2OsuRf/E7MR"Ɂ\Hț؈&őEb lMb ` 1@:rQyxNs%~x7n[ZPVohԭIPISs%WWԫ'VP@Tu-JgM{ZaэJ'빑b@47]Q?W93cu%Z66 .ԗj9ojXIK|m,Z[m2Q_cTuR136Izi)foۂL =z{?,xKSB_DUN>X1To"t_(h &|``)ίoy8 /uglZqۿ$tڄ}!(P} ,4z*>gOՎ6r`Tv 775_$00ܑUkv[ 6TPKnMlR}WI5ڽFfwZU)[~tX/gSrW\^+I PIGtw/^.U$n@t`SـYZ>1ݖЕiyalX }MB*q~Kf1`Rzqj^ӏMcjpF>V{,J#̑k^5jUj=)Zo T_uB5*2YxOggtl);|8%INT)bRKIg IPEK;Hɔ*[T٠1m(/uPYֱx>>Noږ= eiVӯdݚfNQ9^{=1.{拨gx QڮLUTEͣ y_%' sR/sVmr1}WIesOC]6R@oUgu6W?sRW/.EZ>`lWw[ĿHʣd.xȽJJ~=՗t)I2 ",&AجR#ٜ-Eo.;/:_T67J f L ZUkӗNIle-zn/ˍCL Z҇@s~Լl{ӎ3Y*p\E $,y/koZ _c+RMYT)$OUɭ}qpm nYvy~IQV}aLΧ {9`_kqI偱\j9Y0Z~>毩k"rK> W7LsE_suԍg\'NYqqU{Ti}KJfj}W2VQkZkY?J̪}SoO.^6- UZs)ƛNqnԷMuu>J5j6Y3:vta(5%;Lөѡ c/ }(ъImzo׵z tڎTҚ'Nj6%VNu&v^^a_1rHX5ZI7ܺʔ>ZZAK ‡81Z\V3-BҜP,!R}z/w3Wm8b)SKtn`g*_%,Xda\[wi6}E䴩wZ|&J"ԸJ N6*R7eR?%4#1rIlU 4{FJk9Hֺ/|n][?nne(&ɮ uMWP}[IatjК#{^GSc,d(VDy~6:G]Ծ0`lrK + $PR'rI~$|~@jVZ;~Ee,|kYn`j+;/RڿLђʤ[EO)o[tyqwҴE?zJ|W1RP8~Tc 5kNo]'FrV9?cjgEmсtJ@&Ұe5-SDRiSk{T"ZIk] ˧J;7QpeRqpe^RKn"g5=˾apM` l">I0=# ,H"6&mMm JM,Ou5cQG)UU+HY&_m4hɬcڽw$oMR#ZX濣h6/LyP2M+%2г|/$pl}?o^r[T7iͳR]8%Dh kT^V"l[]ѶY(g--t+mC;l\ԕq:5}wJk>[Fn8o,PToB vҌsNJ#FCT){.^ܒ٭|Qr YD|7ď) .v6rt-*Ӻ*q_L tV&x.q^`HX^N5 0N996G@ҝ9JԧS-=uB/q~:4HaFO/OCRj%wGO^QM~ V_suZ4`@SKݙ{X߶oTj]&xMJ֨G 8K Οz˽q/ibZYNf IKimyB_6\+4<9K>Lش}0i7VRZu7cmoj4iG BvʟEw܍l)p:ܯCd/5nokKeRSiyIjQ{)]'_s1ݤյj+kuI;GlClڶm{kOl)GYyΣƛm(Wz{BP p=>{ӄV%Ҷ 2dy#IU{RRPDJնkss,د:V -R${Qt'FY_ dP:4[rWzHT+j5z%6׹,5yzQNJRrOfM)\[GM3FҖI-f^S-SKjymNruNV*nK-y@hŦӵ/Vph)K $ uyuǠC]sg^foOW.[y/07jSe.L%n$a̕?f]2QwipKZ"+G/icKץW]rX`7ڄVw1Zբdu+M6֥1:w4KMXykxߟkRw,V)Gr-Bskeg,e'BT("%i7W52#R<(^QtcQ՚ ͜eRZwTzFSeҩFynԴrVJyqp@r nZR*pU˕ͯݭԯjՊy&4Θj]=MД&FK~ZujpRepM,hE(юmGGާӍt/SVïZ!:֙RXzv.Rum}_MڍR|34Sy * 抗 vWU:ei*#4Iז[ sӛmʣʇ> i]*ӰӡQ,g+6Okjp+KmkYtt>f},b@rፍ[wQea|xSyB8.vJ p߆AK.xT̒[5SIJ)Ty/sҗTe) ㈴cNvѝZsqk{x#yiV(%uK4%6~PbG0NաSXÏ{i}=XʦCQմgZATָRM;Η 7N5ڗuu$vZ_o9֣nZ8O5Ȥ,'S!"#qw ! "dC, dYy@"lY, *k vcBƇm5VX̿lv[Zԫ'VT',KY8Jb=SBƍpx>^:0k=gc7߉%MFݛq~\,)NM%奶~jcߓ^mS(CNq~."t”^l}I Χ9SVrhԛ}oՕN 8.isQ=Jv52P) K8:JtҌsޛN,ʚ8-i\]XE^5(`gKNqjV\BÏi]7EwNbJ,ͯ*1bҺp]c3-XVߪ׋>yN[~R+w!Ty+ ujRwlCZ5> =.ZRS)>u(K8[6/TkVgU!ؓ1_-BnSRsI3V}mUN5պk.8u,_4q潀V2`=N4#MRZQS7.*u UJP T5[9ZjnKTh=w6S[L޴Q,=.))&iSBsM;{Z4G+6?Tsg*kUH~y#֡R2Rgiu Nr)(6S׼t*K~`lk NJXV4c(F~hԚElPס̺z ez{NtjIc _v*pbnEmq:q]}ReFѬ&WuJMe08&\_^$v;R_/4mΚU$`:3hgIb2{ڌiF)(lEN nBva$JVHu-Bm9TK/\uZ3g9R0qR5o%:rm#:9O5ɚ=BG *Rxı_Khwr&[ӏl)=twWW3N](T+w=3Դ,]MfnuI⬦Qh1+yVKmtWn[GփH8@Һt7Yx3o_GĩOO2X?so8fWwlֽG_N)cp2QTe8'e {6Zˁ@F\LO2gE6,"dMbl@<j|9MF'74؜+N<0=1WJUͷbU/7x$ׯ8XNT3}_s۴YIP4U\RQ꛺.k77 ]ǿv]ԧ,|uInygNy|2YMMӎo3eqM~ /F۷-78ۓ uO osj2B%>xFI-D̹.(YɇYdN<-E5̅Wj^OotjkSPX[$:~J)w$ܼ}ahc9UkOv劥Ҝ\Ӕ~m/٥Z|,wf4K>T%^R?OZZ[ _fo6ťkBm]KR:Ӻ&IamyG;t-KHA|m#8/5=]L(֗o#PP累qq/(tͪpK⒛FBkjp9zԟSk5BЊ{/$zREӸ$߃ RΛ ΌqtN\ҩ.gDк;bF+T+QGШQIglRI,42]LeMWQckm#fRqR:W۬kvi:)_N}s^tB*+XSm[xiMj}gZۨ[qNsx*O-}pp~Ns:K㍗=wosS uGc%(E{2B2ji9#EZvԚ+&:oue:5ۖe''XIc(f-5;_JvveZٳ|c뚖ޫZ攖%\`[uݽĮ-(~ۂrzޓ-B^Fqm'z{ĎHƾ(Sm,Igu>Zݍvi8qc˽?btj~9N]\Ϸ)mFMU\ž@e5 2꓋ )qkڗO]g6,ױ^e+Ū[mm#)9A%Nc՚hF֋ZRx|*olOV8.WRֵ+rQo5۞ ac[軾Z)6(NAхYF)Y{07 eJ//ɔ+ W?V# ]yfjj}-/8{ ˹"L,m ⰞGye*S=E&ߺf^SۄROrjKǨdڛܧ[jeQi cJ V>y5BmJԱuVk^ԛe6؀2- 1"؀ Ԛ!sV5E/m_ҵJgz33 ~\qé1? Kf橬Vk}9m{$省k]Euq&YckWWեsRQ[d@d",&2,'Cb2lȀL 0C 0C;C ۵yUuzu5#oW .۬zRKQsS*_ue$cU>-m.aI^ZZE)R9Fo/F<.Qr8^k[<\J0$:_1FTUcS׺jh$XPXctKIJJvGӔMn0r>Q%E8yLZOJ}˳oP8MF6\Uɪo5uA=RlFVz?JZ5|(B;~̴?wH}i.xE{zԿA!mjԪ)ѷ'lzWmiYNʲx nšjKb][I(Z϶<'!X*sS Q[СRqI].(vzO/xuJO]{N{]mi*v뚵#:/Gx_Qo*žwQqa 펗g4xƮBXւ&fî' =Oo*I4膬[£<j&۩N` >tpkn yloOTpm%HJ):I^Fd kp z:Q|S&ڀڮR*4^~.צ6S{:$/sYt:pcSWU~%h-:ңM5N WK{y_MNYGT쏠=Oý~J.#VAoڎ*1|l <ҭzHlEt_u[ Zs6 dH]Uxl 63J?Q({L}ޢc8{մ{؜5MW\FQat yƽjvV8^I. ?*}Iԗ f"6 dX؀D[|`!66E,L`&@&!Ȉ 2  Bcdn y"blȲr l2 dM" NQ:LӭaVOE-i:_o-V qvue_MemnawکZrR[99gJߥ,<'뱽wF/P6x8'%y9ɯޯ9` Iz]ӭ޳{90z2~ ʤ#̒4Kyڧ%S+xQn䲪#B9s"qw%RY5Jwܹ2:u\Kti|V6v@#QKɧ 䢲`cn5Z4ےmb9%y.&Pij9ߒou\& 0#(E(TK(|dns~.Z4gY6TG;hY@YhI}$kr@;jnRk UV9Ԓ^ѺǭXR-)6k"uͽ9UlSZG:ogWQԧ*'),?źXI9代|]r}vhҵ :mF곔ݖo Dl E X"&2,'R"6 "7 E9"Ȱ/ؑ !0#&@l@&&6Ȁ2/ v̆DOߓ])vz*Tw)ʄP6 )I>V^^%>+ڄԒK>#uÍJV;9&w~tJlc9RY _Wk+՛smN{]εFo,j4O2\ rݬ+,kK22zg(8嘆)Ԕ36Ȱ0b|L"6 ,m"Ȱ0 L@ ȃ`|bcd@&6E!7'Ș "0;NAA!;D@V2=ݰH O$\y@Mbl@6d[ -YeQ[TqU$cD {YjeI0/j:R032J2kta KjR'3ZqvI# m|y2:5$Ɂtl:~jsxKcԟ٫K.v}mgZōoj]Cvw}OzgNƣxQ]l7h[zUg{J0J>RKm6װ [ۺ4"$cJRT\m'WZm+Vyro-ғy6 cd@{ l07,m&6E `& dFdY&D&6E~CdX x@FY6D" R"62Rd@2DC>D@ȀdlYBlC Igqy&زlM&6ȶ~r {#{o܈l7 i94JEM,b龝^uRRiyE?_rꦇVꝵ*kRQ|e>u5ZK4쳝xѴ:[Kׯ@mZI*\\ME%KkizuLK+ }"uon*F5d7:ξP[E.0q=^nRoP d@6@ Ȁ0E,LdXC`&Dbl6DLo,F@&&[؀6Ȁ2{&E"Bldd`EƘd,HlYdY &E !6 "d@< Md@m6 D 6 6` ` @& T͇lz鵘s k #\BMtnRQSExmѮWI|:R[ޙ%Ri(actKKXU%zP:qb NQ8'}PvgK'RiYXTJ٬߈*U^[xߪncMͶuUԛyG5us&1l!l#x"1 lȀ l ߐ@&ȃ"؀ `ȰdR"7Dl@ ~@Ell`vyq) ̭(Aɜ&iJzu?@1LӖvl S%F^C$FQq4@`G" D1P"Ȁm `6؀6o&&G <blYl@ M;'Qu+B1Ym#>oNs; &ZM7{Ο+z9R`]69 ͘PTbn~iUEJ ^ v{4yW:w:Pb3-_YjW!N:99Imd6& M `ldX"~X7  A -c" DlL-bd$.y`!62,`E M"917kĕ.2dItsBT^82. A1 U)ILRRM<Z}i^aQ^$iI @w\.= IEǔ#QYXHpm@ boqdز "Ő{yl؛@ M6&"6&.,R1^l3+eVJꮛʖG_Lt)J4XXmrw|;hG Yk7JƥV5:e*yfX~GF~Y)4^2W}]wVO?6ԕY E @l" Ld"'`lalm"O6l@&ȍȲM"L-D>Hd@,RȶO``6E YۦQ2^@bhQki2jŝkTZ6zɽkV/d-q6:oС;?TQ>`Y j^^ɠ1LtjxDKCWQFF8pk;ZP{l6,@ M@@1dM 6 ؛"&$@y $ZGGMzF2rI,{qA9I$'<S Gᮓ;k*1pK e,,ΟVֱ'C&jo*IB 1ϐQBbOnx|]jF=LxӪ)\]:OwޯSo@ 6 ȱDM{06b2-d[|"dXȰ6X2 %'dȰɀ6 l"2- z⟐q|U-krؼ,}/ UkD<LVZy@h+-aPx75]00/?G,Jq+Y/&E "+xȶ\+J q9GȦybEw#x[ewאHIg'ww4ܞ~Uж,$%*-tB҄a\wG`VTe_CZ5 iR/"nJǑ,5[ 8^_/2{`w^!^:˽r䗍;=`Q`؀d@6Ȁ2/d[Ȱ `&A "E lmxDdL@&b{"6"l&Bc" 5. x\4'&(^@Z+*qfSLoa~z_Zd'o%N/ȃ2n9F8ޒ[ !VQY ~N@Nj<$z+T>bޥeeIH 5K|=R%f'Kء:;p*IQ!:)Y+JE7JmnSMDd;S:7Ee^G$2Ekz?e(QNOKxW}׽z[E}#г1EE~Rm+N\RIg3ZM-I(`ǂ JR* M[w8I{ZH˾@U T9,nmKh.nt*ױ˥_k'8,@/SIsJo?} {{F݋L|ΛxixViQ B%-b7dX b`&El@->DRbl2 6 `` ` `h@ 6| " "1, MMX1/=^gȮYv-x@XN)j2҄e)vtUV2P:+ 4{CNFvagCإ*>fv :32S ;b{)J^ 70^iqJ-&wJgqQw&N=9oKKnYqjn1/Ӑ8Ÿj+ktKVQxԴMʚJ 龞*qZk5m)Bb & s42ni|hŨ>si7mn%^$\ qSM IlS_CSw'mp_&VjAK)WRwO HP[K_]\P̳ܽQN֤'iqzk@yYO c2&?WNH$6DR6 `ȶ C"Eb "LM `El@l؀2 r`E B|""ll &l@X BT"\ӣRoh 1t >P[#,B̧ZUer| 4sND&ænn)vb&%FFU ^)>6:MeЄw[oiM(-F?F5%d)ynkv-2ɗQ(旰G2iV˾#y}5'e;HK~bQk'd*X2@;zJW q& [l@ 0l1cl@l`&!blmoЄ16l؀ M"ȶ`m-H*ЊYM,}@^ҩjSidEOd\Ưzm6mhe)֪(a+8,uN OgIe,ຩB0kyUqme% w9b+%[[v[EԖۮ 7n4$7 (f + nc{r} EJ+旛2Vӊ^Ԫ+{zt#-JGww-ej忘oV)<|)3XM$eYQ٤~עO+o܏]NM^N*lnp4cgu7FEY|J~R튝tԩ'ǩ-[[Px Oޗ|cc ZkKiTkg嚎^N!%@h-d\M?Y[q,gA_do,mV.]Ȼiz0-v%:gp)6E9g;c ` @& M` -@R{d[ 66A`E@ &` *Œ]QRݶ>frLpri bOJr2+VxTnE`X~ѦQkvc }ԨUt|(H|˟swm*N6~mjw8S?eTd-Hʳ[˫B3YwK;? N "Uv[˂"kLkE(G"dX?1:2H bu~tywN ,;j)ѸJ[ޤ{WZ*1R0^iW_؞=Yh_檺*YԊK Q5 ֋x@UlrQBwPj{:ҧW5iBucqom3OxJQ6ږXi?kVeK|ůeuJI6؇Sq 2 Q0" ßYJI"I mȀ2,2Xb`&ȍ| | `& dF؀% $).(PriF-c5tԓz{-TxD4릻(?3s k_C}-4Ԟ66[*43(F.i-GяouwKb`k/6S|y?AJ[ලk\›Fg5MNvьpuδy^IǢɆT#4}5utnj9/rZ%^旛8Vԫ-}Lm^orTSÚǖ^I[quS{?SuTI)y_oAVXqy5V᪔yo_CVVY[ em{S+7U&߫ݺΕ(k5gNmnүɽhyb/ fB_z1Yrr9w9p/_+w\nIZB}G=B1p|hks^G0Klaz:_ZHJ G, ].X\ӗDo-)G[gwjܩM<̧Fp84kpŢ:% ˧#q[Sx[pc:(p~-E6!-jڦTek:xpfP.>kմ;5h]Aє:SRϓX.7ﶵ6)MN,=s1mQqeCKKgWj ƫm҃ms8 㚳_Dcl]7+k7EΫiF)q}p?Ez5{9TS[mq¤wȽ9>=6CѼ,<Ӗ7B8խ5P|CpnT㷡a(8NKdZע3U,伋ZK8:R ezඩC/,{{ѷǐC "v)Q`QleIS ^@"/DM"`& @X6 4J]Iokn455;,u^*R۹jW:Ծnj WxU|aieXF!ڸ@Vc*ؔ5-v 9%䙨W)ң4 [RZ'u8?CT۪y~^Y¼x@l7Z6b|BOoC^ZN DޯsZOi?ruͶl#'r/)W)>@r"؀ kK9EU#KT)K6._LmW}΍חrtj* [o{g:cQ}$^杝x@^p{%ٯ]iޣ4C:7gl\Y4Fiյ/:0tٖrs=B^u$rmBmgnQ.\w:noiQӸ会yE@{þ%Oɛ) 磺MJEOuYje KO 9uTnRkF-++)pF-jQNQi6(^[R,O\2UXTlhmFH{zIds!<{B?Ǔ1zcG[$b4*ܷ9H Z2n^9(KoqϑW+%\u56,kt缠LdJPʭfSRԕEǑ_ K@e\N_2ʻSN[6:wƢh DZ3E?8K9 Ѧ7/+) lC]I8KXIaYiTE(> >Bi9RӤ%(ctIROZ\SsK1aZl1:ޗ(v1Mh*mY }M⥢EŔ BzmDQoV1Hj|PZS)Kവ+t-6~; $om m1[i>eO O)' ]XO,d 2b=`8)$`"h^Lie[^z-fj&K}JҤ7N9PX|-&/soYK@lvKӏld뗷Wj 9wJs1[4[&JMpZ\莔{j?N _u-XƔ̪Y+QM:Ed][Ex17Z[xy,*J\^/?)gR4IՔ7@:6Ȁ +ZZTۥ*J9#PKl'4:@=)kGN!%ˉRƔmN{-hz]IwEpoysRnNo f5bUN֫J{c֪WL%Nᶚ-g\]Vsy` ?uNrH_ڝ=>loU+;FYXԏ1yGB}~ f[I`zy^!jכPRo o/iSHKz\B(2^ngF&^7G6:\R@%Aw._*U:rK]~ =*K1eEXB4J0үO4ӕJBoc]nZ) MQNz{[xٖfvö eN[IW:ouGU07G5^s$}k?3a?sqMfUnM{^-gVrJx[oЁJ0j*8IzKN9F5#,5%sӖѣAvkꢨoUG@1}MfeRO_*khoٳ׊nO9ݚP^Q#cVr60zjXtX#k2I'6a+G Ud@N)*K؏(PT_ +T$^C|p)6E^#%01;żFNj-F?R-Ӣ :Vv֥ x[h&u:/mH| ٷ?dٓT_zm +EaA/C1_G RMs5CMsdw1WvIwR΢Ypef ssKeJOt=3fCأ:v`"P ҦMq:jK,8F2߶m` y(ΆJt=3 C 3R`?libtuxcap-1.4.0/tuxcap-build/images/unicron_baby.JPG0000644000175000017500000002246210641010423022246 0ustar inniyahinniyahJFIFHHExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:01 18:42:09(&QHHJFIFHH Adobe_CMAdobed            "?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?iu.j_#pfk\Ϭr Ip~c4t쮙r3-c;-͵Et r2(cwY!Qб4c`ԞNmÌrߛ={bv= ~c}*P[8icg!/pU~W:fʈL9|h?M-:pad; <g% adobe:docid:photoshop:8e42182c-74c3-11d9-8a14-c426ef2c7c0c Adobed@        s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?:-ևh~d*A%-it"[cD"BdcR6RLm0O4}?>mBVUCId$Q?j>!=m>v]>0 ?y?m[?%I>libtuxcap-1.4.0/tuxcap-build/images/bomb_radial_death.jpg0000644000175000017500000006214010641010423023331 0ustar inniyahinniyahJFIFHH.ExifMM*bj(1r2iHHAdobe Photoshop 7.02005:02:01 18:40:19X<(&HHPhotoshop 3.08BIM%8BIMHH8BIM&?8BIM 8BIM8BIM 8BIM 8BIM' 8BIMH/fflff/ff2Z5-8BIMp8BIM@@8BIM8BIMW<Xbomb_radial_deathX<nullboundsObjcRct1Top longLeftlongBtomlong<RghtlongXslicesVlLsObjcslicesliceIDlonggroupIDlongoriginenum ESliceOrigin autoGeneratedTypeenum ESliceTypeImg boundsObjcRct1Top longLeftlongBtomlong<RghtlongXurlTEXTnullTEXTMsgeTEXTaltTagTEXTcellTextIsHTMLboolcellTextTEXT horzAlignenumESliceHorzAligndefault vertAlignenumESliceVertAligndefault bgColorTypeenumESliceBGColorTypeNone topOutsetlong leftOutsetlong bottomOutsetlong rightOutsetlong8BIM8BIM8BIM!UAdobe PhotoshopAdobe Photoshop 7.08BIMHhttp://ns.adobe.com/xap/1.0/ adobe:docid:photoshop:8e421826-74c3-11d9-8a14-c426ef2c7c0c Adobed@      <XK  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?x{UثWb]v*UثWb]v*UU؍݁]v*Qn,J򶩬 {(Jl1JBìv-9Ku-"J)FFp9md3Kr[Wb&@q1By#˫+ϫ܀l|fmz)"&# ah(yZɘsPȀ+jAdUr+j[Mt*8XG,dhBMCP݆.&S3?&`O- X`{W7AXPGW[Z;+mFi4_J1w%ثWbYP ܓ00HǙz1F|\@Ϝv7 !7=$xM{O]e>;[yf֙wz%ݼHp>AMl8䌇H?rBAKad & 3I}3HӮuMBXDJ@I!S5Ip\g6iB<̍z/;Ja2P7T -tS3%y'wx~buB鲘_ZJeE?;.WfvW3|yb=X8f?⇜I buwz<.ʼnlz&rCu2Lv68ذ̈`ۊG;T:xcQ!/%ho|fq5I{waI/Pa/2k %<8Qӯ#ƽdd&''I4_8f,2fv=~({k *bWwl;y^/ vi[&[U?nxC9;F'4n_s߾qK9rT%GSM$Azgߗm5mJ#}Cje1 w'x9㦯0uYh1[6f=:Ssyg8Z"g?;f_̙5?NDIi׵xH|9-,]FXeD~O8ӧ^y$y[O Ey7n S`ʮ S>lj$ojx;N???sIүyɽ{9 ݓFWly?{#<:L#|rc 5oݺmT󏿑/ΟnE'urm- TҊ>9̖t = o٭/}Y% >˸ywߘ͏>0e, Zm3mj lG!DGqwoKZί{;'&(`Uj)\ 3nc5XӀ% 72'o9gyR򿛣?4zwY1"0Lݽ9 &HwK?#F!ɤHEkߜW?0m4{:~J]Omk*w!"I+985Iwݩ쾳g{@cSËWQFGk(i9ޟg@CX[I]'j>vbl& WծGmccliEA*ՈQ.O@R{'HsFc9mDwN~thZ#`ĉoeRLٶřy5d N8cspLqçRC\!%п,o]'Qv  u1he9bǀl ?ڒ8urh)\KIЎ7a^V-'k`:}^8qzq#u=# <[w]7^t5]SJ?yW7&8jrc3G|}Ci5g5P\LJi}PL9qOk5o_R,PK4α ;TAFmYF2纞_ϠSgfʴrXM0 RYTڪ 3@˸eԏnxV\(W.di5m. i):n买thc0j:|]jzFLb}~Oڽ_C& xe :ا^f--xڌ.Vido7I)FAFj1ďz4~G42KE"!B9 $zJ$vG(lt;A@-3Z2s"m$Eb)mW̬q2H]}~˫Ly'Ξߙ ^s_j/wypCRh(l S,dlqc@~7=An[WB("%xZ&}ݞPk^h gqa,O'^{2q3 9Gg sM*t۝"k LDHI:I̮e\ݏgk=FЃx{UةW`Z(^@:RVLFڥ1F)RAd'kp3v*UثUx7&+Mb2 s|gK.ayb'2M)!dl{SpshE{ugsd;a9^K؊$bhè_]݊z!^W?Bǥs+Ie%Ӝ^8'+-2k9yTv>lCC9mh#>"y{S|ea^֧m0">`\;ä d /1ykGȖku1jMvJM|s߮:l{lݳ"8"be^i~<忮kW̜9@_5i,0ϣvOKU3)FeoK鑗=SX4}R9z92彦1\[1CI$PiI[  ?5]ƬNbG|!?ů'FfO?)t٭mZRx-+ԶsY U `e{S]Wg n}D1VA?+?+6yZ˥ΰ( S33h43s{_0 " c\@k7ȟ{n/42dMxfAW;'OfцI6W_xFߦ-n*azz4;~"x/'ys{^K N#sldžEsd{uȼH`Mjp ѧZN{miio! 4S} ;+#ir|[ۏa3걙bG*}OȭI6K?),$ 2S:\ݍFq< ٟJcOM$$hoԆYS8iD<z.IY}F$rzfV:l8u{mOm]Tt?"#y swckRE{]SVJPc&#r;ޗLC2] 2UX5?/0|q#:h$$ЯNi6^`Wf`<,=AlU.[fU?us/Qپ6ݕ `1>sl V'!OsQ}M#MzEKcˁ,FC LLdɯ'/X˚ej:h-EjxQOe ~)7]6{w>HDD) Mv0Ga5,oilD>_eC^(R,#k9,0OhivUX-TuO501Jd]n v߸ &b緛'6xMk b 0?A%͟!`gk`3H<2n>6gQ6#RǍAxI_7O:lx>n?_7y&[5fHu)6 U`zsdW>.[G=$XYK4yC̃ZGS J,@zn`8.AWtOO$+_7_6qY~cywpgC}!+27xpr"AFyd켼dG!vsQ+d>U6IFpֺpJáY`v*H yk&P.G5 z5EY^h-51YjK̎ynLKn_h5&ᔱd=xxύOpGyz(4idHY Q*(W#FYzP_e[gYX#)DaKF*E!43SM\=Ϧoo1m$׶G:c $*A$8aF-'tڎdIYFUi}:2rk6μsm.?; <h cpWpK3SGyj0N8c˧?˿&Yߔm4hcэr[WfX<*CC xi;WKF0#O>ˏKz̒w2gbثTH{N5 Ίƀ6$嘣 ]nQ y|ۯ7~Vi]n;,Jysz{gvoga8q߃Ǵ@ksK$üb]{LwmbV.>u)ĶhD%ODP]> R:dq $hm>Ov5 i V(𯈥s̻c ɔJ~3rK' ȹs;fb^_*X)!nUJ YG{wzxF$$G|L!US I띧eC_#8ߗ}zs`K6GǩߣY|`t+y~@̍)aRIfn=I'ίc1oij59%UW"dk+rΚ^V<)dD4>,"8bLcj=5O`7H9h70/gu.MpIxm;C.܋wa KI&M`Ri=޵SVm1=aS~a|O]'XjOm HM0^?[D 5w߿_ʟ"O'#}}$:rPj3'}UwЎԍ/Thc`Ȋ(+"0`E f]<Oo;DS 7LB/l{[!6Ǜ]jPM~SJ"'O=)Rrn:g!RyuFds<:\ܗK @L,uϗW^9a|hrrϚޏ2K-JPg=]tN(c ۝:DK?:^GI+%yT9 GjK/7gЉ7; 3Փf/ "=Ǔ"g'XIn#F] $}me8tYGq̏ ~ȵ{ϐt#6Z,* u>^41@?>;hj' ' G甼e{[ʆ ̏ 䍫6>ˌ!3pD<FM=,c6eD}(oyNm"(^(1­v6G6> ~vvg̉:=-Oǟ4/i^koD7ZR31ը3"}Ǵ}'58">?m;^O#3Ȗr:Oj* *͗n놟OSl Q{_yI}A!v>v ل~ZpkBѮ[Uit庍\9gOYSuYGDmFmWr~AǙom\PvFT2g!)6t_3OֆF!~?&?m˧_\_ VH8 rDGcoGrc"Q$˓_vfs:~>"hXP|& s\ՈjrCDƿ󎶺?1/a")`]#|G`&S[>ӜRv!G6c]x?,i.UA9rv(7.=e\7RAycn[h^sLҔ. <2ޠr'gBu9vvGd7)1ms~;̵ٌV${z%;~?YzHC:a)ȟ1\w2."tf)XgW1&_hr@j#)STW=O0^; kӐuץ@3O6y~KRgSڂ4]#disSkTm3Qďg+Dν SJGDw?Qisl$-Bi- x2#@O.D:}X"NCƠ~PmZ_q|<7ńosfʧbqɖ>h5$9cA޴+޽3kxFI{ldiOOqF5 gE4%w3xh8D9G!g]=8 ە<li~ N_][)#"a{-OZ|&8˼GE-OʧZ{2pLǗJjxGx{UO~R"lDHd >C32bDt'( q}_}^5'h6 H=;;X4~-$֧:KD|8e.}Ǭs~o$.r?_5~rjBLӴ}?QhFަ8 P=|:f9wd*7}?d Ϋ$)8Yp>]_ ,lRD!PFHaq1=_XFUkơE(-͚]\K'P*(}t=q_W=&4ˌD@?*<_wPm=Y[[b"0jtwg:vlx?H;z]t~mCͺ7rMtIn" 6UE(y޻Qnd&=D.vXaKWbfؽ$޻N6xi=kW&^r3O2i0Hޅ֠а3'H*y?;wί~1X~viNK˚Ynv Ti;>HTd[,rb%,c{J7tOa~T]jLE{t.|rAg Zjׅv=vH{J^\Ů-@hڎ}>۵ U49,F]Ɉ;y5WٟbikuB.Y-l6gdŌ-A3GJ:t?˶?_DeW{ 78cP1_QxYd#՝6t~vo(~o<&yvj$o\ Fht>ٗ~CP|<=X7`#5Qj~dtZSG< }]404UX xwco]K^$o]jv48NNr<|}=TyGLPIF(g!fK,3 q }OҎcb'~$Ϻ{yѣqBq&&,8A-򽏘$ XJ=!xk;O&+$<_ʉSkI,Nu\:l;˶CO'"ӾDg_.Wk_469}UH7^êzn FIqսyKލ杯̟+ti nQZhbn™-.]D0ewo~m^h"ZQ߹ψUKCVhwږu)[qE8R(r6C#$G'YX1v~Sg! 82xͿ?;]~o o'SX@C ?,Pr16-u{m?sDZ@TE)L}-FbC~bN2h>oJ/5(Yik~dd.lxByfVt=3Ť`7#{oXj!Ab\V!g#9[wAοw,W^eXj +LƏgRCiteSfj{1ʼo?^pYysF׶,Pb{W LcD{͏#I3A5㪜ȮockRΑm?m*?9<3qi2a,1L~~c2C1y??IoM.XYHjur3ٿ%}Rni꺅oⶄ5X4[O7.?c's֙(.<\"SyLKB//ijYy`h"W'SMFljxzHϱG콙rco#_,9O>_%yk/]:4L9y#xW賘j1G%_󊿕jlC;B:]]غ|y~CY?+q<@g{x疮*?&?,Q5mS:2l-a5tX&FG]/iGӈB@tz0̍~j\^Zz}aiAwnc4m v}'xocs 'W?V ?f>42>Ou ޿ =!(31:?F_ݗFJxqd?NZE#ޏN  _Ӯv `|,d_zC[ڙI͒B8{;l{켑ɪ\K 1X6Vx!?e/!(E︶L_th4qқΛ":$t̽>O7Y֍ Ɠ 'sC<.Cs/q%QD@@;s~Osz͛Q7؝=9uPE˗Aƛ)$$}h`o6W ,yx;99WlK0ܗaيF;J$RHŝIOM \7Rvt'/$XTaXX{~'xpgx{UثWb]v*UwZm6\YͨO%o &rdžp1G SdUثW`(<~yQEIuk)$Ҵ1W̓> .g8 ~הywB3̗zuGvOø!7zizfX\)ߛt<߬Iw@_Z%@uM a:?w\V.<=:~ؔl~5yv؆}&z:#΃%8G& 6hKa2M{Q89$>R$Vӕ}SQ@Z#+׬~_\wn`vVFI}s܏pfkrHTGX\Ԕ2FiҴfkCS#=~לQ@KL,'{Sbbe9|!sexgp~(03X% _-shR 4ͮ.8A^;7Gs2R}{q5-^& <3oپЈS9rypk1Bu1l_z~A6~X\ߗ#]H r-ԁ^W:>^.`}?kv֚='GR*n~jd~lyͯh~N%mBI٤  c٤{5Q9 c^;i#$cT*-+ +pʓy+Gϟ'#*J6_JP.|33G"x.t: Ѭ*&@xAR=Q_ν/I[XΥ"vh;ٯ5Q̽baO-զ[R8ɫ{?Dv>92b kq}0>LMvY1/o?{/˫/ u| F;mA8w=Sˤ#ryxGYW-5ucDZKNm9Z#c5:M>\ڑ<ۚ-b_fN#bQG>O=c{gzSa$kK*M3iN21Ô^=6 ~_3~q_0 \6te#Yw1Q Ԏ n&C49ΛΏ;_hȇM/@zԓ#d9t>bւpxR@|:C^E~]eYƳy7 O‰~E3if5/#F_{{E7d!1 D".Rw u8 ;s04;u/sLvs+E,NFE` A|'g}'hVLHX#pA߈{eh_zg(};L~TCp᯽s_:b!A={W=Ͻ4iݍs;~Ǐ9  C '1Ȼb .޳]N[?<?>N&ަxkm.1vOް>N߳]9nӞ H?\>dռ=k:ֵmvK@ 5(TQT͒S2o|+fhip NJ" .dd*:Fj}_C-hEhY-6H^`}si˫ӟS/$/4;/ c4ȓڔ.& UXuTZèq-ڐa" H(/0~bIiLƾoRY朩V5qq#@ Y\ h"Ri?<><[kjT4v2 YD;E fgꐨGY=!<7njt4}sz燯Eٖi&dhY^[ts:OYNjs/CsfAtR6eaq@6GӱdUؠ 8PU349FxbF"d`,t7xq'/%R 4P*Ƅ k255?ru.YOU\1< YBix{UثWb]v*UثWb]v**etthƁq*<Y ҇"j{7HWuyqy+Ou!V+2$rq`(`u; v*Uߓf۸Y9f&3geὲ반iZVĭQ֧3#c;%ـmOtFMַrOL$ȾMKV=~s3;I v*/Ƞ_FG  Yy_i)LcL7v ǔ`l鵺p_GzXRy zn?#EX~=#ܞ^cK20LiCpݝ M7Mc\es+2/BpdgͻIǦenc|NA;Ϫ[zhOC FL/5?ntmJ[ 82#wwK"h6A{S,>"}y˷^KS9_h" Gg=.:\BCoO$XjI޹0ɴ:&`xOCR!*fgbjrOsrkRhAms't #wB]1\{x~*(9}è|ߞentf/'󉿘wqbI4lSMdiAߵpjvsr#۱bť9Y~\/2Y[~iQ<^Ggc؆)a NbB?vb{aYţyO3OV;]$ 1x=;oVZgW[*[~hiII(uWhB2'\GSPu18u7rA"L<8XIȋOo4=XicvSkIgS_ə&+1wAI#|lҁ/&18i8ו /]2QԗFGU{½~/<9dB(H ܤy@G%nwAUϑu)mu/-\E x:Y@~ɞſ# r}X|cͫqN8u:|\D#=ݳ-fA$ =a1q#ȏ֙Y40iz%chn?!{'  ~N(fמFɠߔdy|׮[R-YJeЅ?,@G,4690,@tskb<:xOd+!xbsq!kΫܛ (UUPl˖Y 8 #$;w%-݈L4F}:ׅRELWVQZ90w <osv|5XI G8ˡ}<;mX-?d2M}j'urw@zuNd;NˢC_qc3- E*aŨsQ14]-Tr Ѓvv[ Ɲjzi--Y"hEK<AO`Nd'v (rGaOpSFl;y-)S%G8h,hBj40By8b0;:zLݡ1-P7 <1`d c8_x{UثWb]v*UثWb]v*UثWb]vmyW{S01u^ާ?nU8P8zRn]v*h~kʻeظ.=XQH}zfF_{G.?G;y G|*Sv)v*mn^뒍yx8}\o4}RkӾe~O;>.{zZ4k0wH ]v(݊6ݳj٬(7ٯ|)fb[p>pq+VRF'́4k .\+ uT9~ү>_.? U~1_CEѾ^ڝ:mOxL;~N9$ǷmOb5_wwp} z }MޏѳXW|[uE)mrkX_+鿫z*k_>uqt<<5w!?Y?yuWɟ&1^?1⟯g?^Dž>KƝ8ڟ}w{/?zW?Vc݊libtuxcap-1.4.0/tuxcap-build/properties/0000755000175000017500000000000011212652052020160 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/properties/demo.xml0000644000175000017500000000242210641010425021623 0ustar inniyahinniyah true 1234 Text for Section2/Subsection/Item2 libtuxcap-1.4.0/tuxcap-build/properties/resources.xml0000644000175000017500000001440210641010425022712 0ustar inniyahinniyah libtuxcap-1.4.0/tuxcap-build/fonts/0000755000175000017500000000000011330673043017121 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/fonts/supernova20.txt0000644000175000017500000000207210641010424022037 0ustar inniyahinniyahDefine CharList ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '-', ',' , ':'); Define WidthList ( 13, 12, 13, 12, 13, 13, 13, 12, 13, 13, 13, 9, 3 , 3); Define RectList ( ( 0, 0, 12, 28), ( 13, 0, 4, 28), ( 18, 0, 12, 28), ( 31, 0, 12, 28), ( 44, 0, 12, 28), ( 57, 0, 12, 28), ( 70, 0, 12, 28), ( 83, 0, 11, 28), ( 95, 0, 12, 28), ( 108, 0, 12, 28), ( 121, 0, 12, 28), ( 134, 0, 9, 28), ( 144, 0, 3, 28), ( 148, 0, 3, 28)); Define OffsetList ( ( 0, 0), ( 6, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0)); CreateLayer Main; LayerSetImage Main 'supernova20'; LayerSetAscent Main 23; LayerSetCharWidths Main CharList WidthList; LayerSetCharWidths Main (' ') (8); LayerSetImageMap Main CharList RectList; LayerSetCharOffsets Main CharList OffsetList; LayerSetAscentPadding Main 0; LayerSetLineSpacingOffset Main 0; LayerSetPointSize Main 20; SetDefaultPointSize 20; libtuxcap-1.4.0/tuxcap-build/fonts/Andy28Bold.txt0000644000175000017500000003224110751375104021535 0ustar inniyahinniyahDefine CharList ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', ';', ':',"'", '"', ',', '<', '.', '>', '/', '?', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); Define WidthList ( 20, 24, 21, 21, 22, 19, 24, 21, 10, 19, 22, 19, 28, 25, 21, 18, 23, 21, 20, 19, 22, 19, 26, 20, 16, 20, 15, 17, 14, 18, 15, 10, 17, 17, 8, 9, 15, 8, 25, 18, 16, 16, 17, 14, 15, 10, 18, 15, 19, 15, 13, 16, 18, 10, 18, 17, 18, 17, 19, 14, 17, 16, 18, 8, 8, 21, 19, 20, 25, 11, 21, 18, 12, 12, 21, 36, 21, 19, 12, 12, 12, 12, 8, 8, 6, 11, 8, 21, 8, 21, 15, 17, 8, 14, 19, 16, 20, 14, 21, 17, 20, 20, 20, 20, 20, 20, 26, 21, 22, 22, 22, 22, 10, 10, 10, 10, 26, 26, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 24, 15, 15, 15, 15, 15, 15, 26, 14, 15, 15, 15, 15, 8, 8, 8, 8, 16, 18, 16, 16, 16, 16, 16, 16, 18, 18, 18, 18, 13, 13); Define RectList ( ( 0, 0, 31, 51), ( 32, 0, 32, 51), ( 65, 0, 30, 51), ( 96, 0, 27, 51), ( 124, 0, 30, 51), ( 155, 0, 27, 51), ( 183, 0, 32, 51), ( 216, 0, 27, 51), ( 244, 0, 15, 51), ( 260, 0, 31, 51), ( 292, 0, 28, 51), ( 321, 0, 28, 51), ( 350, 0, 34, 51), ( 385, 0, 32, 51), ( 418, 0, 29, 51), ( 448, 0, 29, 51), ( 478, 0, 30, 51), ( 509, 0, 33, 51), ( 543, 0, 29, 51), ( 573, 0, 29, 51), ( 603, 0, 28, 51), ( 632, 0, 27, 51), ( 660, 0, 33, 51), ( 694, 0, 29, 51), ( 724, 0, 26, 51), ( 751, 0, 31, 51), ( 783, 0, 23, 51), ( 807, 0, 25, 51), ( 833, 0, 23, 51), ( 857, 0, 26, 51), ( 884, 0, 23, 51), ( 908, 0, 22, 51), ( 931, 0, 24, 51), ( 956, 0, 25, 51), ( 982, 0, 14, 51), ( 997, 0, 23, 51), (1021, 0, 25, 51), (1047, 0, 16, 51), (1064, 0, 31, 51), (1096, 0, 24, 51), (1121, 0, 24, 51), (1146, 0, 24, 51), (1171, 0, 25, 51), (1197, 0, 22, 51), (1220, 0, 24, 51), (1245, 0, 19, 51), (1265, 0, 25, 51), (1291, 0, 24, 51), (1316, 0, 26, 51), (1343, 0, 25, 51), (1369, 0, 22, 51), (1392, 0, 26, 51), (1419, 0, 25, 51), (1445, 0, 15, 51), (1461, 0, 28, 51), (1490, 0, 27, 51), (1518, 0, 26, 51), (1545, 0, 25, 51), (1571, 0, 27, 51), (1599, 0, 25, 51), (1625, 0, 27, 51), (1653, 0, 23, 51), (1677, 0, 27, 51), (1705, 0, 16, 51), (1722, 0, 14, 51), (1737, 0, 27, 51), (1765, 0, 24, 51), (1790, 0, 29, 51), (1820, 0, 29, 51), (1850, 0, 20, 51), (1871, 0, 32, 51), (1904, 0, 23, 51), (1928, 0, 22, 51), (1951, 0, 22, 51), (1974, 0, 22, 51), (1997, 0, 48, 51), (2046, 0, 23, 51), (2070, 0, 22, 51), (2093, 0, 20, 51), (2114, 0, 20, 51), (2135, 0, 20, 51), (2156, 0, 20, 51), (2177, 0, 16, 51), (2194, 0, 14, 51), (2209, 0, 16, 51), (2226, 0, 22, 51), (2249, 0, 16, 51), (2266, 0, 21, 51), (2288, 0, 14, 51), (2303, 0, 21, 51), (2325, 0, 24, 51), (2350, 0, 24, 51), (2375, 0, 16, 51), (2392, 0, 29, 51), (2422, 0, 34, 51), (2457, 0, 32, 51), (2490, 0, 37, 51), (2528, 0, 29, 51), (2558, 0, 41, 51), (2600, 0, 30, 51), (2631, 0, 39, 51), (2671, 0, 39, 51), (2711, 0, 39, 51), (2751, 0, 39, 51), (2791, 0, 39, 51), (2831, 0, 39, 51), (2871, 0, 41, 51), (2913, 0, 38, 51), (2952, 0, 38, 51), (2991, 0, 38, 51), (3030, 0, 38, 51), (3069, 0, 38, 51), (3108, 0, 17, 51), (3126, 0, 17, 51), (3144, 0, 17, 51), (3162, 0, 17, 51), (3180, 0, 41, 51), (3222, 0, 41, 51), (3264, 0, 37, 51), (3302, 0, 37, 51), (3340, 0, 37, 51), (3378, 0, 37, 51), (3416, 0, 37, 51), (3454, 0, 37, 51), (3492, 0, 34, 51), (3527, 0, 34, 51), (3562, 0, 34, 51), (3597, 0, 34, 51), (3632, 0, 34, 51), (3667, 0, 40, 51), (3708, 0, 29, 51), (3738, 0, 29, 51), (3768, 0, 29, 51), (3798, 0, 29, 51), (3828, 0, 29, 51), (3858, 0, 29, 51), (3888, 0, 41, 51), (3930, 0, 29, 51), (3960, 0, 29, 51), (3990, 0, 29, 51), (4020, 0, 29, 51), (4050, 0, 29, 51), (4080, 0, 16, 51), (4097, 0, 16, 51), (4114, 0, 16, 51), (4131, 0, 16, 51), (4148, 0, 30, 51), (4179, 0, 30, 51), (4210, 0, 30, 51), (4241, 0, 30, 51), (4272, 0, 30, 51), (4303, 0, 30, 51), (4334, 0, 30, 51), (4365, 0, 30, 51), (4396, 0, 31, 51), (4428, 0, 31, 51), (4460, 0, 31, 51), (4492, 0, 31, 51), (4524, 0, 26, 51), (4551, 0, 26, 51)); Define OffsetList ( (-4, 0), (-4, 0), (-4, 0), (-3, 0), (-4, 0), (-3, 0), (-4, 0), (-3, 0), (-3, 0), (-5, 0), (-3, 0), (-4, 0), (-3, 0), (-3, 0), (-4, 0), (-6, 0), (-4, 0), (-4, 0), (-5, 0), (-5, 0), (-4, 0), (-5, 0), (-4, 0), (-5, 0), (-5, 0), (-5, 0), (-4, 0), (-4, 0), (-4, 0), (-4, 0), (-4, 0), (-5, 0), (-3, 0), (-4, 0), (-3, 0), (-10, 0), (-4, 0), (-5, 0), (-4, 0), (-3, 0), (-4, 0), (-4, 0), (-4, 0), (-3, 0), (-5, 0), (-5, 0), (-3, 0), (-5, 0), (-4, 0), (-5, 0), (-5, 0), (-5, 0), (-3, 0), (-2, 0), (-5, 0), (-6, 0), (-4, 0), (-4, 0), (-4, 0), (-7, 0), (-4, 0), (-3, 0), (-4, 0), (-3, 0), (-3, 0), (-3, 0), (-3, 0), (-5, 0), (-2, 0), (-5, 0), (-4, 0), (-3, 0), (-3, 0), (-7, 0), ( 0, 0), (-6, 0), ( 0, 0), (-1, 0), (-1, 0), (-3, 0), (-6, 0), (-5, 0), (-5, 0), (-2, 0), (-5, 0), (-6, 0), (-4, 0), ( 0, 0), (-2, 0), ( 0, 0), (-5, 0), (-4, 0), (-4, 0), (-7, 0), (-7, 0), (-8, 0), (-9, 0), (-7, 0), (-8, 0), (-7, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-4, 0), (-4, 0), (-4, 0), (-4, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-8, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-8, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-8, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-4, 0), (-4, 0), (-4, 0), (-4, 0), (-7, 0), (-6, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-7, 0), (-6, 0), (-6, 0), (-6, 0), (-6, 0), (-7, 0), (-7, 0)); Define KerningPairs ("!)","!*","!Y","\"0","\"1","\"4","\"7","\"A","#T","#W","#Y","#q","#x","$c","$e","$g", "%e","&K","'0","'7","'9","(j","*!","*A","*C","*a","*c","*g","*i","*q","+A","+C", "+a",",T",",V","-A","-T","-X","-Z","-a","-b","-c","-d","-v",".K",".M",".T",".V", ".Z",".f","/P","/T","/a","/e","/g","/o","/q","/s","/u","0)","0,","0.","0W","1Y", "3,","3.","5Y","6.","6y","7J","7S","8)","8,","8.","8J","8N","8O","8Q","8U","8b", "8c","8d","8e","8g","8h","8o","8s","8u","8y","9X","9Y",":T",":Z",";T",";Z",">q", ">v","?A","@A","@Z","A*","Aq","B,","B.","B:","B;","B?","B","B","B/","CJ","CT", "D,","D.","DA","DT","Da","E.","ES","ET","F\"","F'","F,","F.","F?","FA","FC","Fa", "Fe","Fg","Fi","Fn","Fo","Fr","Fs","Fu","Fy","G\"","G'","GT","I7","J!","J\"","J#", "J'","J,","J-","J.","J/","J0","J4","J5","J6","J9","J:","J;","J?","J@","JA","JC", "JE","JN","JQ","JT","JX","JY","JZ","J[","J]","Ja","Jc","Jd","Je","Jf","Jg","Ji", "Jk","Jm","Jn","Jo","Jp","Jq","Jr","Js","Jt","Ju","Jv","Jw","Jx","Jy","Jz","J{", "J}","J~","J","J","J","J=","J=","J","J","J","Ji","K\"","K'","K,","K-","K.", "K0","K4","K5","K6","K7","K8","K9","K@","KA","KG","KK","KT","Kg","Kr","Ks","Kv", "Kw","Ky","Kz","K~","K","K","L\"","L#","L'","L*","L-","L7","L9","LS","LT","LV", "LY","Lc","Lj","N7","O)","O,","O.","O/","O:","O;","O?","Oa","O","O","O/","P\"", "P%","P'","P(","P+","P,","P-","P.","P/","P0","P:","P;","P<","P=","P@","PA","PC", "PG","PP","PT","Pa","Pc","Pd","Pe","Pg","Po","Pq","Ps","Py","P~","P","P","P=", "P=","P","P","P","P","P/","Q\"","Q'","Q)","Q,","Q.","Q7","Q;","Q?","QT","QV", "Q`","R9","S\"","S&","S'","ST","Sc","Se","Sg","Ss","T\"","T#","T'","T,","T-","T.", "T:","T;","T@","TA","TC","TE","TG","TM","TO","TQ","TW","TZ","Ta","Tb","Tc","Td", "Te","Tf","Tg","Th","Ti","Tk","Tl","Tm","Tn","To","Tp","Tq","Tr","Ts","Tt","Tu", "Tv","Tw","Tx","Ty","Tz","T","T","T","T","V,","V.","V;","VC","Va","Vj","Vq", "W:","Wa","Wc","Wi","W","X*","X-","X.","X9","XM","XT","XV","XW","XX","XY","XZ", "Xt","Xw","Xy","Y\"","Y#","Y'","Y*","Y,","Y-","Y.","Y0","Y4","Y7","Y9","Y:","Y;", "Y@","YA","YC","YG","YT","YV","Ya","Yc","Yd","Ye","Yg","Yi","Yn","Yo","Yp","Yq", "Yr","Ys","Yu","Yv","Yz","Y","Y","Y","Y","Y","Y","Z\"","Z'","Z*","Z-","ZA", "ZG","ZT","ZV","ZW","Zy","Z","Z","Z","[b","a\"","a'","a)","a,","a.","a7","aT", "aY","a","b\"","b'","b*","b.","bT","bZ","b[","c%","c)","cT","c","d-","d=","d", "e\"","e'","e,","e.","e7","e:","eT","eV","e","f$","f%","f'","f.","f=","f?","fP", "fS","fT","fV","fX","fY","f[","f]","f{","g\"","g'","gT","g","h\"","h'","i7","j-", "j9","l9","l","mT","n\"","n'","n?","nT","o\"","o'","o,","o.","oT","p\"","p'","p,", "p.","pT","q\"","q'","q:","qY","q","r,","r-","r.","rc","rd","rg","rq","r","s\"", "s'","s/","s7","sT","si","t:","u\"","u'","v,","v.","vT","w\"","w'","x*","x7","x9", "xT","xV","y,","y-","y.","y7","y<","y=","y@","yT","y","y","z\"","z#","z'","z-", "z9","zT","zV","zt","zy","}B","}P","}d","}e","}y","T","A","T","a","T","Z", "a","q","B","T","V","Z","a","t","S","T","a","S","T","x","T"); Define KerningValues ( -1, -1, 1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 2, -1, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -2, -1, -2, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -2, -1, -2, -2, -2, -2, -2, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -2, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, -1); CreateLayer Main; LayerSetImage Main 'Andy28Bold'; LayerSetAscent Main 34; LayerSetCharWidths Main CharList WidthList; LayerSetCharWidths Main (' ') (12); LayerSetKerningPairs Main KerningPairs KerningValues; LayerSetImageMap Main CharList RectList; LayerSetCharOffsets Main CharList OffsetList; LayerSetAscentPadding Main 5; LayerSetLineSpacingOffset Main 0; LayerSetPointSize Main 28; SetDefaultPointSize 28; libtuxcap-1.4.0/tuxcap-build/fonts/Kiloton9.txt0000644000175000017500000000630210641010424021363 0ustar inniyahinniyahDefine CharList ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '!',"'", '"', ',', '.', '?'); Define WidthList ( 12, 12, 12, 12, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 12, 6, 6, 10, 6, 6, 12); Define RectList ( ( 0, 0, 9, 12), ( 10, 0, 9, 12), ( 20, 0, 9, 12), ( 30, 0, 9, 12), ( 40, 0, 9, 12), ( 50, 0, 9, 12), ( 60, 0, 9, 12), ( 70, 0, 9, 12), ( 80, 0, 3, 12), ( 84, 0, 9, 12), ( 94, 0, 9, 12), ( 104, 0, 9, 12), ( 114, 0, 9, 12), ( 124, 0, 9, 12), ( 134, 0, 9, 12), ( 144, 0, 9, 12), ( 154, 0, 9, 12), ( 164, 0, 9, 12), ( 174, 0, 9, 12), ( 184, 0, 9, 12), ( 194, 0, 9, 12), ( 204, 0, 9, 12), ( 214, 0, 9, 12), ( 224, 0, 9, 12), ( 234, 0, 9, 12), ( 244, 0, 9, 12), ( 254, 0, 9, 12), ( 264, 0, 9, 12), ( 274, 0, 9, 12), ( 284, 0, 9, 12), ( 294, 0, 9, 12), ( 304, 0, 9, 12), ( 314, 0, 9, 12), ( 324, 0, 9, 12), ( 334, 0, 3, 12), ( 338, 0, 9, 12), ( 348, 0, 9, 12), ( 358, 0, 9, 12), ( 368, 0, 9, 12), ( 378, 0, 9, 12), ( 388, 0, 9, 12), ( 398, 0, 9, 12), ( 408, 0, 9, 12), ( 418, 0, 9, 12), ( 428, 0, 9, 12), ( 438, 0, 9, 12), ( 448, 0, 9, 12), ( 458, 0, 9, 12), ( 468, 0, 9, 12), ( 478, 0, 9, 12), ( 488, 0, 9, 12), ( 498, 0, 9, 12), ( 508, 0, 10, 12), ( 519, 0, 6, 12), ( 526, 0, 9, 12), ( 536, 0, 9, 12), ( 546, 0, 9, 12), ( 556, 0, 9, 12), ( 566, 0, 9, 12), ( 576, 0, 9, 12), ( 586, 0, 9, 12), ( 596, 0, 9, 12), ( 606, 0, 3, 12), ( 610, 0, 3, 12), ( 614, 0, 8, 12), ( 623, 0, 3, 12), ( 627, 0, 3, 12), ( 631, 0, 9, 12)); Define OffsetList ( ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0)); CreateLayer Main; LayerSetImage Main 'Kiloton9'; LayerSetAscent Main 10; LayerSetCharWidths Main CharList WidthList; LayerSetCharWidths Main (' ') (6); LayerSetImageMap Main CharList RectList; LayerSetCharOffsets Main CharList OffsetList; LayerSetAscentPadding Main 0; LayerSetLineSpacingOffset Main 0; LayerSetPointSize Main 9; SetDefaultPointSize 9; libtuxcap-1.4.0/tuxcap-build/fonts/ContinuumBold12.txt0000644000175000017500000001552310641010424022605 0ustar inniyahinniyahDefine CharList ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', ';', ':',"'", '"', ',', '<', '.', '>', '/', '?', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); Define WidthList ( 10, 9, 8, 9, 8, 8, 9, 9, 4, 5, 9, 8, 12, 9, 9, 9, 9, 9, 8, 7, 9, 9, 13, 9, 9, 8, 8, 8, 7, 8, 8, 4, 8, 8, 3, 3, 8, 3, 12, 8, 8, 8, 8, 4, 7, 4, 8, 8, 11, 7, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 5, 4, 11, 11, 8, 14, 9, 0, 7, 5, 5, 5, 8, 10, 9, 4, 5, 4, 5, 4, 4, 3, 5, 3, 9, 3, 9, 9, 8, 4, 7, 10, 11, 8, 12, 12, 8, 10, 10, 10, 10, 10, 10, 19, 10, 8, 8, 8, 9, 4, 5, 4, 4, 11, 9, 9, 9, 9, 9, 9, 13, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 9, 14, 8, 8, 8, 8, 8, 4, 4, 4, 4, 10, 9, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 8, 8); Define RectList ( ( 0, 0, 10, 19), ( 11, 0, 9, 19), ( 21, 0, 8, 19), ( 30, 0, 9, 19), ( 40, 0, 8, 19), ( 49, 0, 8, 19), ( 58, 0, 9, 19), ( 68, 0, 9, 19), ( 78, 0, 3, 19), ( 82, 0, 5, 19), ( 88, 0, 9, 19), ( 98, 0, 8, 19), ( 107, 0, 12, 19), ( 120, 0, 9, 19), ( 130, 0, 9, 19), ( 140, 0, 9, 19), ( 150, 0, 8, 19), ( 159, 0, 8, 19), ( 168, 0, 8, 19), ( 177, 0, 8, 19), ( 186, 0, 9, 19), ( 196, 0, 10, 19), ( 207, 0, 13, 19), ( 221, 0, 10, 19), ( 232, 0, 10, 19), ( 243, 0, 9, 19), ( 253, 0, 8, 19), ( 262, 0, 8, 19), ( 271, 0, 7, 19), ( 279, 0, 8, 19), ( 288, 0, 8, 19), ( 297, 0, 4, 19), ( 302, 0, 8, 19), ( 311, 0, 8, 19), ( 320, 0, 3, 19), ( 324, 0, 5, 19), ( 330, 0, 8, 19), ( 339, 0, 3, 19), ( 343, 0, 11, 19), ( 355, 0, 8, 19), ( 364, 0, 8, 19), ( 373, 0, 8, 19), ( 382, 0, 8, 19), ( 391, 0, 4, 19), ( 396, 0, 7, 19), ( 404, 0, 4, 19), ( 409, 0, 8, 19), ( 418, 0, 9, 19), ( 428, 0, 11, 19), ( 440, 0, 8, 19), ( 449, 0, 8, 19), ( 458, 0, 8, 19), ( 467, 0, 9, 19), ( 477, 0, 3, 19), ( 481, 0, 8, 19), ( 490, 0, 8, 19), ( 499, 0, 8, 19), ( 508, 0, 7, 19), ( 516, 0, 9, 19), ( 526, 0, 8, 19), ( 535, 0, 9, 19), ( 545, 0, 9, 19), ( 555, 0, 8, 19), ( 564, 0, 5, 19), ( 570, 0, 3, 19), ( 574, 0, 11, 19), ( 586, 0, 11, 19), ( 598, 0, 8, 19), ( 607, 0, 14, 19), ( 622, 0, 8, 19), ( 631, 0, 10, 19), ( 642, 0, 7, 19), ( 650, 0, 4, 19), ( 655, 0, 4, 19), ( 660, 0, 5, 19), ( 666, 0, 9, 19), ( 676, 0, 10, 19), ( 687, 0, 9, 19), ( 697, 0, 3, 19), ( 701, 0, 5, 19), ( 707, 0, 3, 19), ( 711, 0, 5, 19), ( 717, 0, 4, 19), ( 722, 0, 4, 19), ( 727, 0, 3, 19), ( 731, 0, 5, 19), ( 737, 0, 3, 19), ( 741, 0, 9, 19), ( 751, 0, 3, 19), ( 755, 0, 9, 19), ( 765, 0, 9, 19), ( 775, 0, 8, 19), ( 784, 0, 3, 19), ( 788, 0, 7, 19), ( 796, 0, 10, 19), ( 807, 0, 13, 19), ( 821, 0, 8, 19), ( 830, 0, 12, 19), ( 843, 0, 12, 19), ( 856, 0, 8, 19), ( 865, 0, 10, 19), ( 876, 0, 10, 19), ( 887, 0, 10, 19), ( 898, 0, 10, 19), ( 909, 0, 10, 19), ( 920, 0, 10, 19), ( 931, 0, 21, 19), ( 953, 0, 10, 19), ( 964, 0, 8, 19), ( 973, 0, 8, 19), ( 982, 0, 8, 19), ( 991, 0, 8, 19), (1000, 0, 5, 19), (1006, 0, 5, 19), (1012, 0, 7, 19), (1020, 0, 6, 19), (1027, 0, 11, 19), (1039, 0, 9, 19), (1049, 0, 9, 19), (1059, 0, 9, 19), (1069, 0, 9, 19), (1079, 0, 9, 19), (1089, 0, 9, 19), (1099, 0, 13, 19), (1113, 0, 9, 19), (1123, 0, 9, 19), (1133, 0, 9, 19), (1143, 0, 9, 19), (1153, 0, 10, 19), (1164, 0, 8, 19), (1173, 0, 7, 19), (1181, 0, 8, 19), (1190, 0, 8, 19), (1199, 0, 8, 19), (1208, 0, 8, 19), (1217, 0, 9, 19), (1227, 0, 14, 19), (1242, 0, 9, 19), (1252, 0, 8, 19), (1261, 0, 8, 19), (1270, 0, 8, 19), (1279, 0, 8, 19), (1288, 0, 3, 19), (1292, 0, 5, 19), (1298, 0, 6, 19), (1305, 0, 6, 19), (1312, 0, 9, 19), (1322, 0, 8, 19), (1331, 0, 8, 19), (1340, 0, 8, 19), (1349, 0, 9, 19), (1359, 0, 9, 19), (1369, 0, 8, 19), (1378, 0, 11, 19), (1390, 0, 8, 19), (1399, 0, 8, 19), (1408, 0, 8, 19), (1417, 0, 8, 19), (1426, 0, 8, 19), (1435, 0, 8, 19)); Define OffsetList ( ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), (-1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 3, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), (-1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), (-1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), (-1, 0), ( 0, 0), (-1, 0), (-1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), (-1, 0), (-1, 0), (-1, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0), ( 0, 0)); CreateLayer Main; LayerSetImage Main 'ContinuumBold12'; LayerSetAscent Main 16; LayerSetCharWidths Main CharList WidthList; LayerSetCharWidths Main (' ') (9); LayerSetImageMap Main CharList RectList; LayerSetCharOffsets Main CharList OffsetList; LayerSetAscentPadding Main 0; LayerSetLineSpacingOffset Main 0; LayerSetPointSize Main 12; SetDefaultPointSize 12; libtuxcap-1.4.0/tuxcap-build/fonts/ArmorPiercing22.txt0000644000175000017500000001022410641010424022556 0ustar inniyahinniyahDefine CharList ( 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '[', '{', ']', '}', ';', ':',"'", '"', ',', '<', '.', '>', '/', '?'); Define WidthList ( 11, 10, 11, 11, 11, 11, 11, 12, 7, 11, 12, 11, 14, 12, 11, 11, 11, 10, 10, 11, 11, 12, 14, 13, 11, 11, 11, 10, 11, 11, 11, 11, 11, 12, 7, 11, 12, 11, 14, 12, 11, 11, 11, 10, 10, 11, 11, 12, 14, 13, 11, 11, 11, 9, 11, 11, 11, 11, 11, 10, 11, 11, 15, 7, 8, 18, 18, 12, 20, 15, 11, 12, 12, 11, 12, 10, 12, 12, 11, 15, 11, 15, 7, 7, 7, 11, 7, 13, 7, 13, 13, 12); Define RectList ( ( 0, 0, 10, 32), ( 11, 0, 10, 32), ( 22, 0, 8, 32), ( 31, 0, 9, 32), ( 41, 0, 8, 32), ( 50, 0, 8, 32), ( 59, 0, 8, 32), ( 68, 0, 9, 32), ( 78, 0, 3, 32), ( 82, 0, 8, 32), ( 91, 0, 9, 32), ( 101, 0, 8, 32), ( 110, 0, 14, 32), ( 125, 0, 9, 32), ( 135, 0, 8, 32), ( 144, 0, 9, 32), ( 154, 0, 8, 32), ( 163, 0, 10, 32), ( 174, 0, 9, 32), ( 184, 0, 7, 32), ( 192, 0, 8, 32), ( 201, 0, 10, 32), ( 212, 0, 14, 32), ( 227, 0, 10, 32), ( 238, 0, 8, 32), ( 247, 0, 8, 32), ( 256, 0, 10, 32), ( 267, 0, 10, 32), ( 278, 0, 8, 32), ( 287, 0, 9, 32), ( 297, 0, 8, 32), ( 306, 0, 8, 32), ( 315, 0, 8, 32), ( 324, 0, 9, 32), ( 334, 0, 3, 32), ( 338, 0, 8, 32), ( 347, 0, 9, 32), ( 357, 0, 8, 32), ( 366, 0, 14, 32), ( 381, 0, 9, 32), ( 391, 0, 8, 32), ( 400, 0, 9, 32), ( 410, 0, 8, 32), ( 419, 0, 10, 32), ( 430, 0, 9, 32), ( 440, 0, 7, 32), ( 448, 0, 8, 32), ( 457, 0, 10, 32), ( 468, 0, 14, 32), ( 483, 0, 10, 32), ( 494, 0, 8, 32), ( 503, 0, 8, 32), ( 512, 0, 8, 32), ( 521, 0, 5, 32), ( 527, 0, 8, 32), ( 536, 0, 8, 32), ( 545, 0, 8, 32), ( 554, 0, 8, 32), ( 563, 0, 9, 32), ( 573, 0, 10, 32), ( 584, 0, 8, 32), ( 593, 0, 9, 32), ( 603, 0, 12, 32), ( 616, 0, 4, 32), ( 621, 0, 5, 32), ( 627, 0, 18, 32), ( 646, 0, 15, 32), ( 662, 0, 8, 32), ( 671, 0, 17, 32), ( 689, 0, 12, 32), ( 702, 0, 7, 32), ( 710, 0, 11, 32), ( 722, 0, 8, 32), ( 731, 0, 7, 32), ( 739, 0, 9, 32), ( 749, 0, 10, 32), ( 760, 0, 9, 32), ( 770, 0, 9, 32), ( 780, 0, 8, 32), ( 789, 0, 12, 32), ( 802, 0, 8, 32), ( 811, 0, 12, 32), ( 824, 0, 3, 32), ( 828, 0, 3, 32), ( 832, 0, 3, 32), ( 836, 0, 8, 32), ( 845, 0, 3, 32), ( 849, 0, 11, 32), ( 861, 0, 3, 32), ( 865, 0, 12, 32), ( 878, 0, 10, 32), ( 889, 0, 9, 32)); Define OffsetList ( ( 0, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), (-1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 1, 0), ( 0, 0), ( 1, 0), ( 1, 0)); CreateLayer Main; LayerSetImage Main 'ArmorPiercing22'; LayerSetAscent Main 32; LayerSetCharWidths Main CharList WidthList; LayerSetCharWidths Main (' ') (7); LayerSetImageMap Main CharList RectList; LayerSetCharOffsets Main CharList OffsetList; LayerSetAscentPadding Main 0; LayerSetLineSpacingOffset Main 0; LayerSetPointSize Main 22; SetDefaultPointSize 22; libtuxcap-1.4.0/tuxcap-build/sounds/0000755000175000017500000000000011330673043017303 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/sounds/metal_loop.wav0000644000175000017500000011457210641010425022160 0ustar inniyahinniyahRIFFrWAVEfmt +Ddata$| & /3*>@+jXCw8 Ue` lQV+fH}p2y#Tv)2^pwP:;4)1OC8U)@hI_gA$'{TmzwBa!PA?3G I5% (aS^>+[>3 WJ: &q\ -^-j){$ J,vA~76hT&Z~SKY:l L! (I1q4Hkh q$x,2?O`BQPL ]$r)=9{${5EAk2Xq4d1Q,Ty? v|b47%T(XP;MGl[## .[0N;TWjlTI>X 0s }3o[:S[Dz  VGG+&RLNz ]fn1s%VMWP" 4 }=c1k",R%NgBt{8Vi= [tZ<<qD u  r D l 2 *o  ;@}tN&_35IwE N 6  y } , @iRS'M4 ] g$oCB eL@n ^!. vBT &w CU@9tV   uC,qog3A9u:IYng[ j ,  A< Xc  ju t * m q wYa>2[}0oS %  K Lh 6 ? w_^z%;Nc Ldl!(6  w j~x t}} 4UM% I q?<V e,hX:< aW4< 3 (Uo >Y@d FA: H tRll7HJ L2b{@I>)00F>!X? = | B) [Ts Q &a4E2h`D?FUUj %NXu<JX  ]' _  VrMx-z3k$KzPV$ .4" dP NSv A; \R3C4@wA7~NwK +@m.a2h wva asPfN A3McAzu.hNH7bW(G bl @Z7w,! .bHU_A <y, iEh!gg] Hi6#|EilU nL ~ v " : 9g:<C-K2 cvU_"J&N&a#;%"-&`"lelV/F I 7-^"%$x"vOpq Zrf>i* "' H ; # $H m) [M :q' <tZ lKpK9  (Yi0 KA SjV~ bK4i-kx݇`8DTӺ]x/sޥ0yn ) :%p>\`k4Kw R,Jsd " %) m  w'( m L&U4!#/)'ڙ)[$D#Z,b*$v3S$da 3Z _HoK '/ +%q^V3/9юDpԓҶy% 5>?a5Ee`I\ S0 *yL<+&!  q],Z7?k E$/,-Q&a)L6<={(7S=t5$50v"AB_B  e(o** 8%C cIo^n"PV eKK ?\BXO: 290(0ܳ\w\ɲ򼳯з;A ẔZT#'A$ yq '#\vl_ۋCڲrߤ{j;W  : m 8~z _\p$f%$02Q@oMKb`TyXiS-?L69V&}RcOr[AH7#d(>*'>U   = d Q G 4 CI b3#r\/ kZej4#S% wFvjKH  g _ t "$&C(8b=V;= @ CMiG gJN_!HFQQIf)O uP,ZU\2BVQ/XcFSORWJu= ,7 %g7J =BM04x ;  Wd7.$#v|mwнV붿?^b|̧ܭ  ɟ A ;U$@{h^ ܳtC G.Yb($`'hA*gGjQRiJaVU`T+V)SP>!5~1#rTOz * K%+GFYx 5 GT B 7S 3?y b;f \\ҭm\.Mgf^@)OޝX%-쮑'bbD\YP\G.hlz_B C(-8 B ??C`BUWG!LOy?S@ZP]ZVVU>VW8WbNf@M48i45.f$!-!#&T$j)i.R+J-(F'10V"/#;R%l -o*Aư 9]teУMq }  ~"e t_,x>)P2s!F(Y]3!FfMPX \ n]`Y*\20_GYwyXsܑ nSC'g pX-DLC0PVW|dGg: ^`v \a ld[/\dZTRI?3AtJL jL YNMJJC =@o:;8BM>5Gy212(6 2 "JsLG DyWv#qvrtִw lW0K ʛ z:ՉTf-@ 튡<6$6ɹ{˿/tkz"` Hv4LکmOinDc- \J;Hֵw(,5 <} 7*9xI8eRX`.]:XYWRqXX\2act\ 0U QJvFA<:(143+! dpeՓ A Ǩ .8B)¢vkL(:5v0+ Uk\-R t ro lbz,6BcoC³ą (Hq? v[ʞ q, o ~w~;Bе:d 15{410/ 8Du|zS6 C  X`U#]J, 6 53 >ES{U5FMFPIS_^aPH&^?Tp@X8&y ~l hr})D_ȲR # >Q׬D1QNhMͰs%= $2 ٕHNKݟYTВ׉yۭEa߻~  @t+d ]%Jd,k D-#|'0%+q3p =;4ILGJN1 KIJJGwQxUQIHw&"} u^[4YEd?7ъ ˛Q ¢<ư|ŊhHhKXRӻ-ؾ^/)ÿ4ti]haߙ9ۀ"& > [ܢ MPQM   0 J \ I 'ko\'{,%0 |'Mt*/1D"IH>BDzVEZN /PS LR\J>^'S"N} '%YR +ho L>"C.`Y;RB&y TXlSbOL#Jܚ6be(ܬ5kſt ȝ lھݎ( }*_?8?HOj . <;b }  z$"/s7B6d,;? L}QeWT~U^YMQ F3 D)I(m;"V<0 u *^I  P m 9 W ) HY ^G Bw+ F x$Q(l Z 6gѾDCT~X SсN&TJ p m%  s t h$00o9<<<G>aA C)WB,8i715.r&Bjr: n6D8b`2\kGJ #h٬ aNkwuЕP^~ӻ(ÍUĎ˩"?Dϰρѿy7Q:&79lQi 6=k Z ) n3 v 8!)&/0Q(W%P`G@%Y.4. 4P#(t!Y?<r K <jgp Z  DMo  6S/'+<|ݱ҃CPӘ_. ҆}G.8Bc)ۘFP 0}Jr*+S#!#$,!Q5?,o B((80v.5\==}sux a P^ "y3 5\ xCHA0.jݚVCXѢGYtbѺc H|qo  s~ ;\t<8Pd#d`N! ]%]- M0VN !%1'%%G 6!kZX Zy W qH [gL=]31݁E:H#72#%Ҥ0|ӄ`3QjbԤT65 /  W 9{(0AAn;U<0V(}C x # ! |$$ "? n m T &  w!kd$(4&'$VNhI>/c 9 ~B   $:1 khD1$ 'Z%_ Fd < / %u ݎ%SB9ذC W[7 t  uFio%L+XӂoP9)FjBo$ lkO }- f4'4B*gLR]Fp  7a1 3(`1 F8G70! u xr.(oʶZӴ6nfg) s@2rz;:=2V0'} J"%* 5d6{ GFJI= ,FM n,/Gō=毌Nh-L_gW`b+ KX/R+LJPHuIE%:;+~` ݲ) 8zqg  (59- Q !7j:  ֻ1ε4B*t "Ff;@^*Qȉ`3(p7[޸r h!7&RAjg:hMPS1Ķ:|P3SoXS7ɯ|+ WE ISj {M 7 #e K`GV]e.< v  F22f[L^LWHL 7q{x^ YrD)1㻄s,ŁL ȓV{ Ki!K `2hyfӇ-wY*'P9vH@U/ *q   ?7cF  ېT Sz -Xbm-KJhrUI+|@?3-Q Yބݡ] @\بi ،:%[KL k @*]&F*9P!u9c68BB) C%ev&٨xnO؉( I c Q')gg J4"IDOf<OR+#*4[6-&`P|'*@y߿u{0%. 9:*`<%.2 `4(qL!#$()R, /7Ո0\.D+٬'"%j"zd^+}u=E G3 w=z, QmQXaWq! l-`Ahk۽vWߢTgPkg  >a 4<Z!G k2uWD$,`*/tF3,57= B4 E C!?:524S(1 lv7@3G$7|M~)R~1.ݪTϜ7 I 5̙хa3T8ck` 'VM& 0 5 b J~4 /UeNd'/7f;:;:9,21&Jo< !cS kVcϊԸW ) ILC B0"еxw R 6ܯ0CĺhGo1#NR6LDM{QOTNI$@t 5f'  +yW QXe1x /%Y)|c*&|!s F ]gMTUJ=0*ca]nڽiٱP0T#h@7kQSj!}8}}L}}}j}*v{GfjU"?(L,w96(c Ms#@+ L.*F O'70x#KH- HÇ b am5UNc- Ot}}}}etta+cN:z)r [@b4O0t"5I ^pm}E }/}J}} zw hP4D Oӥ_Oz\{/Z'}#)&6#|( |aE ;ҭ:i!I/<{ R)GCWh}}}}}J},}}3}g}g%N2v`iݝcQyH&p7wSD-nO%W _XULJ=~ * iq~ֽҽR T wpcqx~yCR-*9}FDMIclJC :.) 6bL/V% B6UQ d*Z@UkYl}'}}}Fx\f =J%, q] ʞ p\.I6Kri$*]B*v Wz  rھ׻t``Gj mY]w{[[ 2 .2m8C<==:@3(l?0SPj9VjR0 $b<RPq\bd"Ya Y{M'M=X("[*, fı Fc?׬cضln<1z L Pn=̏6+;FVg jTX <#3FTU8~aQij-bpUHD:- V!Y_> Q-4YM#/E O9  6X @}ȍBk9~Y*SD &l-MS%R<X8!_ym4LJLMH ! CN b P,;HHR6Zi f\ ]GfZ UL dD8j,$Iv3%:ݬ iiU`yQf % >~E{·̀Vn˦~Î e'԰ q)Awj6 i 6Q WI7N ' eL{VgMZj I6 _ v2!)+4^8b>RAGEGOHeC==U2'e  W  Rh(H ~%6BɃAG\ܤ% b5(MDg? !C"$! P"0 "W#"@!j3eCc  c = b |dZ x .4a0w!$ $! 3 d d#yHlp^7o9͆ˊc ͎El4ځ @JDYCMp@f;m60r*H#}tCinUA3H wRKA~9W:O J  K wVf/'u{`[* 8t7"mBUok E?0\ tZ uE$'/^<6>:@GVDC;0"6$7,$A4_ |Dc^SF?dFK.`=I0t#!stz%K1  H)(#7#"C{{rعb5d_ۺ +4ތJS v    8# (%Ct%  1[?`hM   t0 tVG׸f4/"٣?'^*+"-=1 4I5;52.!,('&|v"vln xuh; L م  ο 6)  :{3F.+se`"ӫ_ZftgAO,)` 2B#F6<omu3^)l ;<u 7#)/I39`z;I>A#m@AoAQ?>q×R1]\}A a-MeVbJ7%w?dLAG k.+ % o;L#+/OA4=70;@vD BH$KMlOPhNK.IAD'Ba>{9Y4/+ (# ` 2^XOY~ : }]( q+>MK;xe I odIlmH:TȲ"TĤ ]"`aQ6 vLdEiDOR'H]z9   o"BsQW%.+a3?,<BBzuGYzLMPyPk_NUGOXO~wOyNT H lB A<`76qi:==s9I61 620-R.-J-H-)$aY l ] " A5 Q6\o[ M s:*|l+ItU'كh0j{s2˿eɻc6ѹ1Ҽ|K2KхcXS OC`Va)0^Cl)1bS# Z ^ %&$.i0327Y67o=,:8}082|2Q2,L+BR&&`(H(M[$ir RG ><=%x7H/g&ԒHGN(/t`$ƙQzſok%6`WM j!%&&v#g$'X+;0X~3-5C4b0-8,-`/0-[~)##n6h7Ua p < #$ : : I; # ^Jhgf}+oPa&ڼրu,uֹMkܚ*ݺܕ'Q(_v^? RXs $)q|&r"O!!)"$ E!\!XA/Aq%?;(.w4 E# o!  9 o U! wf s B 6lzW\ o C Wggߘ|$ڿJ֗kSOҶы @ٗRߟNڜ{-M >Y ]$x"8!M XAq^;IG8h|u  q" X x  p? a3":()m-L(5  |] j&$ !n B#eY q` ^ Q1 ,593y  @!xD60x+HJ| 2bG\RfUނ<_Q,J=$ (/.,# $&DW ^Uwko\A^  &(a*q`-' Vi V6 rt}O aI+.<A.F?DG&A28}~+#-{ kVufJ؞ Yr>52zfgZ {]%f(,$X $T V TE z<*9 Mr*]$ *[ Q%( kJfb\Co)D|ʷ>X h b N-pxC  z 9u) --(]dD1#UM qS$u= mc7#i Xt ؗT T%]r&h+Y m%%)&  YG 'ɾ#3ɪN23+&t )K*(D!$& aKuq \x?߉ ;J X qe$)p >_ P  dHN58/І]ƛDw6xYp4 @g$$a"!W ).nb> Pё¡񼷩km^uP], yq Lm mm! #u?Xy flhE 9 @{ w 3a(0^6Pc I\ IST/I [)<9W?8i614$ \L>%xE6K,nW(+%&D fm 0 fS[#3964G"D0 44Ԟ:S œ >qK*D*Q8<2  CS(-l5KC aJ Kp@ /8-u '[ FA ]wV0 4H h3W= ` c GPr~r1V Ei/' <4T ^>'r +>12;0L)&*!rxcEKݽ*(9\ 4  +*5= iBWC@VJ;63?*X!2L y9A66k|.OujҼ9ѯъV'֢`]s&06V4 "7}߾2s #U%[(*m,,N,/'R!C@|A9K1T"=+ ,v0.Q%} ([3 n ! T%ގ>u"!̈́D$!J* G b 0ۯ p- X{ @Rz*"/7-O8J6] /{&\` v! E߆S&h/goC ] q/J;]'k|  t  U 9R r*'e p %,B /2m0)-("".  :[kl1&9+]3d45 4?_/$nh~ |k)UP*Sj35KfgX;wD:R:( s"ֱҼt;C̀5so؈ igvD9|*MnH&y1Ans Z :"w &#*)^5&!"d"]%C *<,,r8,Z/Z_-J-<* $$c%.&V'"V_yP{Fw}ETީF 9T  Q  C T ; z4: C! Ո sL.ɩeKl}*A4:u dehjj)q$x$3*^0*68[:9;9:%<9=:362g.$*'&L))'Qq"|B?nk'-"\)0 )]7~p O 6s )b ײβ.h J]Ș} ^pM׻,Ӆ)U++HC)GM l VM !(2.L/:-*Mx),~*/6R<:-\3+)82:;8b-T/2K 0A5V2Y0+VV8Nz#c%$`t^0 ]E A/3 ih_#GN4K+8}V>b.+ԏ{ϕQ,FK(aLûO)cϋVv$ U #9~M$Q\A,~OGTHPKL  [ !-56869[>C0?]EF:FPCh J6IgIjHAtH8$87!5`/ cKDVPp{`w7 *9 ^ I/ @ n H Y" E zCh /.]ܬx3 Ƅ * L ),|#@m˗҃l"P b<$3@. 2;<;4=CF{>_CJ=nA)B? 96?B= ]/83}+),!X%$-|#by "X$8>%!KB"P4w W~ z #6  bM G6X  - O9r߇"oXϧÆc4ռC뻴cۼ{6cR,ہ-1I*21%$)b6a67+>;z9=*+EmA#G`H>AZC>6&;R;{X772S1O1<+,gd+D){L* J(6 H"t"^ j|jAUi  O nj Y 2 #f:-c9Ӽ< ŬDq ٥rc v  /B~|(i#S )(\058 :<<8ADlGPKNOTWX*XV6ORDogIHCBk@GP@Ar@@@a<837>!5c5z^4{0g0v.V_*A)$I!w ]1V`>n3O]3'okv; HK ?z1׃eШ̘M.-{W3 ^v2IzeQ $Eۂb[RT.Ao&+;.26;>>E?Dw>D?-=R854C1-*(tr+8,]++, ,4C,6(>$2#!| hk!POM M  % w0|<^]}WvQғOȢh{.Cs&t~n f{gĠ̃Ύ[1~އd,uLK]V;'~-t(w &֊CMjяϾNҫH [ W*cK !  3W0$ +^.s2s679`Z9554 413O / +)+)$8W"n 5T?uCk~-݇՞gS*#ǀĔcŲoǖ:ιԟb.?tF% %#Ef/ )9x&s[ d` &CdF ADg!Y&(+j/1[4c4 55 1+S+#36>N\&^,, YFJ ۊ[\0]ҪW(.֍kK{޴?cߙ y#s " )SL#gi~qU>&K [8  4 S !'?F,f,)+d ,+J,11*2/| ( %&(, + ="n N{ $ar)WZ$ (:  ` @ D #* \: SX =hVH`jZB x~ ~unN,E)$);+ # A$h bLC[hJp BW Dp=6&nڜiQ޼HI  jh +R]I[+ +T<H!-jS.\xzo    D#o /&\ /oqN# 5$r Wh9(b~jho t  U!<8 )m# W=T`I7'^@ OKl qb8LaMMt\8_MYn  }m i 5  !CbK} 9Gur82(3 H 6k  )mU ` g\- < R ~SgI! '  oRBF\e2] FhA;;M>;Qv^h  n~h.#Z5 4H7L0 sd| K  yEs $ NC 02<}Rh H`oZ2: /E8X6 8f'D!} ]q (e@=} 3} W  4&CDw? 9 -  ep ɞT'  ("=$jY: /92hMw?Qs c='xI-u.0)q S k9N+P Rdm)B&< {&74&$a i%_+'/3@(.3X(bS9ХU]4xR %% L"K[G:|I"#$#0Js R]ߐptm: LۙdX 2,Uc1=2I !` ld`w 7$ H 4 Ts #6 $t7 w h9N`l}&8QfFu&6''+L1ަ )܆ڄ"f8i  mI2zh%1 h%. 9Xx^btv} Yw/ N"#WQ=7}] K@o dgw$0c4)ny  pQFyeiU8D Ag, Q&Nq  ؼ`[B 3 s  1>;/B%<4  / l,-E`EgPE W@ VM? ot(%uu G; rMJ]+'_ .#+, > ݘ  HSN !  fmx )cUt< ~ 0u p 2"])>X|I &  ZOnfu); u?'{e++`aW V2 _u0=VJ$>lVj^ufhT!r[:cnK[Iv6CU =  XTc w0r  9V2s/d  E$ @6^jW08$хsGB rM/%}*uUE k~TSqX)cwҬ{t ;B!S !C,[)!Wk 2=K:k, 6Vy 3    x>F=e׀%&0#UW gy4sDH%#r6;v3%8#6Zz"Ex6\f3.. "I SN 'l k!d$ ^;"x" _`? U'x1# . +uDQxZ vT (Lܜ&N.k.$}% 3F Q"}CF!i(6)/!  i{]NS9 7 % +[  pH(;bB\3qJ!>!̿ Ƈ:lʄm!Ϛ۳D +F%" ,}eYxv&Z'=*޺%PC*=>(8z  0 : v0im =  3$ +'F-&Q,I1"s1.&A+-84<>".%('5ocxss7g$RxۦA"}͙\9ݝNI#K! xQ (Xa{BW:=/)\:/?=j7/CRERW D}A8q63522"a(#+<}+o,]1 '(  <(T%',# %|-(H|r6עX!D- ZKD  []dTO`@oՆcw. 4,NRz ߞ`ڏܺES1'C N AScod< z N_ #%*%u#%%NC MO@F J#[_YmF I'S.O}P28 /v6y ;*$ 8nbwg 7 F4 m" s5!\"~1WHV$= %yo[[k9rS ^ğHyFͣĞD?eDe]  (:8=uw* ,67, 904@/251)v=5!eIN&#$T8*6+w2" {' &$###F"%{ 0n ji)0&_Ng U H ü^2޽}ەIxƵвsԟSǩ~e D    A E v^ 7=y1 37"4` CmMC`DH9YSM?(N5BCC?AGGT>W-<.'52+;!m& *^* #zkXQ  &#R  ["A)}UV bYzEtl;缸#9>`RzḨ ɯ]ﯽ"622-Z +x6Η2@fU.r /#"KݢU@SF!gh vm ta"M#)1-k< B AA ZHJDV]_z[N\6 X `\|KOI EJ*H+6.,(r#/| p0k dS 3A $ (i"T5ם*/ùH·C QìmȽC2MP 6U5"'|;OHP?JrILS.TmU\MO4_Y*gX2 LI?PGM< J6',+%%/12-(evW%k,|/"/\(-y,$CxO?C"]P1:oϡ^Gђ bT շ@wRKꧭ:j` y†>S|_ϻ ei֍SZ%>+ra/*$) V\R]۰TW*٘޽q]^3 $#!H, HBEvG:4:JNa SM!TGe~eatTS)K56MGu65?5p(9Y5$nI ] K %cd ~ *EUZ :|E ̐,'->ſ_nkɸTֳ"6򍢼?볬0jU뫺!WD<мXݷN,(R#$S).+)VJ"sbeVh  PszGB(9u?H;F&>{KLfLkVC^.D NoQRPFE6J2By1'6 >E'.1..(*b)Sش픡7;NrʿYERTcфݛx@p 2 ,C"> (*',e8ZDGkJL0OpRPDvFI|.C->_86?924}.s\64;)d,J@&*'$n ~J " >Tv )A Om ,  -g `MrfJg՞2% ʾXxytSخ9io$){-}cƵ n3W  ޑ  r^ ^Qk]a+GVƑcl俇޼N!I쿞=ϳKv݋aZ-"8 ^}$") 4F=SC"L5 PRU\QSVPOjW }vբiоh5 Ю  a g9 > b O `Ɉo*=t Ʊt/]aS_4~R<i3d b;@|Yb:k`   # K/:UCQLn?P PO}IDD@z&;97cz5%P2^0,%W ttQ!3k w'u6-!:%B 4TΠQ #$ LISTBINFOICRD 2002-05-13IENG ArchitektISFTSound Forge 4.5libtuxcap-1.4.0/tuxcap-build/pythondemo_template/0000755000175000017500000000000011212652361022050 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/pythondemo_template/game.py0000644000175000017500000000127011212513776023341 0ustar inniyahinniyah# Template pycap game v1.0 # Written by Farbs appIni = { "mCompanyName" : "CompanyNameGoesHere", "mFullCompanyName" : "CompanyNameGoesHere", "mProdName" : "Pycap Template Game", "mProductVersion" : "1.0", "mTitle" : "TuxCap: Pycap Template Game v1.0", "mRegKey" : "TuxCap\\Pythondemo_Template", "mWidth" : 800, "mHeight" : 600, "mAutoEnable3D" : 0, "mTest3D" : 1, "mVSyncUpdates" : 1, "mWindowIconBMP": "unicron_baby.bmp", "mWaitForVSync" : 1} import Pycap as PC PCR = None def loadBase(): import PycapRes global PCR PCR = PycapRes def init(): pass def update( delta ): PC.markDirty() def draw(): pass libtuxcap-1.4.0/tuxcap-build/pythondemo1/0000755000175000017500000000000011212652314020234 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/pythondemo1/game.py0000644000175000017500000001503411062533667021536 0ustar inniyahinniyah# Simple demo game showing the basics of pycap # This dict provides the basic information required to initialize the application. # Filling it out is a great way to pretend that you're making progress on a new project. appIni = { "mCompanyName" : "CompanyNameGoesHere", "mFullCompanyName" : "CompanyNameGoesHere", "mProdName" : "Game Name Goes Here", "mProductVersion" : "1.0", "mTitle" : "TuxCap: Pythondemo1", "mRegKey" : "TuxCap\\Pythondemo1", "mWidth" : 800, "mHeight" : 600, "mAutoEnable3D" : 0, "mTest3D" : 1, "mVSyncUpdates" : 1, "mWindowIconBMP": "unicron_baby.bmp", "mWaitForVSync" : 1} # The Pycap module (imported here as "PC") gives us access to drawing functions, sound functions, and fun stuff like that. import Pycap as PC # The PycapRes module (which we'll import as "PCR" a bit later) gives us access to resource management functions. # It's used to load images and music and fonts and sounds, and to figure out stuff like image widths and font heights. PCR = None # The current state of some of the keyboard keys leftDown = 0 rightDown = 0 upDown = 0 downDown = 0 # the key codes used by some of the keys in this demo # if you want to find out the codes for some other keys, just add "print key" to the keydown function, run the game, and hit the key a few times. Then go read out.txt. KEYLEFT = 37 KEYRIGHT = 39 KEYUP = 38 KEYDOWN = 40 KEYESC = 27 # Whether the game should exit now. In this game we set this to true when the escape key is pressed. doExit = 0 # These are some game objects we'll create in init() player = None things = [] # This class represents the player avatar. The engine doesn't require it, or even know about it. I've just added it to make this demo a little more interesting. class PlayerGuy: # This function is called whenever a playerguy is constructed. def __init__( self, x, y ): # store the x and y parameters as our location self.x = x self.y = y # we'll call this from the main update function def update( self, delta ): # calculate x and y speed from input and scaling factor 1.5 (increase to move faster) dx = ( rightDown - leftDown ) * 1.5 dy = ( downDown - upDown ) *1.5 # apply speed to position for this timestep self.x += dx * delta self.y += dy * delta # we'll call this from the main draw function def draw( self ): # call the draw function. This version takes floating point arguments so the object moves smoothly, rather than jumping one pixel at a time # we offset by the width and the height so that the image is drawn with self.x and self.y at its middle. PC.drawImageF( self.image, self.x - self.width * 0.5, self.y - self.height * 0.5 ) # This class represents an entity other than the player. It's pretty bare. class Thing: def __init__( self, x, y, a ): self.x = x self.y = y self.a = a # current angle def update( self, delta ): # spin! self.a += delta * 0.03 def draw( self ): # to make this a little more interesting we'll tint it and spin it around PC.setColourize( 1 ) # enable tinting PC.setColour( 255, 45, 45, 127 ) # tint red and semi transparent PC.drawImageRotF( self.image, self.x - self.width * 0.5, self.y - self.height * 0.5, self.a ) # draw rotated image PC.setColourize( 0 ) # disable tinting # This function is called first, and is a handy place to load the games resources def loadBase(): # PycapRes is ready to be imported now, so we do it here import PycapRes global PCR PCR = PycapRes # load an image # this image is built from two image files, one for RGB, and another with an underscore for alpha. They can be jpg, png, gif, bmp, whatever. Just make sure they have the same dimensions. PlayerGuy.image = PCR.loadImage( "..\\images\\ImageSample" ) # grab the width and height of the image. We could do this elsewhere, but here'll do. PlayerGuy.width = PCR.imageWidth( PlayerGuy.image ) PlayerGuy.height = PCR.imageHeight( PlayerGuy.image ) # copy the image for use with the Thing class too. I can't be arsed creating more sample data :) Thing.image = PlayerGuy.image Thing.width = PlayerGuy.width Thing.height = PlayerGuy.height # This is called once on startup, after loadBase and before update or draw # It's a pretty good place to initialize game data. def init(): # create some game objects # player global player player = PlayerGuy( 100, 400 ) # create player at location 100, 100 # things global things for i in range( 10 ): things.append( Thing( i * 50, i * 50, i * 0.2 ) ) # create a line of "Thing" objects, one for each i in range 0..9 # This is called regularly, and is where you're expected to update game data. # The parameter "delta" is the amount of time that's passed since this was last called, in centiseconds. I think that's what the unit's called anyway. There's 100 of them every second. # This means you'll need to use some very basic calculus to ensure things don't speed up or slow down with the framerate. def update( delta ): # Tell the engine that we need to call the draw function PC.markDirty() # update the player player.update( delta ) # update the things for t in things: t.update( delta ) # This is called when the engine wants to redraw the screen. # All drawing functions must be called from within this function, or the engine will get shirty. def draw(): # clear the screen PC.setColour( 255, 255, 255, 255 ) PC.fillRect( 0, 0, 800, 600 ) # draw the player player.draw() # draw the things for t in things: t.draw() # This is called every time a key is pressed, with a number corresponding to the key that was pressed. # To find a key's code, add a "print key" line at the start of this function, run the game, press the key a bunch of times, then quit and read out.txt. def keyDown( key ): # if arrow keys have changed, store them in our global variables if key == KEYLEFT: global leftDown leftDown = 1 elif key == KEYRIGHT: global rightDown rightDown = 1 elif key == KEYUP: global upDown upDown = 1 elif key == KEYDOWN: global downDown downDown = 1 elif key == KEYESC: global doExit doExit = 1 # This is just like keydown, but it's called when a key is released. def keyUp( key ): # if arrow keys have changed, store them in our global variables if key == KEYLEFT: global leftDown leftDown = 0 elif key == KEYRIGHT: global rightDown rightDown = 0 elif key == KEYUP: global upDown upDown = 0 elif key == KEYDOWN: global downDown downDown = 0 # This is called by the game every frame to ask if the application should exit. Return 1 here to close the game. def exitGame(): return doExit libtuxcap-1.4.0/tuxcap-build/pythondemo2/0000755000175000017500000000000011212652352020237 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/pythondemo2/game.py0000644000175000017500000005142511062533667021543 0ustar inniyahinniyah# normal imports import random, math ########################################### # Application initialization data ########################################### appIni = { "mCompanyName" : "Farbs", "mFullCompanyName" : "Farbs", "mProdName" : "Petal Hero Prototype", "mProductVersion" : "1.0", "mTitle" : "TuxCap: Petal Hero (Prototype) v1.0", "mRegKey" : "TuxCap\\Pythondemo2", "mWidth" : 800, "mHeight" : 600, "mAutoEnable3D" : 0, "mTest3D" : 1, "mVSyncUpdates" : 1, "mWindowIconBMP": "unicron_baby.bmp", "mWaitForVSync" : 1} doExit = 0 # flag specifying whether or not the game should continue to run (not a hook) res = None PC = None PCR = None hero = None planes = [] playerShots = [] enemyShots = [] explosions = [] bestTime = 0 gameTime = 0 firstRun = 1 font = None squadCount = 0 level = 0 canvasImage = None backgroundImage = None skyImage = None mousex = 0 mousey = 0 nextPlaneTime = 0.0 time = 0.0 PLANEMODE_DELAY = 0 PLANEMODE_ACTIVE = 1 PLANEMODE_DONE = 2 def vToA( x, y, a ): """calculate angle from a 2D vector and default value""" if y == 0: # dangerous special case (avoids div by 0 in dx/dy) if x > 0: return math.pi * 0.5 elif x < 0: return -math.pi * 0.5 else: # don't change angle... previous is probably best return a else: # safe to use atan technique a = math.atan( x / y ) if y < 0: # inverted a += math.pi return a class Hero: """Player 'plane class""" image = None def __init__( self, x, y ): self.x = x self.y = y self.left = 0 self.right = 0 self.up = 0 self.down = 0 self.radius = PCR.imageWidth( self.image ) * 0.5 self.lives = 3 self.lifeTimer = 0 self.a = 0 self.dx = 0 self.dy = 0 def fire( self ): global playerShots if len( playerShots ) < 6: playerShots.append( Shot( self.x + math.cos( self.a ) * 10.0, self.y - math.sin( self.a ) * 10.0, math.sin( self.a ) * 10.0 + self.dx, math.cos( self.a ) * 10.0 + self.dy, 0 ) ) playerShots.append( Shot( self.x - math.cos( self.a ) * 10.0, self.y + math.sin( self.a ) * 10.0, math.sin( self.a ) * 10.0 + self.dx, math.cos( self.a ) * 10.0 + self.dy, 0 ) ) # recoil #self.dx -= math.sin( self.a ) * 2 #self.dy -= math.cos( self.a ) * 2 def hit( self, x, y ): """Accept a hit, return whether still alive or not""" # ignore if recently hit if self.lifeTimer < 0: return 1 # test for lives remaining if self.lives != 0: # damage self.lives -= 1 self.lifeTimer = -100 # bounce n = normScale( x - self.x, y - self.y ) s = -5.0 self.dx += n * s * ( x - self.x ) self.dy += n * s * ( y - self.y ) return 1 else: # death return 0 def update( self, delta ): # move # calc angle self.a = vToA( mousex - self.x, mousey - self.y, self.a ) # drag d = pow( 0.98, delta ) self.dx *= d self.dy *= d # thrust s = 0.1 self.dx += math.sin( self.a ) * s self.dy += math.cos( self.a ) * s # move self.x += self.dx * delta self.y += self.dy * delta # bound the 'plane if self.x < self.radius: self.x = self.radius if self.x > 800 - self.radius: self.x = 800 - self.radius if self.y < self.radius: self.y = self.radius if self.y > 600 - self.radius: self.y = 600 - self.radius # extra life check if self.lives < 3: self.lifeTimer += delta if self.lifeTimer > 500: self.lives += 1 self.lifeTimer -= 500 def draw( self ): # draw the 'plane sprite if self.lifeTimer < 0: # damaged if ( self.lifeTimer % 5.0 ) < 2.5: PC.drawImageRot( self.damageImage, self.x - self.radius, self.y - self.radius, math.pi + self.a ) else: PC.drawImageRot( self.image, self.x - self.radius, self.y - self.radius, math.pi + self.a ) # draw cursor PC.setColour( 0, 0, 0, 255 ) PC.fillRect( mousex - 1, mousey - 1, 3, 3 ) class Plane: """Enemy aeroplane class""" image = None def __init__( self, xi, yi, xa, ya, xb, yb, dxi, dyi, dxa, dya, dxb, dyb, pathTime, delay, fireTime, type ): self.type = type self.radius = PCR.imageWidth( self.image ) * 0.5 areaWidth = 800 + self.radius * 2 areaHeight = 600 + self.radius * 2 self.xi = xi * areaWidth - self.radius self.yi = yi * areaHeight - self.radius self.xa = xa * areaWidth - self.radius self.ya = ya * areaHeight - self.radius self.xb = xb * areaWidth - self.radius self.yb = yb * areaHeight - self.radius self.dxi = dxi * areaWidth - self.radius self.dyi = dyi * areaHeight - self.radius self.dxa = dxa * areaWidth - self.radius self.dya = dya * areaHeight - self.radius self.dxb = dxb * areaWidth - self.radius self.dyb = dyb * areaHeight - self.radius self.pathTime = pathTime self.time = -delay self.fireTime = fireTime self.x = self.xi self.y = self.yi self.a = 0 self.dx = self.dxi self.dy = self.dyi if delay == 0: self.mode = PLANEMODE_ACTIVE else: self.mode = PLANEMODE_DELAY def update( self, delta ): # increment timer self.time += delta # move if active if self.time >= 0 and self.mode != PLANEMODE_DONE: # set to active self.mode = PLANEMODE_ACTIVE # determine path count, time alpha and blend weight t = float( self.time ) / self.pathTime a = t%1 c = int( t ) b = -math.cos( a * math.pi ) * 0.5 + 0.5 # record old position ox = self.x oy = self.y # set new position based on current path and time in it if c == 0: # initial path from i to a self.x = ( self.xi + a*self.dxi ) * (1-b) + ( self.xa + (a-1)*self.dxa ) * b self.y = ( self.yi + a*self.dyi ) * (1-b) + ( self.ya + (a-1)*self.dya ) * b elif c % 2 == 1: # path from a to b self.x = ( self.xa + a*self.dxa ) * (1-b) + ( self.xb + (a-1)*self.dxb ) * b self.y = ( self.ya + a*self.dya ) * (1-b) + ( self.yb + (a-1)*self.dyb ) * b else: # path from b back to a self.x = ( self.xb + a*self.dxb ) * (1-b) + ( self.xa + (a-1)*self.dxa ) * b self.y = ( self.yb + a*self.dyb ) * (1-b) + ( self.ya + (a-1)*self.dya ) * b # record estimated velocity ( I'm too lazy for calculus ) self.dx = ( self.x - ox ) / delta self.dy = ( self.y - oy ) / delta # fire if appropriate global enemyShots if self.fireTime != 0 and int( ( self.time - delta + self.fireTime / 2.0 ) / self.fireTime ) != int( ( self.time + self.fireTime / 2.0 ) / self.fireTime ): n = normScale( self.dx, self.dy ) if n != 0: enemyShots.append( Shot( self.x, self.y, self.dx * n * 4, self.dy * n * 4, 0 ) ) # record current angle self.a = dToA( self.dx, self.dy ) def draw( self ): # draw the 'plane sprite if it's active if self.mode == PLANEMODE_ACTIVE: PC.setColourize( 1 ) levelAlpha = min( gameTime / 6000.0, 1 ) PC.setColour( ( 50 + int( 205 * levelAlpha ) )/ 2 , 50, ( 255 - int( 205 * levelAlpha ) ) /2, 255 ) PC.drawImageRot( self.image, self.x - self.radius, self.y - self.radius, self.a ) PC.setColourize( 0 ) class Shot: """Bullet class""" image = None def __init__( self, x, y, dx, dy, type ): self.x = x self.y = y self.dx = dx self.dy = dy if dx == 0 and dy == 0: self.dy = 1 self.type = type self.radius = PCR.imageWidth( self.image ) * 0.5 self.done = 0 def update( self, delta ): # move self.x += self.dx * delta self.y += self.dy * delta if self.x < 0 - self.radius or self.x > 800 + self.radius or self.y < 0 - self.radius or self.y > 600 + self.radius: self.done = 1 def draw( self ): PC.setColourize( 1 ) PC.setColour( 0, 0, 0, 255 ) PC.drawImageF( self.image, self.x - self.radius, self.y - self.radius ) PC.setColourize( 0 ) class Explosion: """Dodgy particle class""" image = None def __init__( self, x, y ): self.x = x self.y = y self.radius = PCR.imageWidth( self.image ) * 0.5 self.done = 0 self.lifespan = 100 self.age = 0 def update( self, delta ): # age self.age += delta if self.age > self.lifespan: self.done = 1 def draw( self ): PC.setColourize( 1 ) PC.setColour( 255, 255, 255, int( 255 * pow( 1 - self.age / self.lifespan, 1 ) ) ) s = 150 PC.drawImageScaled( self.image, self.x - s / 2, self.y - s / 2, s, s ) PC.setColourize( 0 ) class SquadType: """Basic variables defining a squad type""" def __init__( self, difficulty ): # assumes random number generator is already seeded and ready for use d = difficulty + 1 # shorthand # set base values self.squadSize = int( 1 + random.random() * difficulty ) self.checkpointTime = 800 / difficulty * ( 1 + random.random() ) self.spawnTime = 800 / difficulty * ( 1 + random.random() ) self.fireTime = 400 / difficulty * ( 1 + random.random() ) # choose one value to make more extreme switch = int( random.random() * 4 ) if switch == 0: self.squadSize = difficulty * 4 if switch == 1: self.checkpointTime = 100.0 / difficulty if switch == 2: self.spawnTime = 200 - 150 / difficulty if switch == 3: self.fireTime = 100 / difficulty # other values self.mirror = int( random.random() * 2 ) if self.mirror: self.spawnTime *= 2 switch = random.random() * 10 if switch < 5: self.spawnLoc = 0 # front elif switch < 8: self.spawnLoc = 1 # sides else: self.spawnLoc = 2 # behind def loadBase(): # import res module import PycapRes global PCR PCR = PycapRes # load images global canvasImage, backgroundImage, skyImage, explosionImage, tune Hero.image = PCR.loadImage( "..\\images\\hero" ) Hero.damageImage = PCR.loadImage( "..\\images\\heroDamage" ) Plane.image = PCR.loadImage( "..\\images\\dragonfly" ) Shot.image = PCR.loadImage( "..\\images\\smallShot" ) canvasImage = PCR.loadImage( "..\\images\\bigcanvas" ) backgroundImage = PCR.loadImage( "..\\images\\backgroundbig" ) skyImage = PCR.loadImage( "..\\images\\sky" ) Explosion.image = PCR.loadImage( "..\\images\\explosion" ) tune = PCR.loadTune("..\\music\\m.Mid") # load font global font font = PCR.loadFont( "..\\fonts\\Andy28Bold.txt" ) def init(): # load the pycap module import Pycap global PC PC = Pycap global KEYDOWN , KEYESC, KEYLEFT, KEYRIGHT, KEYUP, KEYSHIFT KEYDOWN = PC.getKeyCode("DOWN") KEYUP = PC.getKeyCode("UP") KEYLEFT = PC.getKeyCode("LEFT") KEYRIGHT = PC.getKeyCode("RIGHT") KEYESC = PC.getKeyCode("ESCAPE") KEYSHIFT = PC.getKeyCode("RSHIFT") # hide the mouse PC.showMouse( 0 ) # add the player 'plane global hero hero = Hero( 400, 300 ) # get ready to spawn some stuff global nextPlaneTime global time global squadCount nextPlaneTime = 300.0 time = 0 squadCount = 0 # set initial random seed random.seed(level+345345) global planes global playerShots global enemyShots planes = [] playerShots = [] enemyShots = [] # load the savegame file & current high score # skip loading if we're re-initializing global bestTime global firstRun if firstRun: try: saveFile = open( "lib.py", "r" ) bestTime = float( saveFile.read() ) saveFile.close() except: pass firstRun = 0 # set current game timer global gameTime gameTime = 0 PC.playTune(tune) def fini(): # attempt to write best time to file try: saveFile = open( "lib.py", "w" ) saveFile.write( str( bestTime ) ) saveFile.close() except: pass def keydown( key ): if key == KEYESC: global doExit doExit = 1 elif key == KEYLEFT: hero.left = 1 elif key == KEYRIGHT: hero.right = 1 elif key == KEYUP: hero.up = 1 elif key == KEYDOWN: hero.down = 1 elif key == KEYSHIFT: hero.fire() def keyup( key ): if key == KEYLEFT: hero.left = 0 elif key == KEYRIGHT: hero.right = 0 elif key == KEYUP: hero.up = 0 elif key == KEYDOWN: hero.down = 0 def mouseDown( x, y, i ): hero.fire() global mousex, mousey mousex = x mousey = y def mouseMove( x, y ): global mousex, mousey mousex = x mousey = y def exitGame(): return doExit; def spawnSquadron( time ): # generate squad control data # number to spawn i = int( math.pow( random.random(), 6 ) * 9 + 1 ) # mirror this? m = int( random.random() + 0.2 ) # time stagger if int( random.random() + 0.5 ): timeStagger = random.random() * 30.0 + 10.0 else: timeStagger = 0 # time between checkpoints airTime = random.random() * 500.0 + 150.0 # entry points, including optional stagger entry = random.random() if int( random.random() + 0.5 ): entryAlt = random.random() else: entryAlt = entry # checkpoint speeds, including optional stagger dxi = random.random() * random.random() * 4.0 - 2.0 if int( random.random() + 0.2 ): dxia = random.random() * random.random() * 4.0 - 2.0 else: dxia = dxi dyi = random.random() * random.random() * 4.0 - 2.0 if int( random.random() + 0.2 ): dyia = random.random() * random.random() * 4.0 - 2.0 else: dyia = dyi dxa = random.random() * random.random() * 2.0 - 1.0 if int( random.random() + 0.2 ): dxaa = random.random() * random.random() * 2.0 - 1.0 else: dxaa = dxa dya = random.random() * random.random() * 2.0 - 1.0 if int( random.random() + 0.2 ): dyaa = random.random() * random.random() * 2.0 - 1.0 else: dyaa = dya dxb = random.random() * random.random() * 2.0 - 1.0 if int( random.random() + 0.2 ): dxba = random.random() * random.random() * 2.0 - 1.0 else: dxba = dxb dyb = random.random() * random.random() * 2.0 - 1.0 if int( random.random() + 0.2 ): dyba = random.random() * random.random() * 2.0 - 1.0 else: dyba = dyb # pick an entry side & set up for it side = random.random() if side < 0.2: # left dxi = abs( dxi ) dxia = abs( dxia ) xi = 0 xia = 0 yi = entry yia = entryAlt elif side < 0.4: # right dxi = -abs( dxi ) dxia = -abs( dxia ) xi = 1 xia = 1 yi = entry yia = entryAlt elif side < 0.95: # top dyi = abs( dyi ) dyia = abs( dyia ) xi = entry xia = entryAlt yi = 0 yia = 0 else: # bottom dyi = -abs( dyi ) dyia = -abs( dyia ) xi = entry xia = entryAlt yi = 1 yia = 1 # pick loop path points & optionally stagger xa = random.random() * 0.4 + 0.3 if random.random() < 0.5: xaa = random.random() * 0.4 + 0.3 else: xaa = xa ya = random.random() * 0.4 + 0.1 if random.random() < 0.5: yaa = random.random() * 0.4 + 0.1 else: yaa = xa xb = random.random() * 0.4 + 0.3 if random.random() < 0.5: xba = random.random() * 0.4 + 0.3 else: xba = xb yb = random.random() * 0.4 + 0.1 if random.random() < 0.5: yba = random.random() * 0.4 + 0.1 else: yba = xb # rate of fire, if any if random.random() < 0.5: fireRate = random.random() * 200 + 100 else: fireRate = 0 # test some overrides fireRate = 100 / ( 0.5 + level * 1.0 ) # program planes global planes delay = 0 for p in range( i ): a = float( p ) / i na = 1 - a # add a plane planes.append( Plane( a * xi + na * xia, a * yi + na * yia, a * xa + na * xaa, a * ya + na * yaa, a * xb + na * xba, a * yb + na * yba, a * dxi + na * dxia, a * dyi + na * dyia, a * dxa + na * dxaa, a * dya + na * dyaa, a * dxb + na * dxba, a * dyb + na * dyba, airTime, delay, fireRate, 0 ) ) if m: # add mirrored plane planes.append( Plane( 1 - a * xi - na * xia, a * yi + na * yia, 1 - a * xa - na * xaa, a * ya + na * yaa, 1 - a * xb - na * xba, a * yb + na * yba, -( a * dxi + na * dxia ), a * dyi + na * dyia, -( a * dxa + na * dxaa ), a * dya + na * dyaa, -( a * dxb + na * dxba ), a * dyb + na * dyba, airTime, delay, fireRate, 0 ) ) delay += timeStagger def dToA( dx, dy ): """Translates a vector to an angle""" # check dangerous special case if dy == 0: if dx > 0: return math.pi / 2 else: return 3 * math.pi / 2 # safe cases a = math.atan( dx / dy ) if dy > 0: a += math.pi # return output rolled into 0..2pi return a % ( 2 * math.pi ) def hitTest( a, b ): """Circular collision test. Assumes x, y, and radius members on both objects.""" r = a.radius + b.radius x = abs( a.x - b.x ) y = abs( a.y - b.y ) if x <= r and y <= r and x*x + y*y <= r*r: return 1 return 0 def normScale( x, y ): """Scale to apply to an xy vector to normalize it, or 0 if it's a 0 vector""" if x == 0 and y == 0: return 0 else: return 1.0 / pow( x*x + y*y, 0.5 ) def update( delta ): # update timers global gameTime global bestTime global level global explosions gameTime += delta if gameTime > bestTime: bestTime = gameTime # spawn new enemy planes global nextPlaneTime global time time += delta nextPlaneTime -= delta if gameTime < 6000: if nextPlaneTime <= 0: nextPlaneTime = random.random() * random.random() * random.random() * 1600 / ( gameTime * 0.0001 + 1 ) + 100 global squadCount squadCount += 1 if squadCount % 10 == 0: nextPlaneTime += 500.0 spawnSquadron( time ) # tick the player 'plane hero.update( delta ) # update explosions, removing those that're done doneList = [] for e in explosions: e.update( delta ) if e.done: doneList.append( e ) for e in doneList: explosions.remove( e ) # update bullets, removing those that're done doneList = [] for s in playerShots: s.update( delta * 0.5 ) if s.done: doneList.append( s ) for s in doneList: playerShots.remove( s ) doneList = [] for s in enemyShots: s.update( delta * 0.5 ) if s.done: doneList.append( s ) for s in doneList: enemyShots.remove( s ) # update enemy 'planes doneList = [] for p in planes: p.update( delta * 0.5 ) if p.mode == PLANEMODE_DONE: doneList.append( p ) # remove dead or finished planes for d in doneList: planes.remove( d ) # test for player-shot collisions global doExit for s in enemyShots: if hitTest( s, hero ): # hit the hero plane if not hero.hit( s.x, s.y ): # player death init() else: # particle explosions.append( Explosion( hero.x, hero.y ) ) # test for player-plane collisions for p in planes: if hitTest( p, hero ): # hit the hero plane if not hero.hit( p.x, p.y ): # player death init() # break out early PC.markDirty() return else: # particle explosions.append( Explosion( hero.x, hero.y ) ) # test for playerShot-plane collisions deadPlanes = [] deadShots = [] for s in playerShots: for p in planes: if hitTest( s, p ): # remove if deadPlanes.count( p ) == 0: deadPlanes.append( p ) if deadShots.count( s ) == 0: deadShots.append( s ) # particle explosions.append( Explosion( p.x, p.y ) ) for p in deadPlanes: planes.remove( p ) for s in deadShots: playerShots.remove( s ) # call the draw function PC.markDirty() # test for level win if gameTime >= 6000 and len( planes ) == 0: level += 1 # next level init() # break out early PC.markDirty() return def draw(): global time # levelAlpha: distance through the level levelAlpha = min( gameTime / 6000.0, 1 ) # draw the background # clear PC.setColour( 255, 255, 255, 255 ) PC.fillRect( 0, 0, 800, 600 ) # prep for layers PC.setColour( 50 + int( 205 * levelAlpha ) , 100, 255 - int( 205 * levelAlpha ), 255 ) PC.setColourize( 1 ) # draw sky scroll = time % 800 PC.drawImageF( skyImage, scroll - 800, 0 ) if PC.getIs3DAccelerated(): PC.drawImageF( skyImage, scroll, 0 ) else: PC.drawImageF( skyImage, scroll - 2, 0 ) # foreground PC.drawImage( backgroundImage, 0, 0 ) PC.setColourize( 0 ) # explosions for e in explosions: e.draw() # draw shots for s in enemyShots: s.draw() for s in playerShots: s.draw() # draw enemy 'planes for p in planes: p.draw() # draw the player 'plane hero.draw() # draw the HUD elements # time PC.setColour( 255, 255, 255, 255 ) time = max( 0, 6000 - gameTime ) string = "Time Left: " + timeString( time ) PC.setFont( font ) PC.drawString( string, 25, PCR.fontAscent( font ) ) # current level string = "Level: " + str( level ) PC.drawString( string, 775 - PCR.stringWidth( string, font ), PCR.fontAscent( font ) ) # lives remaining if hero.lives > 0: string = "Lives: " width = PCR.stringWidth( string, font ) x = 400 - width * 0.5 - hero.radius * 4 PC.drawString( string, x, 575 ) # draw life counter for i in range( hero.lives ): PC.drawImageF( hero.image, x + width + hero.radius * ( 2 * i ), 575 - hero.radius * 2 ) else: # flashing warning if ( gameTime % 10.0 ) < 5.0: string = "NO LIVES LEFT!" PC.drawString( string, 400 - PCR.stringWidth( string, font ) * 0.5, 575 ) # draw the canvas overlay PC.setColourize( 1 ) PC.setColour( 0, 0, 0, 255 ) PC.drawImage( canvasImage, 0, 0 ) PC.setColourize( 0 ) def timeString( time ): minutes = int( time * 0.01 ) / 60 seconds = int( time * 0.01 ) - 60 * minutes minutesString = str( minutes ) secondsString = str( seconds ) # add seconds padding if necessary if len( secondsString ) == 1: secondsString = "0" + str( seconds ) return minutesString + ":" + secondsString libtuxcap-1.4.0/tuxcap-build/music/0000755000175000017500000000000011330673043017110 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap-build/music/m.Mid0000644000175000017500000002012310751375104020000 0ustar inniyahinniyahMThdMTrk QR/MTrkDiscoDrum $*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i*+*5..`*j*v.\.*b*~.T. *_*.k.u.l.*?*1*x*x..h*<*4*s*}..q**h.x.x*E*+*\*.c. *:*6*|*t.Z.*t*|$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i*+*5..`*j*v.\.*b*~.T. *_*.k.u.l.*?*1*x*x..h*<*4*s*}..q**h.x.x*E*+*\*.c. *:*6*|*t.Z.*t*|$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i*+*5..`*j*v.\.*b*~.T. *_*.k.u.l.*?*1*x*x..h*<*4*s*}..q**h.x.x*E*+*\*.c. *:*6*|*t.Z.*t*|$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i*+*5..`*j*v.\.*b*~.T. *_*.k.u.l.*?*1*x*x..h*<*4*s*}..q**h.x.x*E*+*\*.c. *:*6*|*t.Z.*t*|$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i$*f*"$X.p.p(*h(*v.Z.$*N*-$e*o*q(*1(* ..K$*f*"$X*o*q(*h(*v.Z.$*N*-$e.o.q(*1(* ..K$*f*"$X*j*v(.Z.(x*N*"*@*0$p. $ .K*o*(*1(>*.o.*w*i$*f* *$W**j*v(.Z.(x*N*"..[$p* $d*q*o*(.1(>..o.*w*i*+*5..`*j*v.\.*b*~.T. *_*.k.u.l.*?*1*x*x..h*<*4*s*}..q**h.x.x*E*+*\*.c. *:*6*|*t.Z.*t*|/MTrk~bnoodle   ( (& &#`#&`&(@(   #@#&@&#@#   #@#( (&@&#`#&`&(`(  ` # #`( (,@,(`(,`,(`(`,`,`/o/q/`/`2@24@(=4&0(0(&/T( 2%/:2/[/,,#/`,/O/w,i4"/4(6( &^&( /8((2/$4 2542_2/@4K/u(&4&(E&( /(@/2`/A2/,,'/`,0/0/^,4//(4z(3&`(S&K(& #*&I#  C   ( (& &#`#&`&(@(   #@#&@&#@#   #@#( (&@&#`#&`&(`(  ` # #`( (,@,(`(,`,(`(`,`,`/o/q/`/`2@24@(=4&0(0(&/T( 2%/:2/[/,,#/`,/O/w,i4"/4(6( &^&( /8((2/$4 2542_2/@4K/u(&4&(E&( /(@/2`/A2/,,'/`,0/0/^,4//(4z(3&`(S&K(& #*&I# ` < c  ( (& &#`#&`&(@(   #@#&@&#@#   #@#( (&@&#`#&`&(`(  ` # #`( (,@,(`(,`,(`(`,`,`/o/q/`/`2@2@/MTrkCymbalHit 19?19A19?19A19?19A19?19A19?19A19?19/MTrk|FunSounds ::`6(66Q6o66<6686(66Q6o66<66X::}HHhOoONoNOoOqN_NO_OH_HaH_Ha::`6(66Q6o66<6686(66Q6o66<66X::}HHhOoONoNOoOqN_NO_OH_HaH_Ha/libtuxcap-1.4.0/tuxcap-build/music/music.mo30000644000175000017500000123703010641010414020645 0ustar inniyahinniyahMO3untitled+"&@i @H7@ 7:2!1!1l (08@HPX`hpxD$ ! "  @% #h<,i  M  3h(Xi63-0 19ks 9e9 4!6`"9#$%&'([`&)"*+9$,-M.b9C,f/0`192(3456M7e8694E:;?Q@EAB@CcD9EXF M9G 0HIJKS1L9M(N2OhP0rq& ld(20x}P:0]0ZʉA Yi#-Ї GgoDQ$o7Z    !   &tЭpr Xe#($-2b71p4 Y2 t2 ;10 Y0Q PLXdu_hWlb+' cM(=@,.  hH0 r wi[GpVPmeC, .@P*?\ 7ŭ ~#XJl (JxtA-D)A%_7pղ 24=C*  Pngq[s ?05xVA1 c6- 5^[ @[ qE{p Xyױ9'QFT[5~K JAc, po?\0S@o`>5!A!Ab !?b b;c0 Wb#Gji=:47441.#+(i%"i iG@XfMm\y (FaP'tTB&48ig KMe=42Q! 2 Ea/K&>d PwD>N%1@Yy O ` A \-v( #2   3k鑂y&M$"4 ~C9M4#}1e 4 M3-T25; 6޸2z k"H( )@) (1Ay(5(Ї!;xrL10A $P7 =M@+"$!_XYAe f Apv~A(d2AX 7d-# 17ڱb<̏Y+[Ž<"R!̀ @Fq?e7`@k@g":=:C7d41A.+d(%A"dAd A dX@]::aL%N ,?"? ? ??2?x7z;  @    m (T{1` 4; 63 LF)cfS Mxkia Y"iץ##-( #+k3 XxS tA#p&=,r5Y-dd-Ya` ]R4 1A* a*0#NDkPQp\Ȱ0"27#Y7lC7S 36?DtJ@ c3E7u\ !3A!!lc !液 1 ((#((-TE  P|,!AD#(-D2A7<yn,N^)0# ' M5ʑ"; .c$&!zP$Y'X*TA036T4(-A ?Zν+omx)G 0K/YL? )[]IBճ-Չ!YS#/00\&@l(- L/P.2L.)v*aH'>PDxz7*(2i(0,WOhd[*ǫK~v;t~, 270@ ab1ʈMXJXK  2ALlb? p^M JK &L <DLV'Y`a0 N@&9 B0O8!t #!$ð"l 8[}@ #=;u0@ujUp+Y! CC"d$@d6hۺNnt Kx>@ ,bMJK# h(\e- SobC MA_M 2GH"(!,6ur 9: < u~^j,MVc :0l'& `5Fa9:B0Qa)88cD@3 btuH<`.;im _.ˀ+#FWCe7O]cA(N2:bwP@7BA7] _]A@Jw^Y&@}M Z6B7|!Na :KaPIl\A"POl5`eM?@4ABMCD4EFMGH4IJMKL4MNMOP4QRMST4UVMWX4YZM[\4]^M_`4abMcd4efMgh4ijPk_mMJ<:?iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii i i i i i i i i i i i i i i i i i i i i i i i  i i i i i i i i i i i i i i i i i i i i i i i 6@6:D M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M XuM 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 :7 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 M 4 7M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M47M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M45w{6uMu|^ G^]*o=8iiii !"#i$%&'i()*+i,-./i0123i4567i89:;i<=>?i@ABCiDEFGiHIJKiLMNOiPQRSiTUVWiXYZ[i\]^_i`abcidefgihijkilmnoipqrsituvw|:M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4N+I23]XdՄM:;4<=M>?4@AMBC4DEMFG4HIMJK4LMWNVe1QRSMTU4VKYIZ[\]i^_`aibcdeifghiijklminopqirstuivw:q4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4M4A@&'M0wpC1 )q-0}A2|032S.Œ, K }<"%)aSvPNy_k4<\ )A[lSA/l)7~ }qSa,)v M9^JC0SC,D56xRA~tR}?)y<%!A1o2Va   w#10OMXD b$;ChorusD{c \?> G=a?@>R ?L0,>EchnyeR>e̜>OggSZvvorbisD8OggSZ"p-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS?ZTleB Xl1¿%%<Ε'F8gwT“d/| \e|>ڽrJ0*DfZ*]Gp'sMzDJ_ҧ[|׷~d$~.O\^А~*`R_E`^\%ŶBƞuijtK2(Zt# Y;uHa/WiuaQ^QG!`9 7XCIӧ.md25}# H0vI%0C F@?-@VȖ[g6<-tD68r~9M̶5oy,SƦnTM}G ^k]^Cw"H2$fTeU[5 6g*Ei E|53ZQxDB2)y T"ɪ?ӣG-t|4mGQV @S?'g-W:rהf ,ML ^PS˱?hWRVCmC|^S= ,K^&{xm#uNl?Z夋ěkLO*[\q !}x~OOnKG&dDMj[RqS#2B#=si^_)$ O U{ L1Ǧ5ETQgXW^NmX4w|}Z1i jt\SFn?r_iϪtw7=td0;(TLWrR-ƴRɾyrElDӴ+1 /whctu|&1ZPY7WߗhF) R]W\<Uwظ, 2k i=g SuX8( 4"$/vt46w|fbZwCc6G6 Նg(w#R0*UNTȍ/6^"+JPF#9.UGVL4nW!};q>u@#m7Fp6fAPkN$&8LZC{@9Id5kT Rl(E!ws'X*T1x!Eyjϲ2TU"ȺVcp Z̩m'ԫoIU54sqIM;z-9: $~T //ٌ(! uBQU)@mV$MhbXpcB'_Wi㕥](OhJza@hFY<{55Fs'TjjQag)wS:6Rkb#4do/<Vvw@I$Wv ᜵r!jԋor2#zNUg7{ZW/y$u@Mrڝq8Ywr?|fqwBC!p萮 *Wk=]'guǷ BG-_̬ۻf;}0s8͊"^ĵX-'p˗ʥɀjFO0 @`D)UJ8ŝg'QhbB-8)YC_yqBZ7rw^ [ ,%M%e=Qf~A;=:Eau3$e)Ȉ@TKKޜy͂+MvEI 7. 4ՃpCS{h J(M?|4;JJ~8FNK䳙s4hbH? KVBsV%wA_LmzO-|Ci O.2gUL<7 2/0iB2<6arjoΧF?v6 Zod]~sUՓ#t$$$.ipaߚ3y|,_)8uL>*K nRQRc^{./[S$B8v.oyQm|\wf[ioSzO#g^n[-^MvMJt*gOU FcI)|Jkbv+\3e H個[UvI p(mڅs>x}\LG7Bc hfķȿѽ}zS,ԊzM!WP3GP#5lY|sڦOHDHL綤 CZGR,V _?ߘ/EMPJh"Asm.37O o3N03SB':B? tWDz.f@q},Qx ,]^a/@9Ft2E+ u,f]Tb[+{fm e ! !M[ʞdl%.s% 4+ϐ TL$}#@s #I]+kbBt=vz}^rZ~~EG0(]'&4vlVRfWwZYM=p]3s &*E }rMwZ&9i/fK9@_݃iVao#( Rwz (b|Q]Ek/m+Q*^⇷tB"NS̞(*\ڢu1v2uk:OXqIWQk@F^ŻSmvl!Acヨ&Uen+r"weci2,^x&z'ɑs娞xe9q^jU}l& ^mN@so|;H)"TUGIsMEg i, J-[ՅB1G0 ?r@'G. mUSv&)-bq:O @m5!)M)SwO?s"!Tыu}]Ieuj[USh6YEWՎfdIdٖPnVN B yq979 Tu kÀ O(J(A VJJV恞m*4Ojp|^\O\ z:2g;ƞjzZ &]>:dznbALrqۍQɅ+e88ױ*«VἺCUWTI9X|ax$Ȱ"53ؑEw_TOhLM4:%j~n(ӽW]HdT{2c x}_{׮?y"DOV8i?|';0,TEܕCufE#d6(sPpG&~h$NdiGя42 'vV ,(Lq^CtFm:)޹ńANg3z t@vMCl-ճ1DuئQ W Mˎ'kw_ f=E2[g"MogR_dSoYose jE\tizk\;TߦNLDlBXQtUY Pe {@\AEC{yO/t_xWĕ`-:{eHߖ\T"!7ެsJ=N !G9)^_[zG ;Tӳ3?EOBEES jEMWCz  MJ]tKy)s_%˄ݲ`d׽c< ENbh_qC1( /jdB¢5)Bc~_Rߝ*yֵ]X 5 "]?ul?ʌW}UoNKvQuu{ e޳*L)[Q,Ҳu9 ?tr}p|=qaE^~4'NmdU7o= N8Se0Fo}3>+yA]Mx-7V6bLб}1&^DOu@]䨽Ę._:wm%u),GPVN<#uV)A/ز81nKD,8\DdN϶Uflg+~٪K.DgĀX%k1^z`zUћ$wǟm*5\oQ 84&ӊ[Wz|>.}0ٽauV'ta6< Y=6CDzr K)$aDe1r{XgF/@@?† EKTϧt)!TxI-~o~{Ymhi \3}g.p6[>g~QBeP,֟0f+w7:r>T^-`r!{="#A[(*Ȯ) 6vLOf)M"⭹_ ob8 \}i{*g3:Wd.Ka>uUq[cw~OYʳN%{0q,V Xx{Frr{߮!>l[0:Խ+DP-D04SZ>I 7&ʱZ,Q"$Jm!wn tѷS2 MCt^5̷ ;M-~QEQڗj l%N7Ko>W?O3w#)#jWe~Yt힓R9/'pcǞf~ļ<|WV(n+vTEc`޷:_2;Vn=K~Y:5H34 $W^diA1^Ӽ[LVyDK'aU`3R/4^.>oFtwfnPBp!ӗ15I}Lgp*2BZ44oW%:#'㣟Ԇ;Z5]^R~M* R=ΨQ/3Eٚ8ŵ}oooauG\60,ㅰ{Zo\7a92 S^/W/DXn^ /^^Pv OggSZ7z%&'(&512,((.).20. MT/~@pX5n?t`]V?PC̦sG6qfdņ+S1~WF ~[{ `/Zv]sĸ?Pº~hd]usb/'! &y{F|˰ZrMCBN;,.4CL:# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@EZXya&-10/./%-32&1//13'+111.5nPШ?^b3puH=.]f_u}}}l] N}_YC;8T2hɶĜ>*.yaI[ߒ7'ape3C|zꇞ{^= 8{on}rǷ -pIm*cTg,?: s&ZE>{ѮdI$k %v/ K`i 4f̱)Kt&0O7r~Fٿ[+~_ehcuMn2Rv(0_lF,vΚL)56Y x4j P/ZX=$)}sy]y5ט.坌_rvu먪zӟ1%Eл/{l/I}M\>蜾lB'uZT B$_RY`Q4|Vx7᜝-ZCp߂ B?RVgՂDoaWxG2U =u4\ 睐"PM}7 Mj{JMcQsN4W:Y k̫uB=mdGHK>,,eh|ـ Gn*MUFh?$U.6X_2vq$ʷč_}חm3/z/soZ|* Z8c1+%?zqz\C1R'^dBp1%K}aqS1_`Q|>dk|j:k'O=$D _zVm -dfB{n1RY_rÍ[[@%M<@/6(t7ݦ'^5leؚscT^ *3%':wڿ1::B&y n[}wf7R1ƒ ?z(FeFfh~o=E>(3Z5^kmsYwk¸$ރ˜g MZD]X_OƲ<$?}*s%KfBywȠ ~+V*QqeNFu 5L pYwu&IcK>Ďxt5?E #2K3W˽\(rvOg]J9sE9rFh/WԦ$îk\tVʑ;U}kPKY")e;, |(lKoL0A`ԅ{6bf&cVIv8 +4k$RߙMq:02mC;ڭG2HEnO>UP bt#˕$/̙|$]hJZ ;`AE4O~LqM4>y Tтžj2?\O6N' Ub`PZZR!.;KPDu9,D̐L׀i{]m!vI'on> 6qwOoPdf,L8dU2ۖ ܸQCjU'f||'F{CϩY'FV6D5|>m#1SC3W,g>c7뫩IUhX*M tMƜ ^u؋(IEzBj߾;T*oNjd/1O= vwaT a_uf6,~IO-*-}2$F]3ݹ x_;e^ z|.Rni]x=AX_F{Vj<I Q!/m \fEuD7q\E0wA'uhs#>OggSZ>'t&'&''&/1/ȹż(,2LQЂA^OWZ: 6 jDQ.8%C'1#>tŻ8e)Uj,Kp-Yd1an9dL%}1+U!~ <.X DJ4f[V. 9s!BU?lDnߺ%!9Ū6/iɱ ˋe!uW ,Mh1DQ^e;@^%a/vuE{"zH:PDQl.M ^*d.7ՌzKۗZ;8-W='_~x:%~&~ä|aBxbϏNcTŜjCGxxRYT-ONqJ9YID]`a㏗حOOҵq!OWt E3Vն]'2鳇?@BvoY#=q]^k4Pl8GޜWkYFl0*#T)^^Q8̦Pu:Laܣ'FF؍Q0ʅaxB;j07&~=M>[%>66c8K2;&Ih3%یwz_6i%ba+R!mܿͫBv;d=%{U'3_ַReж*ŗa&6 Vgr{< Xy}X@X>(NybЪPwZy (&O(BGQ i gZ׃_/_X] $QArl)Ub.nM\M4D;Fj=Ŕ Z$/+A c~ZUn|s K&VuEʞw^gO |W"3'=h˷$=!E9*Mh LZ1y,EL[I䢖a76gmv}TҸkyA`_cW 8 2+&J 2:`#'JF1f9)4({>:ɦ|UX{Bkՠ|MDj/p \^+y  a2'E$՛>Ӧscv%GÜZWmiEvڡI 4q4~a! ~? (KE/1ep%*&G䒿-Z}ZOUXLLuRy++Vi>u +AKI w"oϰ y- @B!C I*Mcގ%9jL&ʌ02`a\:0_ssbK i(kvc=ʑ%>*C;O!!HT_ռB+aڦ%zK~S%A wKT$L%RQ9Е6ޭۻ4w(CN]H" ŏ3a%E+dOrK8R`9G "s^fh5jJa\3@bfX1ixKD[<'L=}|/$IiDv/ZMvGDI fpΐgEB\??D禾?5wsX)p+>ym:S@jjf&sfWM+w\7-*ィ7v!U8X ҀU8إi8+E_YAhU'¹T"Tw +mK[T8 7F<(: 42j'DBv)d2-498q^r.D-J2YnTlVg֖j5M@c zL. E7xRWz$8L!S[Z%2%"ʕ,V|a1h?u`)w<39ü}H\^ښ聗-!)b-Z`xCH]K|tz ]۫AE^# T Z5 eyWoq5Lo!)@Bt/bRi>I6؞5q<RեB0{:Ͷk!߯PII;Æ)؆Kw" wB8va737]૒Wi n en=﨔&6Qԛgiޚcv}<-א>/Ţj;myQ2Uk߻aInͨkKJXKLʴ8`Ϥq4)E4UK$"$Mۗ_~m.s^]왈.BG( H 5ؐrȣK,m癿xח# gz칖I[Sin.E wmf3\;$m ;ݖy3rB8ѴnNN}R`5amH$kYߩN1.YA#TUՅTʯ%ћ<V][c6kav⌎4N8Ƅr8*aZa_mߍq:5`c&Iv*gۋa?]S˗-,VC" `ii@?9kXF繾c' *KlIP5zn]N+ݹJ-2W1拆Xѧˠ@O@T1 .S@LY` 8jzRw?oiu60?@LUY(@T۹zEi{{sϖ;Sb_Yǣ7?JH"JWwy ~r3Y+Ę%i4WT0GLYqOggSZpvorbisD8OggSZF-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@DZo+42.(113)))&&%%0-/021('00'/320,OPKөoؙM7<+%H7wo3o2;cF t0-ݬ_%kq{n⥶P|.Ra"<jJAx渻7z^W/ m&eN :j s߈7]<0N=N tW,M=ΗyS#3IYB5|NnM\.RbEmUGܨOaK2S@]U䪂wi{ê8X Fr%) zBF&ΓA<5\gѺP}H'4rvRȚRP#+Ee7L ?;EYv鴡] 8 I$svXozܒ:6gޤz`IF/+F:͎+הwgytgE~V  .%Ra:3jE%[EVv T{] 8y\f6(m9_*A0v~Q(-{Pf\ˍ>b#"sZ'.!54: ]?8#r&̮/W,Ln[(<|`DZ1x&"ZWZԩo뷣W5t8rSYC$ΌSrǚ>kJ'?Mh4^}4о"O~9-. +'Ͻ=I1UbQ⻯?Ʒ* 7uFNtwH$+_wjҺy|Y;FN}#"nv o >W860H"8t'$zY6gmnNEtj{zL5M0Ќکd,Jx^}=mck*9$")Z(,Q]$fH6-?=m kv`;dPT}"'@DE8"q0\ݬ@7LqT ,і%84*3HQpLSf&=}(b ) I A(N$T?tdQx|K6QUeܧKmM&ֽN*Y\ZS5=1 Ma {H}p0(N#1Ͳ0'I05%7@#/k,`ǺULƐ7y]TK4Z"nO}5.Y:I0v"~q}z=?co_/zֿha _MQyЩT|{pԠc*sO؅~ LlwպЅi]STHyzio&7U{9"qEW%,1 ~b- J;[gCܒW0ܨ1Aj1?E' "Vaoq8_r덨bm.ZG6IstD1'17xdyS \2[׃9`fƜu$Ψzr@Z/HN^}LvߓA<} C;J8E?0hW VSE~}%uؔB7 B`GYu,ܿk$ &DM!Q24g>}-nT5ũX K,|y T?*jVx{Q$OS_ -ڏ]yXn~*9LPȣ'CEР10rR@|3(& 8I zCs=;ω렻Փ] !maJ1=Q}9`gn1|DF`~:hLm Hyy.o㹼grzj>% "\uȓ׬HuxhY57WX( ky@# 1#>jo&VCS_,Ɗ/:̈́qCG^ 3"|6c{)C.6$`꺗Øa^Q` 52zUH1#j4kӲ$Ԓ*Kq]}?c1ĺ6Ƕiڎ zV&liZSskTCPl<. =z@l;D,yuWI ݍOggSZ<'*1123̼'-..2-%500''//013&''()%3|s/th&lXvY$ȍ.-ȲIcTz$Hx߲^hPUrD뜇 |^Ff+~`xe~Z}suTע)5 2뢙u0Q"UTWfLhgDuzop竷hkC8wܶZD$teXKd|m $4uN znԏWoU c >3Öz<'rJKxY9aIҌ_GQ^]2, [ ،M}3NL^s n)Cf6ZwH Q.C;w :#^`) S}DZ`4{cמW)|;:tLX0P3L|RK\2f(?`2k* z`Q:UGcيS֣nb^ _W^{ꑿ;'E' \д4] {n,ȴ^B$$qL +=^^.wff5buEіk]a7~B%BsOb'_0T'^I(Y5>_ueE0\֣s,heg @=u>Y}/kL-û85Ѐb' Da4v=<]v4<5󜾭ht/E4h$&߱hxS|iL$,޺,zFGR5H@(>;:OY2'$)KPlM}2~ϵ _=BO~"E8įD̢dBV'^TV3wFZ4}J-ܣh (&NEL$9{"< XSF?CST^"_OQ+ ~݉JSαV@[7ɄVvz`E­?Wy6\ȅڵ#>#sot3l# 9s"G]O;"WMqʻ2dTˌ7Po.2-]HJT`^]Ga:33V~S,f]߲ljD|qS<n9FT7{[Fmcʯ+ȢM(4c^|x^Z|YoTj2jٿ߃gs6x!Uxs.B!DWo}yuPㅖPgD貧ײ YQ#"Ffd yC8 Y&3M=f9Y3Ϫ /3\n << O~^&B6Ksa XGii,2'Nz-NrTwjI}Zϑ{JRzԹ6L~C =owN4Zᨅ^yNGz" HBo߮9Ƒys{U"rxLwgG ,HpH=f;mYNgؑN,ގNX]URDL)UgLgeR4rMjgǓ#K̞/foFHWS)>qEMfJWj(rWWv"f H9qX?=&kyaqe#aZϞ ѵ*~*cGOpIHr_V$})Ђ[OggSZpvorbisD8OggSZF-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSBZ~X 11.2*30'%(''',00132)'2.22'1300&*(()')1Jr: _oWBu{X## laDӾ.,JOm3k'z:K|a ~g'@ICsr*hNhĽ aFm_-ɵk~zr TBko}w0ٻ#$DߙmN=PSIfUoI>݆۴{Kum/UiYMFQ|2RU[^Nt$L쐤$HbRScPF54, j)gw6 ;d@óaS#ʼvoҠ3'C!C IEL’hYFwy6wwI(/7m#fy3߾iM7=6?+~ouD4]:'lmBIm7WZxCO2ͻfˋOjnV۳bE)Ja2muguaIBh -6nܛ1,mFhCy$jDw,A!Ц I "?)SSƘ&KBS S#0xyxΤAq/_Κ $O"Dp(,1ܵɵcy⋒{C7J2*r)%<Л =X 1;,[!Xc1sxx%oo4aHZ-,kZEu Qv@pBN3qy^\K0'0YT|z5[!ڻEI/2<@-$ż _JOEVf{- wD˩&ZwŤ2'Ӥ"&<3Dw eRCC,xtV`b?|͊/ni/Zb悝?ް}?W $ ;ak K0=(lT TޣFQ]V447e$SD=/jeo$T%bn3ܽ' )7R'/ZlTLa? ,Y2 &)F,?l9( C^8f@RWg[db`#*G%vV#>&npN׌e8L"lۖT4z|7{?k u =%^5|^ur@F{>g˝b:`{F ÄàҜtېcփxA)ŞYʤ( yZ8"B9dJ̭uw'/ m틿CLձY@*Q!`h2Wŭyx)<9ف9#!= M;+d=}Wp{URE ơ;겗HRK;R=uDXH+ mijfI5Z bWPxC"8O"N}%'In40\^FNߡCʒNt̂^ x9Ev9n p,݈M^P I@gϮ1(<9bƪ>uíb\s5s biYh"+D8EM.:KE2lţYaX?{y"Zf`L4ȠKRH]GN6w$!i D! 8+dĢșG\u[?mf>2Qbm3U }IщLY`ރ0'{_:ؙ/UXeFtT[@pP`CTA}T9f`Tw{_[KDYRfz {NvҮUs^Ξ!scVw<}vw|_0A s(7T|3κXL.EB 0r뉚^I?Nr܁b@ݽ:rh^;ҡGUmV~i8KW "F7 u4ӦhVBNϼvP?DɥI7E+uyqa:YvXq$H$(Լ&N:/@|r=<[Pr[ dLy9Ƚ9V<]Xg+)i*܅$e}l޳=ZP}ݜkwsˌq#6" N)^#2+kb׽U]z_UZvݗC#(>/rAVx%hwm]_FًbV; SqJǩQ*q0hYӨ!$ Z hls,S.>T 68x=j 3尬m؎]^ ٳס f_GgQdi-QSWԻȰ.krz6tpa'@&$8``2]Z5@ov1hk^>ZIK™jpd aשb$0#>SjZ3[./kOj.,rȷ=au˄yK(侮^JHCá|I=W 4$9 3Ulf):U_| V}Y&qrL']HJⶓ],C2}vn$7Wx),Vp9*;,|#^3QQ|o7z]7FiĠLw^Ԅ-sON`O2XAܹo=㓱7ڛ" Ǝ뼂 ,aȝPAQ|UW,Oҡa_7uq3y<7B.EQjs X^2>?b&>?Lsy^NrnjhUo?}o?_qD& g &po+o7W{.=]"B؎麵fתF>UQ6zYWLglQBAtԊΩ9z6K5;(  b{ WtOEH@{j^b4ż\L3&͔723K-N5 BO&٥WZ25Y\ppjT0,W2hW_b ô4gvLȊ{P=m4w$M.4-t"pfkz9-_ov(f H_*ZuQHA_6Q8l90:c{ INV 8,v8{O?I4IM *Hռ.*^Ӌ~H@.PH^/Q՟Mlql£"LwOggSZ-0/0))(*)(02/&'///&&%&&.515..0*(%&120dW>L&YN9/{v\-=㜾qAj- LJkhr65kVf>FHN$`H-p |w/1A`u )eMF.^Q5)PoOT?"QQVؙNs;.K_&2 ؃Ȭ*6׏=[$ח&s aogz7-;~}3e<||a(<1G0jNUJ>N(퉑_K.:I^?oTY~+@^j,Ğ5zv.otyCJcܘNWqM~Wu;\jjl>|lڕ=vEg%,[uCnՑ-{wxJ^8?/nSa?dy-{I oez#Mηg$R+ "JFK& J%g<+2c{dJ!k7%L1!=Q /}?]=encԞ+, ӿxeXF62z{xW1h ,Bs.ӫ$:S(̈/b1Ԣ̋8;Ii*\ݦuaAη)gi~:%F;%MJܬǷ]'Be7E?Vl0TOՇ^ ґ*9mEŚ7 DO?^0~E*E!Rb>^L?3 -;4>C=Z{|=VX~o/^.ʘ5^Q|TiWVa>wUwtU\.#V%zxb/%\,Z]rLmLV(DO(5Sy:/?&!hA.À^Jf9Ȯ0q^z!00 YImZTWo}2H %ME۪|ze.$4S !G+T,dwn %- Qc\U o=@I7T:KNdETW%|BK&j>]$_Ί$c,8Q+LYfRcCN3 |rԈy04Q5_`7BzըNxɶ^m.jZUKts^pWMh:YP?D,Fa9N Q*hfiq[7qĝ ޺ s#mیw1_\\ڵH"B7[omSݻv,A6F+]%Gj/!n:ag%הrݢlr P۽p4 */tk"QUIgd[DרL}TזV @m1Kj>}Ujz4t~Ed+],=GV-x}T9/{ީ1LOxߦ$ʄ%˞I5]sBF"#qִo@L_;W,VLN_f߽۾-\ eiGIe/LWp!iX߀~Tyܯ/륃V;`KĹGO"hz`D[@AaZGpFHLNqoݽڞMz5v[a~0CP=v%Dґlgǖc27ur﷯JǙYyA"@b$&eJjJSYta J%ڮ{RdwY:>nTu Ng{OYo~AsS4O?;ѫ鬒8Q^a5Ӭe&Q<_inHWKb{ϾtY-K# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS?Z720-1/-%'&%%&.-.10&')')%'11/-'%0.)'('(''-12004YM^P\k;4vu)W{"4teR z.8o_h?>/l,\{6s%HlGJ'ِ%`CW|&N =iٶ{#z8j֮&ʑE%>mX;?!$Z~=ނG(x(M0{-j]$3f ȚIDw\DDŃ=K /^e'ʂ&#QiI\$a\Oyz O1Qim߮OkgtT![wKVJH ~Z݋D[q2OgwݓwɕW7˹l}K=P.>i]1$U~m&bRY1 aW}bޑg3rC!j3aDsN8 e4ׁ() 2#%Xi#:=NN (N"hDk_YݓzwDPJf' EE#oUНcWA>@@<Gn'i1B~?vg{u~GL*!'LSbĀ`# L>Mϛ:+JU%d]yʻY4 DO=R~}zq7omO1p\_ER¨=R j'RF2,O6ubzmCƻx".;7˥WU1# rC88ftu]Esr/lċ"&̀DOvsG=Xr[,)Y6^Qfl{8NWiͦ[L)(=xj؀(fC>pŚN?˝{JcHJ 4φ9{ m9z{'N=Y }mvwEwo{q LW}WBF$ SUV19~_1i~ +(jpDSp10)cGF=45Lf{n'U^_LSbS]rxOuӰ<'uQርT3nARbYjT-viK'g $`u-DD(߳ уځ8eד#Vo]~Iε B`VO+^8fy}ŅkctfM?Jeg{v,H'BZ4TgfĜv|v2yJa",*mp`ȇe_34/O DS"%zmXAcQbȓ!4OU px[=cdf0IM1ZLQ$a4JOT _s@3!FDMw*D[)fxYb-SIuDQ` e( `T;O ]!ϯse7\SҀ~!<+6Cuw5zTQR~p!ç{sI7gWBfGSbξ9[&=odiߐ8 -[n[J DY|1,$83#éu9 FKq ?Y)s&c pD΢\tb펥H 4{d+2]J!AQ7Sr^4KB-%P)ghdDf@zZ0ӫşQrh^zCh.KnИ)g[pߚH5񙆬1Z$\^&Se8bQ 3gv)<A 3HjwBQ`UkjSq{݆mrQ j:SYGNo ③r AQUV<±J$KyIx$]Ja> mp)J㧏p!yp!49.+]ǡv]&[狽=p\:BcTY*M=AMp8_`w<}nRx!Y\c(I $Ͽ'ѴS/q*>c}sDD~:-0* C" ԑ$"3&[SΥ³ ,]~u`|sV/,"e&V84RtÊWxټZQv{~fYx,YRv) ljXY[vxp[kkp\X8~ހ*RQI" |c+cz=-t,6qB sQk p[%M6fA0ʋTivDDd[cߤǹx }úc?]*셕|ga.;anV\wЖ/u,ͥ;G570'aZI/ Gl)1n3 S(M7CCZaY[j6XKF;p{p(5Q$OhCW@0ZAo%/7(n,O{v_t5wQS *_Rr?B笜,Q%Ug gݴu3t=6UW$S`KS9=)]'yw*e %<$M!ϩ%pO=G7gȣ&s/@4PO/0a'ZD{e?ɏM/'یOZhc$IG6i+\AiZV ^<ձB@5x?fse\3axzU*$LW y7iV{A#o!۫j>W vm;Dapls#p9473@z]N޸q64i-XD2]Xǔu.bML^_6_pMR!vxv"?_/;]n@VP{ 5v+wprwn롷Qdt5XN=~FHpTmŹ@|M e?É,aziKY{'PCw(yu>TF#`r. cxi"kEQ~ڨUF?=4,+00΃6J d-{7֪'S\=vP8ZGsI է=$i;уl*LI)^bH !KUdmѸQl =8/>ҋ~{krGDfʭ_O\] F2NSZsuAqOggSZخ(7//)(*))'(./2͸(10+,((($&'$../32./)()'(()--(/11TSvCV޽ꋕx.N$zzW$`AWz)o-aA؇qǜ O# ל~}=ge+,_=Zw YBh4]ńiVmXH/vP}\/'6ߴ5yǗW4Uptf8+rZ_zf$#"ɠr![ƼYo<K޼&=/6]!蝆9 !Vg¯\+#r#E`/uP*^*Ìɰ}W'LxCj5ba ߣeVSW3K&N赣RG>GKAV2d#;/1?Lx7Bԗ AR ) [gwƌR8&{HxA إ 8,ӾG|y&>=$t6E L[rU3@72Dٯ4])~\2N [20uX{IYDSjkNKt2W+W-t@kћmʼnRdp0!g70t_+P7+_k- 4pB]9',K7 I\ /޳xaԐ-s= *TVreבaXm5LnNg[gf^?vltE$S%aW3M6Yku56kw őhs1%э-D[ C,GHj*H,f{m2UhX>08 `ZM񴒙֠pՃE=6x/ϼユgڢIIK0a/ZART>}\bnqPek'aH/Y屪SzV;կ>ejV2!2 7"(?P|˺\yd^%#芖Bak|9:9;&8pmXσƗ[v*xw|_(E/3GcLJ?9bW䎔Y m?hOivm!2֞<{/1Lbȉ'C Ɗ;192zB H pZSA,_Ǔ4PETO%y/&*hC2T>ad҆|r 2n#Gp.P1p\rbLUE=!WE,*k$Rs!LWi1vZ9bZ[&˹2 #_rqDU@@uIFՒ?=:evUF&\SK ;k:R$Epl\Uča$BоГu=|YFRs"2LQRB="0+j};ƬA7Sdko!dYFտ^Fڂ̀~FWC0P%+T\K:af&TwOBt~1,w￾v7|[ /2`w 6uI=;[BЉ_S5Q,t\Uҥ8kD5wLgQ ctiG;S=xU"K?U\mQsiull_׹7q Xpitzg-q|k< xM1+%ѳ32h .'/`g!"nȍ-!P;To|(0jm[a  yiWTk$$Nfb?|\&W9k 3MQ7"(3g!xq[v{3]|dI4SE'@M PzMeUdjgZ D)DU!LPzCh( l?:h/M%9A|?B1%dWJSdlN>Mhtvh^S5<F3,ўsS qB^z ~QIU x~f/ 0biS?o` 4@uyT4SP2 aKkS2B6*LW VmUVt$[B{&CɬUbI >YQ/J̒IՓiV5n}VK5~ b._|>oTuw"ߌ @AYOS䲽3هPެ] "qE8vxDb *V~Qt tl+c0 MM/ŌȦ}<)1KCA;nPe$Z&w wv؟;cs(1Yw8͸JJ% V躮"Fux[F"o]0@g3EW=# 3'szb3V'HDGFښOggSZpvorbisD8OggSZF-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS>Z8121/1.-/0)))((('-32'&))'(2//..)'(''''.2/&1.23'$M̀ZBuCu@ó}2? ]Y!ds2D}D~#L;,Lxd&i%!TJ\{8#!2)rC܂efPՈ=Qω,%2H @6:3 $#B;nBoG7s(BujO|D\ j]E3b"{=?2xǴ=6:e!NB ;-@H|<dGc߆D˚F|ktD\z9R?XǦbu#%]bH,/-~%G+4H}UCyTYNޕY4)Q/|;M4_ۘMOw2yMaOwƭ`EUyXR"?㺳糴nPIdc~:EdV?^M=e(_}xADaHOgwI%<-auĘ$SՌ,i%5xW)]c$XW- 1/q,7o4M a*}ݒ~u򞌈^:|)D+EeO 3˷ANų;=|_Fw r|ڹ\}~  ڎkwCdW/Fv> ##[^Z;CdpUHԜ_z 7=Z_Y4W2 (ۀ3-G,c*a˜mNcxեz\UyÝ ·UhxѯzlmODOD0x\O`5a)a{ʷ]4fҕ_z:A(X?*$v⬻=SSHڥ<ݗ1_ڧ>9&c6z|&vvt/Kon#L@US+~;ids|- urj\>~%3X鐞d\soߐ?sɰD^C|y6f@Ƴݨ_ɏ 7Cy /4݉* ۚN2޿/Uq!6+me}=b,dA1ߕnX\_3) LS?a(3 uvz39 35,ML0B*௴ZÂ17/n>|%<0?z>8;+IMq'f̓ɜė֧u*c=R 9Bo<֮:.$o8TU 틳4?u_6!~'~*HZ|ۨ^.Gf*? [ 36/J+&3UNVF,r-T@l'xu5]﹙/[]wC- 72"F-CS^5"TU4S^X< ȼ5i l}+ |,DUL4Ԫ>-l2_~4t6W9+u8ɯG(giQm1LpL]6 ?x o]'Q/N摗![2ݐ=K:TдZn}{ϒmL6+6lc*uKҾ[O`i[zTkt؏4UmZ  V2HjTf$=<3 [ϗ ˋf(w4h3QDQ@f6APỷk^/%o)[OggSZ}֫02((')''0.-&'''(&/0/11ʽ-/-''(&)&10/5.0%#&DW 21!\ǺQس띸gb:^ٷbLQL `4dU 2Y $ԽO.'/W|jY:L[YoDfrȼe]'_V0y+eߧK,_Jdr=։rZtzN|Mci-c^ivww,8Bt=|m%kz1/o q|CTte-d$(5R #e.Be% ?) tQ]]D&6ϡOC}6S/sֆA gq8b;!Fۣμ`W&'՞Vҟ ߴ40e`T4O^W 󌧼¬10`f!#nMeLo[@$KV uzn~R$MPp48=5[" [x0퍶tM?8XQ%!hXD˚U[:%ĽAMiF8Yҩ,[S ($:s*DQlwoup8ZO_A7C¾Adav{|[u5tov\S/_ Ksy3,'ȇGo8T: qSR0sOWa802jw$I8>w7Ǽ!/F\\'%rϥ0Ws3d-4.!bhȄ;P)ڤ>LCtNn1hI1}`>dLJDAS/O r}߬s*q/,@|޽=FoypazQ WFunU`кKn&YXPvє]k*9pNu=$)8͖AG%gϓSFs崧V,L.$wTqmOf9' WrC_ʖ-7P]w'35p]b@1QW`Pdk;`g,{ *xFFpp[(43L\y?#xf #UuQۈmϚ USy=屄[2ѩ/o&Chz6~*zKg!̳mX?Ŀw7ytp8H@X@[42Go ]{1ڵ{9xonaya݈(>??Rc!A2%-$u1ZdMI&GtW~UX'vVZ+h̖nf}=K$Q'<@rPS>N3Ny^}b}U;[3Y<.5JkͯM2Wrkص{N)ăheyEB`IdzTe{Qai3g~Fu#3bt+Qkv5LV}/$P(mshh:XRj 79薃22']sK1y>־y'{<|Ф wmW|qT-O& ҽTelDkѮF Mml[Ow0DìblQOSax L}u!LO[\Um i4c:I !f̩֒{d>R\J3 n}2jU9 "@2$݅$Q|;L>z~rZyk_]ܭkƌӷx2|tWOO̫WŨaJFW&(yd*#iگ9MRۑ>?L ?.(G$n4FӻC1MCepր=wPRXt2CAo& TW  !hz$AoӦ I$g]DW V pho$>?izsN!c*vLW  }dDIjIxL:$9\Ut pcIJ3]bLW<WꎼI]޳{p_W5(V>DU(eq.!×Iҭ([띭\\Yz%1onY[ },=hq&?m93 TYgb_ ;TKن%9H6~LUa,]+rf;XLo7%Cd&[ ?שt_`>Nd8 Hzi&TO:Tg?vxJؕ'^NKƗ ]]D @"-ݻK$,mG\I6\-w?A[+DYR\ӯqVqa4Oem6pLgAAHӓh\9q(5pm:ަ9#5cn?{OPXѠ]KiV~Ȉ3"h<*#9 x|8Ǵ:5Ѕ( O :${s H8P{e2) 3Vw/;k3goMbAszֈDG= 3M9FnѰ ç]YRJsU5hP:^ҫکh)ѐ_eE5ŬKʍA/ G Ơ)App`a/A-U`x S PHm.TڽlUӛXCVj{ˬ>zƪ_ dg::uWDkJ.ҽT(`hM!fe'Z;%uA߹IpYCޡX^d2%*#(a,bh/b%0,;o}٨ f!BK$(Gɺ o2ތ,~>4\)~2GI! 節 üú Oz0<OggSZ.6 ,/&((/-DjSVr\ÉйED_P! g?UN!^GX"(:}GLqio񖲌`tb>꒏D'by )̤̃?AOḚJp M1wؑH)i$G| Yݗv_g-ݜPBgok7)p?<͒MSi:pˣG$`V+T($VZU5E7Hٌ,w~ӅHa/3IY,?3k^m\RhksOjk}BG,sCOS'bl=Ljڙ_ntaFϣ3K.[1Fqg\},{b8MOsMG Y(q:ޮ'ItOggSZpvorbisD8OggSZF-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@GZ*010)0/'(')+)'-0+'(..4))'+/.ĿlU ׯS#pX;?ͣްE^% t_ 뿯N:kkt\Ls܊_\](Tt>Wzy8cY[ hBՐڂ|kypwoF LQs?lO[j@U*`xx,PrXsC3ڵ;35ףG3䙩jVK(kBp(ͅ+(>Y݉ˏSݓrͱy̒xZ> ֠ \ NIu0) *\l:0UT ׮frlV`1䦙/ ~q<(TU+Lu0EX>)I$+h93w;Lvw0د]klւex>0S(2^4C7X<҂IGs hc1=WzD*,Xݥb$:;I?ΊqPU\|o$@(zR3@kTIǜryp{XnP(QoǚF6Ҙnsf27T\̙.ˠJztu]cҼ^;0iG$d]_Yw'-җ\Ϭ2 /N3d9y#nrR,9 v.1φ|#dAҞd:% ٚ]J/PjFLFe^m=oLAˬٽeǗfYSlab5ٻh"%#j }?m? lg5o**4|Y~Ͽhw-5i!mmd4USq>W~0yW#DIhG28B\TO[U*Wv-W@vivۻ8KkXP7~}z ̪^j%`kp<-Ԏ[snem .,eL ,B:bAO1jlpX"4jlFRi{%s> D 5=Ȫ;6%].B!u PJK*U_y*%t#t+.@w\z. 3LT -͌ 6r, ׾G8Ai4DRE082A׿=;J\\*&EE؇YtJiX^ 6x}uj ˥f]`>Ɩ 8Mr/HiƲSm\~ߎB%Zƅݩ8*j1S 9Oɑ8zS ͔} z&ܧ=]39aM:> ~X׎;H5bz+J4p2IXJwMC%؎-65w1a׺lsu[ײ<ֵ4:1U+i,ѯ8-avFQ<DQ|znZ:;zY&bZAY5nuDA kUu/8J]s8Ƭ1'xUj~@N2Ta*Wפ8) NW>w 䦫L cdӺ@VGK*uv>88R;hR}c7DVLjS3Atw5߷_a'!3Mͮ'D]EMvm:l%M$㚃]zXs}Wo aZKo "X:!ksܪLz FsQ6 ]wU4xL i/F~JF C: U1[4ۦg3"nUY# ug3,Irh;Xz+6JJSoMPd .;Ϊ ȺI+ȳjoKwSbR͚l_5;KMTn':O(ZwD=W׻3GyQ7ܖtU Y6^f`tsxlr B],3*y;4+/ !gAyѳakl qN*U7+S`AAΰ ?;R ' OggSZ~a>¾&/0/&('&021)(&&1/-,01.0()('+%020//%'((&/0&(/-.(0202,)-Sx,=$Q&-cr4 .k_Oc ǐ)?59`R|)VkDS4 yf`j_dtJIǵȰSFD Iڍs!9~qn{$kd\Jŕ -'{B*Q7-)mTv 8R8v\9J:BW0&dLu)Uds~a @6 U1͙k~B3~K y FSߝgY#~ "Y CB3 Wt94?<}퓘\hf`Ŷ[6k^ҹ`PK %bѿY ,=և΃BfD\Ka-q@]OrǙ[֊4ڻPYRYFޗyb ;Ieq”V@/ONqsݾ m\*Of4tl=-@_Pz槜2.ٻUК`\e_<X)!`b_JI[(#f%I;edߧF$vLCIIBzܽ=/FM %?l7sN 8\.,.fU.6fq<~}=9d {;Det朑o !UJt |??-蓗Q6iL2*EUGaU5Vn0spi:麿14A6?V[v1prG(-o6J0di5Skuȼ#K 5'AE/w417rGxl\5IXh_:ӛh#mjFZdXLc&@Hz _? uyy=6mt=' @J\ Mß_{xé?w2ja^= .?!z&tj& ]K2=Ȍv$|# ׻̳Q>IB=e7 sAFfyүG- +2JG[S6Zٳ2WI2{:pMI& M(kԄ/x=%`6I-bF,:*Ǐ>_OvTjz3Fi'oku6_ʩ(TP9IsX:dsr#`A)!W̱d-¨cŌ k0 jrw /<Ptکu[r\ߛ:BDeh%@ '󁩱E#lyN_Р4S]:Գؖ6a"'ǻ"1HC?DSM='p[,<&9Y wn\_ceȜkAcs<> o6wF7c^V,+ ?B<ۆo7p?D[gu}W">{7a :G[v3~"Yt;5S崀,`J a]D%a%d[?Dӆn2皶{ GHt=rU_,ɰrvG$!-Tx@o@{ ϴ!]F_ Vjtd7<;UN9T]oF}M\aoS/Io zL )8V=);lq#BLlGx5GrqS$L*{)fda<~pҍ6@$#.E8J~o_^^^N\|9rBf0K}>0 fc$B|NĿ 1i"''_j`}{ߨ^:#e|˦TW6 YU,%a"VB&GΕe+#CeőM )W|Hhj2;H[qGײS)g (Y33!zk_[uT/["hqyүtEa@DOߴ 8|ީ/ڄˌ%kpۙ|g=_@иѾS Migo.84oT|]bwׁ֙p8b4SC/xMb \l)U:4.g- W=㰿(D߿1N>#ˉ|aS>ۯCp߿e/OwIZY!+5Lۼ29?>2t+{u U.ں&T__RLp(UdLb~5[g랹u8;d9YL]0N⟶Wioi=o!ȉ,TǩOggSZyY)()%-3-*0/1403/3--.-+,0123.\Wkβ>^d"nr"'@-"+8)d?^-8uI*.{ro@i6Ͱ d7[|HzfJ@CΗ'+޳:$ l_Ei! h|Cz !xPL Lit71c,ˊƹa^2ȥTY|uUy`5js =s??2~dL! "zirꇜb5Ɉ{sYtp`7 T`o18DT6 `̪U&RdD eۉ*;gb߿~ɘoZSQ$~܏}16(|a[/)w`5x1F"-رKL9ߡ|c~o qؘ~_OwlsI=y>}=ta- "֟{hQxxg 粄|"T/Nb0=U<ݿ-}!o 귤VT|vg4pHC=bn}iWxe]燞X' l_-~19s7wҚx3R8%<{)XR\ak=<1;$STީTbOU|d_/89nW X/\$7g Ft# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSJZd8Y%.-ɼ()(+001ƺ')*)10/2/14ɿ(dۓKz M4~.6ӿ41'_7l=kCK vV+(+zY:{eNlIŊa(ǝHIPq7DV|ɘmV0ռSW^~іlf1kMuҮ\XY4o֏6稸6kДn䍮WR[#aCr{pu~!+ؕ,W:.76t*"̘|P>NeX<^$3k3>}A) &Ƅ_*G{o&a_9hЍ,`hU~Bq{-7.ܒ4T#u=)1K)cRp-* K& dpVw8#tjQn+2T"\ zeNIFbVm n< R]TgYW5`%\|K ?>~J c3f/nde984G Q5 :L_tzMBܕH*uB Rٴ!qo$عIXADc#ڮ'ci?4LkV'y抈{a^T:I@̮j򾦿'0GU}}J5a8&$ &n2^ sR]o~ؔDw$ ]JFA(oŇ$'50XU:8 ^$~4rFz!;Ď͋M9WwHdGW~Rv?Gؔ)wzǑH+7׫-y^/|$~&CSΆ7\bGXj{MiLL[0E:[8nܦT8 jG|…Y"HO#[6~\RYq -ׇa{ :eHdRGPNzcwl $ MḄδP$x-+oa 2!k,/9_bw.wL ,\C`V]r|LR՛ą̣M/(lQkey/V20L渧EFiŁO:z[1vGwq?$hn H$PE[BpmT10ū6 tt)- antY==سwQ.6ŲGWREst4ͱyj]'@)]s|#crUyϮ|ұ:{{Z}r/=ptwu o>{,İE=J Rr]ko`՗}@kM' v/ٹxMp4S_-~WHw^!!GŪIӆ"}L$/vtaLӺ* Ac[  }JSq~>,7`;sZ[~-$ͱrNۇG屳[-DAogMB,x7u~g.ymkIu! eW D @XvѾedFI` L.!_;P<Ēty3^Ngi\vkZ<φrէ# ~@oU%%a1fN7x|8-V$ m fv)RaeKQHj W66&S?*Νaۑ k>>.Pؾ]6U1<>K(t! ZY)I6F htj+[eiOuP̳ *m)%"5,M@iWRԺ|Pǀ}-sxwG:r>)-X|B{|ۚy9AD^MB A]=_֪i8mBM] >ď+'"f.FnciGT7n]XIk42ufI1D&NOmYzڨ+9g#7N`%K *}Y}l_'⑒Ҷ G%?" T `J,@^5;;>M{>#&Ww!ID{쟉kHk[H13Yپ3 .[[]cldtt?Ե~r%A=lBZe7R }6ty\m'Q.ZnnIVm,"]@Hi[p 1gWX Bְ](w"@,7n^ %E k99ΰyt!#Kٯ=ݚUOٚe+%\vu^c0*122290Fuo=$75Jys[Ʃ='ιoejV3s/E<n*zՒsSȌ@{b(Y  H ,^)ܖ~eؾQD@4]b!Ihj<I%e&ge0e述x(a6q|a)[}ƶv)+Ә&Vc>{U2vybΚƫj=OسӋky >W90ZT~WVfc )mH2*@6 NN ݔ2Ww”鶆8:zgoL?ޏ{-W42Ơr .N A06~,ÍjOD5tkT?kgHvx8bƍg#⚇0]}JK|T$ valvhd&gIf!%PӺ:u E{hھ/vΒ!KcO 䮋O/vf@slN7'1nuTP$%TygKs(PTVM(L)Z~J%qMrCF5sA[wɐ$zbέΑU2ҭ;$jQ]>%WZɮFj9Ebc,' o#u_ ;gOI3]د;=V&>)(S602kR;ɻ/I]l1޵EҚaFT//*9|aCBC)a., V,daÉj+>O?\dY;2_HDs3{&^Q,i-@W%Qno޼pMK5LXu=';;wm)pUx&.Q/{$n57 CaB.㦝yUa-,Ivhzui\_O  \h+0^٘-ϬֹLM@"(Jk͝z y%z/LTQ+ Y ̟Jh54yISF7DGDOAӦ 8ߤftN'ɺ㕙UJC1]q7{yڎ^r[u-f.>@PhLbџwȏp&]^lFXM#& Wg&*Cߠ&<0F%1ؤ9񻥞uZ%*y-ec5rN:d"@եFs*8y:ZВZ;Kon ddc־5aKP:*r'ew OB<JK>^^A\#lj*xHyl9b~lNO;]/?}{DyI DM+7 };~ tcCMr#oǨ2[K,Eϟz)v=2gݍ[s~tF|gTX[Lu_4mTyY ^p1M,T?ޒYf%r36Y=%evZ3<%߼j'3qQZMԱ)si`j6 J\"es+g: DM@(<S[YmT4GS;_눸bgf .ڦeƪiԝ8|Y ְpH|ߌAF%=AǓ.g}) uv%|_^=6R3twoMȑ;;ڿ?˭#4-4|Coȥq'BcIY&.1qhZzA =}DK΋xvm493>GH<3cQD4e|uaAIwh 3Iģ)+=>@hW$k̝m m%?Qho*k!4Y.S8(@F UVVϊp1nٴH/>CɏS"{dHtRIm֎ü.Mm]f+*o|a|6 [<Cj) OmҊeKO,@Lj$_n35rśaҭ&M <:03.{7߽Aͤ8x.Bi# Ƅw\_hp^TNfvk/1~DU ?~SjlaAgB_vvT>L;nܹi\{^Jsb勧JOggSZ6)*'.134Y=p xKSnpDۂiA/L"Z(Փۈ&ŵ)OggSZa{{+vorbisD8OggSZU -nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSLZbw e'-*)",+,/*,+-$&%%&$-/*.L|\كvN:Fzb;*{7rO,|@@ NJY˱ٞ:'yVo e𵘞 W @#A ГO%ÖO>jS&4>G>g 0F@wDU麮0F#_TsAuO~I%&^3*W9&H&RT\``S%`!'Iח2P_jFT' JvwZ闢8+YԙԵ  E`l~O@gڏs7!!Qch:X?q~}!S}r H#4Y+ywG$@U;aK)BlMI8h%PI%ZIG/08b,2i  @@CX^Om0QdY$uyc3EwN|9\8\"-k1V ӌx"' j.:B|=jd&uz2c1w O-L L}5] C{,u K=M  PKFܐ$ UےLH5@ Qo݂pq=TPzOkuFűrJL 8kƒɡ }UguΌS&ˍy=V6|ྴ%Y}( J;? %؅{,vJ8ڼbp^G?9?w?iHTg M#,ϸGvzof9([<>Z2;bWGp>vP %yTHǀf>)"d`BpVgt]IRu=+ 9B>N]?R |6G0|ar"'*D6m s+jΩHD՗rt Bw+R͚l.dDO m\1ЇĔ"w@ͩ_0fk@i%|msﱐ!Y %5S+`U؏PH gZ @7#I2fHA5Uދգv}Tf^~} \O,xp>ض-X!>p!eYwMO+cҰ]q lS_$~ɭQxTUWQ9":J?wiuA7ouZZnd"T}Lt4$Yk(RJ కV60o{g]YxaJettzF@{W4} ӫc}oܛ3r _#j `{^IT]:Эq/1>hWf*zV_xWGsN#4*׽FΟbRM,էzO'O:% t :KO-i9X\gs@+̅XqQTwqm7i/Pd nNL+K<ܔ¹mh6)}Cy'/|ZvUN^ⳳxȚ}aC;oNRԓ/ya=V+Ǎ{c߾] ,#j%Qu;a2=]iW %JN߄@y3{3vGR{_b.;p,ޖȼH{@gO䒹̀CY@+xȖA02 _%x)Tt`5IpDuqהs,Ķ #FL/)~ bgG< ƿYn1 p:m}G<@{eceo0 Q}&1wxG|&o!iIuwdVY{LޞJnB7%/Ce{i0OS3K?Iݬw"E냉pX8'Li3tjI dF֌BO!H>1t\8`(} ׌a>?zby6l00`C.$Q‘2&n} e=HfҗtBӦ<&;E; q#t k~HS!r6r tw7)Y׿bfֵ&<ӓM2xÆod[3*8'b7D~~*/3˾nZjU <^w:5u|8l޾5\n*y{) ųo_Ps:P卻pfy=-}"ZyT ~QvɵrAq<yꭊɤ!9nSl qIPudЯGj/Gic3yK%K{ /ӅxٿiWK&3,9gK2<i z1M oU&̯܅7JG̬HH3;FlAӃ;L&OggSZ]2+',&&&%%&$*(*$$$#,)($++),,,+&'%'%(,,.ݦ!鹀,6׿ѝ1c fC%٥|/5/m/m%c!i ڍ]2,!sl4þmE2"c ( $F]E@M~B"󒥫%L]GE X%H!ʎE c'Lc 6dVH4>3!_Cjt 8>aRz=ND]eL S9w"=OUS~Q7N<[e >\ϸ +*B{{#G$U56 2E*,oǏ3꙱R,,Ӿ'et9*/qܐ^t$ӓzѽ+Vw>YJ֧79z彼$AK&޻Fz47t~)zPr j$﹟q@}Q**b%`w}ۮ<-м4-^ZqmfO`uGRUvkf'-Vv'3^ckG1|1 MȞVzV<:YpҊD#&% *?"]dcш?L! ,$1ʠS=l`B@ތ.a '3y52dM$> Ģ#y4Y+?1;|D 5wD'fUb;H'|bƚm '`%m=d f7^ætMgA @ۧ3lL $Lx]Pf븓^n&yjm{s^j<^I_LUd@lU3hPio׺9;9Rpd#E&nǛeu?z>4GFsP81٢RƆd^NĎs}!twHEV0aH`V fӴ:v)dweXl~#~Oo~,GqVE]%5'f)yy9!Sk\^3wvoL|T圮>,TQtmj~$?YvuWZlv+` ~!_n]\n&Qv1|,Ͷ`ƶD~":}KK3+͞e8ʓPFr>w!rI_f!|׀4NbV3ad;1WC$=,KcὼIpH׸:?:Bkq+.n90 t.ν7dp:@]{yu3ܱ AA&qΑ9oiXw 4ƪ;ЪifTk̼|-bEQwG[ڥsE%C$z@UH,}ς]"H#~n-x(xiIA|pi$It>|O2WQ0I:wLsBR.{=%KRvlYNM*rXWNлGp郸gYK(k刲ZUx^먺%ӧa uRK{67U.q_z:1.}]s=t ).myJ 07 HP%x>'0+I̙VnvV}rl+K{ioH{du;UxͬnݧZN^p֙ 4^z1hGeB3 2S㬔+q*i nne]}<2& hLݩƩ}@,ӲfČKg`[&Lݻf@>ya#Mus='o(&D'1 LizU~95w[??:I }mWPQX|g h&jŇQXf}?[ |Ǒ|L:ƨmnUb3JJwӎ݃ʍ{j g)qy9O/tAL R5/3|&{3sfP|dق E嫇sj4_g ݈C,_NOv}'e'^pB2SɞPgD')vfzA6t N>' դx)3e'2^(sΔ twI5g+ϧ}>4VZgizc5"ޫv˻=X&M"F~\g\2ǒD͎?( Ikrnщ۵`i=P@!8kG'J|3oCk^O41akEA~G/ȥKlDsh@ް4z_Myk9tFsmWbe& t%h8D: }W~XZl4h~04U~ na}6"-b94_^mOZ8Ҟd?盥S;_/GM[TO)Ý@m*/޵]){sJb'zB9_OggSZa{{+vorbisD8OggSZU -nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@Zk4/34/0/&*%&&&//00,(%0-'&0-.21&(-/)/3/011&*4Y͘^jp8JF( WA<]lcRL VTblA˽h3WZt\& \(A]R~歏֟z9GeߙY+DiW5#-uZ*\GǪ~'q79UWI kI׺%}oo}o7%#9^xvK{

1>x3/c\4TߑnҮZuo ‚,N\- 0"ao9i*{e, Jcw'` 'Mn{ mdr P DC~I%@`0S"?-@c@i"'Ad x { `V\!? K`ϡFDF[|Ϝ 5\ΛDOO#X-z;ȏx %~S<˄ {JD^AXɦFeڞlܡSK•* O) pjmzOi/oRgJ:?,(?TQ( ˉu> %aZg;SHZY' K)/lr6\U}юbЭݽzgpyIV4Or$ivw/F"Xi_zֺ 褫b&w[\}:ƽ:i*bHoX*]<^!Z=pžwҜ/2 zȵ x\L[H;(l$ Ug& ^K9[cAX[XІ=a[X(V !CU4O(z0M?_+ćpO \QPc}!_vіWs on u)Ы TOL~'!8,^λlbma5gſ ˗],KT[Yg?&}Rca_pK{a㔾D+G1jRi .ztu7KuJ{I"4I9Q߉af&g=GGB[8v\7ݿx_F\>kϏ߿MW^Eub.$Y_oӯ(ʕTIsOFoSَw9ǵ#::XBCBh%'r7t*!঵/sL=:  W_RX` H zIާ*FYVѕǨ rehyb_jd 6QKBfP*UR:LUqf%;Xo`GC{%WpuR%\[0&&j3 ٵg(tД ;K{Kw;ٳ .cƵePv hեza9_CīaBbz/Y|Wd[ik[OE?ZpByQGO{{&@Z9Vk[΃A亟P)/lUG= fyϯļL]FVDs!P1y|S;6[f[pя#X|@Pl]VGZX" :$82Є@#+ 1]| P>aol('_T Rl`G͝`=F CBGto`k˴RU7 VbYj&ȟp/, RU` I6GM-qbȡ^a~ ,_A`a &vxfL"CeP`-n$OhúaF'~>.BOhJs !ËPAVbR/4h5V/?bi@%2()rgHG*B8c_z1('e_NP]JI+voQ^KSedRV#CtPʻt&} ۈ|oƓ2l Yiq&{tނ73/#C=P4$:TdC{/\oI$Ɋvo4P@pW2@3N2:TĜn=$̻9Iq(q+-pz\glwۻ1Ph8DP.+WpShZ(3[%"94H 6 z3%ͣ?RIq A=h:(VTu5WLfj.$Y /plExmµX%[瓤?E/ IQP p 00_͉cA3d> %?cB Qhj&fpi$n}}_|7yfYYV}M3M%eIlٕ{2ZD?=wשr$e)Ȉ@TK89M3[++~Z/q%&<gh"̭rb2vN)u8W'o{WMwcʘh.dMY[zfO5xi1GZ=KtjP/5$U\xA4]*j}ڳofet&'ާP-XhmR.Jyqޙ^$6 RE˳i}ߖҫ*uߔej?"g~AbQ)M;j-\5q2cšWv1~5wĐP|9B<klqX0__íh)Ay9!YL. ߪfӒK 8Ew>kX4x,L?Ƒ7| I^>v,\RDnx* <:YxOggSZR%Q.(*)/3)()('(*/12,200/ȿ&(.00/'+./101HhRS){GЗ"hP&F*:1%o+7FhR8(];22eNp07g J7!~$0z=q^c獞̲~Q)$\Q*E޽Cfuxr]xُGZjK a !ӫs$*^ܞT;iݛ/q~]rڵ@|xћv b_OʰUsyixG_/r=&'O><ڧG=R"KԩG D<_"gqnl3ܓ)+wj~8ʀznud`>XrLMN޲erG o.~]SQ)c/쩜z]0,ʡ{{12/J ; ,7Lp J辡~lDcK2~h/Q깃bCje@NT~j@ml|OW1w#f$i&*/'Mw25|2Y>rԋ:ӥr$*1^܋J?ZZBL_6b n7jyXwTm6k"58Idi67p˸5ua֊YcN̏6\jx9ؒ6) Sxø$y'Mp@!ET 3Yb֯qOuزt3.g5YUM4D=/&ݩ9sfe>fU!')c'E.PیgdZ/2"dbx F9(gcn@OpU@#/4OP`Pkoam߻vmGK=?;>O*d]~=#x&9Asgyozg^mz ~ cЭ?3;z{*ְx|*:Uތ+lF|adn/aCzcS?y:'㏮# =-!\%!_ˍzڵItU &a\O>?2_^kW9cҧ>L]b MzKD=+ ;GQP+i Pٙ$q_4ο;'^mb|A?s?^PK']d .(0E P%`Q'5&޹Dvoc<'.#208HPQ|jc]1b5 U&ḑ(a\.]TXmŷG/&rlnh J~ :Nsf;6qĪ=2Z U fFe q9;d J3 PqBoY@>\~a-18/VǬެkuC~Ui6庋:uc2 IKDIqNgU s*)kPꡱQ`;8뽤\d)ܬ?!ucSL]4lh¥꼐 C,+$b[*FejsD.x[[q e4-5FDOBF5 C6]F5#HBv3- -!,4 u÷;:^[OX4Mj锡}YI@=0ٺ]N/!6lflUZo\X8DgFV w^;{ڕvB]Yi@$ 󾳆\oQ$p@i=mU>#IvO}VW1tcxn!#EG\aC~}s ~ E)"mRxbpE֣m5K4_LN=:Q 1&dBPwdI/fnζ>q8fWeP,d}V f+e2_ⓢXrXk%;U$0 6f^͋J`""Ԙa+/O5jᙘVfFQPyWKL+KUՂuk䧀GXIJw:J(%Ȯ)6v#8:c-4z.Sx_ i^ͬpǓvvf9yj;{`7m7-v {!Sw]Q@l)icD_~ijalC.K`q37fM+mL4ɭ0ׇ`[1WءZa i|>T^[42֏1S#>q= xU6WIRw4)k4U lϐ`,+.s1n/[t~, M} CtV#r]>}K05QpwN9^Oo\yJg/7qw\@[mr=B U)p۬[l4?nͧYX{HzCwО $K.Pw1\Dmޟwz}H<-G]"2Q1ɂ'[4)Xn|*K ݉sєVDT>}4p#I+ϙL낂+sWئZiOs3iV|I$/yl@w^1u~>?1i :DN4c]~]`|nļ)2ī9u /Ab_^mԬX2Y-k!a p {,c[=L^#n<=vCھdrV1^8ǞkiD bZvV(EYŗ\.?]l?e+[ǺL&XncEQ/4!`&L'5fxyzyq)$u\t @3o) /Q"wjfLjkzo-J}OnYQ\qcFnNHewE2! _+_zc`A%Ukɩ) ,~q[0LgxNuj $ytHcJ h,LPE@RYD2"ڙsa-5 <3 ٯWKYT#RJ6)]A{םX&/iA'pƔ QUzRFobD=Zyoo*ǼgH7:ʒд3}&܊I ͣ_)U_$[~\=|J/y'G ;jt BR_v1/iPɏo x4Z OggSZa{{+vorbisD8OggSZU -nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS0%ZMFJ+--)..,(-.*),',,-&+++(,*)+*($++)**(,+)#+*&*+*')+((*+%)))#+)%))'&*,'+)($+*T]}j+[nbӈ͎lgni*z70HU&M.Ώ4b[r~h9#W3h!w!ky1OdOI|)g.,lo3Yb{G=Gb߽M eUHk%9߰" joþe HO O3AÐ^Ezʼ_G-lo9;@msHur#v\穞] \i:?h c1_xB & U'H\kz0='J]ehY.E#q'3anӅEDtm>)~h#`*;۞3Gሦ+Ll}peIk@9\3slk'!haY7 ߅bLD|o- E.{2gs#N\ϺL|ob?@^Lƶ4H<\͝ETuz%=Deh-=:<$31;Y[f}8N{9J@&>Y`~u{irpk#KKlKnH{@̵'mEuvB21b\;@%5$wx7D"2l1jj(W@0i>AiXss²W{q EM40~/0?`;byxy{~t.៌v|;5 K^Iy5=pg#RU7Tq70<ݙR"S\a CV [SH_]k$ UGh)9:}3a1\Yfx犤l :?#E[De WF9QYkYd;_WZ`@3l;i0KgcuM/,黴  G31þ%_8.W!fY ~"Я1vctj n6 8WpZwjL#K$i#n5yOJ%Z:݉O D]Wu*!gϡ ڿOx.)ܺtD %3O0Re%7=ӤHIlD2:LfZADs sl雴OS "З~: BteV.~8779#OIkͩ"gt~2]PPj@(J3''ðST?$y{5~!hpZ5u+w][qbc=$0TSEW54_j'_v)3?ZRuOC |)~!}|sK_YL>z?sI6Pr+tS[0 >3@7G3^l˵fT4@J+9|xrj;5DU^qɄeۃqS]D6?, :)8D_GMsn/̦^%. 6&Qv{ o&mK"ⴅlbUDB2?TSW[[zr6 !b<γ_lk%δ9IS3DMz9NW>x~ZO\/yG`4y M~)ŋf a) X)&3H3t9V\e B>3dq*g{(9 tYOsƳ u녷^0}LQV4@tDvx*a;_`]>rRӞR6Eߧ%Vmӥɽ2WxYdQ_-$;CXޣ] sDse^itM|C {BЋVB ~q?s)zܾ7GmX|iB~@62 6= g 7Pͼtk^MACog|?{͊~[q%4t{d@/pHVVe'e>c3G2 $D>Yy!Rty ˆ3+RČ<sAX~Dztry*OG .\S_Ĩ 2H[5 -PEr|SQ"k5Ll[g5<}Ri,A4oOftr>xӘO2!\>f9 k|PJ M<^|+8K?5 l{d@RoYy[HuQ+,|@8YK1ZN 3~flgr)OgߔC$ߨ3~I4 {%~JٝIzh^ gTSFm?ۖnr2=o봃Bmhp7n0IGX:|>FIیǪ}+۳U[/L g+ ӈ]Ƨ=0ñV#ITZvF[pfEuVV=~K%ҢoCᔧû^o޹ߍ狆3 Kx&C0@O ChOggSZa{{+vorbisD8OggSZU -nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@DZ +50.4(/0.41-29'''$%/4/&($&112UAFܕuma؜5p֑Ӭtoj45J=?dG!ˑIdeXA\ao=>?;Cؽa8ek`h`A8|9_N|~yd} m5} iF8?V @KMޖdKL9%qPĄw׌gB/~,8u+\ c{)5"Ovr9 kI1Жe\t{_??NaeOSoc@`^xb|uiR}>[hFҠzula lm{F@=T}0ɫ72%al *܋^WiFJGm]Ǻ|"vUrsZϐP<8nk[d %a$+w3twLL/rExuE~Z\,ǟHPbĸ@uy㚰*?baw3_~v2_k\#^^dqkIlCE(ê2 ϗ2<탵Z/88b ;;tcm&@^*~gwd[&B@p,5_}^nE4>iGY}UDNTRt5[N,NcS :WFRIхfqu_՞Qnv%2-;z`dMq,̙7f,B`OvCz)F3hdiТ}`?<J|'@Ɍ]یSWw&ea %9<,OcNv7.եwRW;N׮ۜtT1/{ݍ~ va}H%T|^S>/ZE'HtNJ|C `Vy $fqUcv6Ô p<"t[&.؝5FOLZP6hC ;Vb\-|WH%[oYŤX@ewRP+,KFLe}d8شmue6]s]mvϯ8pQ箥zC ZIN+A:ӎw|1(/ڰ]K1 )5驑ԸvTy5oỰkT TOrM$)J}X9 h~9tBh^%P0 yBFXĮu|$ْ!]C}e|{aJ_e;;m8bCC[y.=_PoF-saFAY#"r% kU(MJ- VּJf{,dܷј%  C$9J}s2mD̰6~JT5ðVG@~5%Nr:Oχ1Fn%"Iˮe#L%1z{c+KAI*3T`yeQS& h;Zx1Ą Z_Ӑ%7\/tXb]FC{r^ʔEQ3[K֏ywNx*tZ<[XZYOjP D<hH4`l]m5V95 (p:twlPo{60ÑmH#G em>㐓 emW1/Owi׽OG $gI pw""gx9rZQP&4c6a/0UmDQ (#!׶8ʭ7wVn)lENN4,W2 >HԕSh9ΕہkmTYN0V xy$C<-2#N%f:%m@N`8XRR]+Ikn9uw>3+xtmSZյz)\'t+y;c(|wѯ F,Jf" kņ=Ѻ.a ,U" vׯ4?`.GO`@uJ@(EWH!6<ɓƙwĐ\]JL IR벨WeU7If/#ٴcԌJ/NK:ͶQ/RS~,Kˢ9:V\UH5MYhR 0Ԭ%=z1 Ҽn:CXӺQpp`~}/ *i`If0 {"_:6P (Ds\ۈ-:U) VnjGAؗ3ufRdGrֈOggSZ<|q*/11''*((&4/511/4'%&.//(&$''/L4`4"xLqnk: Ы& =Gpv=[<\\+ƌ:ZT`s'&TQ [ duZdDγث`{{ͽT΢i35Acytc1_h2EXvyAip/MY2gE5v-i-~{TvI}tCfAQ{ Ztvi'5ӌj> ʵRs/Drx^ںz 3UC 0½k}b~VT!TM~z?!^̪h". *nŃ:ƙ]"!Z_Lp9ܖfKʒWr3ևNmھW4ppX}!3+o*T6Q5x~vNxiT ?kgB>Qk[>Hd'uy^*cKGFÃ[zXxݛu .BҾ?:?sƾ GSgYy}. [|k k3忰>ڜsZJ@'@{5cP͎V$1$ez)Qf~M \yGn'e<V״2"q`M׏c*3ޮy\ [z8\'dyawY˟\V8׻\pVj8bSr|iX@Gd.Bw6Ċ ooWrr>{b{ *<0jGeO = J231̹Q~E;N\NVtG6ЬBUxM}е]Ċ> ؉4dz@ #vA9yHg&hK\'dy ѳ.Դp"ȴBF>tgנc&A2o _pD3}&>%M kJ)LJxIk!o3_էN50a~3+0&Msiu- sׇi$Qyv9*l)(WZ`&H=ʯlþEMHg/%0<`X~wB_tg~qr/]3?͊.K֧\}P'R޼AhۍUEt<ѕ吻p/ Y!4-'3na:mN\ >Ȇ][SffџN0oP"a^z.3cHIf>IŞs?xT2rm^T{k/І;m?ul0_2GPZOvmUFKPBC . '0?=C zkv eZbЂCJ coaep^$C<%\ȘdR(X??554V/Sv7V|Z9%$q+,!_ؗB-&D.z}a~L|AJHr|d02C~Jw媡{T#uޘO[k+L'VZm/0A* DuIImk>T-F{.ˮ9b%X:|0x& dLb1RԻ'^P]@7d'QjxI_e'l* kU0Lt;Yj=uvh*Fm猕&M;ѱH_|shLzu'f:J hq<&{ih~>hf_wmImhwZ\ƞ\4[9hf_ xV\^}j1mX zfe M>;Y3~/f7R3kk(C8itnCukIlJ\Eև}b~H5E|4>-w^#aܣz=Q$PI'~.e[vsbsP!c buS4حz7 dmS PHY;S9ݚ$MtNoU/$,5bv4M l.߯^g۶|uH@LUP0 (x' U+S{{ rzMR%3-@wwfiL1OV3Vz,s-Z,{RV,ms2Xx6}TgHq\-HlmӐ֜Q2r{\*PYad9ͳ*gV :M9Zt^ d4 BETU܆@4ve+ giv,'s) dB{nTSf; 8>%$~uk"كWXgYLS,D08 !%w_./1P?.;ȿ[e3][},Q@@ ]AKin 4Uf}S4M~RA#_c+S]{;5Ey,Մڼ*Mh?=vpM$OΣrD+vrIAG׏aOggSZCvorbisD8OggSZ-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS:ZB111&2.2.3/23.00.('((005')(('%(0001&&((((/23+20'&('%('002Rd (ȼWeP &4ST6ζb< x(K$b~07Ė |_ <$w_|nIS3>oexT=aҁU3)cMϿo]6o˧mWsۍ~uh@y_B пC6j5{䔼<:#a,Yd[2\A 8ڎVɟxW}ro L_ʇ Hc=wRc̗~&?o @RtY$_kH@F8l96>+䰦>+HH3%y{DSE\M8mگY \]n ozD+HxbcK}"B~g^ >B52i4O=12'GnRkFvFzF1]u:.ChD~Po!eW9"Z桬~X楓)(jń^XZQaqhdZ(,l Hm#qϓi.05#xMJ(^wTB~uݵQM:sKB>A]J?FTj !3Oˆcf&~epHro2CۼH4O(bWoA;vI +0 Mp1%B"&S5D+0-"1TNUq8r4ebywNL/)]|M{RLa+zб$_ץ˳l/k!C͖D h@a؛dSNE=KX_?ʖ}"kl:)!gȒ+d&Þ0!X\bγiGbMc<5*dgl,X!1y'}vື?yG*#Z؋)鰟#2nt=m"̭q>VN7U};.Km?{9?ozs S& K{ac`’wi,OKQޥ- U Џe vq?Ըbٱ''tJ QD`&I@zOӾg5u R&U_ 0Kwރr[Ttr>zіH EO NJvug{:g,_}˶RۈĞYίmL_Џyo9: 챛a?r9DZ&޻.t[\ir+:8qh XD=~p[/6܄r DFamB|s^zu ^]:#By_P3uűG^1b|b:XiuQnJjcqU4ڋr!uU|Ђ`ϊP&2o h;ȒyW/a<_^B]6UO|~Q %ƍ] 0yȸW02s6"$8&XYI}Buꆧ}G[PNA ?aVފLq[ˡv=xU^llQ\{Zp=}]B&q}d/㒙ex`ړ_ jZ^4ʼk8e%o/lNZ~*EZl8^w~y%7q̄_Cj6 #C>M3'ʷr]#Xp ; ͆0TW,9 a Q7vZ/tida[N@Y_zԜi}swԺ}  ?toTX}B7Y ?3x|ș{oao[i&K~ǏS;TGy9ݝHsbG?{'h9MUoދDM΋!!i)'E=~"׋!b`1biyOYGy(BV^e̳Ĉt(J{.7}6p?/V7C2<{{+ix=O1Hh.rlt0֝O 8!kM61}15䯂{吃5d1|'tĠ"-DAA[K(h"b[^Zp>VpyoGɄz@rǮd_!rx_o(gQ+ ndI "W V\d?]0pX/sٿ3_"Ejb̝doC4܁E=C/8jū4!L܃!n|d3iώg\p$XrxFB+6.Qދڵ28Y2j5&"G?ߖD&?FnϾ?]&ri=lϵZa%>۬"9 k_Luuvݵ@RUO #?R:,YB$HȲ[%uV ݉r3OĝaBmS[nʕϽ.s,# 1=6R}tT[ Ëfsbf8H}Z4ưٯc9!-Kr|tePB|1(4f8,A\4Qfsxká_T}zz9 `^ @'']*I=tgO?\f- ~rƥjR)μ@*$66QU-#ϭeHj܁p^>p9ؔ6tM>?Ah,o|U\ F\.ʐ, vHx0dE ݵcHX&z/ 8[fjy!c$vtUO.$Hj:jp^Ԁ_NO>^6ڏO˺44_0CjV}n]߅7X}>5EgemSLgI&sf1wp8#צӴG;׿w{2Z4 'J /OcXP;c"ta F7]xٝr4k6T/DJ;]{IpY/NLk/'O7a0 a"nF2N)̗WS*1>^Pwcp> %0nhǠyCqR"l"gimi㨥=a~óa; U]oFCc<^dEl<W +3V4@UqBY|EwZO$ql([@|KI.+2hu|+~ Q\ 8υVQBڂ=O7/tg{3 S/] yF=eV*{厌-nXN|Q -hY*`fnx\gVysyUl CA3N@g931#'͟z4z-Q̛fú.E=D[ˈŜs"p.#T߶{!hT:/zG^ $gbfh|F<'gKIχ%gY5=H4k6niU'2s1sGmޗό/:b?\"4iUĽ!+ٖQڽ<(DibMSߞX J0I/+y^n&f?c}F@b-N/0129l ҥ9 z!ZPHaK<[bzWWt~`O٧ U .j`@?9H~ v0\b!wWR&oA}xϬ=K&%4dƌnoR~adM_ɐzpgӡVÊ Q0"߶`v[%kSoŧO3IvDEާTWr]ȕcg$e_BO)ϓf*;It] &48؟ORKdn[r@$}9CoYP%gtEuޔ=v΁P؇gGɹڊSS_Hg| [}%ow&=W-+~wi,UK,&,S?P{LJ 0-Ϊ@6 #r ]n눙Yȭ1% }u,/'k]ZΈpޞ^LL LKbOUF.ͪӘLƩNתZ|Ef7eКmY5<אm-CPC8,SU/ŝQ 6%qXq2OJ Kb6 T{|;|x!rM/)TSD7]t8T~8t KN+8&5zi-uJa''*$eL&q8zwɕ9齨ӤZ{["~ǚC0]BurȽӏm?JzG sy|G43 S)sO9~,p|*$q!^[.z9 b%"{Y"gkȃ;x\PY<0yi?GzEW:FB{!- }^]Kv;Rdu>IʖcAUߩUH׸_:m;,+Α5NXﲦx~ٽ{މqycg[Vh*QlTm!uafK0b$̂0_d'Na0!/(HDJOR\NjDs&gwNVJmS%[(P׵tRq|#ؙ7χC=/SxoIHYVGTeQȽ~t\Ϲc5th.UcKbs 7woHf ̫R깸 C=_c!D[ϽoGNf򏑚z1.'eQ֩-qT{aәE:ǩ+JpAՁ JWxy }RՕ9#: - Ĕ;y/4s6L ESٮbj ]}Wa}x? i:Z\Q1-@n"꤇pδwZy'w>MbQFo/ y|]WCEmٺcuG`:~ەNN@<.xA-Uh6Exyy#Tn3O5oF%xrgE$qXV~ü,v Uж M;QÑ"?m7,oB*EH!FOggSZ%((''''.,.&'%%('(-//'(($''#*.0KE:#=Ԕa^DoC@**N=F&4D> r$iב'M&^?Bje $*VV6_ R/iǞul=W/X+!oI6L5Y8~yCM`5? I ,o chUɛn!q9pme\+FT'9Ti$gZxInf快 ȇC?jQCh7n%lKi A?<=LJoH뜳 @Z$)Z5kXj}V5YXk[aVkJ(:ԥ饗NY{(yv{KyUW,IyN\ -O~c%crC#u *xF!~(:jdr"@Xr /U(0 sfHA7YT 8=-ڭ*Q1e:BP$bQND>H`^AVrjtY%c5|9~boXk01R<H`N+ifhyjzS$>Q!B1oa{J8JK#( UՄ!遻t-<&e'}lk[ҘN$n23d҅O?v#Iֵ WѸ@@_P/E2 Q+!s@}TxcxG47'wF̐WIg0]yYV}ƚ,_Dt5Uחa.L)22pl<4ل} /;6+5OggSZCvorbisD8OggSZ-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSBZRi91/0.''$&&%/,(##224131/.201.$227յ*&1-ɷ)-J0JSsc`>%ыGˍXg`c$2Dg. (Ms$-h/|p m=2WU\{\m ڏTL,Zy>1_Ǹzl 3#:K&% PA.y{ЫjRh2W\lC0IVASzcT,vBIT$%=1OZ.'b?k)NicO;ԑ#D5l޾pF)d[ 5G"\;]?yRnz3ԕAw? '~3E;cC>kUl˝9'k) [)*ʠ_f*YQU('d Y<]˙zq4Pu "PݩB4(v](Kw7ust}yG sT$PrT%]ś곗RE#FE18|WcOD̶:4OB,ċy4Q," }8 }"CCgQoJ&ۥن Ϗ\QM. *וZu=KM*4ʏsGRHU-) %?w%a#]x8A `M@05}|xx 鱷CtSMeLC27|H-?԰w}a;ׯF%@ º=5,pP93pYX0iL`TbH8$8FWPy:%;4Z-0>-Y%cNeb88Ro銦6T:͚CX5do~&0P6VޅTQI 2X:!7N-pp3o{8-w+A*_ X)lE[ t]rbCm{CE}:}XVl^khUH{2 .p[}Vp+Ǒ4@pX5SF rB zV/2]< *)?[72h`yhK{Bt ⒖ki~j&,So0PquwiѣX-o=y=(5/Ugk-Mۍus1 t?kuvmpL 2o_CIXFUE+U g{w ANtJJѝU{B*y|}\"n#Uf Gd~Hj`O%222@ ﳟ~egWqL9=Fu]F~5v G @5E.+@6V%Jwn/ђӝ' 8 եB-+j"#5DԖ"Nǎ\+gy 5ȳ @U6/AU+Z<'t {ӋbL'_#iWóyŬ/߲0K ;{~dvjΠw0VMd C[Ц yGeM@n 3CDkpIƱxڕVx*zFc#%a}nyHx;C} a4tOf,Sq6j.k8|Ik"qI_HLUof' ]7@bRbS MHN`(7xwn}H{=1:fcu|橎N7vn¡hZ;jn[<=`r툧UJT+ =DsZT3ڒ4gDVjPן@&n[' dʦ&ȇ+쁐{U1x6PMi)z9UyՓ1'9|/ewͽ4|cZ?:m5(b(Q:q>J(3S2Q-cCmuzWu sw,ZG܎ئΑN9njcC|#:؞{s-G'~nS' 6 "]ЛOwBH{#ھbgD; Dy:.=H؃ dЈ Uo^:~ kT˅3d"4Gf/# N Jߜ@GkϨ1*Mj |/l@Q^ߌaL&*B=tCVH)y 6VXr四%IqIO;{xjlޫF۾UtPLóR {^& MΧ1nwuZҡ~:ܸܕ@%(gF}~Z?5/W1zWHֿqcT@?9Y!333\|>_B̺}R^4:nhPc^hYzCe1GhY9G<'οH8@+Nm@ݽ* 5> e UPyGM \> =Jթ6LB)o1ϐԗ ^0Qg@;[#!-&#(5ewkRR'  S^PE'獵o"ht- !PjسO۫ܺ$wMMSbL)k6Q֤1AorhE6Y$1ITHeDў,r{&hT|G"|-,-Y(Nݔ 24%Q]TVB(ߎ^CccQں1>.@H> ϨU`ޫD% ך _ ":@\^l/ڴeO%'~ 0&7.r1&P{c2Rsuy5D!9ju"<ψ59$̶/hEvN;9lp?t\k$JE^&ӧow)b;LHyߩj뇔l.&759e OkF$PsC,xgzn. _YnAN 3;A Il۞%~c32'U_瓒Z#kn卵9݋-=s$KʑwjQNz!&H2 C ys 4aE]MJ}_>N "tP{.|mx֐x 0pkCNkp{:S*'-VK N-gT<Ʒ|;3?dzP$'SvҭjJv>U#\"(O)G@ m0ßCN[({;m  $kLxk 4ռJO!: DUY i= Fkb1y98P I,$cY_㶖=Z$jg1jɗ.Y0>4ɞT =Ji. v_\m'R90#@r>Cs\.{nTąӦF):vmhTA&@Χv@mtZM4DyM]3kpljOc +'xi_R0xdw@{or%v>‰-n:_||N8SH=#g)2+ntw*PcP,6uGZW}m#5AxW aQxRePj8DjkZٯ:!5o|,NrN0"葞-!X{ }uAcZA:ms$|I1|9zVM;s^v|4TJl}fEڕ,ԗʦ)3!c\C iS2xj^VL:'V}h>6c^zիW^zs]IDn8!5t{էܿ%x拚NMYѢyoV!Z,f?-`ōtbzцSxzx x=Pfq|!\05ZV'mj0SU7o=HUR{Edwϟ7HJ|~bAHGVb1]üS d S>R( 5~pg [M&q?(=:Q\N kڗKo7t@6f%2<6!(2i+=2 vo l:8Nrz軟o xi2u"ހ_?m4{^ڛqsY? 0&P+,1yO{q&M?R}WUu'$5Lߞ<>]#rpcjŽ+ٴGB04'l`e 1jPV{ GM=̑ph t>N8V FCGV6a3qt>k 8NOb #'gDo\+[Ja*Wf|νb=L -UgՒ^h\8n=@^аb%!P1WݣSĔNqxE+Δj%K t}Tj,b;8 N~Pyz[m_"DfτRe ~IW_p>}E gcV<9G{u@?|{ /Z;,f?T59҄9"V*Z4d%YWTE5/6(/k@'}.>>W1BQ溶N7OZ:ϲ%0.vBb>`h:fKz;IC37>h7~/ ϊ(/&)'+u\AK*);4dK ڷc}K@P*.,} P5Js@v^լ0)" uP ~@eY#U7k .o"X $8PXT@ )T$}Wږ!f>JZx'zg# .˓4SMPNED{Y$1TϦ뒿7oO#t~N)[S˵oˡϏ/f0yܶ$ N5Ǩ@;=VRoOǾi -_Jx]dY$PװO>忋4jGkI 9A0h#Ce{`*5L=w{eSM;">jfk+#9{Zs˃*ٶYyjO " }Vˏ~>xENXZOggSZM'21%''''(0-.((*/,210,+)**'#.200.,2.2,11*/('$#%%$$(30)'''))*20-()*(*,(170C7q:6 3sc^y^reE!!*E챒>5(%LofiʴL- o Ջ>TfH!P&yX~DSf454bfn4i?Wn7ZW3>=_Q^Lnش̥X;͉e}a;#%onyb=>6iHt.i DyIs)'M6ql:9w)= %XiyfjSLjoܰ ا?UqY? 6)4jo+uKh~%~ٺI.,9bSd t]?Sg|dCJ yϜ5<!6B5ۃc/{~Ԩ jW6MhNsbZZx_)^hfFdaYD^'ӼvZ2?[z"yl(( hjom5t\so]N,_ %C>yGLX `:bK{1^7&$9W:l)##ls斗>z<_Ip}r&yGՃF%A 8=⹄J9è_TTDx:,`;V1Btl,mz;v%EYdȴ6tә~q <-ssﹸy 9 -0HmI4w2ʇ'2jƾvm=QG3$P4Y~xӑ+Y#|φtX~O'\ɂס3LS##?r3=”Oh2NWC:[E{N@P6茴a4 f _Qj@{mq9B[ZF6xB; !f+"_}48q']ּRr`PmUDb&#ַܟR$ e'[X`p~WZyBn ?usyύ~z]u]]]t;jB&yҚV/1wI*Q+{]L(IA䢴le`^4EʒU,fQRfY UsԩJ%7^y5#ٌ[}8&l=f_SM867p mMt218qpO^Μ>:RϽ}.Uh8~rGя mE+?˿(|ōڗ7O_z{Ÿ]뺮A'.3IL=OouT,amRux*sWoP**̤zN_ww^G.eD]_n.r i#U7<]nGPTZ#wp+HD>=4@x6'G Gϳێ|^^z5}Nl H92*2/ǣa79þ8f٘ZFp.n s|@%^ɥτS!333ВOt&aF?$////oFӢphKÍɼzzѶi 3`:2n8 n $9al"Tmm~uL$YڙEh [)h; ䷃'<Κ@M;k/&gzɉA")o2q)I2UŴnBROl.Jw[7aaW}N?*=2aP2mRtO{T8({tT+q`5?y<]K-1j,}*vmCdsi?Ҽ" zsE4W쳭+#k <4\@z%k㋺>Mk"WոɵoIurQ;/xǐ_e{kaf|~іpH˔k;#e@tJm( kCƞ`Nj0/YFnQPserN4c mw#Yq9e\׾*̆#r /N< m7q8#YT@ P/̤#7!jxuwvO/$orHkS@ hVyjxvV2 @(׋?ȚpD$^jxUwDMO5-C GQ_6Pjxn$W' tv+[ l\)uIjxnݳI 6m~4B(Ē$ hSwt=@0ЪKe TtXiP=s.q5-yV^f5[y/)ArĶ륁@ܳYmm&=5=Գuu+ğ-649#kG13/ `%VWG1J,:Qn>y7,%򗺔FjRKJWL>Qo>wi%-uAF젭WJZ;'A'HUoCP='h Q&%3 %4X(!nHG[^'.E^$tl4H uW5dğgO\Il–;P4y%"AYbTQr&17㙂@.rڳP"N 4Qd6R% :,XphMgk2Zk9^grz>~O3Pj*З 76sEj,'5Hk3oz&ZNxA Se/x Pr(E4+ηdcӆd[4S` {` zyt M[@}~6Bd=Bg`wS4ЫF/j-@ SyLiCMsJ7J%Q9hGk0{* ŬkIuǁyxL Hm]9T?Sf @!;(97U#0Loߕi1CSHuhpj<'8y=_ӎ`'#9w{Rə9`ge 6wea}xߣZqo2LE)$XmxOֿz)n 6t뉆@}Q(NOggSZB;())(''&/4%,3.(('%%''2/3413,-+**.44310'',.,-1ƹ+44ι&--/+O8z5bĥ:?@r:R]MXj') K? ߟ@@i4 4)bpgcdpkZf̉k>&2fns?j]BbĿ}k=zzc %4A)\?,2G뷎[ gQOf_mq4@eq3 U([`o wFbݦz[1"LOlrzݣjUh?jZ5nS6lЭ xJB^j 8 ;1/RC~W;?&-v{06͵{1 k1 9T%?]`r*fٙgHߧg}7 WhEsaZ:Aڻگ^,$1:HENQ(5ܬtK*@΁0+_t11Hܩg 3K?1/L,3v{XЗxW7NƲve?8 ~8R(v[h w$ZF&\3U8f/aDjf쾾܏F(j]4ig\{]#)xX_IR{}j̩>~SĄp"DT %kۚ)Sc?թMs)_Z^pL..u-"b]}F˰5UUh 7f,y(^/1!R>p|v! Mz:M8@{q16~]@jӥV~(yq91T`D{N }fIݳAz}K@xDƼ)!em4,1.)cL9ɺq&{yL&u hɥ?xNU'G'@ho*޾>$ܳ8 up P=Y钊20ytbZ`k9(c@0{n>T8".ΗLݴя49M^F!ɒ{?BH' Ҍ.mH~)@a450v=ݮ] M!w/ r0:y*sW,81 D.-jX&^&]wu #DH α.Rc%Ԧ(~rH&2o І3DI-!,{Hip+_tf||1 ΆgoKn2,qnyVaF-yF/v/A4 H]B~*Ҹ/ QTr., oBhK$"W/?O:8T7ݒ.<u'mp|MB~{k*;RµU@Wyg,[^,ݗ)F,mBw"GkzWdj}U 8#.yjRݱ<,DDjcN~kRB×cmQYNM l $QBWc^.  3K!?_<kD[7 JX- :}sʒƞc|Qn/ +x#gDpm-AĀSU3( Z}{+QXh@sզMd1m@DUtxLjƫBA}CfOU/J/^ gjzfj4f%g_{{{ZInvXX؉ExW5мx*G~EE'1c~:"bYqؓQV4ߗY&]h0(-~&n؝&! ޗ]V ۠D0OMI_L7Ru9[BAzٿ޺rn <ֳk{g[Pѿ{t{6]hs#YsCgYxU;B{Х#^K(wMoodgLˋ{]8ؗg^*;z<}5 GEodYzJdy]z1l1?Ks#gE2dܬ,nazWx$5*#?Z9;1"a,ٳc4Mw|ƤЗ9|/PQTz=3o{ )g},q2:~?><='ي=ƞsMmM|S&\JߏsF$p C9OpmLSS$M}RjI-o}F_܀`:ɥxP^{黡_ t 'f'T#,2n_ V'4f~1?[V7 Qb7)ZxzLՈ?irl_>a3E|`z~(T<puuS<ݕ-%qsW (GŗRfw~ 3OEٶ]e\6cN]\ $/ûoܪO-ss`@_r_"jKs|(oW˝|JI@aZYDDr<$! 2x6eVI_ dNn.qw`Jw6Z0D^:p  /xW:wgE nX rD> N#yx:L0䷦=f[^nt,)+wY} `IxGY$~#,9OX>5{ω]4Ԇ;0-,)6̀?Fά^ ;OC_[$)'f}w#u BȆ nx!64zeY e>13#`f2,R+;|ɄY,ieyi.[ag' <߿UFYDh@[c\52LCnq#E$n7&c",íIحӿ&8|gϯ4Usu4EvtԀt.;; O!P"!Kl$߿3Dpt{?<{t]#7\9ӟ{,ݿ+,ߪ{Ifg3Ȣ?-ww:=Ã&g_g9==k0 f@HRq> hђQ_"/W]k S̎-ZW h|D!R?ӭyE鉵krRmt/УRکR@4eX'QuB*Bҗ-Mzoy] k:SN4a7:3_#=Y7{ilZ̹8l;~S;dI\NnEuXPj.^ݗfTN˕agAAv(ʼs4iz࿥\ vs6@|y{;c AG J n1kIofiۣz,^2_h0_=Z EN#cU=WS.gWPW8r fڞ o5"y߯nW{qXއQN@).\R(L߿joTuQn|YhVj5WIj)Dۿ3k F姖rէJwȀ>~;NO @%)\n"|q" `B6 }#d\HϜtye~qΣ (_kx%q\K:yߡ(}Y˘ogAسe L7)~1R=@8<>c~m_0/}_Nj?Y OggSZCvorbisD8OggSZ-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@GZY#,--1(&-/(%'-.()'-10<#+dW:起-wY6R7*^5j >,ӿ=s~icV= g`UYS.(1f<_i&r`n'D㲷ߣrIf7 Tez5NgYV1CZ [O&#v @gw Y@8 h(|DbT35 }|!Qn|S1^Oh ':п+lUЕS%5SөW)׫ ne]k:H*\g$&ngvN荂 / p [ 7RFTG-𷪠%c8 `$0 [f~l8 !L3/s,Eu g"ЩV`ԊEP&qJ j_(" 3MckWRy[mD m;\w [ Uh^+0@p (p 5n2ԔG+@O:`2ӀDB8|ܕ6 `d 9!ސ5Z@\eQ @ͣt p zۡ~*QKȗk&2V5\v&ICi|5qLӔӥ[ 1cԡIZ wg[ (, 6{v9L/k0 qz־ocGbhmt Tk=r;{Q} /MXtYwjT5~&g{Rhx8P@W;2l1"@ @J׷Z$P&({4PND) q430*݇;d`xGTe-PW$ͫOnx0z?uo|43e9 @k[Sι*^Rc]7-DӫV]\)5(gQ+xEv"\-yRD G"@J/q:X-nNsKC;ܦa x > Ȑ`-@8(s#8*kP;ZQ Lw* F!7w *R3 @ oBX^bO 1B HZ j_.qi\`4K@)xap >-.< julxrh\@'A YA`ծ! "+H)hPr w-6'!Dc- @CiK4dt~PpR tHWT|[9C|rF[9#O:O_ c=)Nc=r@֨U|޾u K:'~$"e/`Ity=a'"f! #>: E in* ,I&ȖD/C?ٻD;Nw^랺P ZTQ n&rX8m^>Xا#}0x n9₱Hf t>hG 4,+-K'^L83Oc`C^迗F,׫.N `J@|dRJjݽI?_NDY$[uO;qfCj)e8y 4 W6t[]Ysu1_rr٪S`d2v/k/O+=1_BZ {#9 l3;z߾E%@\xGŵ9נovj͊ߚOA Ttɍx uI4NS#; 2@Ov0({6q*رc<vPc}8uydǍD"QW(D~99yx@=vi~c1 ~% "3 ! DWxKC&sƮJO`*w, O_g[;0` 6x{ @@-pQ(c_fƵͥI).`gWf ~r=%≂{(~wC,jt@ 8TkdUfJ̀K8 aQ#3/\rPh>g[($_Z@WeF~ : @\Ej}M`tIxX4 FP.lݲاTiMD qnQ+ zӕ|ӄ W t4U)jX; KD{y_L|}TAE.M—9$M:}5O[.|CzS(vP* ֨ h2Ḓ:' j=`}W h6NSA,,ZĿoJ% WB@Z47'9v1Kp|*[xҢ[4{׿^sծq'&&@03h{ xctoX2. U7'K̂ɃP6QcQ[@OggS@Z|'../(()/.,$-..ٽ,[#@Ӎ:UϘdҒ=/`;^4oQmz0+I ױ䘌&bkGlYt<ݿzuN(z8>\۟XÙAD߿3ʞ ƙsgb؆|+>uh#=vTR&=NU]__u;T T|&8(Q?qnZ(egP(Bcʎ?׻-Gq(i %e@ۊ}76 hR鏗AGs W= &MixJ$ L4o ּr2/P6h]f|UYg4o6UT :"˷Q^Ge7_ ,oTh 0NpkDb+/[ײT*$oh`6@[hi_㑺}6<0L&&da]}]GRc֓Qc{ X+ \vmFʹtǎ :ڵ!Ds>(?2vxY*'I.&\6$^gu,`ؓ 뒏"Eche+ H)?[sϵ/ݾ:VW4O "%VTuRpH3`S2}5RNiU%2n |km&xxzg :22!b:7+hEJ*q;GaV׆) ,l^I&'ɹF,"p  XNx &pw@58Lhlxp?5 R) .#;.`OTnQj(4"9=|AU uJ-Q )VhP@~ݏ \;7 *)//ᗅ p\wAkfvKLtlʝ%C hT~iIx~:V蜃LAN,p6L Dz>bTk D+,-@<9Gk:|k$X 9@5PKuZzʆլAc#@&PG,M|[0Xx,@BԳ g xlWV)f!bA Ya:ƀ0qh&*`jNzSV]aA m|`L)P۶Pw$S1kCͻt3@;P[{6M <&pzx[&x] `a&Ri~WѶ5T奢A(;U5AMPOƿ^ա\į;(FVp7GAW @_O+W p@@B sضeQ駣~,hV5Z* jMw'K,p;)J>D; -ہmP+ PRe?uxYUMp"L.P.[I@ ]Pt-ߥjȸ Gb0ո" x( ܁1%8:La",t [ӳʥ_(0 @X(glΆ_0KrT" 5j +RJ'N.+05_+rS0|KA "?z` cly5oyW%# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS7Z_M-,.1/''0-lW>OF, !Ggk\v(>tn"lWޤ% x#ݦ>gDTCZtYrqIpwM=r<%Dg|FkXɽz\dWQnrOw݄XY ٫RE{?Dܽ 5QiPb8X "Vsˠz>`.Tk GNJ=D@5mSDlب k7t*j= rE<.EjCM׃cAwK|ZSykMKPt) HYJW۰64ڱU:@E 'i&l%mx& W-s S`zڵ.D1L}j OJQ<=Epo69L !.ʓ8 'w>,Y}}e#V@ȿJrgʊXѥ)ni ntхIWwf,I;RudYTl[{ejՑv ZƼє "D ~cX`A־,Aڅ p.S*aޫou1ޜ8ӆ8w(`w(Rw%Bdp/ h)bA5XЧm&ňϞ\B_ чrk<}Q;ޱD*ϋ'g o Fi漤Ng D,dz!NX! `AZ{g *  Ɲ]F)#@ܒ*SKd$ qx C4ӀڍB~r| ҮJ]u>_$C>  LQVh/Y,́QD` g7Th?8 ;εYQ(o~]ÕSW>Hl7…@eB̠tBB  ]H@v&HosF`)tӻ^]-x*n 2Tp+ZFOߺvğ LU/58i*l|(֓p b= ِ>&xD "#G!; ] !}pP'K]:,lv~3we3:_٬Zi_,`,3|Yr@nC D'ς Mx@s AEѮ <@P2:yl(aK A@r-&ZJ&@ 섇)` gl6` Hx&43$`X&O@5 ۆ_e>P> -U7؇(EE 4AOi@TPZ6F;:-(T;n|zd(Ǫ Uq(n} S@\.kJ7D}R$-&"G[T@VBOK,XJ$Рx,  AAX%ȗ B \4yH ])(@@w 8j50 \MBˠӒ Mt%|P5EoV*b/) ?Ji-6i.z81؀oT~TDAv >0Ģ^튫] y ; &=TȀ#Al5H`5a?`I|`N`֠ L]a@X#G ?ku(>(Ta}i9* WO pvxEP5BD@,gA2Nw(pr( 5vYd  +/Z# ;=U0/U!6ܨ L&*:tvTx,Xp\`Hn 0O a&}BzFA"DQat xXzK P@CwJ ) N*m@4}S# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@KZ./2 MϪ# a1 ;ۇ0alo\s133mDUʊ]px]5|ڷ:]&n qyTTa@ݽWݺIR߻j\?_KН۪1c:jFxPZ_p{〆:L@o p @`9@qнJ1NZTI54Dޓ x%5s<5A:I$F oMn@Bk~BUm~n!J"l ZP-y"i M?k+4K H54ie&yj pfz#@6 2*`Wz FpIPZ.݄*h(] ~^&bPx,p%/kċu;wSS [4G= Itxt[p(0S!+zN!pX4$ r"uƲ]l,まuΝ@ ;@QXþo ZY?ْ=e'Fb'Po`su2܂ >׽Zr  [C \z=d00@5da,K<&am|co6IP"tdCͧ*! ~%tԗ6l$!zxVP.Z.c"Q _;#Krot(Mx@@~=R@_;n0A5-~i.N"8AN2 @ \S lBd(bf=v-ꡲj3E[R`_@DN\Q:"5Hj{iDWvU$J;tݖڇ`O<U"XvDDc_ @_ Pۏ+@T)' ǫ:'=!Q2 ѯ@9i#H{(2AptE_VึeƶBZ>b PpW@y*LTŎ@2!TlXYK7n8}6i`EG Ake^tO0 03t:6p?N0>X1ڊ%ʄ頶;_T #?(t67O/>:Zjf!I _`ϕA얀 ?'l`]j6Ifo1ӷ u6uH @ʻEl (]۔,'CeX?`/+ٞ!bq&ncQ4OίP?OED R\s =C##6pI[I$ %BGS^tbzM[L` @`PYpBfAIkKI\tBoPW)B}'x)i$ nK?$N l6(W y@yms>a(3N ~T<@o߿H9ÑpBt 0 k|5\أѝSvz( .~׆ :PQH%j[ `]v ˖0,__.0- T8]~ޑ*n.RP{]r9/.ܯ%TY+%p{T>X-.1\\N xx'6@kLFj >zbL5ui@ ڂ.vSxx_՟O'Q~~7w]g{ \j9G" GL-b#*?L'DOP*~@sl18>Hસ?G!xnt6 Xf``qgsP+KoKdjg4pVc v}Ǐ]옊T?I3XoV!΁h9}L(mj]FOp`F@]X ?9B|@ڮ . H@ 2@dVY ? .ˡ10NK@Z fu\`@. HB_Kk9(y~ @[w /A>P{RѶ B* %(!Jk@M 1-+VmNu(qnXɲiWWn|o-A7N`MERK ݊g޸ޮĵ$8O?_otm+ 0 4xod`01g9U: ]t(^ 傪GTJFCR AjzK`C݇*;51{ґbwKUN 鍘4&YܗJ 0! '3[ ̊~P.~^%C_^Nõ ;~dng^jF0fZ`:ekZ9m?#is5Q[ǨI8T4vv3vh.1xU(M4]]U;@: #Okl*T P@T;V6~ҁC@ ( X>HTtaE%Ra4co8|t= ߧ 2,Pi'3ejs`rixʥ; h>R8k `5~ !HC#Au&k'Aʥ{): ~0^%ׄsv\ Jw@K_)@OggSZ}˾)'*'(2.,,02þIvAz&5!ξPW  6,Pn . d8C>#o (^%5z9t(2X^-  /gu%chG`$1FB5& GlOIu:$Q%^:TZIE~_1jq ϩ OBT5 f9qk+EP:-"'Fn|8BTwN`+pwG~9>yӧcg-߷z @_H0>50I< 1Rѵ0Qhgkޗp'gcmf#ONcX`-i@.?8eY&aS2V o(|>G78@@^IV8Lrn3F z }5GC`@hEp' %!6sؒJD#!%tWusÜ@[p= _>S ՠD{C[/as$BVSP< p Oπrb9GEh dɶ?jǥ464 @'>o^u&ޘ傺CA{ p-pHxs\{Le z({p]>i{s^v|iE |ˡ\+Ub (@^ϣ(Wcs|n!bٮAw&Pϝ$#d{?c"O99?xPQp|){ XUEn 2~Dmΰ5c @0 (@:CExV8zvǐfdJC?v/ }(Oq˲RlplB'GE1N;(A@( &y> sqWw7{&pu/Do *(yހ;CbX<}Imܞ#*"p ~=H8j7Me|}_p2O`R [P.lqG[~{(?uۥAQN>  L+$!ӡb&56}!C.Iפ[%rJ'>0̠1%$k sdj3@D u5jbڣ!1*-%c-8LH(hdñ E@G^nP1|qHP3]_,p@E8y~IX 3\u]ׄ2_YG̟W,` @0EO/xZN82x7ٯE**`փ d   ^tqQD|_hIN d '`!X!.g%*[=tؤ3jh)@N'Ge)pn3HۂGE * ֏Ӓ %M2 wGmXlx8>]sd,TL fPp0~6w6g)M_ǹM> 4+c0^e@( D48v1ӲY?" 'tpwF{V"´!(N-<nX@,]N0(0,a y5%@iy$  ӮHe"Į S 95;b8/t I $ c> CN֐*;uj.:Mտ#XtؑkPrE5Yndk- ]I&:כQ[ŅYEMcEY(DNo]\O$d&g]G7Azc"p?XA}5e z4_ F[C!ƣpyv5.W_}~z :ATiW먬w8|0ՆU{(oJ}6yg*FDTd>۹74Ik$ۖ?-l'GQI<{$끷JUop`++lmX&ػ@n5M^<'M2`\$&OM mKR]u)C?4(p9٦ign g^_K @A+PS+ ZlED]P|F,yJ2aO=gah#) VV@u*,*xًy_3Ys5<49E% ;(EP@"9~c݃˚B{Z}]f[OP=eu͜$Ӯ"}HTo   8YŠDv aؙ7$߿ӊ<@%U &]hU6S?03qE!<㫍OTܸ \X_JbәOcTXIᗆ?ٛzpS'0~/.I,!B( (kJ*8yAO3]{SFj*5$G_gdnGF_N  U*dtByP_erPbO+7I*x+S`o8Gd}5/ zMmP0GI%Yg|QQCUxB^/P_XOggSZCMvorbisD8OggSZ #-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS7Z* E00+.0-.+*201('05,+'+(//3,33*)*&**/32*--/75.*413,**1--+,..//85/)n )a"e3{ijc|!ҽ@he9j%?n52Q0x#l4ɯ5T{ z@iGWɝ&m6ܣy`w! sж#mI$3.7 Lk KUInGAy$RqZߐC8h_wOf ޫr\:>Ǿ c(.]g d;=EEÃX1[_3$PK{33DP!7!C>~ʍtOyL?juIH{>J  @M#Y%kYE\_ i`{ ,2X]!D(8MXҠxꟀA*wk9X,䨊%V;yBvy? v0 Hc  a6盅ЉGƴgКՅJo?$V]vI *}2TY7`)de(b_cڃuDMv4KǔU a?{oX2:qQ2a;p.wY'@K(XEFʰ~44 TR]<:^:P`Nրn :@In0C^z fàY1|@EOB+̚QHA `@\mU qg.QS7YH>` f` }j!Jvz6Kӌ? ǧV$+"`fnwLJB)q>7NEꛘQ`\ l.&T@r7G7M{$\(seb|ܔJ ֗7$ Bӎ5]NFX#BڴTfm쏍`pLzkg=L6]:KG0M7Fj%xCLR ߩMTs14ңޮzVbLD"`n"˺M)kajA 3ᶆVrI SA[<]wskwg=c1 36X5ǰ|:psDv^5TQ* L<ωPE1 /ru[N*POVa@JG>pӰb_WMUWNWֻ@B[pY |4q{(1bfBq;O=T) >S+R@`E@kG,2]KvMV{6G^qҦSCs [ۛ-{,FM\T~ !$;H^j 1%D"j  H,<#yLz"Y*2XPQ;'M w5?CC4Luϝ{;eL![>7Zw۞!DJv_Z˵t:RC`jxX' mw*rtNcC(%tk$OJ >|<?n˱B*OOQMI@]ÞPV$}qiOD-Q |z}eXn =]<`p݇=8׀ PbPF/qn9KUiX ǎ:9iHUn?/M P8,YA HRb߮w/2_RiJeSgN`QIpTH{u>|jOؐP.KEv L_`fl߶4 oYBuRqyV NQv= 7X?y̞D!HzSD˛2E^whVh¨iӑ,xOKD K>WoX{,N(r<2`dyw*!61I]o\5lX,w!STL#L+.$KVyfX.u*; dx~l\~gYq1R :7Vy+v|9ХYvI.=PY(o5qQϣ"^:Ш7ﮢ}ϓ_߭<< 6Tߚ Q/e!/oq߻qa JuJؽzc}CN,VANx%U p 2%wּl":&Zզ>j =?B3׮&^4\ z H!D: ~zgQZU4^{s> ,4 @}*L]NZ95 ֜L`gMCImwR9FE";V@~/83  h8ZGH,YICAZZ?~'<,И= a x-%{{/>KhHT譧&%{LjM^5FUp|O]n;&@{h5م{n|{^VAJvk?Ty[{įRbC{=.NތHl(Ap(h\7()т?]EH8nyDȍ)YVmɑYQE~4zOJ6 LiDTg >'1hC[!JkUPݹj Zs5Lpxxڍd a&07M ~b5q0ER. һ} aJH" 1ܦ> O ȿwT^RUkh hzg/B:@DJ{GT3*P^;[yN%׺EUGǐPfi..1aM;=&8@I8/HiC/E[Uz [r(dA(;`xX?i(¬ӭD%СKr-##^8Ho $4cxcHEdkD\^6D!uD) +H{P=MUO Dz4]r:5.;|74B9g[*JCHrf^Zs6jW;,@ TMmgmzEV',{` `FKOggS@kZtLI*)+*&'2/228.000.*304**%+'&./215664321125,,+)11002-/,.-,32/0134.,4346ӬXrv5@oS2v4(# vUx މH du3m|dX5fqV;}K u<<UD`ZusOzN8qknQhCÑ] T= LR6e 6@W l ޿D V1f2fǙÉ TsU٘MA=x<~8ب ~n|N4d |ӗJgRk,k;P o 8[wOcUy'5u{!!,* +oo9@@6iw,KLF=m'B߷rΗf̠H݇ {{ً0!Ӳ}DQO;LMǹ2 /_L۫D<[ph/>Duϛݩ?ݚ`7JX{=3s_=Gd^aoiu|U{,!Ms}8{!=tsBsSm^c> MnqPH$f?ǒzb$;oN\d꼱3L֟wES@fXnV6%:G}NjP' #߶~ <_mXי` j{!0 [{D/C=mU%p9U-VeGmI&qi&yɻjgy}֙3haeC,)X:4=w9#ᱝWt`>e&KQkT%Hҟ9Sb9`ln.2aWҘ~;xI IQnFP3wj̋G(|YeLܸ3U*K=hThBL_o CE=A|i6̷-#zt4ˌ7n߹5?O<`SN*Ǣ${y_*iA 8 ^][y kaI: l!g97F&7nxߞ5svL~(˔hGԏoތ)H^*ܢ8Mlt\?«\ `GZ~<ک->T[/}ȭ +4d~\/@$9*c$/NYgX˿1݀ g?k9ZK7GD:>cq=Qn5Y#% \9zF4{wlzUUJ[d4FlatjGZЙ:^iD_#RJ]Qv (4%r OggSZt#(+),-,*00097.4423.-590//.55/^W%bdgTlڃƦ]o) ڋi4!x& B0$.%fP7_и=6 Td_w\Iyg7@o PzbG*pP'PCKO3te%*>,"l;:ldESȹPFH=j\`cpO0//0 ^gE giak[ii%+%GmC%N뽬?(NU7I4P37 [MnLToDk܃N>S_,N@fe4TMT PAYi^ ( 4:"nk;3IBPM?_2(^'%JQZ{Ѓsb9{ ݝ?Hꘁ9Clg O9*~G1f8|9T=vSx]@jU :dK[aB=XkŬ¢HeWB/ t$<8޷@韁/H@&Q/<ìE'%q U >S=)oNbڜfYhV dC:ߒܖ|.*I*RץLđV7LU¢>!K GՔ/t U*)@]ѭSpCFxEPPu #^!?چãw@#|z:f0XhX7W;AXx3JT >teJÞZy,յ3h\4sx\^0쯿][Sb,?[V3ylK0N)PkA+C8Zq&2t'ZOetr5:q=yJS1'^$!M*hk~fϓDF@X_@: a6A}|q_tbEB׵ @A&pdRGrR+p}j{s{vQ *F:_ Ȍ[ڍDM'U)*ہB? ,YޛBG@U}f%\%wB='qі!Hݠ ?.-m ?)vfiJ<( @U*j@ i:!s9nz9`{_'gn;>.6R73N9Tf-&Q0n%+uNh+B4pth@8fn%+qd]]8%mS3Ą'L=~z0ce T [.,2_HdBx.N觙j5,Y4xudd{\ _ !ʖmX8oBlm54Ci_;j,DrxŘ,lm< 3ģbcZ9)[aT h}+1у #Me$Ӱ緿}_N.u}EJ^W RAfZKa_ȫ#,K.fc\ } T3"Wo&`@PH>Dh1yYRG4i/GsZ.x:_ֿ / _npQRpT]` p4;hLA4H"@@l 28Hp3r7,p X/ЎK&g^d\oFf ݻ'?K)Z'}׾CJIsn6D_="tNOJ5Հgef'_ ML:9 ԋb>3m*%Le ˀ=U 7ഀOggSZCMvorbisD8OggSZ #-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS^JZ1.Ƽ¿+)24HY?gWrr.~*#[ 4?7=r?VH3;OTlL+OyS#`ϵfX^(T-#0:tz}6ْM'3F~vqUNR/R cTgduJ&TVXLFBz*$6;ۛ:ZkIp`qc׳> *8q@NX!X#г ,"<Ռ3x@'I.$Q/Y*o9&DS>]$cp\+{{sHďؖ;vR_W_{}F2$~7%3͚[/B )[`"峫M6[MֈDS"r̴qz-KB lIAY٠,a}IlQw,85K϶i҆ӡj]HB Ga9:kމTXŮ&B]3ȤaLD1\|?"+:gnbuI-/AP4뾓{y}ۣ} X8G~DJN )ءdQ"h-mA/śPtslc.g,hc`1}N{]N@/~kz__->܏JzĭK q)RSUhm7«Ϻ]pWד* PEuG^3=[΢k 41ywsB)]:zH1eXt6{/E1YY߅'tp w,hwz?ԇpyd]$ZK$ d.´/ØJF_~ާh*!4>""s햇ctJÕdZa7Pb>zȽ.VtϹFYv VT@cwU动Ye:OJS^,x6Is6dIgD ˽nвYn>fnՃ~4GyD{,2r%cMЋBz|U#6;Tv͞€@/XY^G6@ %]4{]Q`ww$4.y}eEخW>;!PWKDӃՒߡ8P3 ✿-,چ]a.>TgU[ 1N*{Y9p GtcG,TDHTzS2Dw`u^WN㳡sN̊:rcYuU*,a>h^Oˢ!zc5[M+IRm9xߍ.ϻ(b(%OZG[dJh} ay}T(*oHRbr`1 ` {sVl!|+u/dkF94(cmD~vdb=i3gQ{yQCG7%]WJTu9=jc,׸JYM 52wB߰ zs+4옪zy8}灓Εy'B"8zg#I[0eFC2/tR\ .@ᴞَh6:.}Aʳ',ovYl@AV*ܢr~asbR{ A6ވ ;q?^^RX~q\ՃPvqp(фT7 ʈWKjAPӼ@F<펔EuZRhΊF}&Kqm/AO:~.Qy4JMSD[{Ųz G%e}HD?Ry}e0/J14"ɊXA^$T$ݝEeJ]A_mޖ~P@7X2ˌ{s$l"f׶T8CgVq0U)8 サ9/PrqP# 1p}D3 +`KgocgR aww$ݥ$UTB [1.{ B@f~SGZlT*v3ҍ1_HBKUtf(z<Һ93 ux7m`YQWR z`%v-{=:Vjd(~pŵE+nh0HFxV($g ?D5<^yCD(OiKjݺw4~;P!}jaBz;0V Ҵkpt>aHu?WVoi4qOf+P&)&l>NG>8VTLsMg97Si؉:4+֗*۔|ak`|'VHgjkh#s-FύXnyh.E[1".)skix }f0 о5N%'FӒFHkItCL_^^OggSZCMvorbisD8OggSZ #-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSNZk01 3>5!L1y$K㿣BqΗȧ$Kǰ30?^79jrXb ;z, B'Pύ^:< pD%CӚB:CCf- |qfj.$Ֆak@##@sulo e;^@Jun24A qBB"/1 V9 EfܓҾ%J-6D+}$rCa&9V8U*ElsR ` ,4Pxw5NFZ%2^q6O`g]Kv*F7l)m /ʙUYe-tgns@̃j?C;_GyOv5 l*n4؏e#v@9LY}oZW=t|xP|E}l>e./zx-T*:}&Y0q9 9$  !ҢA0['(xgL1t0)3PiD~T?bۢf2q} E:.MUu6BZ)J V])XL(D_Y9Q|42O]-/@}/\Ꮺ&HwQ>S dx xPBVog e-u=tWG~:- `j3VB|m@'.39% dK~JϾ-P[@cUޥ4!Pn}@lDXwZ1#`4,P)]rcO/ 6$9 :?xiىUtWx(Z`WLPusp70Q `PìiJ.TZp5Mэܑ:aDX{xv5񺉟M#|0e}'fF- @^ @ Pbo!l&_* IV+ZV~Bnor ;4WA.,y]Q.rL 0ݛ`NGacwج,7'{5B~SW6Sj-%TYFʥoVڈ"qddQ0!dt94i+@ -qW+{h^{a-]_QK_ʳ)~GBKkU#|.\`KqnyL>-Ph+:)Jٹlf:JT]"@.Jhڔ3M\m0U< U>euJNc3p{;3*`Ka@h&ZYߘn!ꬩu$^}ڗ!s9LpaIԜ,}8'T+dX8{- yG&͞,MWsi"ЭY^w@ò텙n;?M`9C 2CtX c`,5$ A?rv4mkm , B{uQ~x ohiyocaG@ hhb^($~NѨjxgCH2`8l ˨}-hBو*鴊1҅XXԼܱ T]nF.8jrf2bMFϞ=~zQC!MV*n]&wo@eXcX繥35َ5Y?nTBVfp8M'uke4) G3~t l` W?X7vᶒeV0zB)_zm }/3 }? Y;'MYԗ93+М3p&FKg~z-`QH9=NLRuSvHI].C59zc4w]D-yI6_\3P*žn]@~,Bb|| ~kՈp|WhTj7:+Zk ԬfW< mEl: @^ s؋y̛e>*΃!d.Gc9~n`JkϦJ.l!*Ӻ9谓<WKyTd[ZU]_5CwjR@'H(s3Jl;N@)@Կ(@=p4 غ=S d",XY!*%~VR@3XId6ӀX *M(VU3:wH]] "PO"h.kzgc O@J hbnxey>$-  Q7T!/KXadm%k+d;Knk +v+nNL܊~BĈ!ڌ `g IBw++ii综Ѕu*ѕf 3zM`̑_G0~wc{bN'PKF:mBQs;jSZ&ݓ42 &ENA'4G;aև4O2榘#6i)1Y|XPdfj!IЋ*m%`*(J"I5'M¦ɞ i!L6(wt'PR!t$Sl2b*~f_(Y] ۂNl n?e>Oq>P$7{[̭B^M(YP{uA!湙ձ5@/vs^,|8zf@~_xaG~W7!C^;AIY*z>팤AŹ&ѳu:;B4HdCg1($%?>7jmv=ӝ砖 !دE8_:aT.?@t yieKǩЦlK? 3%n͠߹,zv`cM.b5`A*F#@Fpte5`>@oC>  م}cџgFud0SK n$f5z_f*[hB'  kSDydw*yK,tdD׃jE F׎DI^l=."% >~ukMw08(${c)@ uVlda:MW&!~q=7i$g@I!3_^Ve,?,orNR ĩYm;p ^`-T)2*A,њy71v+:Z0Yp-ݿ"ICٕO|e[2+IC*b0U Q'C}gC_<؂FY?n@.޹  7tOVЃtKًl|v'oO6`czU lnS9 k_~vm|2 8M橔R-{U l`.SbXLVsao>P(x)xMl CAo鈂N*w[OS ռ~€%D@H i KW 3:τ\.F( 1rkji;klD7mSvLbVq9݁rt=6{nVX5ZpigoDp\" Q'!zٵ aOFP57f=xm_ ^bJ,[B4րc5gZ$ ܮ5 W.*I7. JQ(0ÃC㉺j1(P[74>z- ƛ:"CT#;-[<`Pk= ==ńҀ:Y½p)} %sZO v^p TZ&t0Ԓ ֕5^Tn젺Zm+v"2a+u^ĊԶC^@(P@V] W2Ƽ%w#Gs4tǻ69\VϓYg)+ \Mw[;Dk\n0a-zJ7ꝗ $ٗ+ˣX@(jm4D)׀6zjc%WE7R2Z)b׈my bf?^VT5a<?FD:@mdJNS" bYzA ('@+e\\}"[ǏŪiFAA( x'`~Z-%6y<0~0G} kB"D}cd-ᷓ-9L?$ (K6 )aqDӅ탶D"p{||qGЀ.X.=$Z:Y}YΦ_85FVP&q.9;{|}9`$~S@N2c7饟HNHzowIM0k4p fd\n f o3[e=lZl$? $mu *S_5 DMK h=!~=36L쵹&D)𥋩8#Mk*t4A@=_t7ꖬ]%箢%t늌b+033 |dca3%oͧ9YFTJ|<%K(G )ZC|+5Aq"j*1(U&@7MohnUxI;pֶ^jY ^G{WRvHWH7]BZpO[Ԍ3&r hq?cA^dV,Ɍ=CRTS|UM^T1ѓwssn_aɈrɔ1cg9%S|jQ,m@@~zY >ݤ=}%؛FZ|@FHi=k{[|ԐW˙*zBr2tHK @]Z"̥]M/M3E"55\]2Ab`xtc߫LMs] ԫBGflHZNa.@V . nuL.MZZD|*eQ.q=2*_l%,{GߦZ'O@bju J=U(ZuھdDQ:?:TChDw5 4pG(j[e02 1vyj ֠j+3qեb^-6x#%L߆JKV5?lM@<Gb|9:$_\_GdJB`{P͸8|﹵~Ǻw>~_uCW CTFJ0 C rg?ΎK+mzȍ1Rd_8 {KZ!5@%sTMM{%0M ge v[plݸ8~4;'B7Ll=7G4Heq%/Rnc㱹Eg o8.l;(ǵK*hv"UɎ 9 0wR6 CC m /\áY·,avW|D[ yUjGW19ZBeyt0ΰH\; aO.df}-<⼨/?O,iQEBӆOOO[_ʰT Y>N^hT~GRmx%_h*?SK^/za~Ԧs~[缥Ԇz OggSZCMvorbisD8OggSZ #-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@AZ~_G32//&&*0../#+..'-0223((//./#%$$#%&-,//./A?@QyNxu 05>0 >-}Ѳm?A Ռf<{ MOJk~z BAsLӺMyLÔ01L3gw:lHX0UQU7GptX] 5%|^`TUV;ʼ#- ?7Co\EգdWL|G(/מx%xKXϺ] :Yn6O5LS; 튇8y]<=w { R]v  => q[(V>%9pƖ9xg\)Gz!#8NTr#Ǵ&mMzS;^^݁V{,bsQ(mapZ>M*&1ӯ/0n!H3 |%IJo oF_D`VtVíj *jp~O< #8gW)  ,vߓq 9powtr3`E=#|D~7F'3t=8ƌ_H%1%A[LQcJO\mR4t_Ԡ'mˣ*oTO!J@R +RRPzTPz=ӳX1]'` ЭwFVqV`Ӗ_m @ pݝ(6d:L;54,LeGs96$N\:vq8SYCn.aj<;p??BJMIP4"3!%^_ݚ#uڊ42EP>Op0a%rҾZo>0n4ϩL@@U.a+[FuͻMYr쇣N4kGB:r_3?|߿&\oNIrVBS%"@܏_kdhzža)Vq̱Ku j /=9˜>?5w_k7nԠYQ\]ux ݎ-omW驨V3j2=[g&}w \`mK"T)Gc8dQk[i_|=: V1/)|8wˠ `3:N=ݽ"3 ~]r"ZMjmtyj [?knHq`qnN fţ~V@uMB~1LŤ3ŵh0W}s>oTĹ?~U|2n `{^$^Z_c2bX v|YxBu*_W  ^lYzUKr=M+'BK{a8.Kk_pH$:?:"C=|}49@#owՄ3C4 i\Ys6O J.^`ڝ^v]H1.|y}117ciQޱozXmkP=M '#'n!|d iǼ 5@p 9@b4%`uB[Iwwuww}9^czqb|^ҐiNGRQ*˛x ]Ipo$bH}KJΖk% t!"*;b1MABֿ mQ}rR='ٿ ^LIF7ش@Mk6n}O Hp0%LI.UD;:у `/;LNIiau\]{g$KN%nwn LI/?Yf`9e<qJly68&nv{x{o)+/jȼe`YlSONa9u15/j?]>"@Pr_>q!L <̩ sʩ.  1_yb~y!0_xc^jR䶷/S 19O+S~)=;Z 0*LdL;M)@F&V`bUL,= Ѐʒq_1 oEGWb DQVLd-@ojf5IA݈>C{NGМH n̟nS5N^)DL%Jqk9N3~]8pl u:aeQZl]ҜaP٫ppWScuܢȾDPX.' ͈񦻾t]ƚ%K(}=LqCnFG2,dA0UX4,^*!g`#D* aWĘm5t3\#v1vB`Ns^?>YǏ'ދQ63v8L̞Y1qUMvy TL0w3 dx)8$4N J>E4U//{Xb++J7A2b@V絷~/0%L7 3,Nq$|32v`[MViawB/=L70CN[\WYTx}~3yFX٩ȱ=': YnwTwD#~,qWR2xPǗt5؄9yw-FD}'#_V\as:H4׺^<܄:T=f畽_^$*/o^ %fKC-B_^xtׁ  $0^X-?IVI#֚mH G9XYBi@Zy[btz^MkaihMdkkTU0?sTSz7M@gefpVDJrd=l oƲ FPغ]N14'ی6P yNG5W#+! 8] `W3f @KFK@"8u'~iv/> 9T.~,~(Ek # e'T{!@5JDz댨yTUIwBTp'D3_F:>,@@%/11o7hO:զ  ru'eM˗:%#_ACTULؽ-_\Q\&js=\v3%tc^]P=#"$Ϝ%<ҷs }BIչ6> L܃84Z#os\,zXoEc ӺKb/^]bxHtyeDq=^=즭-V(ƲV!ŏ9GL}YT[^jFG$Jt>Y*id C~N,Rg-R XX| b6s<}+ne/#;';8Dw׋;ѵRY*8Fkoo/٢~!t흦C2 -A73j TECΘY?"/eip?ȋPUt@o<=]}qΧeH~ g:JN0 =#}vvO NhSN={$橓ySĴ4/F N-i:4 ƧD#d\{FL6?c}V`S8hr䩌HFZvbã+vsȒ>au ʱV39=$ɦUw뻇'{yw֯aۗ9+!:Iy|OcQr3nBȮƃWhԓ3VB<W|nHf֖}}VA>W|r?VĿ;ʆs-'k+Y2Î􅒆,^N?3#Hؙ^o{9*>dP}|N2?5XrSF_4G=ϩT[+v!,Z.Ry h'VرW,a"D1y& jsluHy5xڱz/|u ,TUPXם#%ۭOyA 6LDŋΰv$U{bZJv 뢗1q~GA/b Z@dv\p8&Gu3Ԇo LΚz~үK跧oUvlL70 +8f愞u3ǾҎ~fJ,Ѹ~sU,ibp~jB1J|t. nx^qHDӼ|Sf:pb;oVKvpL?gsK9L񃴟0);m~@GwDB9@v=74aX8p:=ѥ qd4%2+,Mn}|Fph4|sjfzܽ^N;aRH 0L [{.~S~I}P@Y(0/ &wĉߞyw!%Mw/KtMh@L Cm.U>娇 w%je ѺHnW;u庺4}\UiyφJw씁egcL72~U/ ھw׋+P_9\ֱzȻpK H=og<{FRXe?J Ji, iT7xc"!|דZ?5+"{@?) Kα\ޮ疴.%T,_L]JtW,)S^Ua ծ_fpƖ&MvM 0otuͽ6@V7jG% ;ڮNlZ'FaQ|3ԱEa\L|[h(}&{E;TnA_Qbͦo'nb#8њڮDg'9_ǒE$,=d5o`cDaE?09O ӖȸxXt NG. q!'šDay6ġmQ|$2n6Hhvzqh W!Ʊ)*H@"bbT^kx--hDDQY~,HtDڣ;VW1Gu~+5&*uq n,u?broJ΂+MUK~M1!A XrP*%1d OQpIhiMQ<#-B <zvpvyVh QJg#?W4'бEN ΟaǼ<՟ <$˸#'pweQWN|=uDour\Ѵ_&j!@{Hg 3s>.4SFcNҷa~sw;)GTae~R|^b/nU21J^r)~|=_?8=9F2VL'ɘ91 TkiO%?E?_rw$L'D~-nxraHu6 Cxq=B @KI4yj5I},<_a9{Nː[mY'^_NMNwt j&"٥QY;ցAx%ԥNr}3,@ q%Q|VmT5P%VJzm'fTq,Rݿy)N|)q "tKn]Bsӻ! -!3͍;0rN !>9[q,sܗ*-LvV &;d_:e6n P ܟ2͐Cbn59Q_T1 BŃiQoP9MNud WY3Mˆ-vp{SALs/`y@mhE!Ka_v?O8d RX_?sp-ɵ􊪔τsNe\jTYI A/>ٲLXpXgbZu,#WvoJjꑻo&GH7qx͛, pȋvTV[Wl$gs 1ȱ\4rÆCN$-QqTAhʱ׾(QXo [U6@gV慯_U?N K? am>ć|ߕ+O;A?,cR]DN84 n}i ˿{'K,a܏<":94RM\xsq5`:hv4ɪ?c WJ *u**(?j,t0|v1Gq'7@6Sz-zOq7UnzcجRtb~g~ o^'d Jw:~r= :4JP'jA[g ڳe=ZdvdvL¼j/>>nm,vݳe7PH$P OggSZzvorbisD8OggSZ@-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSIZV{s.-.*/5/.<݋zyc!k;CCddY" ۋ<=Nu3}}T\+?iݭڿ/wr^t L{A˯!``Bo'T@ukwޠUu'$ Ƒs]:&&}Q80+G@q~9 E0p .(dsrz)&!8ܩUo }[PW`LhH`x@2`\&Gs UFpXM[Aw濸Pee @(XIpxh8 NP ], t ]:n)S/`[c6cxTG /P`Y_5TS/BO< yxy6}iI J #5IPF.21✋:;=> T-$ /x 9@BӎAB`u;1^uz[wvHLVzm<< + w' }j$_ȁ?Vz, g>9.=F=z.^) Ax~ ౟KK+% ^ Y$g 0ys5i~@pP?JJkӹ4{hjfPhN@cw *8Gv:bSh5.Pd*@VoQ6@d:ʞ&Zzaz_;'_rA (__5/=XfrIԎ\=Αmy 5n\vbe]=$@' ɲHuJ;o1[Zk>χ#sxޛ| pZAzP)@JtGvNE*PBT>\`i@;_pJ(>z2f75H LEG#_ @τGPd*}ޗ:;!7cFh36@϶"@1{ڶ+x+B7;1B994ȍL^n$ƌR2 AؘJtu N,/@* * 8hP1`|v Ws郃t, 7i~G3>NxB p-T `sXg N@@ &aPЙ(N :IL!L;"QQ ŴqHO!HomezP)W#hjG@(3s/l@* ߯"\ߑ_J*֪ sV2' < xp H,(4^펢\0t<[StN\H H 9X=0XⲘQ7ijá@޵ G!P}"QZuX@(69wwp%" )X-bu{.Lp-yP|ffZ^ dr@z%TB .RvigU %9 gH{J0$ Uu`@@X00B~PS @ _ f<7KV܍Z}{3' apT F@Z F2: u GC",oE(oQ8Ojp+` XU@/^PHz) 9f 8 } I)* M$WWq,Y<"@A1DO 82}Яg!t7//v?g OWbNB7|)Jb XրPl"=X.Th> ./Rv8ꉀjzP@5 ! ߗt@r@?8 @'` e0\`L*~[~!uT]XtU*Sl 6=~2iA nWS(HB^WWP_( ;Pr(:?,WPlZ`3.` w l% >)WCn}c?C4wmI~`@6 V=?,e]AcW1²?U+x=$F=fpK衬:g #e(R:x!@5P UrAr~Q@zLby@sCFj)tX(0 @)?/3ɬwX)>']J>P`:  ٓpL)@/c9ݥd:A#3@ow_N^ 6A I~U !K(#:@U=r@KDΖjL..@ V(#4H.xH)@48v:梐Ĝ!Bg[ԉD*B NL!W^xs4ة"0.H,L v5*\ ?\ i`q'IQ;ݿ9%ö\_ڦk$.$*N@Z#nk{Qv$!U .:L_E.Jn$\Kpyjwg}14K ;p#h< HH).?⻈>*u'%un9 .% 0:X`P F`U>%T33&ρ.uHnyA4Uwl ߙ"u(q5q$%J+9~<b)A?ԯ 8cPD`a _Ipw<@4Lp,xFq?.}/1C~2t~@HWhNv8IT=-Kbyǁ'z?LOp g9m8Tgu(~R` IjA 0k-Q XQD*SqI%U Wc懂|^^±XOggSZz|˿Ľ~)4D gPSUxt%Hj` A @*%vcCsK*uBk#@^Ɓf*3' r  (@[d5a!(7wCpm X T`B^9^xWh b~ 86`OY$Q!-_Mn{@ ~ @M9|xṊ.B\֍> vg櫪S*Lwo@v 099+0;E< @*;6@Ԁm5$~I.ޥ¶#Q𜤡_aPSe-0NUw>,5ԵG)Oj!4)T=*$o {S9>/5\f %&oD!*1盀j? x@T$<$X^I. 3e>PiN'X[A PUAL[ *58u8ɢ\ 'y9,nwRhy щЊ^pQ{,IF[)UU!pE]-\_w 6<('<9.}bw.Dy<,z*l .UBz>b%f=L[A".ܱ-ـ?i- ^jLe>~|ආ~P(dI7~wݷv;|=0 ~~xlK {A gԃJH,(SߊC/CTI2]*  -TP7ou@R"O-}C-xd8E<#A/p  t9:ze՝9*'2QU 6 *o81F7T"DmZ@ f Ə$)z“j/+AA@[9?Uke(NEY3  0~IԫЍNԝ/W"^uJ a_RY!]VPU=xMpAi{YiDQ&}7Pc {R lƲNQ t3Pb4 &   }hO'[/jݓ~֑`o5`p XiUUZ#*C# <ZP!,QZ)S^q/Ƞ^>o;ܷ#^b5.Ǡ9ԇ9ǶdCm ,  :@BkAL^9ﲼ 2-uZRW? Uo_`Kh&lBʙ49c5emiW66QڕS6$JM(DP. v7OY@ ,P9+ҽ_ս:0z9yWR`'bs¹IPbkqD@JaK:n= 5k>R {bCo` sB6  0H:`>)6mRXE'<'H@|``i*5O TcT@m xw1S"" !pp-*K. 7PR۶p~ɥ 8ףWt@^Pf >9zW9[Ev~4k܎u <:  okYM :ts)(/ެUObq_@(@S6i @74~?$JxR@ uJTnHh$(4) ,,`).ye/V"V±ͪ s  , P@dꑤ-iRIi:yM;I TZ"kPWA>˚I)J}!O_ x>{ kT:-댝ӪE_\G-T@u1Xmkplp @d {ڀ; \(wW 8%OD)$}žfjhL<<6P' p mN-P!MkQ$YY/u7T4DSL ҋ#l54gC$- 3=WS2& ,EU+%-$OggS!ZM}~y>9FKiݏrT1{?Pqޚw `OcjKɑT@>m9RfksUpMui'*t 4ljS@P~I.RH]vέf:?"AO,Hwd ab  ,$%4Ӹs^>P ! 26[UqQYpG=V(»UC" ~\+.<` 4x0F%lX5uH@#40L1$Ճy.{ә !o9*-ݏn(#FZ؃K  8H*`e9.kzEeƆ3&N]q~Q!Mtn@[(J]6}'  kd vP@ : ~YwlppAen @8,: UUá_p8-C @ 4ŕջX"” * DNPcف;O8 B :    ^ v0z~@y fm{0# 4ќDp‹_\]@-b%eRvݞї[*\JR<5*M8@BO`X ^I.PyWwAO$<P=l8QE`T'>3@E p4؁Lشw&=hԷ+@)cv(((/V|&nIP/,)}OKq"fo]߫c͠GO`JհtS=@WM ;hF)HKBxY#z TbQ UAñ̪% d<{`6hthZ_fFtǘ F& p (m@ eAMeBBGw.f'Y%`  D4Hkq5&*nb К Ǩm`v(\^!@nk{* w t4 ^IH`nRRz3 ` UUKJ8{sd(Zj<T7-.9p?n%&pA,@bL:6B0Hx)*\F9oy hjBua&Y9ߔDt䷎jD!6pV`;q^mrvD>@㝰S? #`:40;PYzМ)o Y_JOLF|NC ' >cMVU>5]* (#dɊ . Қ I&K%KѢ5>jAY?H; FO 0<`<&9;?ot;]wuWl !EUOd} ~]<,x{Zk/1? 2@9l6 ^U(8}SXoK4@Sjl(I=d  xY&GzZ `|` d蛀:В||_"S?!R^cݺ2}:VG_'`t{T &P .|98J&0,H.A/ݛd @Q5<4p4@-U C4LK?p=Z Z M7W6w31P(t@LwI$(`ɐs4x@^9V:^1a SjDUDŽ&;8Q Zhuj5]PڶfQ) ōz_`2 kpZ : JT[tx:Y&w]ݗS;?$4w@*2b$^۝Bqw|تdʪͤ6.')EnsQ`%\c:`L`9V: e>;Ś^_Qj.Yz8Jg, M:dJh+WR; VQ!L,x'[I@h@iF/%翩R@mNnXw0TU`Qf4>ͩUPB{& %_ ZsCZPJN@RQհW@yv@ P`s u`M7tPB x8cwulB|}wI h8`@nz^i;;$86iQW@ Q1a=* CSOK’ |t` _; "kATJLL tj&ߗͲ{tl SU@kYFx Ag@-U "E(T(}6?n", W`(+dz#Y&~|s~ XdLc%&<4g'01%MWu Бt2%s4ǡ{_[4[T/: t| 9n4N .-pn =ˑE (+$ FH2`ӊakVśJDq(kt{Z @UL1&P,@OggSZ/}{ywwwvzioi<4 4@H@TL&g\CB(pZ9(g9H"|Nw: k(!B-3 L@pzkz@CP`D9F]*e?9[ FN.,ppp59;*B3,EQ!-ȅ+Z%p폘&w܆\8qt @Bݼ^9 JEOIRmqm0 ,io]z;mxx `1&CTUPx{]5 8[wgnVWܛ"bL/rI_|:Ux0_ɭn 0)`XpBap.@ t0@x>9&W A GH^7g`zF jb"DUZ4fSz. ID]: 2ZR~t),dY()iV.jjr  @mJxP*9N#;!.7x ZfwȒ.+f,p u MBM8 g7L١:¢T@1Q tB K0N$P t<<pSY'& (XRIF߯_i8Nˀ~`9h@@*%H0;AJa&H{. rߴ8ioJ,hP@ $M)%'h<((E^9FſgӬGi3FOD̠ph@Т=ZOu#D)8*p BFO,N f 0<@ p6P$@iơR34h ~+H * ,_`PSR-ij/ÐY=[)tGxPhUA]@(9:/Y7AN0rg`o`PAwyv ރj'ji~r2GKV7A-6|A,'h'-ЀcвϘc(&0$%iEo7N5+c^hX@*E$d*{iȀNUB/epy Zp;~=w|!58߲/v<1'm tpt 1/&J}mM^j;N;HJە&#g.BP 0:@g`0m="X6ޓJ=<G@LY _{NGx dL' *ԟ*8@*𨺳I(˝܇бDx,@/<4`B, >9cq З^ 4^Mȁ*TfϨz.B34g0N?[Q.G n3HaW `wX$4°P܌n ' xxБh@~ :~(ONlT$ @|p U 1#ko-)  )./)dyiW[#&C* vb{ZsSaRxSD _\Fڡ Ї@o\@X.z  (~Y 78 O4<</x UU0%16vx ASkp;f릒 cp &@n_0 @9:+\f)&}]wO .CMO/u1}ņӘde&]~1a׏ ,+r* @@ T`&'>Y]~rbq_t'> ٭!kBl LO%y P <%̒}*J,@}UQ@BPl×BM9.AoUuK470@\d5Q` 7Y9{?z @nT/;!( S H DD%EDQ7T`yXT iEO0K ⇒\< t)=碄Pt'9 63 MU.3jk}^ քvk@kUWo  #:H%~p NN' u a8:L ` >9P`WS;MrC pnUU>Gq)8,KeRA@~N9;Yhl׺;}U&M->(hP$pAA&x>9N[м&;Y <@,PU'v+?&# cT5']M=)yWk NރBx~<LEk @~YBo$]掂_u$?@TU%tbHNW8+ XǗhEPTJY@,>~XGуGyY@w4,I0` x@Ύ7)ֵFI]͉"_U/&䭒\E\ty{g{l&5*5 %# @/f}cFP!wCI -@@HD`Z7xAgM8' `'j (,A@< abNXHL -hA ?4l :@@!(P>x~YaL@5`JfJp UU/,FB&A9IB]𤴺OsVu";8463B:B q5  @&U<IAY:sެBslK @ @C緎}-# 58y H^mv46nąn@p\@=0  : (< xz@/p`:dNMk,^ @" @;t ;> ` 8@,E*Pr[ Zut-[X`e(XIP$h xt @ Iv_R4|gnz՝pι=^XL*cBi7Ŭk'Y}d?gΪ֚FmͿv<Xt _ڛ"Pdp h@x,`H i.^Ҹ;hS8j!^?O O: p]-4 XӜ@.*@Ed- Wr$U 7}@Of% 0AXit OggSZ^ÿ˵9!{p&M< :ux`wXUUzn86 p~l$gx 2; .zHl87L9;;hJwN[BX 'tP̀pr 333P3RTd$ (c=(X` qI.Vc'z* `@  @ \UUgo~fmB[ x@{ @^#r#KfATk>U`>]D.3+@„;A$L' `^91;uͭ ~r9 @`k NTtIBx w0?U-Z+,SiSW杌WATzdZX~| `xPP>9n]|OÐuxƿ ׀A 0~KN 84Uz~w)!Cۤ T CpiIr-_RQÑ@k[L  =. :@ ((~.(wJcͰc~q05' %`: `o`UX@&K(m#4a:gS~xD2q@4+ eN@10>uW;Я<Ȼص  WpxT!5x }'z~#Eշ3~_X5HxH @n3`.x `aL kOՃ!!RJc@z[iLu @K=׿̪)5wPUY .(Me q@G&$t: :H9I2VsN^&3,lxx M0fԝ8-9F lom@ԯ (8F!}U5-@m@FPpIU̺^Iy-p 5mi ^ԅ.H P & ~9&1οvIJ12,^3&04Q]zT޴g;P]=n@9@K[ (PН@@IPfFzlHDK s,2.E$`w.t*Tq'L0E /@P6o"V'}틏S.jy|AROConp6%KK![f_L a)ޥcX5b|ү^KeYOX.~0  ~)Rwʬv!HP| x%`p <` `rHPdt%!=7MC% _@qUzP./(o L(|F UduY:`@:ӠM= >*M@mW 3KQZ%yX#^~H8+X;/l  4Hmv[@/\Hi.0b o+~$+*( ML IӢuT_6Ђ@WxF֔Waj/!_׿& >@L35E G62wa㕀j_O`zI9Pfcl}t(.TO k!<@_ `:.p u 0QI[Πr-y@{ b_Tr=@ HI)P{Z]&80m9 ۙIqh.*.<`AX@rJt@=XNݿt!̗%4`;i``Q @$:Mm;+1^A4dt?C2϶ìCzA@jiQ<U?~F~GX/<KFwgf8apgp~y [x"ޏBxQG{ +FkԻ}&x0>) /R<1ki0pm:/-?:%<U6 N$|=6cP'U`zG% z pE)P~x%( 5S:(`h0usNȤLV7 . mEj1 uN(V}f7,|Vt`!,OggSAZ&e}pvs1Tx?|Uy.,`f<;&Rw}vZdAz^w:&J~T {PSWKЏ]R*Vx!n[Ca0 b o% *<S/yGD0L R:>9.(lqn5S1+@x֠p@-@[fE r!pU(@hcI3{Cq.X@u*&x@_M n|@/\S@AT3 ֚;/  ɿZmi@7T\K.w`Tuh0 w9).(낀0P>PS@WX7U@L;:zt&8IJ缺]u† ;c,8:ԹB\: PCeõo ÀP10GdokW3@M5)@ ;5n|  l yLF5G#𜡓``N+$PkzH β- m4-Q4 WFefCoIͦpyE[e }G__ G`.,0aC[@/"0_#fWr^a5y`S> څAo.c5aJG ~V\[J-y ߟph*ذTF~2 x @'\.<`` Tz$p U@`P5")(@b-X P.C:7% st@OU(u">=u`!S !)8}?Q Xc`@X{8f%~R\~ٵ/y<s?W9; .{ 4L(bx͆^Ai]!%?P5W+qMnºW><s.w]}?~WG_U !T(]H> !ȌĉKy{ ppl nYfVUllWzn ~+ -w4D8ʩ(< ӫ xT j %8]{f(T$W@@߱@0 YW&& 'q\3w5e^?h;`0 0O@N F`w#m&t)4NkznERJ2޽_ݜA5_Zבԩb]bg%3bvvvJ`kpߪa[^O{{% ~*wȄ`cY9( g#9MLNWAa W1P (.R\pa(L0/ >$@u(fȆ  q^@D('pMpBQ޺SW(- xc /88nY[pc 9  X%3h)$.q'Y0xʫ@: <[@& xsS 48zG866;Kξ' ,=' .[`<@'u 'O}^)P*a],*H$ $=N$A{};B źVU %Hn#3? a)x6_s.TvMpك0wdpawؿ૽) ()1>}ҏ5Ӧ@T> _` 2/*@Old,lݸt@VCYpKEI\ )za9˸VD1FյQhcW! ĘL$g],4.@~Fe [7[BR @8 <e'D؃cZ_6>ji~z9R~J~xM`$k,;$xG@.N $ j58{wo)T֕rFāܐv99<6j+r"_ V:t]= @-A!HW_@QWʯݥzk1,] (Mi~~Q0&aʆIl3 ~]pM h= @6/xA}{@`٧`@P'0vSH4*Dޕj%n"Ę*iMZkE3%1Iԫ$ Fm&i ⑕ h1F j`s9}nTR7Q#k{j2l 7@ gw s-@ G&OggSRZv &+)&'/0 -)Yȟn- %<0) h\nUTTaD/OFB۠nQGߋiӤпy )hhFDo@LDaZe;@y@SMLv_D%xQq~_b {[͢ajfP}iK VС<0>k xGm{$ $ aNfd Y>PNh xtL'` OMxܦv 0`2& >ma+h]{+4p ;6qzpS<,D@c/WR5rtd]-D~"@59QJu}TOg༰Hϝ<J@{)#6a,(iXr ~Ӑg b h@+|\[]Ivq  4 Rv? kΈ|inU(,\[4 t*p 5*vXFoRGmAUf\[]n$35w"{IO*-dYh@ɯeVLXGVϲ'>\[g~@IoΈUF5e]\]mi* -Z2=(^Ѻ$gSX\n'=Kao|ÏK}9m~%TIMOggSZzvorbisD8OggSZ@-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS@OZI%0-,+%'.-11&(22,*.00ú$OF `>It Kx o7Xc =$M%ozxTamoD_(Cc$͗IL 3rY_T9?S$DcTe$?CvROR65w[]9? _ x~_}?]7(W>>|Ď(Z DဆS.o/`]"K{+Ѳwrm<\^TZ12 Dݔp+r8zϲ7j{k#ճ\Y$lR‚<Ρ7R  ޿{ʐam$900phpzWe QO={<5+q(0D۱- B1uK =U[+Ϛ;99x?X9Sޫr)pcE%bkmx:n_jwzQ{iLSxz!1o&`Nx&.Vb]Vmo9ds@P7˜bf4/NvװXڻf3`]h3: \K@2Ixuc~Z%q]'W$hW.3o/zk'/hyqGynEٯ{{VϬzTU7ݦoܷ'U\(Y,rMw H>3]e2PS;ᓌ?& iG,d4ZMT $|G6 Z=5FQ j91GH*STjdMt"&BFz|>gW`d$@l=13x>3d}.Q cM&p0~XCǥ;&.y;iI(H)>". P̔k8{:`6t.(EJS8PeB%܏)I萘:??=~$d`F}$W&I55^b~ֲ K 1qKFJuݟsKx9 1 J$!Ӯt^_Lػ}3z$}PLն==Áݔ1OS<Ni^ w} Kcm "|pjA; 51!%1c2%Kg^ Vg$.j}e]1*ZMeӝ {;G Ys6&Ѯf̄+/qL[%ÂEmQt[%Gk_dzYZpӓ2 SI"!ZWbtu@>z%#~yt~ }b&TmQ,6וƚR}0]d?m,@^ F=TOSˊpf* ,3 s6TTh09{dz!"dDNW.uh`raEո284 ?(P=@^'5{ۜf]uwF/o,=mL KRӁ.ֿ g$YiY*qz/o_f(<|J61+۽qٷS<8r?GǐwP̋t|LXЁ;@>"Z=p0hFjBD3J2j#O'C٩2M9g(.f $%#~($TdZյ;"p2@UmTq:٦D&W=a8_XnyT.y1E ZQ1JES#x@wjTS5n tDuc*b] 'lRr \U?YjH9`c'>yc+p1 -Eq辸 t^{mZyڌ"!h8O5Sud{9.7+uNA|cGSڇn "7X6i^Nj"Dm 4@!\463': ~%3> M}朞sfY AԊ5FH3]|Y$(U^6Eos&p3ٱLOLp_"o9Ӫ^/]akvC6q-/-;x5W2NG*(:h^j.z t[=ޙOp1^~޳;4յ zOZRqnG޳icXVeҹ}B'L f!Wl{$ҰYZ&&A%\v'AhgDh"e$ ;(ho|)vl) U#bi0< {IDf3MK3I+=[<T_R5dNz4ֳ~%/ـn½=:Gmʫˈ=@p ]NP> Vq1!Sab `1x &#"?oJed_&VTZ`PU%,!;ez>;*B#6B+KVI@iPof5gܪg)x}xQ \U\i NI h P`OggSRZD}&('&(,/#>܏oH=t2)r36O3= U zVJ2FUz"Π9@A (@<3=B*A 'gxi8 O5+.yM+i,4$@`)+rjJ_f V Jx:lijG^8@;PU6e[g)U3E\Ty{=@Y-k3 DH"HD^B* (d*MK |@sG< :L@L {Դg_B9@N: 7x HHĞCUQIAVKcBtg}"CbLR鷤:Uvi~գ)*' Ч@.'5B7w*J[蛾HuU?mG(O 4, :~V'z2ir M` XV1*MxkO_ -V-0-RC]EzS9WUo aZ= jkۇe+gT+_ s O%x @A@|qc?<ϴH-S<<@'@@$\`h̞ZN:)a'5m=5(vPce$#ӵh. i5-<6Yg^`>z Yct Pc <U{*=&_﷧3MJ{ ne;@@[PzH^mh ~!:t9l` f 0 ޅ@LS7!8 o Vj @>Df:}41My&ޙU-=MlhYp ,^0B<Їn8`F YAUgCtuyHf0!83zC'ҫw@spC?bJ Ɇk"džګT ~=qЁC P|$@3nǶ-ߧ { Pl hM{ |  $hEqr" `=L$#{m3:U\= Hl1ED><,Phn]M D},m&`rxT{Dx,XB < #40 $TީE=;E WZEel Ng DUdF_䨼f֧XPp 4\8?6N#4Eq]>~8O)@} w?(tL$@ fR=_UJ>5Ip'@}x/x0VU?M]]\-5sQJv"5@jSb^CF; r(w+Gc+J8@ &@ h t@0 _?\hqm`kBvp6 "LCW x P,`@06V=BXqMt=W@& ʖD%&%d=?@/4z^Pgx Z hī .xR +wszl ~@v0|$c4G@x@HDabt @~Fn ][ N",tZ4_p0ðUmR󚀨7 |g+ ,aio7w giFbbI%3H<hD?g  7],bF J !U<;}r[c?@mOr( oU8]8*. D<[? 7]9 ƒ"24 z.wn  s9M:`9M8a9^X_o-R-|$yOggSZzvorbisD8OggSZ@-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggS2Z+P1531(,+&.**12,,,-.24/3//(('%%143,-*,)((2-%&&%"#116*'('&'$)514/.&$$#$*3464)40.HYHbu &w9> z_޲@35}!$c4\CEnﳩѿTMUhƢL&v+˚T3Uz\m;n"$UQhs}{5&IF4&_]qགྷ&h|QP*'@jji @4ԙ xXGPz ᝰT0kYέaH0H+}/*GGU@Y:Z>9Dy&վm#>)CSġ%oZD@ED|+ V#H {qwN5w逛(e $aENk7[JP.JPBJU\mPRBiph QQxl\#t?*%%颾ݏb˴ $Oܭ^Y'8Bϳm;_v;8I'4O”"ouu '[G71JUA,Od/+L.k^ DsDK,QxbuX6 3VZH*bEO.MjU+oq~$OI m'GP!?m:BwcAaQ^>Ix$JVLly\oN?=) >}} Y0ͻ}t(av:+D>ͅ[ShdZxl Yse!+8lzog'ʾ t #QbK^\xG)bnt&"O4,uK,~oecƊyZDV)>*W 6드KdÅN&@-r%Whtb> |?!6`]|ޭQ(Vԋ:Ux,5͕6;1-~vjUD)%h&:RxE5l^dj!᩻GٶC.v\|L ΔM+iro֙> ?!+FxƫGMxKs.L\~^ތ}8La|HOJFMFVpfz44ZM ;Peor8S 7HYPAdzpH[=[>D_3K$%H"՞{x@{D---oE ]Zv{soo}1o-ac fc򏌳N:i!8ad<Ǔ FHYlrC#t]D< kO\A|h gJ?IJ3ף 4oo4^G-Թh ʮ7G^EAr#1u+Z(ߗ r7&T 2XijB̤̲j"p ||DL`xd#y JN[FwmXOΙJ?DRa]<xfx\"ZQGu)i,|oX͇MkQW.]+8}VԊ5dx\J-7ed$瓓պEL1bfrhL,śo6,Jfx]m,]ƯdkݣjJWi3뜛 bx7^RpTEOOV, ya\ɘi˹>LD[\^2T~ĐR%Vx]c8p6O!Uz9fOke%05VcL bMJ*kQ 1Eк@Hhn_8;o3E/=x:ObqX5>o{z@)^U vTOD!B\"ټ!XN\Wl=<Fh\&YD|,G(GyeH%,nH&RH\V>MJq(q1raj˞d<__X$JAJ vڅ=/gbN⩥ҊJ*ʱFStNnckY %$3Q="ř0'Q{/\قi.ё#ŭs Rzw aikd V#\ҠLJZZlcOۏ!nMK['/24PKzծѦy:gG\|}80 VhJP9A.ig;et9^>;߈dsh}e֏ _5Uٟ~bC? ~#@GoCi' gb7x K=?Ӫ/)@K,+'RգϨxA el1Y:,>?>)ڹL";nn5rQ(ϲ_ Z+o ?HA8c! vVHhڱhQi]Z8a\{5OCʙD^5\zCF nV0I:ppIțo-:EGx99ޅḫ&&׹`)|k ފaBmq/: mA. Jy~Qi^9Ut:ևL` ޑfncڭ wiPխjMM^LkWbАWO Di;zzCͣi@Xq!:ȧ"@.Z|TכѹOi Pz@-O/s?P3!ħ'w("u WhQ{ _^$cL"??;^I^&d Jx\Yv} !Hۋ'}yppMc_V>A$JhP|=HwKU,^}Jkz._ViAnVުkmˉb[EpwpCrOggS,lxG&GD8;G? K6M=ڷǥJ^6 jMB)j$*l Zm~nj铱6D6v—Ahg9"hꆱD=Я C&=_edfglF2%! ,^%t= 4\%zfhq#aw`9+E*uzGұCyri֒҉ndg)(E@ rx=7AT%L%Z3Y:Dx`;(Z}?ҐNP&9 n߆[Ʃ<_/Q\xE)3}Izd7hIگK~mnH &1K):0;=^3i8)2T3:8,z+1WL1tm[vm^..".nuA;{lUkzخ.ȗ6 ȱؔ"{Z9ӝ3\ý_+F[ }dw|5$_3^\+e̒78\ ;Γ:Z7HLLa{yw^}= jxT+{`8LqO(> ҐɚXRxGʪYLX+82\"Zֆ~J8#c~TxG%h;+Us@+|#rLL. Nx A4 zrIẩY{DsΘ]FxA[a~7zJHEZ~&vZlѲOHmQ6%5G<™zo^|ѩ;=އ?1ODZD< dx\RZU١cH^ucx̌lk'n\ c#7}jx} M-oL# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSCZPL-.00()((('*2.+0//0-ʾ'()()00////*&*XvqEN_l2=yZ÷#Yjy5lkM2正+&9G}V_r46ul_ j1:pXut|gӄn{a_^k [@'Қ%]D N.!Dv5LKv]ye`՘wZB}FG6Lk{>+WE3e)^ʯ]@Iקp̊hp@bs?1OQt8%U|ܿnWb~^^^)(zpYXwt`r:+| ftB)0A!P0Qd xB6`*eXr38(gOmT lX5%gl)usަg.DTWdݒ ­j+ ." NS._I>Dl C k1!}Ḙr/dِQ{4c]UWK/B5i=>Jtzlߔ M CNdn5v+YKʇ!LݴD?N4'0HRҔ{ RLU06[!1/,!D0<"5l:'F6ީ\i , hB˿~|7qmntg3/Ē[Ů~RPW]Tc9 ښ%8scoK3ݑ$y$˹ 3󿄝ŊW7-½qڰvȻ=qt6Ino,KGu~FӶ ibѼy r*mNW~1\bUnw(#RŘָiÇM.P\ZTOz!>g"(z%t8؎zAupAvH+g\5 .]BG{jJ'>.SwssO0l? (Wu WCKuLbȦ٩ХGzU>cn{z},UJr:F_1z#oG/ 4AIR0b.)\ߜ G r<çh/!ğwѡwpL;6mv=αfPn&.EpNٗ\Is\Z#TQ`;I?M2{F<&>y~֒ Akn :IⅠ17.rڴx #n} oMռ%-6**Ƚ! ijzhU}SG`&F#xXaUϬ>ti;߱X +hDQ3@ Sɳ 㣖H+ }TS!}twnY_`Kjvv iӺ $@zH F-6hbϗyDy-)OZH5NcMYhgǚwNi9z㔴]t!KyOkJ.TKJpa_T1gdE=m:[n \dP#,i3@ uYF_ YƧ ޜ"lo[}z{\ dga.q`}>c!S3sy>Cz>#de`'MlݙjwHz,cL8A﯑<־ǶNP[HIݕS&e`uWGo;#%NLA6Jd^ML!$ۗ]-YIpB!-EP5aBzX:XkiFK JY^ċi':F}udDbuInOGoGŏs6QZ2{O~.JqͮrnOUM|Ro}$01[ǽbfg!RЩ8gc 8ފ[h]uoM)V 6ז E9HKCBB4$g_B_od7Dp pN 3Y:qBn˪t,H w=ܿ/#==+y~{iOuC?N|Ēvwp1EmCgfPVB2[e'¤㉮'h2#{7)cgYsK?p_@[ {I0eQM02_)k4n>UÜ:%k<S=RjZtDw?5io9,v4'͛k iՠ|%^VlɪhYnҸ3zUĨVE밉`xAMvC RoF;6ztxY.kL@ha"L*psp39n. !%" ;CC9``n}1_y5`<@'ݾ7m=%aU;Fޗ4gG؇=1Š~[PCLךRspyYIWI+wTlGhW]rEV@ *U|%q؂쏻HNtP\ V Smi?XIK|l2 ޞB-1k6svjw ѓN"3K8kD'[>7U .=Vk{do!P qsl> G1z94B,eBPM+BAP/D/:Pׂܤd[^8TtY=3X {=e4417<[q H3!Nm8SU+[&_qVg LYUÛG;Dل9MܹRk./t[Sq$H0m؝+;+ӑt.\}\[(X#NW7 URw% ӌ"5mLۚ D|g{I٣9pۆQEL;wZQ!|)8±"0C"xuַ1fA):R2qۍ>nU @vcz)!C?ZLI+h-=3T4N 0rWbpL1޶ͭ_+'rKNq?%Ұ5RJ* I=_{8y?e PIɅ)\:( Σ/&6c.~jesQfFϚs9 qUnWp~"@\]]dZڠgh:x `V0q|̰4kY) z؎ùww=Qi22҉7 leD!pX14ogv|+T~߷o|}\[Az?TH!ff\H|ھ/5+CS=43uT]zE.iF:$bF"+z~~3<+Nd];P pz% iEB[ dߴUWyP4͸%+hJcOggSZ?^zD%'))./(0.+.0../&(.-&02/d_d-U5tFm(GY8yfU"\W@.s GRF0::φ %2|)GK T[ P)3Bs,{SI0q l]Aobx-/-8v2z3YTcY<epqcozg,[yQ7/|?: V$<_$~.l=v:H-}񑚏\KdžMw=sed< :rlh۔ӞDb1:5n4ʺR`[ֈSQ|g D[VӕFQ41$^Nk}hD:T5/i„mrCuaώAHlAtB7cY&#"e[zsx֔Ͻِ R!`XnmC;1mD7ھpGS@H`rC)< %m, Fq#ApZ ,⧙+jm`Z];%n<)|! Net&u/}sz݉WdF]s-E_^KFTl,"PuiáJP1^Łi%.!WΥn>*j9޶|iTCF ڹ2AF sZ5 R>t15^ 3TtTYjTܪ!wsi_p˛R_MJTy'ŏLeY D4FzK?Nt~ģYRH0CLc0`4ɑ#٣ki=lF%]oGM(.f._|.=G9 lkDbsM(f~}=i[I O_5xThʌ Z"x/l< _xS_omO0Jg)G=5 *$>\+Oݎ p8xj}ID&b*Z =10/ +:SYj$LN6''2h@6L7.{t]Wµzzb*=_.P7gYoN!\ ~\f"*њ(qr~p sיz"O_AK3=%#eX^ڝ \/4Ŭϙc3%*uEm6 `7M uӞI6ׂLka9G6#p:m_ $mHa*-𴺬# a^#3egr]H_\g n"Maٻpk^E+J+|%_e ښE y;dB^rr8MsD4 ' 4޷eZ{Ql7jjKN1 u5@oϛynAٖp8˔5`Z/-Fy-q/9ؼl dY"H"cl\%$qc2_-\ V LYꉲ@h*3z;Y(^.\'* ˲?_3N>YŷԲ(DeYVmD6ד>wud.g~|sU~ VIJ߯:Z$ע}PKD3HMQ[E1rvWIw: e<һ]5ՅLY.nqK_G}=}p8lUS -2gaErO`[6.Pظ ?704 ~Nwz5%XeIF׮(?^tC ,,·Y{z VJEu _}sHbevd$XCeMVC磭\g?zF&V'YJܟŕ$İEX75Q'ijGOas! 0!HV/voZMY`/!lCByn-Bvc)[iJۦ3kZaqKio)-2~,1\p_>\c E@VNjtlY\ЄЧ Dc^amvvw`_`eT桻'x($$h;ls|Lsf"~{QS̈]ģ<1X=ixd{H1eǮ"Gqڨ.HPWX'oz>>/7.Oz7#+%26 N 3ig|;&ZQQ*Z,@BM5~:usH80<gd8 <uF7 Ʉ\V͎Lzmt6=X+K^uO℁2l{5GCf߸rM#HP@,Ƈk^2B|! 6X.f@b= ''FXR+ҰF#.K۾1Kܨ﷔{fkcWv}^(“G bBL5*ۯ>ċ'&`)zݺ7(SٌFK"(|mQkX0tRтU D˂]bw_ex>`?O6/xG6̅1a;OggSZ 1/-)'&('(---('*)*0+/$o h[Ų:phkٿlw/sݽ#{\mĠׁ0p1oH:#~ǂ_.}fI+Ү,Tc~a fyOXkfCmtCSl|/TaDb8܀Z1Fޙݮ=yLc& pxx])c9f5uPhCTaz p*U.J Ә?*pvͥ\p\cdx>VUXV&:zwPl򇲩ˀF\_Ġ<08  ĤHŻ2^k T]5/)*Jٱ%hp=qdi(yN :?ׇȳ8Ãp/r:jTkfQDeGl։}4Wﯙݰ|O*9ODi&h1H;V<ǼNS&bD3XZkuToH}PLx0R\?FpuWToQTϯY%'X'~w3Uh2<3 Tq".$ 5U߷9^߾o{{ѰxyyyY|by1/$'拿?>btxxxxE2<<<<<< ^^^^^^^^^0zyyyyy2<<<<<<<<< xyyyyyyyy!VOggSZ>vorbisD8OggSZa-nvorbisXiph.Org libVorbis I 20020717vorbis"BCV@$sZ2fs{BB{ALBk!càBcАU@g{˽{Fg{i{Ƚ{ʽ{{{%g{H{G{{eW{({{{G{{'zĬ{7 {{^{{{{$W{({W{h{꽗{{ 4d((  @Qqɑɱ  YHXX%Y%Y%Iy뺮뺮. HPQp YdHh \CTLǕ\5]u]u]UUUUUUUUUUUU Y@i0#BCV0ŀАU@IN(9) YLJ9)G1yTA)RJ)RJ) YJ9)(Y*5)G9yR=)RJ)RJ))yҒA)(iВM=)(EI)RJ)RJ)J RJ)=֓RJ)1J RJ)RJ)RJ) 4dgr(:g(gBiB&9JJ&s9O9' Y@!RH!RH!b!r *J**,2,2,:ꨳB()Z[I[sI)RJs BCV BdQF!b)J*АU Q2Q$Q-53E4]UveYmvuYuٷ}[m׍88888 4d BH!RH)s:! YPGqɑ$I$,M4MDOLO\Qm\mTOTQ5U5]u]U]UVe׶m۶m۶m۶m۶m[BCV:#)")8#I@h*@@(H%Y&iɞ.@h*@h舖(((((((((((((yyy$t$Gr,R$ER,rАU 1$Er,˲4M# ?o U6̘uۨ:c7gn벭 m ʾ.qp*˾ʲۺn}ʲq̶-p7~.l1p p0 "`P1R B(Jjc2ƤTA)BIb BƘ1)J)RZ+JiVkk-PJkJ)-jlZ1&!sLJƘRJk2tIɜRJJbŘ1)sRJ*1RZ+VJi[KbC)Zl-Zb BƘ9)J)UI霓1'Z))9)sR:礔RZ+J[([-VK)-Z,bT[(RJ[k XJi[lcJ)RZl[kK[kjM-Z9cPJkB)1jm1J[)[ŚC)1RZ,b9Vkj[)kVcoZTkZ[o 8P Y D(s*PJsJ霃PJJsJI)PJJPJI lДXА@*`RA))F! R RA(%Z3 Rk9gA(%j RkA(%Z뽤Rk1|I)Z1Zk1Zkb$l=ރNٜsν!2<N Y d dR RH)RL(c B!BH B!B!B!B!B!t9s9s96hJ,PhJ 0F!ƠR SA(%klcB)c圄Z\+ Z5AH%Zk=BJ՚k5Rb5t9b9瞃Zs|O-֜sν჋1לs!d5{:j9BkA` +IgBb9 Bc9Bb9眃Bc9 B(b1眃B!d9B9眃B9!B(R: BRJ!BRJ !B!RJ)!B(RJ)%BRJ)B(RJ)B)RJ)B)RJ)RB %RJ)RJFIFEh…АF5Z+RpB rci3qCHic@iRAB A m! A%@DL Paqvq] 8pp O 78AAqDD44padhlptx|OggSRZZ //ĿſH7d\Lƒ8!Pqe{/3HxK6 p+g|޳qOK㧝t Y[n~xs kXQSaZD2Rq#xsCl>|«?V]z|-Ұ ^N; `e2An[U߉_7qa.U4N28S:}jq{-E Ʃ-j2ỶX%]k=-_] @CT+x,-&mʄ>^ᩙ``yvD:w3Y`w; jc~ɛ˚Ԓ&}C;XboXTZ y{ȅ7#?҇, #F_ޞ`8vc<]gxV- <3ݞɀ炄z98N0#ӽճri# !u~1@/$cnZc<w^&s,xqNtQ${u!Q kjNO^ͳn-㺒ܦWCO \ VX:>K1^JXU:82=?wq|Ȉ0Z !y|Ing2?)l\T8ppZu#0,hcz!n78vh]!I)7 U iPJYgt_ş^e7 :mG%=^@8J246bZʻw eFWhA( y>sE!!ӡ;܌L YT!{b4Vi8wgv{~:"c n\EE!ȓ%}wqCxͻ]c`@^ȅjZ\6G5HYr;dZSQuw14yciY,Nhf];Ȝfv^70yP^XF/#㵈f}+Mʵn1'ozRjLHD|6VO%Rվ&Uc? W{j>KHƅX a1LT}&Rl[jKᶏiIZۈ`NـH9C' dT0P&36}`z i'2>=o]'X]U?0CSO&ϞF[^Ì>pq DK${!Ґ(נ4%}˙=]UoU&&r~U*-MwUrxCl,r$]0R6_%~r {n Bhd :39F,3t^xP!Ծ|Kh#LU i%ky9D|-Ÿ݃bn0ia6iKK;yv6=vޟ]zIZI@lߥGWq<߃m'`*51OCt>r\bR uSa ?>̔=v*;RxPF-~\O^Vy3/ىZX($'cC1CڿG̋2ỊJ(:v{m<Uf>O n*j|*ZD+ָ\ZMwq/37& Pay󪻠ˆ"r=NrKY4JYDI wd@E Jq0~N9^X!,2w&Zú^Y*Dz sq3 ~4%hIs8|B0shۡI%ѐήADf2¨DXk%ID9X<|ӷqD6^\X҅~>G k8 ,8T o17H dybVE˥!sLH}8@wGX5o^8iaa{A}Di<*y)q61y'I+C \sM.W7jJ<5aj+k-1Ger^p~;EYc7jpiaEQg5nȕ~p\G b?L@M# 9vTu!ި>!&)kEy'Z{B"K8חΪ`ZҥFDy]k\|c~(1KP2Wo.HS'ӊ$/^]:*Dw4#Kj-]6V~ֹ&@ U BYGI-DCAr`&  M^.Syr[{:>s#^G.]3]HD[!Km9{jnzE Ϊ5kA][{X?1pƟ^h&`VP.gW7b9 'H[NwKM/)vuh<Er5IܞG:ճ"$4#NpsTP`^#m~5ԯ|x92~:<ڡՆtر@)d[H5ŧix rgXtPpij= hwKaSZILf_ %W9ŬrJBZ! bKLt@G9s"hDNl!tU 6z"̛:kOzt+%'`X~y 'EKIE3hDDhr]shsq.k|!-4k}ی6ռ\ԮIԟ!PApJ^psunKxfl8Zܬտ>ՅpH4ֱ;_izZ@Vp˂|%W _(qfOm:!| %DUG.}SrƬ}CSYoRzIQ]?gVkD"2s.?%fb!.3du<;n JpTHS0J)YCXm<·B6jЅvMlxM$e9X^{R42Df] 0r"oƭIׯ*ˆFαA=IwRwE 2 - #' 0< ¨^}#L\Xpj=suX5ߥ !"xt/xwNQu c;-x䇾YZZZ}HE499{+g6ޣBF)@'戫HmMd +*;tA3wZ%R (9 W0DIcOggS@Zkg ɽ)(-/0ǿȽ̿>(}#9qz777{NfiZnI)+$V\9auV{q6HcgL؊JxKF(Q/BuH^JӸy"=3MŦ'Lga4_Y qY/MZM&Uy~Dx ֚8JmJ y$2%{ɛzPg}ca&G L WBZFɚ%궵' OfOC-ccؚ >3#gD]jAoMQvQ$RPGe%-nf~r^=Pu+耣n>(͔ƣRE>x}3 )6y'{8SoƈVww H!Dss%$O{)̮;#NKDzmr2M{KAnא5מ4ZG([oL fԍB0Nu8 !3k`(lc~/Z:ZE-WˇU`%YpMu X cQ@(}Y9gV b{1-`# $ݏ&ϔy-b^S4v>cd[Z*|θqRv)̫&gCѮ>Z{5ʁM x'c5Ccp?lTfsRi.h bñgc (dYeFF]|`? T8oV~~aLsv;E sHHXR//s^NTF8U+m;]C]}9# -5RI_5@|Y7k'X}uWڌQ:e%W V}D`8`uwRBʫnOͮ-~*dM?T7<{cg]`0헖Mo|!9dA20=X*Q(+͛jB=h 2+l; ^O>2+E1]i.5:wAk *d'M( z,:5V襃_ a>^N0ཿwX辣Nf{zkS"἖|:xU%=ސ1g.6rZ;IWq yTxo\ 61x>W}~9?z/<^o }̊ך[] @09G~94Q&4mmf=\ }>Z~`& $]$E(O;׮&'5-gnѬ!ߪabыhf(ٚ=1 U`ZQy*~XjLHF ;Z jJ@UK#Qd'LwG'\TA6|S9$4@Rt `/G;>>6N:Z5R X|(>@tB8} $E-ȿ߮X8kX{7E,ֺΚOO$gz:|Cl, $v.s93NF={u~,Dmv#Ϳ wq> elpJ*re6_eP€<s8.?3nV[bz_#-nX݋q }&X {*:ڮLQ?fFfAoJ1B M|TB9<vR-D^^}Kl 'Ɖ#e`]$JP~;l*.Rv[u?%W߲]/1ŶV]O=3^>'gq{z~4yS*ByȮ}*|!670 !DuCAz3[M0.|% APF:g }$w3yD:غBחi¿ŦVKuޑc|Ww_Y}_І5C .CJ1Bm+Կ:%¾Pи&,qPv$ nTn;leە2PUF%3n+ٖW<%J!?)$+w 1XqR^h~i_ yNfDDFHй]R"D-tU/s%HlXYYY "sC 3:cZҿgHA0uBuN9R MUfar-Y}Q4)AO+s)P֕8JgU: gvDF+=n9<7c#`X#IDJ8nż>ݺio5^gZ7K+azӳD{OcWm]ku[Uޯζdb;O5X|.!}KEPO!/r5cvs7\BM*'wV%5O8e-I3P@oO`.THl4+J,T>8}#( =3 NX$($_{44QH}߾WڷyQtcmڇ_s@?jR*Ce*\zĢ$7ؾrp(pxuV.m6kSj!| _>$Vl1T(e0{鳍nS.7!Gsse NdzumBN\{*FsOe<]&k+ho?tOw r;gVHCX]9?3}ES *ZB[sg>Y%8~psPmE(a!VbѡM<,-ijߘV/poM'Ѥyi]`8nyR,\xS:vl=ϙ ZH$ʔs\uh鞊t{Op<qh+*ƃ#n%cfkO}{ t%bXDB?Ѯgˌ#9ao@ k#SQJo32*ť:8;~+qS`L@-V:6 ̓%'O)lE{&~|!/Gy_ne#\E->;1ltOPH-i8Jb`-~2j|c!g؝7cl aDBj9=mɉY'OR"M4lnMW0T$RrJ930ѨĪݮ24=U8zƧ>C,X247w0 D=~]SCSpX]c%I{S,h / (c08KxGtQeJulzagՖ^a OggSZ]}^ ((()13>(}# NZlN2 |70,Ԅ$f&g_|e2^IxrN8^|U敠Qk4 惟8dOV#I^{& $Xh,rRCJgR;z Ǭ: iU[bA@!5S455߄Qhb)!UT,8o^neh.5F 2,^~a}8.O{6ơպK`w % %;l i4pI܃aB_#AX%'Hs/[]qOQˆ!/ ss"勏/޿_r O=)g M2lɔ,#,_Msj/܀%{NP 'hWB9n:1By@swgsl=ܿ5@%ze7au(#JV[pݮQfjUM;BVp?Z/EcӴiw^/FʖRm/T.<(+(U F?Fů(+Bg`Xwob5ﲻ1t1B䵍9.V\WUY(!C0cFYz fJ<>?MƩ]Dhy^ɩ7K`bfs=) U辣$YkSˌ˯ƉީSfuWPKݽSwitchScreenMode(true, true) line in GameApp.cpp of the particledemo project to enable 3D acceleration. * Improved cmake files and TuxCap header files to allow system wide installation of TuxCap. * Added software drawing of stretched images in both normal and additive drawing mode. libtuxcap-1.4.0/CMakeLists.txt0000644000175000017500000000031411112475735016133 0ustar inniyahinniyahPROJECT(libtuxcap) cmake_minimum_required(VERSION 2.4) if(COMMAND cmake_policy) cmake_policy(SET CMP0003 OLD) endif(COMMAND cmake_policy) SET (CMAKE_BUILD_TYPE RELEASE) SUBDIRS( tuxcap ) libtuxcap-1.4.0/tuxcap/0000755000175000017500000000000011212652465014677 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/CMakeModules/0000755000175000017500000000000011212652053017201 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/CMakeModules/FindChipmunkLib.cmake0000644000175000017500000000431510665636770023237 0ustar inniyahinniyah# # Adjusted cmake script for Magick++ by Jan Woetzel 10/2004 # -------------------------------- # find the libraries main include header file FIND_PATH(CHIPMUNKLIB_INCLUDE_DIR chipmunk.h "${CHIPMUNKLIB_DIR}/include" "$ENV{CHIPMUNKLIB_DIR}/include" "${CHIPMUNKLIB_HOME}/include" "$ENV{CHIPMUNKLIB_HOME}/include" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Chipmunk\\Current;BinPath]/include" /usr/local/include /usr/local/include/chipmunk /usr/include /opt/net/gcc41/Chipmunk/include /opt/net/gcc33/Chipmunk/include ) #MESSAGE("DBG CHIPMUNKLIB_INCLUDE_DIR=${CHIPMUNKLIB_INCLUDE_DIR}") # set directories to search for libraries: SET(CHIPMUNKLIB_POSSIBLE_LIBRARY_PATHS "${CHIPMUNKLIB_DIR}/lib" "$ENV{CHIPMUNKLIB_DIR}/lib" "${CHIPMUNKLIB_HOME}/lib" "$ENV{CHIPMUNKLIB_HOME}/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Chipmunk\\Current;LibPath]/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Chipmunk\\Current;LibPath]" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Chipmunk\\Current;BinPath]/lib" /usr/local/lib /usr/local/lib/chipmunk /usr/lib /opt/net/gcc41/Chipmunk/lib /opt/net/gcc33/Chipmunk/lib ) #MESSAGE("DBG CHIPMUNKLIB_POSSIBLE_LIBRARY_PATHS=${CHIPMUNKLIB_POSSIBLE_LIBRARY_PATHS}") FIND_LIBRARY(CHIPMUNKLIB_LIBRARY NAMES chipmunk CORE_RL_chipmunk_ CORE_DB_chipmunk_ PATHS ${CHIPMUNKLIB_POSSIBLE_LIBRARY_PATHS} ) #MESSAGE("DBG CHIPMUNKLIB_LIBRARY=${CHIPMUNKLIB_LIBRARY}") # -------------------------------- # decide if we found all we require: IF(NOT CHIPMUNKLIB_LIBRARY) MESSAGE(SEND_ERROR "FindChipmunkLib.cmake could not find CHIPMUNKLIB_LIBRARY") ENDIF(NOT CHIPMUNKLIB_LIBRARY) # get the path(=directory) of the main library: GET_FILENAME_COMPONENT(CHIPMUNKLIB_LINK_DIRECTORIES ${CHIPMUNKLIB_LIBRARY} PATH) IF (CHIPMUNKLIB_INCLUDE_DIR AND CHIPMUNKLIB_LIBRARY) # OK: SET(CHIPMUNKLIB_FOUND TRUE) SET(CHIPMUNKLIB_LIBRARIES ${CHIPMUNKLIB__LIBRARY} ) ELSE (CHIPMUNKLIB_INCLUDE_DIR AND CHIPMUNKLIB_LIBRARY) MESSAGE(SEND_ERROR "FindChipmunkLib.cmake could not find Chipmunk library or header(s)") ENDIF (CHIPMUNKLIB_INCLUDE_DIR AND CHIPMUNKLIB_LIBRARY) MARK_AS_ADVANCED( CHIPMUNKLIB_INCLUDE_DIR CHIPMUNKLIB_LIBRARIES CHIPMUNKLIB_LIBRARY CHIPMUNKLIB_WAND_LIBRARY CHIPMUNKLIB_INCLUDE_DIR ) libtuxcap-1.4.0/tuxcap/CMakeModules/FindAudiereLib.cmake0000644000175000017500000000413210706205237023016 0ustar inniyahinniyah# # Adjusted cmake script for Magick++ by Jan Woetzel 10/2004 # -------------------------------- # find the libraries main include header file FIND_PATH(AUDIERELIB_INCLUDE_DIR audiere.h "${AUDIERELIB_DIR}/include" "$ENV{AUDIERELIB_DIR}/include" "${AUDIERELIB_HOME}/include" "$ENV{AUDIERELIB_HOME}/include" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Audiere\\Current;BinPath]/include" /usr/local/include /usr/include /opt/net/gcc41/Audiere/include /opt/net/gcc33/Audiere/include ) #MESSAGE("DBG AUDIERELIB_INCLUDE_DIR=${AUDIERELIB_INCLUDE_DIR}") # set directories to search for libraries: SET(AUDIERELIB_POSSIBLE_LIBRARY_PATHS "${AUDIERELIB_DIR}/lib" "$ENV{AUDIERELIB_DIR}/lib" "${AUDIERELIB_HOME}/lib" "$ENV{AUDIERELIB_HOME}/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Audiere\\Current;LibPath]/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Audiere\\Current;LibPath]" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Audiere\\Current;BinPath]/lib" /usr/local/lib /usr/lib /opt/net/gcc41/Audiere/lib /opt/net/gcc33/Audiere/lib ) #MESSAGE("DBG AUDIERELIB_POSSIBLE_LIBRARY_PATHS=${AUDIERELIB_POSSIBLE_LIBRARY_PATHS}") FIND_LIBRARY(AUDIERELIB_LIBRARY NAMES audiere CORE_RL_audiere_ CORE_DB_audiere_ PATHS ${AUDIERELIB_POSSIBLE_LIBRARY_PATHS} ) #MESSAGE("DBG AUDIERELIB_LIBRARY=${AUDIERELIB_LIBRARY}") # -------------------------------- # decide if we found all we require: IF(NOT AUDIERELIB_LIBRARY) # MESSAGE(SEND_ERROR "FindAudiereLib.cmake could not find AUDIERELIB_LIBRARY") ENDIF(NOT AUDIERELIB_LIBRARY) # get the path(=directory) of the main library: GET_FILENAME_COMPONENT(AUDIERELIB_LINK_DIRECTORIES ${AUDIERELIB_LIBRARY} PATH) IF (AUDIERELIB_INCLUDE_DIR AND AUDIERELIB_LIBRARY) # OK: SET(AUDIERELIB_FOUND TRUE) SET(AUDIERELIB_LIBRARIES ${AUDIERELIB__LIBRARY} ) ELSE (AUDIERELIB_INCLUDE_DIR AND AUDIERELIB_LIBRARY) # MESSAGE(SEND_ERROR "FindAudiere could not find Audiere library or header(s)") ENDIF (AUDIERELIB_INCLUDE_DIR AND AUDIERELIB_LIBRARY) MARK_AS_ADVANCED( AUDIERELIB_INCLUDE_DIR AUDIERELIB_LIBRARIES AUDIERELIB_LIBRARY AUDIERELIB_WAND_LIBRARY AUDIERELIB_INCLUDE_DIR ) libtuxcap-1.4.0/tuxcap/CMakeModules/FindImageMagickLib.cmake0000644000175000017500000001067511202337472023606 0ustar inniyahinniyah# # Try to find IMAGEMAGICK(++) library # (see www.imagemagick.org) # # Once run this will define: # # IMAGEMAGICKLIB_FOUND # IMAGEMAGICKLIB_LIBRARIES : contains all available Magick++ C and C++ libraries required for linking # IMAGEMAGICKLIB_LINK_DIRECTORIES # IMAGEMAGICKLIB_INCLUDE_DIR # # IMAGEMAGICKLIB_CXX_LIBRARY : ImageMagick++ lib for C++ binding # IMAGEMAGICKLIB_C_LIBRARY : ImageMagick lib for C binding # IMAGEMAGICKLIB_X11_LIBRARY : image.display needs X11 # # # Jan Woetzel 10/2004 # www.mip.informatik.uni-kiel.de/~jw # # tested with (from www.imagemagick.org): # - ImageMagick-6.1.1-Q16 on WinXP, MSVS 7.1 (JW 10/2004) # - ImageMagick 5.5.4 on Linux Suse 8.2, gcc 3.3 (JW 10/2004) # - ImageMagcik 6.2.5 on Linux Suse 10.1, gcc 4.1.0 (JW 06/2006) # - ImageMagick-6.2.5-Q16 on WinXP, MSVS 7.1, 8.0 (JW 06/2006) # -------------------------------- # find the libraries main include header file FIND_PATH(IMAGEMAGICKLIB_INCLUDE_DIR Magick++.h "${IMAGEMAGICKLIB_DIR}/include" "$ENV{IMAGEMAGICKLIB_DIR}/include" "$ENV{MAGICK_DIR}/include" "${IMAGEMAGICKLIB_HOME}/include" "$ENV{IMAGEMAGICKLIB_HOME}/include" "$ENV{MAGICK_HOME}/include" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/include" /usr/local/include /usr/include /usr/include/ImageMagick /opt/net/gcc41/ImageMagick/include /opt/net/gcc33/ImageMagick/include ) #MESSAGE("DBG IMAGEMAGICKLIB_INCLUDE_DIR=${IMAGEMAGICKLIB_INCLUDE_DIR}") # set directories to search for libraries: SET(IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS "${IMAGEMAGICKLIB_DIR}/lib" "$ENV{IMAGEMAGICKLIB_DIR}/lib" "$ENV{MAGICK_DIR}/lib" "${IMAGEMAGICKLIB_HOME}/lib" "$ENV{IMAGEMAGICKLIB_HOME}/lib" "$ENV{MAGICK_HOME}/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;LibPath]/lib" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;LibPath]" "[HKEY_LOCAL_MACHINE\\SOFTWARE\\ImageMagick\\Current;BinPath]/lib" /usr/local/lib /usr/lib /opt/net/gcc41/ImageMagick/lib /opt/net/gcc33/ImageMagick/lib ) #MESSAGE("DBG IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS=${IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS}") # find provided .lib import library files FIND_LIBRARY(IMAGEMAGICKLIB_CXX_LIBRARY NAMES Magick++ CORE_RL_Magick++_ CORE_DB_Magick++_ PATHS ${IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS} ) #MESSAGE("DBG IMAGEMAGICKLIB_CXX_LIBRARY=${IMAGEMAGICKLIB_CXX_LIBRARY}") FIND_LIBRARY(IMAGEMAGICKLIB_C_LIBRARY NAMES Magick CORE_RL_magick_ CORE_DB_magick_ MagickCore PATHS ${IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS} ) #MESSAGE("DBG IMAGEMAGICKLIB_C_LIBRARY=${IMAGEMAGICKLIB_C_LIBRARY}") IF(NOT APPLE) FIND_LIBRARY(IMAGEMAGICKLIB_X11_LIBRARY NAMES X11 PATHS ${IMAGEMAGICKLIB_POSSIBLE_LIBRARY_PATHS} /usr/X11R6/lib /usr/local/lib /usr/openwin/lib /usr/lib ) #MESSAGE("DBG IMAGEMAGICKLIB_X11_LIBRARY=${IMAGEMAGICKLIB_X11_LIBRARY}") ENDIF(NOT APPLE) # -------------------------------- # decide if we found all we require: IF(NOT IMAGEMAGICKLIB_CXX_LIBRARY) MESSAGE(SEND_ERROR "FindImageMagickLib.cmake could not find IMAGEMAGICKLIB_CXX_LIBRARY") ENDIF(NOT IMAGEMAGICKLIB_CXX_LIBRARY) IF(NOT IMAGEMAGICKLIB_C_LIBRARY) MESSAGE(SEND_ERROR "FindImageMagickLib.cmake could not find IMAGEMAGICKLIB_C_LIBRARY") ENDIF(NOT IMAGEMAGICKLIB_C_LIBRARY) IF(NOT APPLE) IF(NOT IMAGEMAGICKLIB_X11_LIBRARY) MESSAGE(SEND_ERROR "FindImageMagickLib.cmake could not find IMAGEMAGICKLIB_X11_LIBRARY") ENDIF(NOT IMAGEMAGICKLIB_X11_LIBRARY) ENDIF(NOT APPLE) # get the path(=directory) of the main library: GET_FILENAME_COMPONENT(IMAGEMAGICKLIB_LINK_DIRECTORIES ${IMAGEMAGICKLIB_CXX_LIBRARY} PATH) IF (IMAGEMAGICKLIB_INCLUDE_DIR AND IMAGEMAGICKLIB_CXX_LIBRARY) # OK: SET(IMAGEMAGICKLIB_FOUND TRUE) SET(IMAGEMAGICKLIB_LIBRARIES ${IMAGEMAGICKLIB_CXX_LIBRARY} ${IMAGEMAGICKLIB_C_LIBRARY} ${IMAGEMAGICKLIB_X11_LIBRARY} ) # add X11 if found (for display) IF (IMAGEMAGICKLIB_X11_LIBRARY) SET(IMAGEMAGICKLIB_LIBRARIES ${IMAGEMAGICKLIB_LIBRARIES} ${IMAGEMAGICKLIB_X11_LIBRARY} ) ENDIF (IMAGEMAGICKLIB_X11_LIBRARY) ELSE (IMAGEMAGICKLIB_INCLUDE_DIR AND IMAGEMAGICKLIB_CXX_LIBRARY) MESSAGE(SEND_ERROR "FindImageMagick could not find ImageMagick++ library or header(s)") ENDIF (IMAGEMAGICKLIB_INCLUDE_DIR AND IMAGEMAGICKLIB_CXX_LIBRARY) MARK_AS_ADVANCED( IMAGEMAGICKLIB_INCLUDE_DIR IMAGEMAGICKLIB_LIBRARIES IMAGEMAGICKLIB_CXX_LIBRARY IMAGEMAGICKLIB_C_LIBRARY IMAGEMAGICKLIB_WAND_LIBRARY IMAGEMAGICKLIB_X11_LIBRARY IMAGEMAGICKLIB_INCLUDE_DIR ) libtuxcap-1.4.0/tuxcap/physicsdemo4/0000755000175000017500000000000011212652053017303 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo4/GameApp.cpp0000644000175000017500000001207311062533667021340 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo4"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo4/CMakeLists.txt0000644000175000017500000000402210762446645022062 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo4") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo4/Board.h0000644000175000017500000001346510667046273020532 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo4/GameApp.h0000644000175000017500000000612110667046273021004 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo4/main.cpp0000644000175000017500000000022710667046273020752 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo4/Board.cpp0000644000175000017500000002240410675254242021052 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetSteps(3); physics->ResizeStaticHash(50.0f,999); physics->ResizeActiveHash(50.0f,999); physics->SetGravity(SexyVector2(0,300)); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(0,475), SexyVector2(625, 475), 0.0f, 1.0f, 1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(635,0), SexyVector2(635, 475), 0.0f,1.0f,1.0f); int num = 4; SexyVector2 verts[] = { SexyVector2(-7,-15), SexyVector2(-7, 15), SexyVector2( 7, 15), SexyVector2( 7,-15), }; for(int i=0; i<47; i++){ int j = i + 1; SexyVector2 a(i*10, i*10); SexyVector2 b(j*10, i*10); SexyVector2 c(j*10, j*10); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(a, b, 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(b, c, 0.0f,1.0f,1.0f); } float moment = physics->ComputeMomentForPoly(1.0, num, verts, SexyVector2(0,-15)); moment += physics->ComputeMomentForCircle(1.0, 0.0, 25.0, SexyVector2(0,15)); obj = physics->CreateObject(1.0f, moment); obj->AddPolyShape(num, verts, SexyVector2(0.0f,-15.0f),0.0f,1.5f); obj->SetPosition(SexyVector2(40, 0)); obj->SetAngularVelocity(-1.0f); obj->AddCircleShape(25.0, SexyVector2(0,15),0.9f,1.5f); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) physics->Draw(g); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); SexyVector2 pos = object->GetPosition(); int shape_index = object->GetCollidingShapeIndex(); if (object->GetShapeType(shape_index) == object->CIRCLE_SHAPE) { float radius = object->GetCircleShapeRadius(shape_index); SexyVector2 center = object->GetCircleShapeCenter(shape_index); float angle = object->GetAngle(); const int segs = 15; const float coef = 2.0f*M_PI/(float)segs; for(int n = 0; n < segs - 1; n++){ float rads_begin = n*coef; float rads_end = (n+1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(rads_end + angle) + center.x), (int)(radius*sinf(rads_end + angle) + center.y)); } float rads_begin = (segs-1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y)); g->DrawLine((int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y), (int)pos.x, (int)pos.y); } else if (object->GetShapeType(shape_index) == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(shape_index); SexyVector2 endpos = object->GetSegmentShapeEnd(shape_index); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType(shape_index) == object->POLY_SHAPE) { int num = object->GetNumberVertices(shape_index); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i,shape_index); SexyVector2 endpos = object->GetVertex(i + 1,shape_index); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1,shape_index); SexyVector2 endpos = object->GetVertex(0,shape_index); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); g->DrawLine((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { physics->Clear(); physics->Init(); InitDemo(); } } libtuxcap-1.4.0/tuxcap/physicsdemo7/0000755000175000017500000000000011212652053017306 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo7/GameApp.cpp0000644000175000017500000001207311062533667021343 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo7"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo7/CMakeLists.txt0000644000175000017500000000402210762446645022065 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo7") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo7/Board.h0000644000175000017500000001422710667046274020533 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; std::vector points; PhysicsObject* chassis; PhysicsObject* wheel1; PhysicsObject* wheel2; void InitDemo(); PhysicsObject* MakeBox(const SexyVector2& position); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); virtual void HandleCollision(CollisionObject* col); virtual void BeforePhysicsStep(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo7/GameApp.h0000644000175000017500000000612110667046274021010 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo7/main.cpp0000644000175000017500000000022710667046274020756 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo7/Board.cpp0000644000175000017500000003263010672744075021064 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetSteps(3); physics->ResizeStaticHash(50.0f,999); physics->ResizeActiveHash(50.0f,999); physics->SetGravity(SexyVector2(0,300)); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(0,470), SexyVector2(640, 470), 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(0,325), SexyVector2(250, 490), 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(300,495), SexyVector2(660, 375), 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(640,0), SexyVector2(640, 480), 0.0f,1.0f,1.0f); PhysicsObject* static_obj = physics->CreateStaticObject(); PhysicsObject* static_obj2 = physics->CreateStaticObject(); static_obj2->SetPosition(SexyVector2(440,200)); PhysicsObject* obj1 = MakeBox(SexyVector2(460,200)); PhysicsObject* obj2 = MakeBox(SexyVector2(500,200)); PhysicsObject* obj3 = MakeBox(SexyVector2(540,200)); PhysicsObject* obj4 = MakeBox(SexyVector2(580,200)); physics->CreatePivotJoint(static_obj2, obj1, SexyVector2(440,200)); physics->CreatePivotJoint(static_obj2, obj2, SexyVector2(440,200)); physics->CreatePivotJoint(static_obj2, obj3, SexyVector2(440,200)); physics->CreatePivotJoint(static_obj2, obj4, SexyVector2(440,200)); obj1 = MakeBox(SexyVector2(220,180)); obj2 = MakeBox(SexyVector2(260,180)); obj3 = MakeBox(SexyVector2(300,180)); obj4 = MakeBox(SexyVector2(340,180)); float max = 25.0f; float min = 10.0f; physics->CreateSlideJoint(static_obj, obj1, SexyVector2(195,180), SexyVector2(-15,0), min,max); physics->CreateSlideJoint(obj1, obj2, SexyVector2(15,0), SexyVector2(-15,0), min,max); physics->CreateSlideJoint(obj2, obj3, SexyVector2(15,0), SexyVector2(-15,0), min,max); physics->CreateSlideJoint(obj3, obj4, SexyVector2(15,0), SexyVector2(-15,0), min,max); physics->CreateSlideJoint(obj4, static_obj, SexyVector2(15,0), SexyVector2(355,180), min,max); obj1 = MakeBox(SexyVector2(320,10)); obj2 = MakeBox(SexyVector2(360,10)); obj3 = MakeBox(SexyVector2(400,10)); obj4 = MakeBox(SexyVector2(440,10)); physics->CreatePinJoint(static_obj, obj1, SexyVector2(195,10), SexyVector2(-15,0)); physics->CreatePinJoint(obj1, obj2, SexyVector2(15,0), SexyVector2(-15,0)); physics->CreatePinJoint(obj2, obj3, SexyVector2(15,0), SexyVector2(-15,0)); physics->CreatePinJoint(obj3, obj4, SexyVector2(15,0), SexyVector2(-15,0)); physics->CreatePinJoint(obj4, static_obj, SexyVector2(15,0), SexyVector2(355,10)); int num = 4; SexyVector2 verts[] = { SexyVector2(-20,-15), SexyVector2(-20, 15), SexyVector2( 20, 15), SexyVector2( 20,-15), }; chassis = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); chassis->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,1.0f); chassis->SetPosition(SexyVector2(60, 250)); float radius = 15; float wheel_mass = 0.3; SexyVector2 offset = SexyVector2(radius + 30, 25); wheel1 = physics->CreateObject(10.0f, physics->ComputeMomentForCircle(wheel_mass, 0.0f, radius, SexyVector2(0.0f,0.0f))); wheel1->SetPosition(chassis->GetPosition() + offset); wheel1->AddCircleShape(radius, SexyVector2(0,0),0.0f,2.5f); wheel1->SetVelocity(chassis->GetVelocity()); physics->CreatePinJoint(chassis, wheel1, SexyVector2(0,0), SexyVector2(0,0)); wheel2 = physics->CreateObject(10.0f, physics->ComputeMomentForCircle(wheel_mass, 0.0f, radius, SexyVector2(0.0f,0.0f))); wheel2->SetPosition(chassis->GetPosition() + SexyVector2(-offset.x, offset.y)); wheel2->AddCircleShape(radius, SexyVector2(0,0),0.0f,2.5f); wheel2->SetVelocity(chassis->GetVelocity()); physics->CreatePinJoint(chassis, wheel2, SexyVector2(0,0), SexyVector2(0,0)); } PhysicsObject* Board::MakeBox(const SexyVector2& position) { int num = 4; SexyVector2 verts[] = { SexyVector2(-15,-7), SexyVector2(-15, 7), SexyVector2( 15, 7), SexyVector2( 15,-7) }; PhysicsObject* obj; obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,1.0f); obj->SetPosition(position); return obj; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) physics->Draw(g); //draw all joints g->SetColor(Color(0,0,255)); std::vector > j = physics->GetJoints(); std::vector >::const_iterator jit = j.begin(); while (jit != j.end()) { SexyVector2 start = (*jit).first; SexyVector2 end = (*jit).second; g->DrawLine((int)start.x, (int)start.y, (int)end.x, (int)end.y); ++jit; } //draw saved collision points g->SetColor(Color(255,0,0)); std::vector::const_iterator it = points.begin(); while (it != points.end()) { SexyVector2 pos = (*it); g->DrawLine((int)pos.x - 2, (int)pos.y, (int)pos.x + 2, (int)pos.y); g->DrawLine((int)pos.x, (int)pos.y - 2, (int)pos.x, (int)pos.y + 2); ++it; } points.clear(); } void Board::HandleCollision(CollisionObject* col) { //Watch it!! col pointer and its object are invalid when this function exits, so if you want to store its data, copy it! for (int i = 0; i < col->num_points; ++i) { points.push_back(SexyVector2(col->points[i].point.x, col->points[i].point.y)); } } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); SexyVector2 pos = object->GetPosition(); if (object->GetShapeType() == object->CIRCLE_SHAPE) { float radius = object->GetCircleShapeRadius(); SexyVector2 center = object->GetCircleShapeCenter(); float angle = object->GetAngle(); const int segs = 15; const float coef = 2.0f*M_PI/(float)segs; for(int n = 0; n < segs - 1; n++){ float rads_begin = n*coef; float rads_end = (n+1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(rads_end + angle) + center.x), (int)(radius*sinf(rads_end + angle) + center.y)); } float rads_begin = (segs-1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y)); g->DrawLine((int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y), (int)pos.x, (int)pos.y); } else if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i); SexyVector2 endpos = object->GetVertex(i + 1); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1); SexyVector2 endpos = object->GetVertex(0); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); g->DrawLine((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } void Board::BeforePhysicsStep() { chassis->ResetForces(); wheel1->ResetForces(); wheel2->ResetForces(); physics->ApplySpringForce(chassis, wheel1, SexyVector2(40,-15), SexyVector2(0,0), 50.0f, 150.0f, 10.0f); physics->ApplySpringForce(chassis, wheel2, SexyVector2(-40,-15), SexyVector2(0,0), 50.0f, 150.0f, 10.0f); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { points.clear(); physics->Clear(); physics->Init(); InitDemo(); } else if (theKey == KEYCODE_ESCAPE) { exit(0); } } libtuxcap-1.4.0/tuxcap/physicsdemo/0000755000175000017500000000000011212652053017217 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo/GameApp.cpp0000644000175000017500000001207311062533667021254 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo1"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo/CMakeLists.txt0000644000175000017500000000401110762446645021774 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo/Board.h0000644000175000017500000001346610667046271020445 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo/GameApp.h0000644000175000017500000000612110665636774020731 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo/main.cpp0000644000175000017500000000022710665636774020677 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo/Board.cpp0000644000175000017500000002106310670535173020766 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetIterations(20); physics->SetSteps(1); physics->ResizeStaticHash(40.0f,1000); physics->ResizeActiveHash(40.0f,1000); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(0,470), SexyVector2(640, 470), 0.0f,1.0f,1.0f); float radius = 15.0f; obj = physics->CreateObject(10.0f, physics->ComputeMomentForCircle(10.0f, 0.0f, radius, SexyVector2(0.0f,0.0f))); obj->SetPosition(SexyVector2(320, 455)); obj->AddCircleShape(radius, SexyVector2(0,0), 1.0f,1.0f); int num = 4; SexyVector2 verts[] = { SexyVector2(-15,-15), SexyVector2(-15, 15), SexyVector2( 15, 15), SexyVector2( 15,-15), }; int i,j; for(i=0; i<14; i++){ for(j=0; j<=i; j++){ PhysicsObject* obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,0.4f); obj->SetPosition(SexyVector2(300 + j*32 - i*16, i*32)); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); physics->Draw(g); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); SexyVector2 pos = object->GetPosition(); if (object->GetShapeType() == object->CIRCLE_SHAPE) { float radius = object->GetCircleShapeRadius(); SexyVector2 center = object->GetCircleShapeCenter(); float angle = object->GetAngle(); const int segs = 15; const float coef = 2.0f*M_PI/(float)segs; for(int n = 0; n < segs - 1; n++){ float rads_begin = n*coef; float rads_end = (n+1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(rads_end + angle) + center.x), (int)(radius*sinf(rads_end + angle) + center.y)); } float rads_begin = (segs-1)*coef; g->DrawLine((int)(radius*cosf(rads_begin + angle) + center.x), (int)(radius*sinf(rads_begin + angle) + center.y), (int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y)); g->DrawLine((int)(radius*cosf(angle) + center.x), (int)(radius*sinf(angle) + center.y), (int)pos.x, (int)pos.y); } else if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i); SexyVector2 endpos = object->GetVertex(i + 1); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1); SexyVector2 endpos = object->GetVertex(0); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); g->DrawLine((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { physics->Clear(); physics->Init(); InitDemo(); } } libtuxcap-1.4.0/tuxcap/hungarr/0000755000175000017500000000000011212652053016336 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/hungarr/GameOverEffect.h0000644000175000017500000002052310641010445021331 0ustar inniyahinniyah////////////////////////////////////////////////////////////////////////// // GameOverEffect.h // // Handles the entire sequence when the user dies. ////////////////////////////////////////////////////////////////////////// #ifndef __GAME_OVER_EFFECT_H__ #define __GAME_OVER_EFFECT_H__ #include "Common.h" namespace Sexy { class Graphics; ////////////////////////////////////////////////////////////////////////// // Represents an exploding planet at a given XY, drawing the given // frame number. ////////////////////////////////////////////////////////////////////////// struct Explosion { int mX, mY; int mFrame; }; ////////////////////////////////////////////////////////////////////////// // Used to spell out "GAME OVER". Each letter, beginning with G, // slowly goes from black to full red. Once all letters are spelled, // the process reverses, making it fade back to black. ////////////////////////////////////////////////////////////////////////// struct Letter { int mRed; SexyString mChar; Letter(SexyString c) {mChar = c; mRed = 0;} }; ////////////////////////////////////////////////////////////////////////// // Stats that summarize the user's entire game. ////////////////////////////////////////////////////////////////////////// struct EndGameStats { SexyString mFavoritePlanet; // We keep track of the planet SexyString mFavoriteExport; // and export eaten most. int mScore; int mLevel; int mNumPlanetsEaten; int mPopulationConsumed; }; ////////////////////////////////////////////////////////////////////////// // The transition to the start of the new game is done by these 1 pixel // wide weird lines that drip from the top of the screen. Each line, as it // drips, draws a black line but the bottommost pixel of the line blinks // using our over-used HSL color effect (see LevelUpEffect for more HSL details). // Once it hits the bottom, it drips upward, this time drawing the whole line // with the HSL color, until the entire screen is flashing and pulsing crazily. // The lines are delayed by a random time interval to make it look more ... drippy. ////////////////////////////////////////////////////////////////////////// struct DrippyLine { int mSpeed; // Pixles per update the lines moves, < 0 for upward. int mX; int mDelay; // How long to wait before dripping down int mHeight; // How far it has dripped so far bool mDripUp; // Dripping upward or downward? DrippyLine(float s, int x, int d) {mSpeed = (int)s; mX = x; mDelay = d; mHeight = 0; mDripUp = false;} }; class GameOverEffect { private: // The states used for this effect enum { RED_FADE_IN, // The pulsating, red fade in that obscures the whole screen RED_HOLD, // We hold the fully opaque, red screen for a short interval for dramatic effect SHOWING_LETTERS, // Displaying the GAME OVER letters in dramatic style FADING_LETTERS, // Making them fade out SHOWING_STATS, // Displaying the user's game performance statistics DRIP_OUT // Doing the weird drippy effect that takes the user to a new game. }; // The whole time this effect is going on, we make these planet explosion animations trigger // randomly around the screen, again for dramatic but fun uselessness. std::vector mExplosion; std::vector mText; // The letters "GAME OVER" std::vector mLines; // Each of the drippy lines EndGameStats mStats; int mState; int mAlpha; // Used for fading the screen in/out int mRed; // The red value during the RED_ states pulses between 200 and 255. int mRedChange; // How fast (and which direction) the red pulsing is going int mUpdateCnt; // Since this isn't a widget, we'll manually track the number of times the update method is called int mHue; // For hue/saturation/luminence crazy weird flashing effect int mRedHoldCount; // Counter for the RED_HOLD state, when it drops to 0 we switch to SHOWING_LETTERS bool mFadeOut; // Indicates if the lines are done dripping and we're doing the final fade out bool mActive; // Indicates if the game over sequence is running or not bool mCanInitFirstLevel; // When true, indicates that the board should set up the first level so that it'll be there when we fade out ////////////////////////////////////////////////////////////////////////// // Function: Init // // Purpose: Sets up and initializes/resets all variables. ////////////////////////////////////////////////////////////////////////// void Init(); ////////////////////////////////////////////////////////////////////////// // Function: PulseRed // // Purpose: Convenience function that handles the pulsing of the red // value between 200 and 255. ////////////////////////////////////////////////////////////////////////// void PulseRed(); public: ////////////////////////////////////////////////////////////////////////// // GameOverEffect ////////////////////////////////////////////////////////////////////////// GameOverEffect(); ////////////////////////////////////////////////////////////////////////// // Draw ////////////////////////////////////////////////////////////////////////// void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Update ////////////////////////////////////////////////////////////////////////// void Update(void); ////////////////////////////////////////////////////////////////////////// // Function: CanInitFirstLevel // Returns: true or false, indicating if the first level can be setup for // restarting. // // Purpose: Called by the Board's Update method, this returns true // when the board should initialize the first level, so that when the // game over effect fades out, the level will appear underneath it. // When the function returns true, it automatically sets internal variables // so that the next time the function is called, it will return false, // preventing the Board from accidentally initializing the first level // multiple times. After the next call to Activate, it is allowed to // return true again. // // Once the screen is totally filled after closing the stats display, // the Board is allowed to init the first level. ////////////////////////////////////////////////////////////////////////// bool CanInitFirstLevel(void); ////////////////////////////////////////////////////////////////////////// // Function: CanStartNewGame // // Purpose: Returns true or false indicating if the user is allowed // to click to start a new game. This can only happen when the user // is viewing the stats and all other states have completed. // This will trigger the effects that transition to the start of a // new game. ////////////////////////////////////////////////////////////////////////// bool CanStartNewGame() {return mState == SHOWING_STATS;} ////////////////////////////////////////////////////////////////////////// // Function: HideBoard // Returns: true or false indicating whether or not the board should // hide all of its display stuff, except for the starfield which always // displays. ////////////////////////////////////////////////////////////////////////// bool HideBoard(); ////////////////////////////////////////////////////////////////////////// // Function: IsActive // Returns: true or false indicating if the sequence is running or not ////////////////////////////////////////////////////////////////////////// bool IsActive() {return mActive;} ////////////////////////////////////////////////////////////////////////// // Function: Activate // Parameters: // ls - A stat structure containing the info for the past level // // Purpose: Begins the game over sequence ////////////////////////////////////////////////////////////////////////// void Activate(EndGameStats es) {Init(); mActive = true; mStats = es;} ////////////////////////////////////////////////////////////////////////// // Function: DoneViewingStats // // Purpose: Called by Board when the user clicks the mouse button, // indicating that they want the stats screen to go away and have the // game restart. ////////////////////////////////////////////////////////////////////////// void DoneViewingStats(); }; } #endif // __GAME_OVER_EFFECT_H__ libtuxcap-1.4.0/tuxcap/hungarr/Res.h0000644000175000017500000000771010643254672017261 0ustar inniyahinniyah#ifndef __Res_H__ #define __Res_H__ namespace Sexy { class ResourceManager; class Image; class Font; Image* LoadImageById(ResourceManager *theManager, int theId); bool ExtractResourcesByName(ResourceManager *theManager, const char *theName); // Game Resources bool ExtractGameResources(ResourceManager *theMgr); extern Image* IMAGE_BG0; extern Image* IMAGE_BG1; extern Image* IMAGE_BG2; extern Image* IMAGE_BUTTON_DOWN; extern Image* IMAGE_BUTTON_NORMAL; extern Image* IMAGE_BUTTON_OVER; extern Image* IMAGE_CHECKBOX; extern Image* IMAGE_DIALOG_BOX; extern Image* IMAGE_DIALOG_BUTTON; extern Image* IMAGE_ROBOTROBOT; extern Image* IMAGE_SLIDER_THUMB; extern Image* IMAGE_SLIDER_TRACK; extern int SOUND_MUTATOR; extern int SOUND_TIMER; // Hungarr Resources bool ExtractHungarrResources(ResourceManager *theMgr); extern Image* IMAGE_ATOMIC_EXPLOSION; extern Image* IMAGE_BOMB_RADIAL_DEATH; extern Image* IMAGE_HUNGARR_BEAM_DOWN; extern Image* IMAGE_HUNGARR_BEAM_LEFT; extern Image* IMAGE_HUNGARR_BEAM_RIGHT; extern Image* IMAGE_HUNGARR_BEAM_UP; extern Image* IMAGE_HUNGARR_HORIZ; extern Image* IMAGE_HUNGARR_SMALL; extern Image* IMAGE_HUNGARR_VERT; extern Image* IMAGE_PARTICLE_LIGHTNING; extern Image* IMAGE_PLANETS; extern Image* IMAGE_SPARK; extern int SOUND_BEAM_HIT; extern int SOUND_BEAM_MOVING; extern int SOUND_BUTTON; extern int SOUND_EXPLOSION; extern int SOUND_GAME_OVER_CLICK; extern int SOUND_GAME_OVER_RESTART; extern int SOUND_GAME_OVER_STATS; extern int SOUND_GAME_OVER_TEXT; extern int SOUND_LEVEL_UP1; extern int SOUND_LEVEL_UP2; extern int SOUND_LEVEL_UP3; extern int SOUND_LEVEL_UP4; extern int SOUND_MAGZAP; extern int SOUND_PLANET; extern int SOUND_PLANET_HIT; extern int SOUND_REGION_FILLED; // Init Resources bool ExtractInitResources(ResourceManager *theMgr); extern Font* FONT_DEFAULT; extern Font* FONT_HUNGARR; extern Image* IMAGE_CUSTOM_DRAGGING; extern Image* IMAGE_CUSTOM_HAND; extern Image* IMAGE_CUSTOM_POINTER; extern Image* IMAGE_CUSTOM_TEXT; extern Image* IMAGE_HUNGARR_LOGO; // TitleScreen Resources bool ExtractTitleScreenResources(ResourceManager *theMgr); extern Image* IMAGE_LOADER_BAR; extern Image* IMAGE_LOADER_LOADINGTXT; extern int SOUND_CONTINUE; enum ResourceId { FONT_DEFAULT_ID, FONT_HUNGARR_ID, IMAGE_CUSTOM_POINTER_ID, IMAGE_CUSTOM_HAND_ID, IMAGE_CUSTOM_DRAGGING_ID, IMAGE_CUSTOM_TEXT_ID, IMAGE_HUNGARR_LOGO_ID, IMAGE_LOADER_BAR_ID, IMAGE_LOADER_LOADINGTXT_ID, SOUND_CONTINUE_ID, SOUND_MUTATOR_ID, SOUND_TIMER_ID, IMAGE_ROBOTROBOT_ID, IMAGE_CHECKBOX_ID, IMAGE_BG0_ID, IMAGE_BG1_ID, IMAGE_BG2_ID, IMAGE_BUTTON_DOWN_ID, IMAGE_BUTTON_OVER_ID, IMAGE_BUTTON_NORMAL_ID, IMAGE_DIALOG_BOX_ID, IMAGE_DIALOG_BUTTON_ID, IMAGE_SLIDER_TRACK_ID, IMAGE_SLIDER_THUMB_ID, IMAGE_HUNGARR_SMALL_ID, IMAGE_HUNGARR_BEAM_UP_ID, IMAGE_HUNGARR_BEAM_DOWN_ID, IMAGE_HUNGARR_BEAM_LEFT_ID, IMAGE_HUNGARR_BEAM_RIGHT_ID, IMAGE_HUNGARR_HORIZ_ID, IMAGE_HUNGARR_VERT_ID, IMAGE_ATOMIC_EXPLOSION_ID, IMAGE_BOMB_RADIAL_DEATH_ID, IMAGE_PLANETS_ID, IMAGE_SPARK_ID, IMAGE_PARTICLE_LIGHTNING_ID, SOUND_MAGZAP_ID, SOUND_BUTTON_ID, SOUND_PLANET_ID, SOUND_LEVEL_UP1_ID, SOUND_LEVEL_UP2_ID, SOUND_EXPLOSION_ID, SOUND_BEAM_HIT_ID, SOUND_PLANET_HIT_ID, SOUND_BEAM_MOVING_ID, SOUND_LEVEL_UP4_ID, SOUND_LEVEL_UP3_ID, SOUND_GAME_OVER_CLICK_ID, SOUND_GAME_OVER_STATS_ID, SOUND_GAME_OVER_RESTART_ID, SOUND_GAME_OVER_TEXT_ID, SOUND_REGION_FILLED_ID, RESOURCE_ID_MAX }; Image* GetImageById(int theId); Font* GetFontById(int theId); int GetSoundById(int theId); ResourceId GetIdByImage(Image *theImage); ResourceId GetIdByFont(Font *theFont); ResourceId GetIdBySound(int theSound); const char* GetStringIdById(int theId); ResourceId GetIdByStringId(const char *theStringId); } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/hungarr/GameApp.cpp0000644000175000017500000002000611062533667020366 0ustar inniyahinniyah#include "GameApp.h" #include "TitleScreen.h" #include "Board.h" #include "OptionsDialog.h" #include "WidgetManager.h" #include "ResourceManager.h" #include "Dialog.h" #include "Res.h" #include "MusicInterface.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { mProdName = "Hun-garr Needs Planets!"; mProductVersion = "1.0"; mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); mRegKey = "TuxCap\\Hungarr"; mWidth = 640; mHeight = 480; mDebugKeysEnabled = true; mWindowIconBMP = "images/unicron_baby.bmp"; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. //mAutoEnable3D = true; mBoard = NULL; mTitleScreen = NULL; // Enable smooth motion via UpdateF mVSyncUpdates = true; // Because it's annoying to hear the sound of the planets hitting a wall too many // times in a second, we'll limit how many can occur. mLastPlanetHitSoundTime = -30; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { if (mBoard != NULL) mWidgetManager->RemoveWidget(mBoard); delete mBoard; if (mTitleScreen != NULL) mWidgetManager->RemoveWidget(mTitleScreen); delete mTitleScreen; // Using "" deletes ALL resources mResourceManager->DeleteResources(""); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { SexyAppBase::Init(); LoadResourceManifest(); if (!mResourceManager->LoadResources("Init")) { mLoadingFailed = true; ShowResourceError(true); return; } if (!ExtractInitResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // To use custom cursors, you have to specify an image resource // to use. The CURSOR_ defines indicate which cursor type you // want to assign the image to. // CURSOR_POINTER is the normal Windows pointer. // CURSOR_HAND is used when mousing over widgets (if mDoFinger is true). // CURSOR_DRAGGING is used when a drag operation is happening. // CURSOR_TEXT is the icon used when entering text in an edit box. SetCursorImage(CURSOR_POINTER, IMAGE_CUSTOM_POINTER); SetCursorImage(CURSOR_HAND, IMAGE_CUSTOM_HAND); SetCursorImage(CURSOR_DRAGGING, IMAGE_CUSTOM_DRAGGING); SetCursorImage(CURSOR_TEXT, IMAGE_CUSTOM_TEXT); if (!mResourceManager->LoadResources("TitleScreen")) { mLoadingFailed = true; ShowResourceError(true); return; } if (!ExtractTitleScreenResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // Now let's create and add our title screen to the widget manager mTitleScreen = new TitleScreen(this); mTitleScreen->Resize(0, 0, mWidth, mHeight); // Let's let the title screen initialize it's widgets and data // before adding it to the widget manager: mTitleScreen->Init(); mWidgetManager->AddWidget(mTitleScreen); // This example just uses 1 standard OGG file instead of a tracker file. // Since we aren't cross fading at all, we'll only load it once. mMusicInterface->LoadMusic(0, "music/hungarr.ogg"); mMusicInterface->FadeIn(0, 0, 0.002, false); mNumLoadingThreadTasks = mResourceManager->GetNumResources("Game") + mResourceManager->GetNumResources("Hungarr"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { mResourceManager->StartLoadResources("Game"); while (mResourceManager->LoadNextResource()) { mCompletedLoadingThreadTasks++; if (mShutdown) return; mTitleScreen->MarkDirty(); } if (mResourceManager->HadError() || !ExtractGameResources(mResourceManager)) { ShowResourceError(false); mLoadingFailed = true; return; } mResourceManager->StartLoadResources("Hungarr"); while (mResourceManager->LoadNextResource()) { mCompletedLoadingThreadTasks++; if (mShutdown) return; mTitleScreen->MarkDirty(); } if (mResourceManager->HadError() || !ExtractHungarrResources(mResourceManager)) { ShowResourceError(false); mLoadingFailed = true; return; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); if (mLoadingFailed) return; mTitleScreen->LoadingComplete(); mTitleScreen->MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::TitleScreenIsFinished() { mTitleScreen = NULL; mBoard = new Board(this); mResourceManager->DeleteResources("TitleScreen"); mBoard->Resize(0, 0, mWidth, mHeight); mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Dialog* GameApp::NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader, const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode) { // Rather than dupliate a lengthy explanation, check out the top of DemoDialog.cpp for a complete description // of what all the parameters and functions are, in Demo5. Dialog* d = new Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, theDialogId, isModal, StringToSexyStringFast(theDialogHeader), StringToSexyStringFast(theDialogLines), StringToSexyStringFast(theDialogFooter), theButtonMode); d->SetButtonFont(FONT_DEFAULT); d->SetLinesFont(FONT_DEFAULT); d->SetHeaderFont(FONT_DEFAULT); d->SetColor(Dialog::COLOR_HEADER, Color::Black); d->SetColor(Dialog::COLOR_LINES, Color::Black); d->mSpaceAfterHeader = 30; d->Resize(100, 100, 300, 250); return d; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LostFocus() { SexyAppBase::LostFocus(); // When losing focus, we should pause the game board if (mBoard) mBoard->Pause(true); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::GotFocus() { SexyAppBase::GotFocus(); if (mBoard) mBoard->Pause(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::ButtonPress(int theId) { if (theId == OptionsDialog::MESSAGE_BOX_ID + 2000) KillDialog(theId - 2000); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::PlaySample(int theSoundNum) { // If playing the sound for when a planet hits a wall, only let it // play if it hasn't played the sound for at least 30 update frames // (30 hundredths of a second). if (theSoundNum == SOUND_PLANET_HIT) { if (mUpdateCount - mLastPlanetHitSoundTime > 30) { mLastPlanetHitSoundTime = mUpdateCount; SexyAppBase::PlaySample(theSoundNum); } } else SexyAppBase::PlaySample(theSoundNum); } libtuxcap-1.4.0/tuxcap/hungarr/GameOverEffect.cpp0000644000175000017500000003141410643254672021703 0ustar inniyahinniyah#pragma warning(disable:4244) #pragma warning(disable:4018) #include "GameOverEffect.h" #include "Res.h" #include "Board.h" #include "SexyAppBase.h" #include "Graphics.h" #include "Font.h" #include "Image.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameOverEffect::GameOverEffect() { Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameOverEffect::Init() { mState = GameOverEffect::RED_FADE_IN; mAlpha = 0; mRed = 200; mRedHoldCount = 100; mRedChange = 4; mActive = false; mUpdateCnt = 0; mHue = 0; mCanInitFirstLevel = false; mFadeOut = false; mExplosion.clear(); mText.clear(); mText.push_back(Letter(_S("G"))); mText.push_back(Letter(_S("A"))); mText.push_back(Letter(_S("M"))); mText.push_back(Letter(_S("E"))); mText.push_back(Letter(_S(" O"))); mText.push_back(Letter(_S("V"))); mText.push_back(Letter(_S("E"))); mText.push_back(Letter(_S("R"))); mLines.clear(); // Make as many lines as the screen is wide, and stagger them by a // random time up to 2 seconds, with speeds between 5 and 10 pixels per update. for (int i = 0; i < gSexyAppBase->mWidth; i++) mLines.push_back(DrippyLine((Rand() % 5) + 5, i, Rand() % 200)); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameOverEffect::Update(void) { ++mUpdateCnt; // HSL is an alternative to specifying an RGB color format. // Using HSL lets us easily do the hyper blinking crazy weird // flashing effect commonly found in old games, such as Robotron. // Below, we increment the value by 7 per update. The &0xFF is an // easy way to clamp the value between 0 and 255 instead of having to // do a separate if (mHue > 255) mHue -= 255. This lets the value // rollover and keep cycling. mHue = (mHue + 7) & 0xFF; if (!mFadeOut) { // 10 times per second we create a new planet explosion animation and place it at a random // position within the grid's area. if (mUpdateCnt % 10 == 0) { Explosion e; e.mFrame = 0; e.mX = GRID_START_X + (Rand() % (GRID_END_X - GRID_START_X - IMAGE_ATOMIC_EXPLOSION->GetCelWidth())); e.mY = GRID_START_Y + (Rand() % (GRID_END_Y - GRID_START_Y - IMAGE_ATOMIC_EXPLOSION->GetCelHeight())); mExplosion.push_back(e); } // Play a sound of a planet exploding ever 4th new planet. If we did this every single // planet, then 10 times per second you'd hear it, and trust me, it's really irritating. if ((mState == RED_FADE_IN) || (mState == RED_HOLD)) if (mUpdateCnt % 40 == 0) gSexyAppBase->PlaySample(SOUND_EXPLOSION); // Update each explosion animation. When it's done, remove it. for (int i = 0; i < mExplosion.size(); i++) { Explosion* e = &mExplosion[i]; // The animation runs at 20FPS, so every 5 updates step the frame. if (mUpdateCnt % 5 == 0) { if (++e->mFrame >+ IMAGE_ATOMIC_EXPLOSION->GetCelWidth()) { mExplosion.erase(mExplosion.begin() + i); --i; } } } } if (mState == GameOverEffect::RED_FADE_IN) { // Slowly make the red effect become fully opaque to cover // the screen, while at the same time making the red value // pulse between 200 and 255. if (++mAlpha >= 255) { mState = GameOverEffect::RED_HOLD; mAlpha = 255; } else PulseRed(); } else if (mState == GameOverEffect::RED_HOLD) { // Hold for 1 second, the red pulsing effect for dramatic fun if (--mRedHoldCount <= 0) { mState = GameOverEffect::SHOWING_LETTERS; mUpdateCnt = 0; gSexyAppBase->PlaySample(SOUND_GAME_OVER_TEXT); } else PulseRed(); } else if (mState == GameOverEffect::SHOWING_LETTERS) { // Start showing the GAME OVER letters. Fade out that fully // red screen, but still let it pulse while we do so. if (mAlpha > 0) { PulseRed(); mAlpha -= 2; } // Increase the red value on each letter by 2 per update. // Once one letter has a red value of 50, let the next letter // after it begin to fade in. Stop looping if a letter has less // than 50 for its red value. bool done = true; for (int i = 0; i < mText.size(); i++) { Letter* l = &mText[i]; if (l->mRed < 254) { done = false; l->mRed += 2; } if (l->mRed < 50) { done = false; break; } } if (done) mState = GameOverEffect::FADING_LETTERS; } else if (mState == GameOverEffect::FADING_LETTERS) { // Now make the lettesr fade out, starting with // the last letter. When a letter's red value drops // below 205, allow the letter before it to also begin // decreasing. bool done = true; for (int i = (int)mText.size() - 1; i >= 0; i--) { Letter* l = &mText[i]; if (l->mRed > 1) { done = false; l->mRed -= 2; } if (l->mRed > 205) { done = false; break; } } if (done) { mAlpha = 0; mState = GameOverEffect::SHOWING_STATS; gSexyAppBase->PlaySample(SOUND_GAME_OVER_STATS); } } else if ((mState == GameOverEffect::DRIP_OUT) && !mFadeOut) { // move the drippy lines, but we aren't fading the screen out yet. bool alldone = true; for (int i = 0; i < mLines.size(); i++) { // Once a line's starting delay has passed, it moves downward. // Once it reaches the bottom of the screen, it begins to then // move back upward. When all lines have moved upward, and thus the // whole screen is totally opaque, we can begin the fade out sequence. DrippyLine* dl = &mLines[i]; if (dl->mDelay > 0) { alldone = false; --dl->mDelay; } else if (!dl->mDripUp) { alldone = false; dl->mHeight += dl->mSpeed; if (dl->mHeight >= gSexyAppBase->mHeight) { dl->mHeight = 0; dl->mSpeed = 10; dl->mDripUp = true; } } else if (dl->mDripUp && (dl->mHeight < gSexyAppBase->mHeight)) { dl->mHeight += dl->mSpeed; if (dl->mHeight >= gSexyAppBase->mHeight) dl->mHeight = gSexyAppBase->mHeight; else alldone = false; } } if (alldone) { // Now that the screen is fully covered, allow the board to set up the first level mCanInitFirstLevel = true; mFadeOut = true; mAlpha = 255; } } else if ((mState == GameOverEffect::DRIP_OUT) && mFadeOut) { if (--mAlpha <= 0) mActive = false; } } /// ////////////////////////////////////////////////////////////////////////// void GameOverEffect::PulseRed() { mRed += mRedChange; if (mRed >= 255) { mRed = 255; mRedChange = -mRedChange; } else if (mRed <= 200) { mRed = 200; mRedChange = -mRedChange; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameOverEffect::Draw(Graphics* g) { // Draw explosions for every state except the final fade out if (!mFadeOut) { for (int i = 0; i < mExplosion.size(); i++) { Explosion* e = &mExplosion[i]; g->DrawImageCel(IMAGE_ATOMIC_EXPLOSION, e->mX, e->mY, e->mFrame); } } if ((mState == GameOverEffect::RED_FADE_IN) || (mState == GameOverEffect::RED_HOLD)) { g->SetColor(Color(mRed, 0, 0, mAlpha)); g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight); } else if ((mState == GameOverEffect::SHOWING_LETTERS) || (mState == GameOverEffect::FADING_LETTERS)) { g->SetFont(FONT_HUNGARR); int x = gSexyAppBase->mWidth / 2 - FONT_HUNGARR->StringWidth(_S("GAME OVER")) / 2; int y = gSexyAppBase->mHeight / 2; for (int i = 0; i < mText.size(); i++) { Letter* l = &mText[i]; if (l->mRed > 0) { g->SetColor(Color(l->mRed, 0, 0)); g->DrawString(l->mChar, x, y); x += FONT_HUNGARR->StringWidth(l->mChar); } } if (mAlpha > 0) { g->SetColor(Color(mRed, 0, 0, mAlpha)); g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight); } } else if (mState == GameOverEffect::SHOWING_STATS) { g->DrawImage(IMAGE_HUNGARR_LOGO, gSexyAppBase->mWidth / 2 - IMAGE_HUNGARR_LOGO->mWidth / 2, 10); g->SetFont(FONT_HUNGARR); g->SetColor(Color::White); int rightX = gSexyAppBase->mWidth / 2; int y = 100; SexyString s; int strWidth; s = _S("FINAL SCORE: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 0, 0)); g->DrawString(CommaSeperate(mStats.mScore), rightX, y); g->SetColor(Color::White); y += FONT_HUNGARR->GetHeight(); s = _S("LEVEL REACHED: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 0, 0)); g->DrawString(StrFormat(_S("%d"), mStats.mLevel), rightX, y); g->SetColor(Color::White); y += FONT_HUNGARR->GetHeight(); s = _S("TOTAL PLANETS EATEN: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 255, 0)); g->DrawString(StrFormat(_S("%d"), mStats.mNumPlanetsEaten), rightX, y); g->SetColor(Color::White); y += FONT_HUNGARR->GetHeight(); s = _S("TOTAL PEOPLE EATEN: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 255, 0)); g->DrawString(CommaSeperate(mStats.mPopulationConsumed), rightX, y); g->SetColor(Color::White); y += FONT_HUNGARR->GetHeight(); s = _S("TASTIEST PLANET: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(0, 255, 0)); g->DrawString(mStats.mFavoritePlanet, rightX, y); g->SetColor(Color::White); y += FONT_HUNGARR->GetHeight(); s = _S("EXPORT EATEN MOST: "); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(0, 255, 0)); g->DrawString(mStats.mFavoriteExport, rightX, y); } else if (mState == GameOverEffect::DRIP_OUT) { if (!mFadeOut) { // This is how we convert an HSL value to an RGB value, which we have to // do to specify the color for the graphics object. The function HSLToRGB // takes as parameters: hue, saturation, luminance. We want to leave the // saturation at max and luminance at half for our particular example. // The returned value is ANDed with 0xFFFFFFFF to clamp the values for // the alpha, red, green, and blue to the valid region of 0 to 255. Color hue = gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFFFF; for (int i = 0; i < mLines.size(); i++) { DrippyLine* dl = &mLines[i]; if (!dl->mDripUp && (dl->mDelay == 0)) { // Draw a black line, with its bottommost pixel using the HSL color g->SetColor(Color(0, 0, 0)); if (dl->mHeight > 0) g->DrawRect(Rect(dl->mX, 0, 1, dl->mHeight - 1)); g->SetColor(hue); g->DrawRect(Rect(dl->mX, dl->mHeight, 1, 1)); } else if (dl->mDelay == 0) { // Moving up, draw the line in HSL and the rest in black if (dl->mHeight < gSexyAppBase->mHeight) { g->SetColor(Color(0, 0, 0)); g->DrawRect(Rect(dl->mX, 0, 1, gSexyAppBase->mHeight - dl->mHeight)); } g->SetColor(hue); g->DrawRect(Rect(dl->mX, gSexyAppBase->mHeight - dl->mHeight, 1, dl->mHeight)); } } } else { // We AND the color with 0xFFFFFF instead of 0xFFFFFFFF. Then, we OR it with the alpha value // that we're fading out with shifted left 24 bits. // This then sticks the alpha value, which changes over time, // into our HSL color. As you may recall from previous demos, the actual color // structure is 32 bit, and looks like this in binary form: // AAAA RRRR GGGG BBBB Where A,R,G,B are alpha, red, green, blue. Color hue = (gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFF) | (mAlpha << 24); g->SetColor(hue); g->FillRect(0, 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool GameOverEffect::CanInitFirstLevel(void) { if (mCanInitFirstLevel) { mCanInitFirstLevel = false; return true; } return false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool GameOverEffect::HideBoard() { return (mState == GameOverEffect::SHOWING_LETTERS) || (mState == GameOverEffect::RED_HOLD) || (mState == GameOverEffect::FADING_LETTERS) || (mState == GameOverEffect::SHOWING_STATS) || ((mState == GameOverEffect::DRIP_OUT) && !mFadeOut); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameOverEffect::DoneViewingStats() { mState = DRIP_OUT; gSexyAppBase->PlaySample(SOUND_GAME_OVER_CLICK); gSexyAppBase->PlaySample(SOUND_GAME_OVER_RESTART); } libtuxcap-1.4.0/tuxcap/hungarr/TitleScreen.cpp0000644000175000017500000001333210643254672021301 0ustar inniyahinniyah#include "TitleScreen.h" #include "GameApp.h" #include "Res.h" #include "Font.h" #include "Graphics.h" #include "Image.h" #include "WidgetManager.h" #include "Rect.h" #include "HyperlinkWidget.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::TitleScreen(GameApp *pApp) { mApp = pApp; mContinueLink = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::~TitleScreen() { delete mContinueLink; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Init(void) { mContinueLink = new HyperlinkWidget(1, this); mContinueLink->SetFont(FONT_DEFAULT); mContinueLink->mLabel = _S("CLICK TO CONTINUE"); mContinueLink->mColor = Color(255, 255, 255); mContinueLink->mOverColor = Color(0, 255, 0); mContinueLink->mUnderlineSize = 1; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::AddedToManager(WidgetManager *theWidgetManager) { Widget::AddedToManager(theWidgetManager); mContinueLink->SetVisible(false); mContinueLink->SetDisabled(true); int labelWidth = FONT_DEFAULT->StringWidth(mContinueLink->mLabel); int labelHeight = FONT_DEFAULT->GetHeight(); mContinueLink->Resize( mWidth / 2 - labelWidth / 2, mHeight - labelHeight - 40, labelWidth, labelHeight+4); mContinueLink->mDoFinger = true; theWidgetManager->AddWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::RemovedFromManager(WidgetManager *theWidgetManager) { Widget::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Draw(Graphics *g) { g->SetColor(Color::Black); g->FillRect(0, 0, mWidth, mHeight); // We want to draw our loader bar to indicate the progress made in // loading all our resources. As you recalll, GameApp::LoadingThreadProc is // the thread that is actually loading everything. The app has a function, // GetLoadingThreadProgress, that returns a value from 0.0 to 1.0 indicating // the % complete it is. We will multiply this % complete by the width // of our progress bar, so that we give the illusion of a growing bar. int loaderBarWidth = IMAGE_LOADER_BAR->GetWidth(); int drawWidth = (int)(mApp->GetLoadingThreadProgress() * loaderBarWidth); if (drawWidth > 0) { // As you may recall from Demo3 where we drew the frames of animation // for the lightning image, the DrawImage call can take a source rectangle // which indicates what chunk of the original image we want to draw. // In our case, we want to start from from the upper left corner of // the loader bar, but we only want to draw "drawWidth" wide. This will // give the illusion that the progress bar is expanding as the resources // are loaded in. g->DrawImage(IMAGE_LOADER_BAR, mWidth / 2 - loaderBarWidth / 2, 400, Rect(0, 0, drawWidth, IMAGE_LOADER_BAR->GetHeight())); } // If our hyperlink widget is false, let's instead draw some // "Loading" text (er, actually in this case it's an image) where // it is located. if (mContinueLink->mVisible == false) g->DrawImage(IMAGE_LOADER_LOADINGTXT, (mWidth / 2) - (IMAGE_LOADER_LOADINGTXT->mWidth / 2), mContinueLink->mY - 80); g->DrawImage(IMAGE_HUNGARR_LOGO, mWidth / 2 - IMAGE_HUNGARR_LOGO->mWidth / 2, 100); g->SetColor(Color::White); g->SetFont(FONT_HUNGARR); SexyString s = _S("HUN-GARR NEEDS PLANETS!"); g->DrawString(s, mWidth / 2 - FONT_HUNGARR->StringWidth(s) / 2, 200); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::LoadingComplete() { // Since the app told us that we're done loading all our resources, // let's unhide and enable our continue link so the user can start // playing. mContinueLink->SetVisible(true); mContinueLink->SetDisabled(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::ButtonDepress(int theId) { if (theId == 1) { // Our hyperlink widget was pressed. We want to remove ourselves // and the hyperlink widget, and tell the app to display the // main board and get the game started. // You might be thinking, "If I delete the title screen and // hyperlink, won't I crash the program?" Yes, you will. That's // why we aren't going to delete them using "delete". We're going // to use SexyAppBase's SafeDeleteWidget method. This places the // widget in a queue that is processed after all widgets and data // get processed, and is then deleted at a time that is safe // and appropriate. We still have to remove ourself and the // hyperlink widget from the WidgetManager. We can easily access // the WidgetManager, as it is a public variable in our game app. mApp->mWidgetManager->RemoveWidget(this); mApp->mWidgetManager->RemoveWidget(mContinueLink); mApp->SafeDeleteWidget(this); mApp->SafeDeleteWidget(mContinueLink); mContinueLink = NULL; mApp->PlaySample(SOUND_CONTINUE); // Now let's tell the game app that it's ok to add the board widget: mApp->TitleScreenIsFinished(); } } libtuxcap-1.4.0/tuxcap/hungarr/OptionsDialog.cpp0000644000175000017500000002644510643254672021644 0ustar inniyahinniyah#include "OptionsDialog.h" #include "Res.h" #include "Board.h" #include "SexyAppBase.h" #include "WidgetManager.h" #include "Font.h" #include "DialogButton.h" #include "Checkbox.h" #include "Slider.h" using namespace Sexy; OptionsDialog::OptionsDialog(Board* b) : Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, OptionsDialog::DIALOG_ID, true, _S("OPTIONS"), _S(""), _S("CLOSE"), Dialog::BUTTONS_FOOTER) { mContentInsets = Insets(23, 20, 23, 20); mSpaceAfterHeader = 30; mBoard = b; SetHeaderFont(FONT_DEFAULT); SetLinesFont(FONT_DEFAULT); SetButtonFont(FONT_DEFAULT); SetColor(COLOR_HEADER, Color::Black); SetColor(COLOR_LINES, Color::Black); mMusicVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, OptionsDialog::MUSIC_SLIDER_ID, this); mMusicVolumeSlider->SetValue(gSexyAppBase->GetMusicVolume()); mSfxVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, OptionsDialog::SFX_SLIDER_ID, this); mSfxVolumeSlider->SetValue(gSexyAppBase->GetSfxVolume()); mQuitBtn = new DialogButton(IMAGE_DIALOG_BUTTON, OptionsDialog::QUIT_BTN_ID, this); mQuitBtn->mLabel = _S("QUIT GAME"); mQuitBtn->SetFont(FONT_DEFAULT); m3DCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, OptionsDialog::HARDWARE_CHECKBOX_ID, this); mFSCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, OptionsDialog::FS_CHECKBOX_ID, this); mCustomCursorsCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, OptionsDialog::FS_CHECKBOX_ID, this); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// OptionsDialog::~OptionsDialog() { delete mMusicVolumeSlider; delete mSfxVolumeSlider; delete mQuitBtn; delete mCustomCursorsCheckbox; delete m3DCheckbox; delete mFSCheckbox; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::Draw(Graphics* g) { Dialog::Draw(g); // Let's draw some labels for the sliders g->SetFont(FONT_DEFAULT); g->SetColor(Color::Black); // We draw the X/Y at the slider's X/Y but we subtract off the dialog box's // X/Y's from that. Why? The slider's XY's are in absolute screen coordinates, // as are the dialog boxes. But as you may recall from Board::Draw(), where // we explain graphics translation, once we get inside the draw loop of a // widget, the graphics object is already moved (translated) to the widget's // coordinates. Thus, in using the Graphics object, g, (0, 0) is located // at the top left corner of the widget (our dialog box). So we // just take the difference between the widget locations to produce the // actual location we want to drawour text at: g->DrawString(_S("Music volume:"), mMusicVolumeSlider->mX - mX, mMusicVolumeSlider->mY - mY - mMusicVolumeSlider->mHeight); g->DrawString(_S("Sound volume:"), mSfxVolumeSlider->mX - mX, mSfxVolumeSlider->mY - mY - mSfxVolumeSlider->mHeight); // Do the same for the checkboxes: g->DrawString(_S("3D Mode:"), m3DCheckbox->mX - mX - 25, m3DCheckbox->mY - mY - m3DCheckbox->mHeight + 20); g->DrawString(_S("Full Screen:"), mFSCheckbox->mX - mX - 25, mFSCheckbox->mY - mY - mFSCheckbox->mHeight + 20); g->DrawString(_S("Custom Cursors:"), mCustomCursorsCheckbox->mX - mX - 25, mCustomCursorsCheckbox->mY - mY - mCustomCursorsCheckbox->mHeight + 20); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::AddedToManager(WidgetManager* theWidgetManager) { Dialog::AddedToManager(theWidgetManager); theWidgetManager->AddWidget(mMusicVolumeSlider); theWidgetManager->AddWidget(mSfxVolumeSlider); theWidgetManager->AddWidget(mQuitBtn); int checkWidth = IMAGE_CHECKBOX->GetWidth() / 2; m3DCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); m3DCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mFSCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mFSCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mCustomCursorsCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mCustomCursorsCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); m3DCheckbox->mChecked = gSexyAppBase->Is3DAccelerated(); mFSCheckbox->mChecked = !gSexyAppBase->mIsWindowed; mCustomCursorsCheckbox->mChecked = gSexyAppBase->mCustomCursorsEnabled; theWidgetManager->AddWidget(m3DCheckbox); theWidgetManager->AddWidget(mFSCheckbox); theWidgetManager->AddWidget(mCustomCursorsCheckbox); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::RemovedFromManager(WidgetManager* theWidgetManager) { Dialog::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mMusicVolumeSlider); theWidgetManager->RemoveWidget(mSfxVolumeSlider); theWidgetManager->RemoveWidget(mQuitBtn); theWidgetManager->RemoveWidget(mCustomCursorsCheckbox); theWidgetManager->RemoveWidget(m3DCheckbox); theWidgetManager->RemoveWidget(mFSCheckbox); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::Resize(int theX, int theY, int theWidth, int theHeight) { Dialog::Resize(theX, theY, theWidth, theHeight); mMusicVolumeSlider->Resize(theX + mContentInsets.mLeft + 50, theY + 100, 245, IMAGE_SLIDER_THUMB->GetHeight()); mSfxVolumeSlider->Layout(LAY_SameLeft | LAY_Below | LAY_SameWidth | LAY_SameHeight, mMusicVolumeSlider, 0, 40, 0, 0); mQuitBtn->Layout(LAY_SameLeft | LAY_SameSize | LAY_Above, mYesButton); m3DCheckbox->Layout(LAY_SameLeft | LAY_Below, mSfxVolumeSlider, 0, 40, 0, 0); m3DCheckbox->Resize(m3DCheckbox->mX, m3DCheckbox->mY, IMAGE_CHECKBOX->mWidth / 2, IMAGE_CHECKBOX->mHeight); mFSCheckbox->Layout(LAY_SameTop | LAY_SameWidth | LAY_SameHeight | LAY_Right, m3DCheckbox, 80); mCustomCursorsCheckbox->Layout(LAY_SameTop | LAY_SameWidth | LAY_SameHeight | LAY_Right, mFSCheckbox, 80); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::SliderVal(int theId, double theVal) { if (theId == OptionsDialog::MUSIC_SLIDER_ID) { // Let's set the music volume to whatever the slider position is gSexyAppBase->SetMusicVolume(theVal); } else if (theId == OptionsDialog::SFX_SLIDER_ID) { // Set the sound value gSexyAppBase->SetSfxVolume(theVal); if (!mSfxVolumeSlider->mDragging) gSexyAppBase->PlaySample(SOUND_TIMER); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::ButtonDepress(int theId) { Dialog::ButtonDepress(theId); // Previously, before framework 1.2, the line below looked like: // else if (theId == 2000 + mId) // With the 1.2 changes, there's just 1 slight incompatibility. // If the DialogListener for a dialog your app (by default), and // you don't implement your own DialogButton(De)press method (see V12Demo for // more info on this), and instead are trapping button presses within ButtonDepress // inside the dialog itself, then instead of the button ID being 2000 or 3000 + mId, // it's just 0 for no/cancel/1-button dialog, and 1 for yes/ok. Hence we changed our // check to look for 0, which is our default single close button at the bottom of this // dialog. if (theId == ID_YES) { // Close button pressed. Tell the app to remove ourselves. This // will automatically safe delete the dialog at a later time. // Let's apply the 3D and fullscreen mode settings first though. // We call SwitchScreenMode. The first parameter is whether or not to run // windowed (false means fullscreen), the second is whether or not to do 3d. gSexyAppBase->SwitchScreenMode(!mFSCheckbox->mChecked, m3DCheckbox->mChecked); gSexyAppBase->EnableCustomCursors(mCustomCursorsCheckbox->mChecked); gSexyAppBase->KillDialog(this); mBoard->OptionsDialogDone(); } else if (theId == mQuitBtn->mId) { // Quit button pressed. Shut down the app. gSexyAppBase->Shutdown(); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void OptionsDialog::CheckboxChecked(int theId, bool checked) { // We'll wait until the dialog box is closed before actually applying any effects, // since it's rather jarring if as soon as a user clicks the 3d or fullscreen // toggle buttons to change right then and there. if (theId == m3DCheckbox->mId) { if (checked) { // Turn on 3D acceleration. But we need to check if the user is // even allowed to have it on. Some cards are just not compatible // with the framework (less than 8MB RAM for instance): if (!gSexyAppBase->Is3DAccelerationSupported()) { // It's not supported. Don't let the checkbox get checked. // Display an error dialog to the user to let them know why this happened. // The reason we don't use a Popup or Windows-based message box here is because // if the user was in full screen mode, they might not see the error message. Using // a game dialog box is the safest way to warn them. m3DCheckbox->SetChecked(false); gSexyAppBase->DoDialog(OptionsDialog::MESSAGE_BOX_ID, true, _S("Not Supported"), _S("Hardware acceleration can not be enabled on this computer. \nYour \ video card does not meet the minimum requirements for this game."), _S("OK"), Dialog::BUTTONS_FOOTER); } else if(!gSexyAppBase->Is3DAccelerationRecommended()) { // We can also check if 3D acceleration is not recommended for this computer // with a call to Is3DAccelerationRecommended. This allows the user to override // the default setting, but with a warning that it might not work or might cause // problems. Some cards fail the detection process but wind up being OK to use. gSexyAppBase->DoDialog(OptionsDialog::MESSAGE_BOX_ID, true, _S("Warning"), _S("Your video card may not fully support this feature.\n\ If you experience slower performance, please disable Hardware Acceleration."), _S("OK"), Dialog::BUTTONS_FOOTER); } } } else if (theId == mFSCheckbox->mId) { // Believe it or not, some people are not allowed to play in windowed mode. // You can only run in windowed mode if your desktop is 16 or 32 bit, and // if the resolution of their desktop is GREATER THAN the resolution of the // game. It doesn't make sense to run a 800x600 game windowed when your desktop // is 800x600 or less. // We can determine if the user is not allowed to run in windowed mode by // checking the value of SexyAppBase's mForceFullScreen variable. if (gSexyAppBase->mForceFullscreen && !checked) { gSexyAppBase->DoDialog(OptionsDialog::MESSAGE_BOX_ID, true, _S("No Windowed Mode"), _S("Windowed mode is only available if your desktop is running in\n\ either 16 bit or 32 bit color mode, which it is not."), _S("OK"), Dialog::BUTTONS_FOOTER); // re-check the box to indicate that fullscreen is still the selected mode: mFSCheckbox->SetChecked(true); } } } libtuxcap-1.4.0/tuxcap/hungarr/CMakeLists.txt0000644000175000017500000000415010762446645021117 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp TitleScreen.cpp OptionsDialog.cpp GameOverEffect.cpp LevelupEffect.cpp Board.cpp GameApp.h GameApp.cpp Res.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Hungarr") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/hungarr/Board.h0000644000175000017500000007436210641010443017546 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// #include "Widget.h" #include "ButtonListener.h" #include "Rect.h" namespace Sexy { class Graphics; class GameApp; class ButtonWidget; class WidgetManager; class LevelupEffect; class GameOverEffect; class SoundInstance; // Each grid piece is this many pixels wide/tall const int GRID_PIX_SIZE = 16; // Starting/ending Y coordinate of the grid (above it is the status display) const int GRID_START_Y = 128; const int GRID_END_Y = 480 - GRID_PIX_SIZE; // Starting/ending X coordinate of the grid const int GRID_START_X = GRID_PIX_SIZE; const int GRID_END_X = 640 - GRID_PIX_SIZE; // Total number of grid tiles wide/tall const int GRID_WIDTH = (GRID_END_X - GRID_START_X) / GRID_PIX_SIZE; const int GRID_HEIGHT = (GRID_END_Y - GRID_START_Y) / GRID_PIX_SIZE; // >= this percent begins the next level const int LEVELUP_PERCENT = 80; // >= this percent gives a bonus const int COMPLETION_BONUS_PCT = 85; // Bonus for >= COMPLETION_BONUS_PCT const int COMPLETION_BONUS = 20000; ////////////////////////////////////////////////////////////////////////// // Represents one segment of the two expanding lines that emit // from the cursor when the left mouse button is pressed on a valid // grid region. ////////////////////////////////////////////////////////////////////////// struct ExpandingLine { bool mIsVertical; // Orientation of the line // When the line reaches its target, that particular segment is done and planets can bounce off it. // If a planet hits it before its done, it will break and you will lose a life bool mDone; bool mBroken; // Indicates if the line broke and thus the player lost a life. float mX; float mY; float mWidth; float mHeight; float mTargetX; // XY coordinate the line is trying to reach float mTargetY; ExpandingLine() {mIsVertical = mDone = true; mBroken = false; mX = mY = mWidth = mHeight = mTargetX = mTargetY = 0;} }; ////////////////////////////////////////////////////////////////////////// // Represents one of the little grid squares on the board. // Each square can have 1 of 3 states. See the Board class for the states. ////////////////////////////////////////////////////////////////////////// struct GridTile { int mFillState; // A rectangle, used when the grid space is being filled in. This indicates // the actual region that is currently filled. The unfilled region is drawn // normally. Regions expand over time, and don't instantly fill up. FRect mFillRect; GridTile() {mFillState = 0;} }; ////////////////////////////////////////////////////////////////////////// // Represents one of the bouncing balls ("Planets" I suppose). For // fun, planets get a random name and export, which the player, "Hun-Garr", // eats. If a planet is inside a region as it fills, the planet will be // destroyed. Each planet destroyed makes the player's beams move faster, // up to a point. ////////////////////////////////////////////////////////////////////////// struct Planet { unsigned int mPopulation; // A fun little stat, indicates how many people live on the planet int mImgCol; // There are 11 planets, this is the column indicating the planet image to draw int mExplodeFrame; // When it's dying, this keeps track of the current frame of animation int mExplodeSpeed; // How fast the death animation runs int mNameIdx, mExportIdx; // Index into the two tables that contain planet names and export lists int mTimer; // Counter used for animation timing float mX, mY; float mVX, mVY; // X/Y speed float mRotationAngle; // In 3D mode, the planets rotate. This is the present angle float mRotateSpeed; // How fast he planet rotates, in 3D mode bool mExploding; // If true, the planet is dying and going through its explosion state Planet() {mPopulation = mImgCol = mExportIdx = mNameIdx = mTimer = 0; mX = mY = mVX = mVY = mRotationAngle = mRotateSpeed = 0; mExplodeSpeed = 8; mExplodeFrame = 0; mExploding = false;} }; ////////////////////////////////////////////////////////////////////////// // Used for the 3 layer star field effect. ////////////////////////////////////////////////////////////////////////// struct Star { float mX, mY; float mSpeed; // How fast the star is moving rightward Color mColor; // Color, for some depth perception trickery }; ////////////////////////////////////////////////////////////////////////// // The flashy bonus text that floats up when you get points ////////////////////////////////////////////////////////////////////////// struct BonusText { int mHue; // See the .CPP file for info on using hue/saturation/luminance values int mAlpha; // How faded out the text is float mX, mY; SexyString mText; BonusText() {mAlpha = 255; mHue = 0; mX = mY = 0;} }; ////////////////////////////////////////////////////////////////////////// // Used for the particle effects that fly off of the moving beams ////////////////////////////////////////////////////////////////////////// struct Particle { float mX, mY; float mVX, mVY; // X/Y speed int mFrame; // Which frame of animation it's on int mTimer; // Used to control the animation Particle(float x, float y, float vx, float vy) {mX = x, mY = y; mVX = vx; mVY = vy; mFrame = 0; mTimer = 0;} }; #define MAX_STARS 300 ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public ButtonListener { private: // The direction that the grid is being filled in enum { FILL_LEFT, FILL_RIGHT, FILL_UP, FILL_DOWN }; // The possible states for each little grid cube enum { GRID_NORMAL, // Drawn regularly, not filled in GRID_FILLING, // In the process of being filled in, will partially draw filled and normal GRID_FILLED // Totally filled in, piece now acts as a wall and draws differently }; // For the stats at the end of the game that display the planet and export you ate the most, // we keep track of them in the maps below. The key is the index from the PLANET_NAME or // PLANET_EXPORTS table, and the value is the number of times it has been consumed. Reset on death std::map mPlanetIdxCount; std::map mExportIdxCount; std::vector mBonusText; std::vector mPlanets; // A list of all the planets bouncing on the level // When a planet is eaten, we dump its name, export, and population (comma delimited) in that // order into this list, which will be passed to the level up class for a stats summary of // the past level. std::vector mPlanetsEaten; std::vector mParticles; GameApp* mApp; // The two beams that the player emits with a left click. Line 1 is ALWAYS either // up or left, and line 2 is ALWAYS either down or right. ExpandingLine mMovingLine1, mMovingLine2; GridTile** mGridState; // 2D array of all the grid tiles Insets mFillRegion; // Indicates the rectangular region being filled. Star mStarField[MAX_STARS]; LevelupEffect* mLevelupEffect; GameOverEffect* mGameOverEffect; ButtonWidget* mOptionsBtn; // The shorting out, electrical sound of the beams moving. We use a SoundInstance pointer // because we want to loop the sound while the beam is moving, and stop it when done. // This is easiest done manually. SoundInstance* mShortSound; bool mHungarrIsVertical; // Orientation of the player: will the lines come out vertical or horizontal? bool mFilling; // Is the grid currently being filled? int mFillDirection; // One of the FILL_ enums int mHungarrX, mHungarrY; // XY of the IMAGE of the player, not exactly where the beams go though int mLevel; int mPopulationEaten; // Number of people eaten this level int mTotalPopulationEaten; // Total number of people eaten this game int mNumPlanetsEaten; // Total number of planets eaten this game int mPercentComplete; // What % filled the grid is // Indicates the number of times the game has been asked to pause. When unpausing, we decrement // this value. Not really needed in this game, but in general a good idea, as every time a dialog // box pops up or the app loses focus or anything like that, you'll want to only fully unpause // everything when ALL the elements that requested a pause are complete, and not just one of them. int mPauseLevel; int mBorderHue; // HSL value of the border for a flashing effect. See .CPP for more info int mFlashCount; // How long the border will flash for int mLives; int mScore; int mBeamPulseVal; // Current intensity for the pulsing effect of the moving beams int mBeamPulseAmt; // Current amount to inc/dec the intensity by for a pulsing effect float mLine1X, mLine1Y; // XYs of the two lines that are drawn underneath Hun-garr. These float mLine2X, mLine2Y; // are always drawn and are not the same as the moving line positions. float mLineSpeed; // Gets faster with each planet destroyed float mFillSpeed; // How quickly to fill in the grid // Current max rate the planets can move at. Used with the planet's angle of motion to determine separate // XY movement values. This increases with each level. float mPlanetSpeed; private: ////////////////////////////////////////////////////////////////////////// // Function: UpdateHungarrPosition // Parameters: // x, y - Pixel location of the Windows cursor // // Purpose: Given a pixel location of the pointer, if it is within the // valid bounds of the grid region, will update the XY to draw the // Hun-garr bitmap at, as well as the little pulsing beams that are attached. ////////////////////////////////////////////////////////////////////////// void UpdateHungarrPosition(int x, int y); ////////////////////////////////////////////////////////////////////////// // Function: UpdatePercentComplete // // Purpose: After the lines are done moving, this is called to see how // full the grid is, and potentially take the player to the next level. ////////////////////////////////////////////////////////////////////////// void UpdatePercentComplete(void); ////////////////////////////////////////////////////////////////////////// // Function: DrawMovingBeams // Parameters: // g - Graphics object to draw to // // Purpose: Helper function, draws the beams as they move across the grid. ////////////////////////////////////////////////////////////////////////// void DrawMovingBeams(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Beam1DrawHelper // Parameters: // g - Graphics object to draw to // // Purpose: Convenience function for DrawMovingBeams to avoid copy/pasting ////////////////////////////////////////////////////////////////////////// void Beam1DrawHelper(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Beam2DrawHelper // Parameters: // g - Graphics object to draw to // // Purpose: Convenience function for DrawMovingBeams to avoid copy/pasting ////////////////////////////////////////////////////////////////////////// void Beam2DrawHelper(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawGrid // Parameters: // g - Graphics object to draw to // // Purpose: Draws all the little rectangles that make up the grid. ////////////////////////////////////////////////////////////////////////// void DrawGrid(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawPlanets // Parameters: // g - Graphics object to draw to // // Purpose: Draws all the planets, convenience function ////////////////////////////////////////////////////////////////////////// void DrawPlanets(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawGrid // Parameters: // g - Graphics object to draw to // // Purpose: Draws the player bitmap and the two pulsing lines that are // attached. ////////////////////////////////////////////////////////////////////////// void DrawHungarr(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawHungarrVertBeamsHelper // Parameters: // g - Graphics object to draw to // // Purpose: Helper function for DrawGrid to avoid copy/pasting ////////////////////////////////////////////////////////////////////////// void DrawHungarrVertBeamsHelper(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawHungarrHorizBeamsHelper // Parameters: // g - Graphics object to draw to // // Purpose: Helper function for DrawGrid to avoid copy/pasting ////////////////////////////////////////////////////////////////////////// void DrawHungarrHorizBeamsHelper(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: DrawUI // Parameters: // g - Graphics object to draw to // // Purpose: Draws the interface elements of the game, such as the stats. ////////////////////////////////////////////////////////////////////////// void DrawUI(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: FillRectF // Parameters: // g - Graphics object to draw to // fr - FRect to draw // // Purpose: Convenience function, since you can't pass an FRect to DrawRect. // Just converts the FRect to a normal Rect. We use FRects though for // more precise motion control. ////////////////////////////////////////////////////////////////////////// void FillRectF(Graphics* g, FRect fr); ////////////////////////////////////////////////////////////////////////// // Function: FillLeft // Parameters: // amt - How many pixels to fill // // Purpose: Updates the filling of the grid if it's moving leftward. ////////////////////////////////////////////////////////////////////////// void FillLeft(float amt); ////////////////////////////////////////////////////////////////////////// // Function: FillRight // Parameters: // amt - How many pixels to fill // // Purpose: Updates the filling of the grid if it's moving rightward. ////////////////////////////////////////////////////////////////////////// void FillRight(float amt); ////////////////////////////////////////////////////////////////////////// // Function: FillUp // Parameters: // amt - How many pixels to fill // // Purpose: Updates the filling of the grid if it's moving upward. ////////////////////////////////////////////////////////////////////////// void FillUp(float amt); ////////////////////////////////////////////////////////////////////////// // Function: FillDown // Parameters: // amt - How many pixels to fill // // Purpose: Updates the filling of the grid if it's moving downward. ////////////////////////////////////////////////////////////////////////// void FillDown(float amt); ////////////////////////////////////////////////////////////////////////// // Function: CalculateFillRegions // // Purpose: Determines which areas need to be filled, once the grid lines // are done moving. ////////////////////////////////////////////////////////////////////////// void CalculateFillRegions(void); ////////////////////////////////////////////////////////////////////////// // Function: GetVerticalFillValues // Parameters: // startCol - Column in which the beams were released // topRow - The row that the top line reached // botRow - The row the the bottom line reached // dir - 1 to compute the target fill line in the rightward direction, // -1 to compute it in the leftward direction. // edge - Set to the column that the filling should proceed towards // // Purpose: Given a direction to look in, finds a column to fill to. // The column selected is the first column found where EVERY grid piece // in it, from topRow to botRow, is in the normal grid state. If one is // not found, the farthest grid edge is used. Partially filled lines are // bypassed. This is used to get the CLOSEST edge to fill to for both of // the possible directions: the edge that is closest to the player is // selected and filling will proceed in that direction. ////////////////////////////////////////////////////////////////////////// void GetVerticalFillValues(int startCol, int topRow, int botRow, int dir, int* edge); ////////////////////////////////////////////////////////////////////////// // Function: GetHorizontalFillValues // Parameters: // startRow - Row in which the beams were released // leftCol - The column that the left line reached // rightCol - The column the the right line reached // dir - 1 to compute the target fill line in the downward direction, // -1 to compute it in the upward direction. // edge - Set to the column that the filling should proceed towards // // Purpose: Given a direction to look in, finds a row to fill to. // The row selected is the first row found where EVERY grid piece // in it, from leftCol to rightCol, is in the normal grid state. If one is // not found, the farthest grid edge is used. Partially filled lines are // bypassed. This is used to get the CLOSEST edge to fill to for both of // the possible directions: the edge that is closest to the player is // selected and filling will proceed in that direction. ////////////////////////////////////////////////////////////////////////// void GetHorizontalFillValues(int startRow, int leftCol, int rightCol, int dir, int* edge); ////////////////////////////////////////////////////////////////////////// // Function: MoveLines // Parameters: // theFrac - Value from UpdateF, used for smooth motion // // Purpose: Handles the moving of the lines once released. ////////////////////////////////////////////////////////////////////////// void MoveLines(float theFrac); ////////////////////////////////////////////////////////////////////////// // Function: MovePlanet // Parameters: // theFrac - Value from UpdateF, used for smooth motion // // Returns: true or false indicating if the planet blew up or not. // // Purpose: Handles the moving/bouncing of the planets ////////////////////////////////////////////////////////////////////////// bool MovePlanet(Planet* p, float theFrac); ////////////////////////////////////////////////////////////////////////// // Function: CheckPlanetBeamCollision // Parameters: // p - A planet to check for collision // // Purpose: Called by MoveLines, checks to see if the given planet // collided with either of the beams. If a beam is still moving, // it will break and the player will lose a life (only 1 life can // be lost though, even if both are broken you don't lose 2 lives). // If the beam is not moving, the planet will bounce off of it. ////////////////////////////////////////////////////////////////////////// void CheckPlanetBeamCollision(Planet* p); ////////////////////////////////////////////////////////////////////////// // Function: InitLevel // Parameters: // level - The level to set up // // Purpose: Initializes the next level ////////////////////////////////////////////////////////////////////////// void InitLevel(int level); ////////////////////////////////////////////////////////////////////////// // Function: GivePlanetBonus // Parameters: // p - The planet that was destroyed // // Purpose: Awards bonuses for destroying a planet and emits bonus text. ////////////////////////////////////////////////////////////////////////// void GivePlanetBonus(Planet* p); ////////////////////////////////////////////////////////////////////////// // Function: AddBonusText // Parameters: // t - The text to add // // Purpose: Adds floating bonus text to the center of the screen ////////////////////////////////////////////////////////////////////////// void AddBonusText(SexyString t); ////////////////////////////////////////////////////////////////////////// // Function: AddBonusText // Parameters: // t - The text to add // x, y - Coordinates to add the text at // // Purpose: Allows exact placement of the bonus text ////////////////////////////////////////////////////////////////////////// void AddBonusText(SexyString t, float x, float y); ////////////////////////////////////////////////////////////////////////// // Function: LostLife // // Purpose: Convenience function, used to decrement the player's // life and if it reaches 0, to start the end game sequence. ////////////////////////////////////////////////////////////////////////// void LostLife(void); ////////////////////////////////////////////////////////////////////////// // Function: EmitSparks // // Purpose: Every frame, sends out more sparks from the edges of // the two beams if they are moving. ////////////////////////////////////////////////////////////////////////// void EmitSparks(void); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: KeyChar // Parameters: // theChar - The ASCII character pressed // // Purpose: Called by the WidgetManager if a key is pressed and the Board // has focus. Used to see if space was pressed, to toggle pause state. ////////////////////////////////////////////////////////////////////////// virtual void KeyChar(char theChar); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: UpdateF // Parameters: // theFrac - The number of updates this time slice represents. // // Returns: none // // Purpose: Like Update, but allows for smooth motion. See previous // demos or the doc for a lengthy explanation. ////////////////////////////////////////////////////////////////////////// virtual void UpdateF(float theFrac); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: MouseMove // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime the // mouse moves. The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored. ////////////////////////////////////////////////////////////////////////// virtual void MouseMove(int x, int y); ////////////////////////////////////////////////////////////////////////// // Function: MouseDown // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // theClickCount - An integer indicating which mouse button // was pressed. One of the following: // 1: Left button // 2: Double-left-click // 3: Middle button // -1: Right button // -2: Double-right-click // // IMPORTANT: Because you can't have a double click with a // single click, you will receive BOTH a left (or right) button as well // as a double left (or right) button message whenever you double-click. // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime // a mouse button is in the down state. // The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored. ////////////////////////////////////////////////////////////////////////// virtual void MouseDown(int x, int y, int theClickCount); ////////////////////////////////////////////////////////////////////////// // Function: MouseDrag // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime the // mouse moves AND a button is held down. This is the same thing as // MouseMove except that it represents a drag operation. When dragging, // MouseDrag will be called INSTEAD OF MouseMove. // The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored. ////////////////////////////////////////////////////////////////////////// virtual void MouseDrag(int x, int y); ////////////////////////////////////////////////////////////////////////// // Function: Pause // Parameters: // p - Boolean indicating pause or unpause // // Purpose: Pauses/unpauses the game ////////////////////////////////////////////////////////////////////////// void Pause(bool p); ////////////////////////////////////////////////////////////////////////// // Function: OptionsDialogDone // // Purpose: Called by the options dialog box when it closes, so the board // can perform some misc tasks. ////////////////////////////////////////////////////////////////////////// void OptionsDialogDone(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/hungarr/GameApp.h0000644000175000017500000001515610644223762020042 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. // // IMPORTANT: Comments for topics covered in the previous demos will // be kept to a minimum and removed in most cases. You should read through // the previous demos to familiarize yourself with anything you don't // understand. All functions, variables, and concepts are explained // either in this demo, or in previous ones if they've already been covered. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" namespace Sexy { class Board; class TitleScreen; class GameApp : public SexyAppBase { private: Board* mBoard; TitleScreen* mTitleScreen; // Because it's annoying to hear the sound of the planets hitting a wall too many // times in a second, we'll limit how many can occur. int mLastPlanetHitSoundTime; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader screen, would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); ////////////////////////////////////////////////////////////////////////// // Function: TitleScreenIsFinished // Parameters: none // Returns: none // // Purpose: Called by the TitleScreen widget when it is about to close // down, this indicates that we should now add the board widget and // start the game. ////////////////////////////////////////////////////////////////////////// void TitleScreenIsFinished(); ////////////////////////////////////////////////////////////////////////// // Function: NewDialog // Parameters: // theDialogId - Unique ID to give this dialog box // isModal - If true, only itself and widgets above it receive // input events. // theDialogHeader - String to display in the header part of the dialog box // theDialogLines - String to use for the body of the dialog. May use // \n characters to indicate new lines. // theDialogFooter - If the button mode is BUTTONS_FOOTER, this is the text // to use for the button, otherwise ignored. // theButtonMode - One of 3 settings: Dialog::BUTTONS_YES_NO creates two // "Yes" "No" buttons, Dialog::BUTTONS_OK_CANCEL creates two // "OK" "Cancel" buttons, Dialog::BUTTONS_FOOTER creates one // button with the text from theDialogFooter. // // Returns: A new dialog pointer for use by SexyAppBase's DoDialog method. // // Purpose: SexyAppBase contains a convenience function, DoDialog, that relies on // this overriden function. DoDialog calls NewDialog which instructs it how to make // a dialog box. You should use DoDialog to create and add your dialog boxes. // The reason for this function is to allow for customized dialog boxes and to avoid // having to have a gigantic function with every possible parameter to pass to the Dialog's // constructor. ////////////////////////////////////////////////////////////////////////// virtual Dialog* NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader, const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode); ////////////////////////////////////////////////////////////////////////// // Function: LostFocus // Parameters: none // Returns: none // // Purpose: Called when the game itself loses focus, such as the user switch // to another application. ////////////////////////////////////////////////////////////////////////// virtual void LostFocus(void); ////////////////////////////////////////////////////////////////////////// // Function: GotFocus // Parameters: none // Returns: none // // Purpose: Called when the app regains focus after losing it. ////////////////////////////////////////////////////////////////////////// virtual void GotFocus(void); ////////////////////////////////////////////////////////////////////////// // Function: ButtonPress: // Parameters: // theId - ID of the button pressed // // Returns: none // // Purpose: Called when the button is pressed, but before the mouse is // released (which would instead generate a ButtonDepress event). ////////////////////////////////////////////////////////////////////////// virtual void ButtonPress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: PlaySample // Parameters: // theSoundNum - The sound ID to play // Returns: none // // Purpose: Plays the sample at normal pitch with no panning. ////////////////////////////////////////////////////////////////////////// virtual void PlaySample(int theSoundNum); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/hungarr/OptionsDialog.h0000644000175000017500000000576710641010445021277 0ustar inniyahinniyah////////////////////////////////////////////////////////////////////////// // OptionsDialog.h // // Represents a standard options dialog box where the user can toggle // 3D mode, full screen, custom cursors, adjust sound volumes, and // quit the game. ////////////////////////////////////////////////////////////////////////// #ifndef __OPTIONS_DIALOG_H__ #define __OPTIONS_DIALOG_H__ #include "Dialog.h" #include "SliderListener.h" #include "CheckboxListener.h" namespace Sexy { class Graphics; class Slider; class DialogButton; class Checkbox; class Board; class OptionsDialog : public Dialog, public SliderListener, public CheckboxListener { protected: Slider* mMusicVolumeSlider; Slider* mSfxVolumeSlider; DialogButton* mQuitBtn; Board* mBoard; public: enum { MUSIC_SLIDER_ID, SFX_SLIDER_ID, QUIT_BTN_ID, FS_CHECKBOX_ID, HARDWARE_CHECKBOX_ID, CUSTOM_CURSORS_CHECKBOX_ID, MESSAGE_BOX_ID, DIALOG_ID }; Checkbox* m3DCheckbox; Checkbox* mFSCheckbox; Checkbox* mCustomCursorsCheckbox; public: ////////////////////////////////////////////////////////////////////////// // Function: OptionsDialog // Parameters: // b - A pointer to the board, used to unpause when dialog closes // // Returns: none ////////////////////////////////////////////////////////////////////////// OptionsDialog(Board* b); virtual ~OptionsDialog(); ////////////////////////////////////////////////////////////////////////// // Draw ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // ButtonDepress ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // AddedToManager ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // RemovedFromManager ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Resize ////////////////////////////////////////////////////////////////////////// virtual void Resize(int theX, int theY, int theWidth, int theHeight); ////////////////////////////////////////////////////////////////////////// // SliderVal ////////////////////////////////////////////////////////////////////////// virtual void SliderVal(int theId, double theVal); ////////////////////////////////////////////////////////////////////////// // CheckboxChecked ////////////////////////////////////////////////////////////////////////// void CheckboxChecked(int theId, bool checked); }; } #endif libtuxcap-1.4.0/tuxcap/hungarr/Res.cpp0000644000175000017500000003023310643254672017610 0ustar inniyahinniyah#include "Res.h" #include "ResourceManager.h" using namespace Sexy; #pragma warning(disable:4311 4312) static bool gNeedRecalcVariableToIdMap = false; bool Sexy::ExtractResourcesByName(ResourceManager *theManager, const char *theName) { if (strcmp(theName,"Game")==0) return ExtractGameResources(theManager); if (strcmp(theName,"Hungarr")==0) return ExtractHungarrResources(theManager); if (strcmp(theName,"Init")==0) return ExtractInitResources(theManager); if (strcmp(theName,"TitleScreen")==0) return ExtractTitleScreenResources(theManager); return false; } Sexy::ResourceId Sexy::GetIdByStringId(const char *theStringId) { typedef std::map MyMap; static MyMap aMap; if(aMap.empty()) { for(int i=0; isecond; } // Game Resources Image* Sexy::IMAGE_BG0; Image* Sexy::IMAGE_BG1; Image* Sexy::IMAGE_BG2; Image* Sexy::IMAGE_BUTTON_DOWN; Image* Sexy::IMAGE_BUTTON_NORMAL; Image* Sexy::IMAGE_BUTTON_OVER; Image* Sexy::IMAGE_CHECKBOX; Image* Sexy::IMAGE_DIALOG_BOX; Image* Sexy::IMAGE_DIALOG_BUTTON; Image* Sexy::IMAGE_ROBOTROBOT; Image* Sexy::IMAGE_SLIDER_THUMB; Image* Sexy::IMAGE_SLIDER_TRACK; int Sexy::SOUND_MUTATOR; int Sexy::SOUND_TIMER; bool Sexy::ExtractGameResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_BG0 = aMgr.GetImageThrow("IMAGE_BG0"); IMAGE_BG1 = aMgr.GetImageThrow("IMAGE_BG1"); IMAGE_BG2 = aMgr.GetImageThrow("IMAGE_BG2"); IMAGE_BUTTON_DOWN = aMgr.GetImageThrow("IMAGE_BUTTON_DOWN"); IMAGE_BUTTON_NORMAL = aMgr.GetImageThrow("IMAGE_BUTTON_NORMAL"); IMAGE_BUTTON_OVER = aMgr.GetImageThrow("IMAGE_BUTTON_OVER"); IMAGE_CHECKBOX = aMgr.GetImageThrow("IMAGE_CHECKBOX"); IMAGE_DIALOG_BOX = aMgr.GetImageThrow("IMAGE_DIALOG_BOX"); IMAGE_DIALOG_BUTTON = aMgr.GetImageThrow("IMAGE_DIALOG_BUTTON"); IMAGE_ROBOTROBOT = aMgr.GetImageThrow("IMAGE_ROBOTROBOT"); IMAGE_SLIDER_THUMB = aMgr.GetImageThrow("IMAGE_SLIDER_THUMB"); IMAGE_SLIDER_TRACK = aMgr.GetImageThrow("IMAGE_SLIDER_TRACK"); SOUND_MUTATOR = aMgr.GetSoundThrow("SOUND_MUTATOR"); SOUND_TIMER = aMgr.GetSoundThrow("SOUND_TIMER"); } catch(ResourceManagerException&) { return false; } return true; } // Hungarr Resources Image* Sexy::IMAGE_ATOMIC_EXPLOSION; Image* Sexy::IMAGE_BOMB_RADIAL_DEATH; Image* Sexy::IMAGE_HUNGARR_BEAM_DOWN; Image* Sexy::IMAGE_HUNGARR_BEAM_LEFT; Image* Sexy::IMAGE_HUNGARR_BEAM_RIGHT; Image* Sexy::IMAGE_HUNGARR_BEAM_UP; Image* Sexy::IMAGE_HUNGARR_HORIZ; Image* Sexy::IMAGE_HUNGARR_SMALL; Image* Sexy::IMAGE_HUNGARR_VERT; Image* Sexy::IMAGE_PARTICLE_LIGHTNING; Image* Sexy::IMAGE_PLANETS; Image* Sexy::IMAGE_SPARK; int Sexy::SOUND_BEAM_HIT; int Sexy::SOUND_BEAM_MOVING; int Sexy::SOUND_BUTTON; int Sexy::SOUND_EXPLOSION; int Sexy::SOUND_GAME_OVER_CLICK; int Sexy::SOUND_GAME_OVER_RESTART; int Sexy::SOUND_GAME_OVER_STATS; int Sexy::SOUND_GAME_OVER_TEXT; int Sexy::SOUND_LEVEL_UP1; int Sexy::SOUND_LEVEL_UP2; int Sexy::SOUND_LEVEL_UP3; int Sexy::SOUND_LEVEL_UP4; int Sexy::SOUND_MAGZAP; int Sexy::SOUND_PLANET; int Sexy::SOUND_PLANET_HIT; int Sexy::SOUND_REGION_FILLED; bool Sexy::ExtractHungarrResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_ATOMIC_EXPLOSION = aMgr.GetImageThrow("IMAGE_ATOMIC_EXPLOSION"); IMAGE_BOMB_RADIAL_DEATH = aMgr.GetImageThrow("IMAGE_BOMB_RADIAL_DEATH"); IMAGE_HUNGARR_BEAM_DOWN = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_DOWN"); IMAGE_HUNGARR_BEAM_LEFT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_LEFT"); IMAGE_HUNGARR_BEAM_RIGHT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_RIGHT"); IMAGE_HUNGARR_BEAM_UP = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_UP"); IMAGE_HUNGARR_HORIZ = aMgr.GetImageThrow("IMAGE_HUNGARR_HORIZ"); IMAGE_HUNGARR_SMALL = aMgr.GetImageThrow("IMAGE_HUNGARR_SMALL"); IMAGE_HUNGARR_VERT = aMgr.GetImageThrow("IMAGE_HUNGARR_VERT"); IMAGE_PARTICLE_LIGHTNING = aMgr.GetImageThrow("IMAGE_PARTICLE_LIGHTNING"); IMAGE_PLANETS = aMgr.GetImageThrow("IMAGE_PLANETS"); IMAGE_SPARK = aMgr.GetImageThrow("IMAGE_SPARK"); SOUND_BEAM_HIT = aMgr.GetSoundThrow("SOUND_BEAM_HIT"); SOUND_BEAM_MOVING = aMgr.GetSoundThrow("SOUND_BEAM_MOVING"); SOUND_BUTTON = aMgr.GetSoundThrow("SOUND_BUTTON"); SOUND_EXPLOSION = aMgr.GetSoundThrow("SOUND_EXPLOSION"); SOUND_GAME_OVER_CLICK = aMgr.GetSoundThrow("SOUND_GAME_OVER_CLICK"); SOUND_GAME_OVER_RESTART = aMgr.GetSoundThrow("SOUND_GAME_OVER_RESTART"); SOUND_GAME_OVER_STATS = aMgr.GetSoundThrow("SOUND_GAME_OVER_STATS"); SOUND_GAME_OVER_TEXT = aMgr.GetSoundThrow("SOUND_GAME_OVER_TEXT"); SOUND_LEVEL_UP1 = aMgr.GetSoundThrow("SOUND_LEVEL_UP1"); SOUND_LEVEL_UP2 = aMgr.GetSoundThrow("SOUND_LEVEL_UP2"); SOUND_LEVEL_UP3 = aMgr.GetSoundThrow("SOUND_LEVEL_UP3"); SOUND_LEVEL_UP4 = aMgr.GetSoundThrow("SOUND_LEVEL_UP4"); SOUND_MAGZAP = aMgr.GetSoundThrow("SOUND_MAGZAP"); SOUND_PLANET = aMgr.GetSoundThrow("SOUND_PLANET"); SOUND_PLANET_HIT = aMgr.GetSoundThrow("SOUND_PLANET_HIT"); SOUND_REGION_FILLED = aMgr.GetSoundThrow("SOUND_REGION_FILLED"); } catch(ResourceManagerException&) { return false; } return true; } // Init Resources Font* Sexy::FONT_DEFAULT; Font* Sexy::FONT_HUNGARR; Image* Sexy::IMAGE_CUSTOM_DRAGGING; Image* Sexy::IMAGE_CUSTOM_HAND; Image* Sexy::IMAGE_CUSTOM_POINTER; Image* Sexy::IMAGE_CUSTOM_TEXT; Image* Sexy::IMAGE_HUNGARR_LOGO; bool Sexy::ExtractInitResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { FONT_DEFAULT = aMgr.GetFontThrow("FONT_DEFAULT"); FONT_HUNGARR = aMgr.GetFontThrow("FONT_HUNGARR"); IMAGE_CUSTOM_DRAGGING = aMgr.GetImageThrow("IMAGE_CUSTOM_DRAGGING"); IMAGE_CUSTOM_HAND = aMgr.GetImageThrow("IMAGE_CUSTOM_HAND"); IMAGE_CUSTOM_POINTER = aMgr.GetImageThrow("IMAGE_CUSTOM_POINTER"); IMAGE_CUSTOM_TEXT = aMgr.GetImageThrow("IMAGE_CUSTOM_TEXT"); IMAGE_HUNGARR_LOGO = aMgr.GetImageThrow("IMAGE_HUNGARR_LOGO"); } catch(ResourceManagerException&) { return false; } return true; } // TitleScreen Resources Image* Sexy::IMAGE_LOADER_BAR; Image* Sexy::IMAGE_LOADER_LOADINGTXT; int Sexy::SOUND_CONTINUE; bool Sexy::ExtractTitleScreenResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_LOADER_BAR = aMgr.GetImageThrow("IMAGE_LOADER_BAR"); IMAGE_LOADER_LOADINGTXT = aMgr.GetImageThrow("IMAGE_LOADER_LOADINGTXT"); SOUND_CONTINUE = aMgr.GetSoundThrow("SOUND_CONTINUE"); } catch(ResourceManagerException&) { return false; } return true; } static void* gResources[] = { &FONT_DEFAULT, &FONT_HUNGARR, &IMAGE_CUSTOM_POINTER, &IMAGE_CUSTOM_HAND, &IMAGE_CUSTOM_DRAGGING, &IMAGE_CUSTOM_TEXT, &IMAGE_HUNGARR_LOGO, &IMAGE_LOADER_BAR, &IMAGE_LOADER_LOADINGTXT, &SOUND_CONTINUE, &SOUND_MUTATOR, &SOUND_TIMER, &IMAGE_ROBOTROBOT, &IMAGE_CHECKBOX, &IMAGE_BG0, &IMAGE_BG1, &IMAGE_BG2, &IMAGE_BUTTON_DOWN, &IMAGE_BUTTON_OVER, &IMAGE_BUTTON_NORMAL, &IMAGE_DIALOG_BOX, &IMAGE_DIALOG_BUTTON, &IMAGE_SLIDER_TRACK, &IMAGE_SLIDER_THUMB, &IMAGE_HUNGARR_SMALL, &IMAGE_HUNGARR_BEAM_UP, &IMAGE_HUNGARR_BEAM_DOWN, &IMAGE_HUNGARR_BEAM_LEFT, &IMAGE_HUNGARR_BEAM_RIGHT, &IMAGE_HUNGARR_HORIZ, &IMAGE_HUNGARR_VERT, &IMAGE_ATOMIC_EXPLOSION, &IMAGE_BOMB_RADIAL_DEATH, &IMAGE_PLANETS, &IMAGE_SPARK, &IMAGE_PARTICLE_LIGHTNING, &SOUND_MAGZAP, &SOUND_BUTTON, &SOUND_PLANET, &SOUND_LEVEL_UP1, &SOUND_LEVEL_UP2, &SOUND_EXPLOSION, &SOUND_BEAM_HIT, &SOUND_PLANET_HIT, &SOUND_BEAM_MOVING, &SOUND_LEVEL_UP4, &SOUND_LEVEL_UP3, &SOUND_GAME_OVER_CLICK, &SOUND_GAME_OVER_STATS, &SOUND_GAME_OVER_RESTART, &SOUND_GAME_OVER_TEXT, &SOUND_REGION_FILLED, NULL }; Image* Sexy::LoadImageById(ResourceManager *theManager, int theId) { return (*((Image**)gResources[theId]) = theManager->LoadImage(GetStringIdById(theId))); } Image* Sexy::GetImageById(int theId) { return *(Image**)gResources[theId]; } Font* Sexy::GetFontById(int theId) { return *(Font**)gResources[theId]; } int Sexy::GetSoundById(int theId) { return *(int*)gResources[theId]; } static Sexy::ResourceId GetIdByVariable(const void *theVariable) { typedef std::map MyMap; static MyMap aMap; if(gNeedRecalcVariableToIdMap) { gNeedRecalcVariableToIdMap = false; aMap.clear(); for(int i=0; isecond; } Sexy::ResourceId Sexy::GetIdByImage(Image *theImage) { return GetIdByVariable(theImage); } Sexy::ResourceId Sexy::GetIdByFont(Font *theFont) { return GetIdByVariable(theFont); } Sexy::ResourceId Sexy::GetIdBySound(int theSound) { return GetIdByVariable((void*)theSound); } const char* Sexy::GetStringIdById(int theId) { switch(theId) { case FONT_DEFAULT_ID: return "FONT_DEFAULT"; case FONT_HUNGARR_ID: return "FONT_HUNGARR"; case IMAGE_CUSTOM_POINTER_ID: return "IMAGE_CUSTOM_POINTER"; case IMAGE_CUSTOM_HAND_ID: return "IMAGE_CUSTOM_HAND"; case IMAGE_CUSTOM_DRAGGING_ID: return "IMAGE_CUSTOM_DRAGGING"; case IMAGE_CUSTOM_TEXT_ID: return "IMAGE_CUSTOM_TEXT"; case IMAGE_HUNGARR_LOGO_ID: return "IMAGE_HUNGARR_LOGO"; case IMAGE_LOADER_BAR_ID: return "IMAGE_LOADER_BAR"; case IMAGE_LOADER_LOADINGTXT_ID: return "IMAGE_LOADER_LOADINGTXT"; case SOUND_CONTINUE_ID: return "SOUND_CONTINUE"; case SOUND_MUTATOR_ID: return "SOUND_MUTATOR"; case SOUND_TIMER_ID: return "SOUND_TIMER"; case IMAGE_ROBOTROBOT_ID: return "IMAGE_ROBOTROBOT"; case IMAGE_CHECKBOX_ID: return "IMAGE_CHECKBOX"; case IMAGE_BG0_ID: return "IMAGE_BG0"; case IMAGE_BG1_ID: return "IMAGE_BG1"; case IMAGE_BG2_ID: return "IMAGE_BG2"; case IMAGE_BUTTON_DOWN_ID: return "IMAGE_BUTTON_DOWN"; case IMAGE_BUTTON_OVER_ID: return "IMAGE_BUTTON_OVER"; case IMAGE_BUTTON_NORMAL_ID: return "IMAGE_BUTTON_NORMAL"; case IMAGE_DIALOG_BOX_ID: return "IMAGE_DIALOG_BOX"; case IMAGE_DIALOG_BUTTON_ID: return "IMAGE_DIALOG_BUTTON"; case IMAGE_SLIDER_TRACK_ID: return "IMAGE_SLIDER_TRACK"; case IMAGE_SLIDER_THUMB_ID: return "IMAGE_SLIDER_THUMB"; case IMAGE_HUNGARR_SMALL_ID: return "IMAGE_HUNGARR_SMALL"; case IMAGE_HUNGARR_BEAM_UP_ID: return "IMAGE_HUNGARR_BEAM_UP"; case IMAGE_HUNGARR_BEAM_DOWN_ID: return "IMAGE_HUNGARR_BEAM_DOWN"; case IMAGE_HUNGARR_BEAM_LEFT_ID: return "IMAGE_HUNGARR_BEAM_LEFT"; case IMAGE_HUNGARR_BEAM_RIGHT_ID: return "IMAGE_HUNGARR_BEAM_RIGHT"; case IMAGE_HUNGARR_HORIZ_ID: return "IMAGE_HUNGARR_HORIZ"; case IMAGE_HUNGARR_VERT_ID: return "IMAGE_HUNGARR_VERT"; case IMAGE_ATOMIC_EXPLOSION_ID: return "IMAGE_ATOMIC_EXPLOSION"; case IMAGE_BOMB_RADIAL_DEATH_ID: return "IMAGE_BOMB_RADIAL_DEATH"; case IMAGE_PLANETS_ID: return "IMAGE_PLANETS"; case IMAGE_SPARK_ID: return "IMAGE_SPARK"; case IMAGE_PARTICLE_LIGHTNING_ID: return "IMAGE_PARTICLE_LIGHTNING"; case SOUND_MAGZAP_ID: return "SOUND_MAGZAP"; case SOUND_BUTTON_ID: return "SOUND_BUTTON"; case SOUND_PLANET_ID: return "SOUND_PLANET"; case SOUND_LEVEL_UP1_ID: return "SOUND_LEVEL_UP1"; case SOUND_LEVEL_UP2_ID: return "SOUND_LEVEL_UP2"; case SOUND_EXPLOSION_ID: return "SOUND_EXPLOSION"; case SOUND_BEAM_HIT_ID: return "SOUND_BEAM_HIT"; case SOUND_PLANET_HIT_ID: return "SOUND_PLANET_HIT"; case SOUND_BEAM_MOVING_ID: return "SOUND_BEAM_MOVING"; case SOUND_LEVEL_UP4_ID: return "SOUND_LEVEL_UP4"; case SOUND_LEVEL_UP3_ID: return "SOUND_LEVEL_UP3"; case SOUND_GAME_OVER_CLICK_ID: return "SOUND_GAME_OVER_CLICK"; case SOUND_GAME_OVER_STATS_ID: return "SOUND_GAME_OVER_STATS"; case SOUND_GAME_OVER_RESTART_ID: return "SOUND_GAME_OVER_RESTART"; case SOUND_GAME_OVER_TEXT_ID: return "SOUND_GAME_OVER_TEXT"; case SOUND_REGION_FILLED_ID: return "SOUND_REGION_FILLED"; default: return ""; } } libtuxcap-1.4.0/tuxcap/hungarr/TitleScreen.h0000644000175000017500000001000510641010445020722 0ustar inniyahinniyah#ifndef __TITLE_SCREEN_H__ #define __TITLE_SCREEN_H__ #include "Widget.h" #include "ButtonListener.h" namespace Sexy { class GameApp; class Graphics; class WidgetManager; class HyperlinkWidget; class TitleScreen : public Widget, public ButtonListener { private: GameApp* mApp; HyperlinkWidget* mContinueLink; public: ////////////////////////////////////////////////////////////////////////// // Function: TitleScreen // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// TitleScreen(GameApp* pApp); virtual ~TitleScreen(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Called BEFORE the title screen is added to the widget manager // by GameApp. This initializes some things like the images used for // our hyperlink widget. ////////////////////////////////////////////////////////////////////////// void Init(void); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager. This is where // we'll do all our display routines for the loading screen. ////////////////////////////////////////////////////////////////////////// void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: LoadingComplete // Parameters: none // Returns: none // // Purpose: Called manually by GameApp when we are done loading all // resources, to let the title screen know that it should unhide and // enable the continue link, so the user can start playing the game. ////////////////////////////////////////////////////////////////////////// void LoadingComplete(); }; } #endif //__TITLE_SCREEN_H__ libtuxcap-1.4.0/tuxcap/hungarr/main.cpp0000644000175000017500000000022710641010443017763 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/hungarr/Board.cpp0000644000175000017500000020347410706205240020102 0ustar inniyahinniyah#pragma warning(disable:4244) #pragma warning(disable:4018) #include "Board.h" #include "GameApp.h" #include "Res.h" #include "LevelupEffect.h" #include "GameOverEffect.h" #include "OptionsDialog.h" #include "Graphics.h" #include "Color.h" #include "Rect.h" #include "ButtonWidget.h" #include "WidgetManager.h" #include "ImageFont.h" #include "SoundManager.h" #include "SoundInstance.h" #include "Buffer.h" #include "MusicInterface.h" #define _USE_MATH_DEFINES #include // VC6 workaround #ifndef M_PI #define M_PI 3.14159265358979323846 #endif using namespace Sexy; // How much faster the beam gets when you eat a planet const float BEAM_INC_SPEED = 0.05f; // Fastest the beam can go const float MAX_BEAM_SPEED = 2.5f; // Table of random planet names const int NUM_PLANET_NAMES = 28; const SexyString PLANET_NAME[] = {_S("Deev-z"), _S("SEN-Hen"), _S("Wallach IX"), _S("Salusa Secundus"), _S("Ridiculous Prime"), _S("Architekt V"), _S("Robot Republica"), _S("Ix"), _S("XOLDOG4000"), _S("Kliprok"), _S("TR-909"), _S("TR-808"), _S("TB-303"), _S("DTR011"), _S("dTech"), _S("Rotwang"), _S("Sukhtek"), _S("Romulox"), _S("Dob Reevz"), _S("Skull XII"), _S("Beefy Prime"), _S("Haas"), _S("Reifenrath"), _S("Gehner Subulon"), _S("ACE-DOGG"), _S("Charolastra"), _S("Nixd"), _S("BASS")}; // Table of random planet exports: const int NUM_PLANET_EXPORTS = 23; const SexyString PLANET_EXPORTS[] = {_S("Happiness"), _S("Donkeys"), _S("Rabies"), _S("AstroPop"), _S("Idiocy"), _S("Minimal Techno"), _S("Citizens"), _S("Pain-relieving Pants"), _S("The Quad-Laser"), _S("Septic Systems"), _S("Video Games"), _S("Robots"), _S("Plaid"), _S("Octagons"), _S("Gingivitis"), _S("Recognizers"), _S("Electro"), _S("Sauce"), _S("Kindness"), _S("Bison"), _S("Saline"), _S("Cholera"), _S("TyperShark")}; ////////////////////////////////////////////////////////////////////////// // Inline functions ////////////////////////////////////////////////////////////////////////// // Given an X coordinate, returns the grid column it maps to inline int GetCol(float x) { return (int) ((x - GRID_START_X) / GRID_PIX_SIZE); } // Given a Y coordinate, returns the grid row it maps to inline int GetRow(float y) { return (int) ((y - GRID_START_Y) / GRID_PIX_SIZE); } // Given a grid column, returns the X pixel of the left edge of it inline float GetColPix(int col) { return col * GRID_PIX_SIZE + GRID_START_X; } // Given a grid row, returns the Y pixel of the top edge of it inline float GetRowPix(int row) { return row * GRID_PIX_SIZE + GRID_START_Y; } // Given an X coordinate, adjusts it so that it is aligned // with the left edge of the grid square it's over inline float GetAlignedX(float x) { return (float)GetCol(x) * GRID_PIX_SIZE + GRID_START_X; } // Given a Y coordinate, adjusts it so that it is aligned // with the top edge of the grid square it's over inline float GetAlignedY(float y) { return (float)GetRow(y) * GRID_PIX_SIZE + GRID_START_Y; } // Checks to see if the Y coordinate is in the grid's bounds. // Needs to know if Hun-garr is oriented vertically or not inline bool YCoordInBounds(float y, bool vertical) { int h = IMAGE_HUNGARR_HORIZ->GetHeight() / 2; if ( (vertical && (y > GRID_START_Y + h) && (y < GRID_END_Y - h)) || (!vertical && (y > GRID_START_Y + 7) && (y < GRID_END_Y - 4)) ) return true; return false; } // Checks to see if the X coordinate is in the grid's bounds inline bool XCoordInBounds(float x) { if ((x > GRID_START_X + 9) && (x < GRID_END_X - 2)) return true; return false; } // Checks to see if the column number points to a valid grid column inline bool ValidCol(int col) { return ((col >= 0) && (col < GRID_WIDTH)); } // Checks to see if the row number points to a valid grid row inline bool ValidRow(int row) { return ((row >= 0) && (row < GRID_HEIGHT)); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; mHungarrIsVertical = true; mLineSpeed = 1.0f; mNumPlanetsEaten = 0; mPercentComplete = 0; mBorderHue = 0; mFlashCount = 0; mLives = 3; mLevel = 1; mScore = 0; mBeamPulseAmt = 30; mBeamPulseVal = 128; // Put Hun-garr in a valid spot UpdateHungarrPosition((int)GetColPix(4), (int)GetRowPix(4)); // Create a 2D array to hold the grid fill state that's of size // GRID_WIDTH x GRID_HEIGHT mGridState = new GridTile* [GRID_HEIGHT]; //vc6 workaround: int i; for (i = 0; i < GRID_HEIGHT; i++) mGridState[i] = new GridTile[GRID_WIDTH]; mFillDirection = FILL_LEFT; mFillSpeed = 20.0f; mPlanetSpeed = 1.5f; mPopulationEaten = mTotalPopulationEaten = 0; mPauseLevel = 0; // Create our starfield for (i = 0; i < MAX_STARS; i++) { Star s; s.mX = Rand() % mApp->mWidth; s.mY = Rand() % mApp->mHeight; int r = Rand() % 3; switch (r) { case 0: s.mSpeed = 0.5f; s.mColor = Color(200, 200, 200, 128); break; case 1: s.mSpeed = 0.25f; s.mColor = Color(100, 100, 100, 128); break; case 2: s.mSpeed = 0.1f; s.mColor = Color(50, 50, 50, 128); break; } mStarField[i] = s; } mLevelupEffect = new LevelupEffect(); mGameOverEffect = new GameOverEffect(); mOptionsBtn = NULL; // The shorting out, electrical sound of the beams moving. We use a SoundInstance pointer // because we want to loop the sound while the beam is moving, and stop it when done. // This is easiest done manually. mShortSound = mApp->mSoundManager->GetSoundInstance(SOUND_BEAM_MOVING); InitLevel(1); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { // Frees up the memory allocated to our manual SoundInstance pointer. Required. mShortSound->Release(); for (int i = GRID_HEIGHT; i > 0; --i) delete[] mGridState[i - 1]; delete[] mGridState; delete mLevelupEffect; delete mGameOverEffect; delete mOptionsBtn; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // If paused, return and don't markdirty, whcih prevents drawing // and the stealing of CPU cycles if (mPauseLevel > 0) return; Widget::Update(); // HSL is an alternative to specifying an RGB color format. // Using HSL lets us easily do the hyper blinking crazy weird // flashing effect commonly found in old games, such as Robotron. // Below, we increment the value by 6 per update. The &0xFF is an // easy way to clamp the value between 0 and 255 instead of having to // do a separate if (mHue > 255) mHue -= 255. This lets the value // rollover and keep cycling. if (--mFlashCount > 0) mBorderHue = (mBorderHue + 6) % 0xFF; if (mGameOverEffect->IsActive()) { mGameOverEffect->Update(); // If the game over effect is in the proper state, we will // be able to initialize the first level so that when it fades out, // the level will appear underneath it. if (mGameOverEffect->CanInitFirstLevel()) { //Reset the critical variables: mBorderHue = 0; mFlashCount = 0; mLives = 3; mLevel = 1; mScore = 0; mFillDirection = FILL_LEFT; mFillSpeed = 20.0f; mPlanetSpeed = 1.5f; mPopulationEaten = mTotalPopulationEaten = 0; mPauseLevel = 0; mLineSpeed = 1.0f; mPlanetIdxCount.clear(); mExportIdxCount.clear(); mOptionsBtn->SetVisible(true); mApp->mMusicInterface->FadeIn(0); InitLevel(1); } } // Make the beams that the player emits pulse with intensity mBeamPulseVal += mBeamPulseAmt; if (mBeamPulseVal >= 255) { mBeamPulseVal = 255; mBeamPulseAmt = -mBeamPulseAmt; } else if (mBeamPulseVal <= 0) { mBeamPulseVal = 0; mBeamPulseAmt = -mBeamPulseAmt; } MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::UpdateF(float theFrac) { if (mPauseLevel > 0) return; if (mFilling) { // If the beams have been released, update the filling of the grid float amt = mFillSpeed * theFrac; if (mFillDirection == FILL_RIGHT) FillRight(amt); else if (mFillDirection == FILL_LEFT) FillLeft(amt); else if (mFillDirection == FILL_UP) FillUp(amt); else if (mFillDirection == FILL_DOWN) FillDown(amt); // Check what % full the filled regions are if it's done filling if (!mFilling) UpdatePercentComplete(); } // Make the bonus text float upwards and fade it out over time. std::vector::iterator it = mBonusText.begin(); while (it != mBonusText.end()) { BonusText* bt = &*it; bt->mY -= 1.00f * theFrac; bt->mHue = (bt->mHue + 5) % 0xFF; if (--bt->mAlpha <= 0) { //Totally faded out, remove it it = mBonusText.erase(it); } else ++it; } // Move the starfield. If a start gets beyond the screen, // randomly place it offscreen again int i; for (i = 0; i < MAX_STARS; i++) { Star* s = &mStarField[i]; s->mX += s->mSpeed; if (s->mX > mWidth) { s->mX = -5; s->mY = Rand() % mHeight; } } if ((!mMovingLine1.mDone || !mMovingLine2.mDone) && !mGameOverEffect->IsActive()) MoveLines(theFrac); // If we're allowed to show the planets and the game isn't paused and the game // over effect isn't playing, then we can move the planets around if ((!mLevelupEffect->HidePlanets() || (mPauseLevel > 0)) && !mGameOverEffect->IsActive()) { // Move the planets int w = IMAGE_PLANETS->GetCelWidth(); int h = IMAGE_PLANETS->GetCelHeight(); // Instead of playing the explosion sound every time a planet gets destroyed, we'll // only play it once. That way, if you destroy more than 1 planet in one go, you won't // hear the same sound played multipled times at once, which would result in this loud, // hideous, flanging sound. bool playSound = false; for (int i = 0; i < mPlanets.size(); i++) { Planet* p = &mPlanets[i]; // Again, the timer is used solely for incrementing the animation frames ++p->mTimer; if (!p->mExploding) { if (MovePlanet(p, theFrac)) playSound = true; // Returns true if the planet is to explode } else { if ((p->mTimer % p->mExplodeSpeed) == 0) { if (++p->mExplodeFrame >= IMAGE_BOMB_RADIAL_DEATH->mNumCols) { mPlanets.erase(mPlanets.begin() + i); --i; } } } } if (playSound) mApp->PlaySample(SOUND_PLANET); } // update and move the particles. When they have reached // their last frame, remove them. for (i = 0; i < mParticles.size(); i++) { Particle* p = &mParticles[i]; ++p->mTimer; p->mX += p->mVX * theFrac; p->mY += p->mVY * theFrac; p->mVY += 0.1f; if (p->mTimer % 6 == 0) { if (++p->mFrame >= IMAGE_PARTICLE_LIGHTNING->mNumCols) { mParticles.erase(mParticles.begin() + i); --i; } } } if (mLevelupEffect->IsActive()) { mLevelupEffect->Update(theFrac); // If the proper state is reached in the level up effect, then we can begin // setting up the next level. if (mLevelupEffect->StartNextLevel()) { // Just finished, start the next level mOptionsBtn->SetVisible(true); InitLevel(mLevel + 1); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::FillRight(float amt) { bool change = true; // Fill the entire line, moving rightward for (int y = mFillRegion.mTop; y <= mFillRegion.mBottom; y++) { GridTile* gt = &mGridState[y][mFillRegion.mLeft]; // We only want to fill those pieces that are in the GRID_FILLING state if (gt->mFillState == GRID_FILLING) { // This piece is filling up, expand its width gt->mFillRect.mWidth += amt; // If the width exceeds that of the grid piece, overflow the result // into the tile next to it so that the filling appears continuous. if (gt->mFillRect.mWidth >= GRID_PIX_SIZE) { float overflow = gt->mFillRect.mWidth - GRID_PIX_SIZE; gt->mFillState = GRID_FILLED; gt->mFillRect.mWidth = GRID_PIX_SIZE; //overflow into next column, if the next column is within our //fill region and if the piece is in the normal tile state. if (mFillRegion.mLeft + 1 <= mFillRegion.mRight) if (mGridState[y][mFillRegion.mLeft + 1].mFillState == GRID_NORMAL) mGridState[y][mFillRegion.mLeft + 1].mFillRect.mWidth += overflow; } else change = false; } } //if "change" is true, then move one column right and begin filling in that column next //time this function is called. If there are no more columns to fill, we're done. if (change && (++mFillRegion.mLeft > mFillRegion.mRight)) mFilling = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::FillLeft(float amt) { float leftX = GetColPix(mFillRegion.mRight); bool change = true; //This algorithm works just like FillRight except that it's filling //from the right side of the grid piece instead of the left, so there's //a couple extra calculations. for (int y = mFillRegion.mTop; y <= mFillRegion.mBottom; y++) { GridTile* gt = &mGridState[y][mFillRegion.mRight]; if (gt->mFillState == GRID_FILLING) { gt->mFillRect.mWidth += amt; gt->mFillRect.mX -= amt; if ((gt->mFillRect.mWidth >= GRID_PIX_SIZE) || (gt->mFillRect.mX < leftX)) { float overflow = gt->mFillRect.mWidth - GRID_PIX_SIZE; gt->mFillState = GRID_FILLED; gt->mFillRect.mWidth = GRID_PIX_SIZE; gt->mFillRect.mX = leftX; //overflow into next column if (mFillRegion.mRight - 1 >= mFillRegion.mLeft) { if (mGridState[y][mFillRegion.mRight - 1].mFillState == GRID_NORMAL) { mGridState[y][mFillRegion.mRight - 1].mFillRect.mWidth += overflow; mGridState[y][mFillRegion.mRight - 1].mFillRect.mX -= overflow; } } } else change = false; } } if (change && (--mFillRegion.mRight < mFillRegion.mLeft)) mFilling = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::FillUp(float amt) { bool change = true; float topY = GetRowPix(mFillRegion.mBottom); //This algorithm works just like FillRight except that it's filling //from the bottom side of the grid piece instead of the left, so there's //a couple extra calculations. for (int x = mFillRegion.mLeft; x <= mFillRegion.mRight; x++) { GridTile* gt = &mGridState[mFillRegion.mBottom][x]; if (gt->mFillState == GRID_FILLING) { gt->mFillRect.mHeight += amt; gt->mFillRect.mY -= amt; if ((gt->mFillRect.mHeight >= GRID_PIX_SIZE) || (gt->mFillRect.mY < topY)) { float overflow = gt->mFillRect.mHeight - GRID_PIX_SIZE; gt->mFillState = GRID_FILLED; gt->mFillRect.mHeight = GRID_PIX_SIZE; gt->mFillRect.mY = topY; //overflow into next row if (mFillRegion.mBottom - 1 > mFillRegion.mTop) { if (mGridState[mFillRegion.mBottom - 1][x].mFillState == GRID_NORMAL) { mGridState[mFillRegion.mBottom - 1][x].mFillRect.mHeight += overflow; mGridState[mFillRegion.mBottom - 1][x].mFillRect.mY -= overflow; } } } else change = false; } } if (change && (--mFillRegion.mBottom < mFillRegion.mTop)) mFilling = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::FillDown(float amt) { bool change = true; //This algorithm works just like FillRight except that it's filling //from the top side of the grid piece instead of the left. for (int x = mFillRegion.mLeft; x <= mFillRegion.mRight; x++) { GridTile* gt = &mGridState[mFillRegion.mTop][x]; if (gt->mFillState == GRID_FILLING) { gt->mFillRect.mHeight += amt; if (gt->mFillRect.mHeight >= GRID_PIX_SIZE) { float overflow = gt->mFillRect.mHeight - GRID_PIX_SIZE; gt->mFillState = GRID_FILLED; gt->mFillRect.mHeight = GRID_PIX_SIZE; //overflow into next row if (mFillRegion.mTop + 1 <= mFillRegion.mBottom) if (mGridState[mFillRegion.mTop + 1][x].mFillState == GRID_NORMAL) mGridState[mFillRegion.mTop + 1][x].mFillRect.mHeight += overflow; } else change = false; } } if (change && (++mFillRegion.mTop > mFillRegion.mBottom)) mFilling = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MoveLines(float theFrac) { // Move the lines, differently depending on if they are oriented verticall // or horizontally. When a line reaches its target, it is done, and planets // can bounce off of it. When both lines are done, we will calculate the region // to fill. int numDone = 0; if (!mMovingLine1.mDone) { float amt = -mLineSpeed * theFrac; if (mMovingLine1.mIsVertical) { mMovingLine1.mY += amt; mMovingLine1.mHeight += fabsf(amt); if (mMovingLine1.mY <= mMovingLine1.mTargetY) { mMovingLine1.mY = mMovingLine1.mTargetY; mMovingLine1.mDone = true; ++numDone; } } else { mMovingLine1.mX += amt; mMovingLine1.mWidth += fabsf(amt); if (mMovingLine1.mX <= mMovingLine1.mTargetX) { mMovingLine1.mX = mMovingLine1.mTargetX; mMovingLine1.mDone = true; ++numDone; } } } if (!mMovingLine2.mDone) { float amt = mLineSpeed * theFrac; if (mMovingLine2.mIsVertical) { mMovingLine2.mHeight += amt; if (mMovingLine2.mY + mMovingLine2.mHeight >= mMovingLine2.mTargetY) { mMovingLine2.mHeight = mMovingLine2.mTargetY - mMovingLine2.mY; mMovingLine2.mDone = true; ++numDone; } } else { mMovingLine2.mWidth += amt; if (mMovingLine2.mX + mMovingLine2.mWidth >= mMovingLine2.mTargetX) { mMovingLine2.mWidth = mMovingLine2.mTargetX - mMovingLine2.mX; mMovingLine2.mDone = true; ++numDone; } } } // While at least one of the lines is still moving, make a bunch of sparks shower off // the edge of them. In non-3d mode, we'll only emit half the sparks to reduce the CPU time consumed. if (!mMovingLine2.mDone || !mMovingLine1.mDone) { int modVal = gSexyAppBase->Is3DAccelerated() ? 2 : 4; if (mUpdateCnt % modVal == 0) EmitSparks(); } // If both are done at the same time, or both are done but perhaps one completed earlier than the other, // then it's time to compute the fill region. if ((numDone == 2) || ((numDone == 1) && mMovingLine1.mDone && mMovingLine2.mDone)) { mFilling = true; CalculateFillRegions(); } // Quit playing the electrical shorting out sound when both lines are broken or // done or any combination of the two. if ((mMovingLine1.mDone && mMovingLine2.mDone) || (mMovingLine1.mBroken && mMovingLine2.mDone) || (mMovingLine2.mBroken && mMovingLine1.mDone)) mShortSound->Stop(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { g->SetColor(Color::Black); g->FillRect(0, 0, mWidth, mHeight); int incAmt = gSexyAppBase->Is3DAccelerated() ? 1 : 2; // Draw less starts if not in 3D mode to reduce CPU usage, since they aren't a critical feature for (int i = 0; i < MAX_STARS; i += incAmt) { Star* s = &mStarField[i]; g->SetColor(s->mColor); g->FillRect((int)s->mX, (int)s->mY, 1, 1); } // We don't draw the other game elements under certain conditions, like // if the level up and game over effects are in a few particular states. if (!mLevelupEffect->HideBoard() && !mGameOverEffect->HideBoard()) { DrawGrid(g); DrawUI(g); // To prevent cheating, don't draw planets if the game is paused. // Also don't show them during certain points of the level up effect if (!mLevelupEffect->HidePlanets() || (mPauseLevel > 0)) DrawPlanets(g); if (!mGameOverEffect->IsActive()) DrawMovingBeams(g); DrawHungarr(g); } if (mLevelupEffect->IsActive()) mLevelupEffect->Draw(g); if (mGameOverEffect->IsActive()) mGameOverEffect->Draw(g); if (mPauseLevel > 0) { // Paused: draw an overlay g->SetColor(Color(0, 0, 0, 128)); g->FillRect(0, 0, mWidth, mHeight); g->SetColor(Color::White); g->SetFont(FONT_HUNGARR); g->DrawString(_S("PAUSED"), mWidth / 2 - FONT_HUNGARR->StringWidth(_S("PAUSED")) / 2, mHeight / 2); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawGrid(Graphics* g) { // Draw an outline around the whole grid region. See LevelUpEffect.cpp or // GameOverEffect.cpp for full details on using HSL instead of RGB for color and // why it's useful. if (mFlashCount > 0) g->SetColor(mApp->HSLToRGB(mBorderHue, 255, 128) & 0xFFFFFFFF); else g->SetColor(Color(255, 0, 0, 64)); // grid outline: g->FillRect(0, GRID_START_Y, GRID_START_X, mHeight - GRID_START_Y); g->FillRect(0, GRID_START_Y - GRID_PIX_SIZE, mWidth, GRID_PIX_SIZE); g->FillRect(GRID_END_X, GRID_START_Y, mWidth - GRID_END_X, mHeight - GRID_START_Y); g->FillRect(GRID_START_X, GRID_END_Y, GRID_END_X - GRID_START_X, mHeight - GRID_END_Y); // To make a weird pattern, a few of the grid pieces will be more brightly // colored than the others, if they are in the normal state. bool startBright = true; for (int y = 0; y < GRID_HEIGHT; y++) { int drawY = (int)GetRowPix(y); for (int x = 0; x < GRID_WIDTH; x++) { int drawX = (int)GetColPix(x); int state = mGridState[y][x].mFillState; if (state == GRID_FILLING) { // The grid piece is in the process of filling up. Draw a different colored rectangle for the // filled in part, and then draw the rest normally. FRect* fr = &mGridState[y][x].mFillRect; Rect normalRect; if (mFillDirection == FILL_RIGHT) normalRect = Rect((int)fr->mX + (int)fr->mWidth, drawY, GRID_PIX_SIZE - (int)fr->mWidth + 1, GRID_PIX_SIZE); else if (mFillDirection == FILL_LEFT) normalRect = Rect(drawX, drawY, GRID_PIX_SIZE - (int)fr->mWidth, GRID_PIX_SIZE); else if (mFillDirection == FILL_UP) normalRect = Rect(drawX, drawY, GRID_PIX_SIZE, GRID_PIX_SIZE - (int)fr->mHeight); else normalRect = Rect(drawX, (int)fr->mY + (int)fr->mHeight, GRID_PIX_SIZE, GRID_PIX_SIZE - (int)fr->mHeight + 1); if ((normalRect.mWidth > 0) && (normalRect.mHeight > 0)) { g->SetColor(Color(255, 255, 0, startBright && (x % 2 == 0) ? 128 : 64)); g->FillRect(normalRect); g->SetColor(Color(0, 0, 0)); g->DrawRect(normalRect); } g->SetColor(Color(255, 255, 0, 100)); FillRectF(g, *fr); } else if (state == GRID_NORMAL) { // Just draw the grid piece normally, with a black outline around it. g->SetColor(Color(255, 255, 0, startBright && (x % 3 == 0) ? 64 : 32)); g->FillRect(drawX, drawY, GRID_PIX_SIZE, GRID_PIX_SIZE); g->SetColor(Color(0, 0, 0)); g->DrawRect(drawX, drawY, GRID_PIX_SIZE, GRID_PIX_SIZE); } else { // The piece is completely filled in, just fill the whole rectangle g->SetColor(Color(255, 255, 0, 100)); FillRectF(g, mGridState[y][x].mFillRect); } } startBright = !startBright; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawUI(Graphics* g) { int ascent = FONT_HUNGARR->GetAscent(); int height = FONT_HUNGARR->GetHeight(); g->SetFont(FONT_HUNGARR); SexyString s; int rightX = FONT_HUNGARR->StringWidth(_S("POPULATION CONSUMED: ")) + 5; int strWidth; s = _S("WORLDS DEVOURED: "); strWidth = FONT_HUNGARR->StringWidth(s); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, rightX - strWidth, ascent); g->SetColor(Color(255, 0, 0, 200)); g->DrawString(StrFormat(_S("%d"), mNumPlanetsEaten), rightX - 5, ascent); s = _S("POPULATION CONSUMED: "); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, 5, height * 2); g->SetColor(Color(255, 0, 0, 200)); g->DrawString(CommaSeperate(mPopulationEaten), rightX - 5, height * 2); s = _S("SCORE: "); strWidth = FONT_HUNGARR->StringWidth(s); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, rightX - strWidth, height * 3); g->SetColor(Color(255, 255, 0, 200)); g->DrawString(StrFormat(_S("%s"), CommaSeperate(mScore).c_str()), rightX - 5, height * 3); int x = 380; s = _S("SYSTEMS SUBJUGATED: "); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, x, ascent); g->SetColor(Color(255, 0, 0, 200)); g->DrawString(StrFormat(_S("%d%%"), mPercentComplete), x + FONT_HUNGARR->StringWidth(s), ascent); s = _S("LIVES: "); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, x, height * 2); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawImage(IMAGE_HUNGARR_SMALL, strWidth + x, ascent); g->SetColor(Color(255, 0, 0, 200)); g->DrawString(StrFormat(_S("x%d"), mLives), x + 10 + strWidth + IMAGE_HUNGARR_SMALL->GetWidth(), height * 2); s = _S("LEVEL: "); g->SetColor(Color(255, 255, 255, 128)); g->DrawString(s, x, height * 3); g->SetColor(Color(255, 255, 0, 200)); g->DrawString(StrFormat(_S("%d"), mLevel), x + FONT_HUNGARR->StringWidth(s), height * 3); for (int i = 0; i < mBonusText.size(); i++) { BonusText* bt = &mBonusText[i]; g->SetColor( (mApp->HSLToRGB(bt->mHue, 255, 128) & 0xFFFFFF) | (bt->mAlpha << 24) ); g->DrawString(bt->mText, (int)bt->mX, (int)bt->mY); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Beam1DrawHelper(Graphics* g) { // In 3D mode we'll use the DrawImageF versions since they look nicer and // perform anti-aliasing, and make floating point movement appear smoother. // Since they are more taxing, we'll use the default integer routines if hardware // mode is not available. // The offsets you see were taken from the actual image itself. You'll notice // that the image has a lot of blank space around the actual beam, so we move things // around a bit to get a nice aligned look. You'd either just play around with these // numbers till it looked right, or your artist would inform you. if (mMovingLine1.mIsVertical) { if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_UP, mMovingLine1.mX - 8, mMovingLine1.mY, Rect(0, 0, IMAGE_HUNGARR_BEAM_UP->GetWidth(), (int)mMovingLine1.mHeight)); } else { g->DrawImage(IMAGE_HUNGARR_BEAM_UP, (int)mMovingLine1.mX - 8, (int)mMovingLine1.mY, Rect(0, 0, IMAGE_HUNGARR_BEAM_UP->GetWidth(), (int)mMovingLine1.mHeight)); } } else { if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_LEFT, mMovingLine1.mX, mMovingLine1.mY - 8, Rect(0, 0, (int)mMovingLine1.mWidth, IMAGE_HUNGARR_BEAM_LEFT->GetHeight())); } else { g->DrawImage(IMAGE_HUNGARR_BEAM_LEFT, (int)mMovingLine1.mX, (int)mMovingLine1.mY - 8, Rect(0, 0, (int)mMovingLine1.mWidth, IMAGE_HUNGARR_BEAM_LEFT->GetHeight())); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Beam2DrawHelper(Graphics* g) { // In 3D mode we'll use the DrawImageF versions since they look nicer and // perform anti-aliasing, and make floating point movement appear smoother. // Since they are more taxing, we'll use the default integer routines if hardware // mode is not available. // The offsets you see were taken from the actual image itself. You'll notice // that the image has a lot of blank space around the actual beam, so we move things // around a bit to get a nice aligned look. You'd either just play around with these // numbers till it looked right, or your artist would inform you. if (mMovingLine2.mIsVertical) { if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_DOWN, mMovingLine2.mX - 8, mMovingLine2.mY - 1, Rect(0, IMAGE_HUNGARR_BEAM_DOWN->GetHeight() - (int)mMovingLine2.mHeight, IMAGE_HUNGARR_BEAM_DOWN->GetWidth(), (int)mMovingLine2.mHeight)); } else { g->DrawImage(IMAGE_HUNGARR_BEAM_DOWN, (int)mMovingLine2.mX - 8, (int)mMovingLine2.mY - 1, Rect(0, IMAGE_HUNGARR_BEAM_DOWN->GetHeight() - (int)mMovingLine2.mHeight, IMAGE_HUNGARR_BEAM_DOWN->GetWidth(), (int)mMovingLine2.mHeight)); } } else { if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_RIGHT, (int)mMovingLine2.mX - 1, (int)mMovingLine2.mY - 8, Rect(IMAGE_HUNGARR_BEAM_RIGHT->GetWidth() - (int)mMovingLine2.mWidth, 0, (int)mMovingLine2.mWidth, IMAGE_HUNGARR_BEAM_RIGHT->GetHeight())); } else { g->DrawImage(IMAGE_HUNGARR_BEAM_RIGHT, (int)mMovingLine2.mX - 1, (int)mMovingLine2.mY - 8, Rect(IMAGE_HUNGARR_BEAM_RIGHT->GetWidth() - (int)mMovingLine2.mWidth, 0, (int)mMovingLine2.mWidth, IMAGE_HUNGARR_BEAM_RIGHT->GetHeight())); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawMovingBeams(Graphics* g) { // If the beams are moving, then draw them. Make them pulse too. You make a // pulsing effect like we did in the previous demos: draw the image a second time on // top of the original additively, and colorize the image, setting the RGB values to // a different intensity. The result is an image that gets brighter and dimmer over time. if (!mMovingLine1.mBroken && (!mMovingLine1.mDone || mFilling || !mMovingLine2.mDone)) { Beam1DrawHelper(g); if (!mMovingLine1.mDone) { g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->SetColorizeImages(true); g->SetColor(Color(mBeamPulseVal, mBeamPulseVal, mBeamPulseVal)); Beam1DrawHelper(g); g->SetColorizeImages(false); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } } if (!mMovingLine2.mDone || mFilling || !mMovingLine1.mDone) { Beam2DrawHelper(g); if (!mMovingLine2.mDone) { g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->SetColorizeImages(true); g->SetColor(Color(mBeamPulseVal, mBeamPulseVal, mBeamPulseVal)); Beam2DrawHelper(g); g->SetColorizeImages(false); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } } g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); for (int i = 0; i < mParticles.size(); i++) { Particle* p = &mParticles[i]; g->DrawImageCel(IMAGE_PARTICLE_LIGHTNING, (int)p->mX, (int)p->mY, p->mFrame); } g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawPlanets(Graphics* g) { // If the user has 3d, we'll rotate the planets using the floating point // smooth rotation function. If they don't, we'll avoid rotating at all to // save on CPU cycles and keep the framerate up. int w = IMAGE_PLANETS->GetCelWidth(); int h = IMAGE_PLANETS->GetCelHeight(); for (int i = 0; i < mPlanets.size(); i++) { Planet* p = &mPlanets[i]; if (p->mExploding) { g->DrawImageCel(IMAGE_BOMB_RADIAL_DEATH, (int)p->mX - (IMAGE_BOMB_RADIAL_DEATH->GetCelWidth() / 2 + w / 2), (int)p->mY - (IMAGE_BOMB_RADIAL_DEATH->GetCelHeight() / 2 + h / 2), p->mExplodeFrame); } else { Rect r = Rect(p->mImgCol * w, 0, w, IMAGE_PLANETS->GetCelHeight()); if (gSexyAppBase->Is3DAccelerated()) g->DrawImageRotatedF(IMAGE_PLANETS, p->mX, p->mY, p->mRotationAngle, &r); else g->DrawImage(IMAGE_PLANETS, (int)p->mX, (int)p->mY, r); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawHungarrVertBeamsHelper(Graphics* g) { // This draws the two little static beams that are always attached to // Hun-garr's bitmap. If the user has hardware acceleration, we'll // draw the beams pulsating. If not, we'll skip it since it's time consuming // and doesn't hurt the game any. It'd be worse to drop the framrate by a few FPS // for this effect. int h = IMAGE_HUNGARR_VERT->GetHeight() / 2; if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_UP, mLine1X, mLine1Y, Rect(0, 0, IMAGE_HUNGARR_BEAM_UP->GetWidth(), h)); g->DrawImageF(IMAGE_HUNGARR_BEAM_DOWN, mLine2X, mLine2Y, Rect(0, IMAGE_HUNGARR_BEAM_DOWN->GetHeight() - h, IMAGE_HUNGARR_BEAM_DOWN->GetWidth(), h)); g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->SetColorizeImages(true); g->SetColor(Color(255, 255, 255, mBeamPulseVal)); g->DrawImageF(IMAGE_HUNGARR_BEAM_UP, mLine1X, mLine1Y, Rect(0, 0, IMAGE_HUNGARR_BEAM_UP->GetWidth(), h)); g->DrawImageF(IMAGE_HUNGARR_BEAM_DOWN, mLine2X, mLine2Y, Rect(0, IMAGE_HUNGARR_BEAM_DOWN->GetHeight() - h, IMAGE_HUNGARR_BEAM_DOWN->GetWidth(), h)); g->SetColorizeImages(false); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } else { g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->DrawImage(IMAGE_HUNGARR_BEAM_UP, (int)mLine1X, (int)mLine1Y, Rect(0, 0, IMAGE_HUNGARR_BEAM_UP->GetWidth(), h)); g->DrawImage(IMAGE_HUNGARR_BEAM_DOWN, (int)mLine2X, (int)mLine2Y, Rect(0, IMAGE_HUNGARR_BEAM_DOWN->GetHeight() - h, IMAGE_HUNGARR_BEAM_DOWN->GetWidth(), h)); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawHungarrHorizBeamsHelper(Graphics* g) { // This draws the two little static beams that are always attached to // Hun-garr's bitmap. If the user has hardware acceleration, we'll // draw the beams pulsating. If not, we'll skip it since it's time consuming // and doesn't hurt the game any. It'd be worse to drop the framrate by a few FPS // for this effect. int w = IMAGE_HUNGARR_HORIZ->GetWidth() / 2; if (gSexyAppBase->Is3DAccelerated()) { g->DrawImageF(IMAGE_HUNGARR_BEAM_LEFT, mLine1X, mLine1Y, Rect(0, 0, w, IMAGE_HUNGARR_BEAM_LEFT->GetHeight())); g->DrawImageF(IMAGE_HUNGARR_BEAM_RIGHT, mLine2X, mLine2Y, Rect(IMAGE_HUNGARR_BEAM_RIGHT->GetWidth() - w, 0, w, IMAGE_HUNGARR_BEAM_RIGHT->GetHeight())); g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->SetColorizeImages(true); g->SetColor(Color(255, 255, 255, mBeamPulseVal)); g->DrawImageF(IMAGE_HUNGARR_BEAM_LEFT, mLine1X, mLine1Y, Rect(0, 0, w, IMAGE_HUNGARR_BEAM_LEFT->GetHeight())); g->DrawImageF(IMAGE_HUNGARR_BEAM_RIGHT, mLine2X, mLine2Y, Rect(IMAGE_HUNGARR_BEAM_RIGHT->GetWidth() - w, 0, w, IMAGE_HUNGARR_BEAM_RIGHT->GetHeight())); g->SetColorizeImages(false); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } else { g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->DrawImage(IMAGE_HUNGARR_BEAM_LEFT, (int)mLine1X, (int)mLine1Y, Rect(0, 0, w, IMAGE_HUNGARR_BEAM_LEFT->GetHeight())); g->DrawImage(IMAGE_HUNGARR_BEAM_RIGHT, (int)mLine2X, (int)mLine2Y, Rect(IMAGE_HUNGARR_BEAM_RIGHT->GetWidth() - w, 0, w, IMAGE_HUNGARR_BEAM_RIGHT->GetHeight())); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::DrawHungarr(Graphics* g) { // again, we use the floating point functions instead of the integer ones // if the user has a 3d card. bool is3d = gSexyAppBase->Is3DAccelerated(); if (mHungarrIsVertical) { DrawHungarrVertBeamsHelper(g); if (is3d) g->DrawImageF(IMAGE_HUNGARR_VERT, mHungarrX, mHungarrY); else g->DrawImage(IMAGE_HUNGARR_VERT, mHungarrX, mHungarrY); } else { DrawHungarrHorizBeamsHelper(g); if (is3d) g->DrawImageF(IMAGE_HUNGARR_HORIZ, mHungarrX, mHungarrY); else g->DrawImage(IMAGE_HUNGARR_HORIZ, mHungarrX, mHungarrY); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { Widget::AddedToManager(theWidgetManager); mOptionsBtn = new ButtonWidget(1, this); mOptionsBtn->SetFont(FONT_DEFAULT); mOptionsBtn->mLabel = _S("Options"); mOptionsBtn->SetColor(ButtonWidget::COLOR_LABEL, Color::White); mOptionsBtn->SetColor(ButtonWidget::COLOR_LABEL_HILITE, Color::White); mOptionsBtn->mOverImage = IMAGE_BUTTON_OVER; mOptionsBtn->mDownImage = IMAGE_BUTTON_DOWN; mOptionsBtn->mButtonImage = IMAGE_BUTTON_NORMAL; mOptionsBtn->mDoFinger = true; mOptionsBtn->Resize(gSexyAppBase->mWidth - IMAGE_BUTTON_NORMAL->GetWidth() - 10, FONT_HUNGARR->GetHeight() * 3 - 20, IMAGE_BUTTON_NORMAL->GetWidth(), IMAGE_BUTTON_NORMAL->GetHeight()); theWidgetManager->AddWidget(mOptionsBtn); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { Widget::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mOptionsBtn); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::ButtonDepress(int theId) { // Play a sound whenever the options button is depressed/sad. if (theId == mOptionsBtn->mId) { // Stop the shorting sound if it's playing, otherwise it's annoying mShortSound->Stop(); mApp->PlaySample(SOUND_BUTTON); Pause(true); OptionsDialog* od = new OptionsDialog(this); od->Resize(mWidth / 2 - 200, mHeight / 2 - 175, 400, 350); mApp->AddDialog(OptionsDialog::DIALOG_ID, od); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseMove(int x, int y) { UpdateHungarrPosition(x, y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseDrag(int x, int y) { UpdateHungarrPosition(x, y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseDown(int x, int y, int theClickCount) { // if the level up effect is displaying stats, or the game over effect is too, // and the user clicked, then start the next phase if (mLevelupEffect->ShowingStats()) mLevelupEffect->DoneViewingStats(); if (mGameOverEffect->CanStartNewGame()) mGameOverEffect->DoneViewingStats(); // ignore mouse clicks when paused or an effect is on screen and the user has no reason to click if (mLevelupEffect->IsActive() || (mPauseLevel > 0) || (mGameOverEffect->IsActive() && !mGameOverEffect->CanStartNewGame())) return; // On a right click, if the click was within the grid bounds, switch hungarr's orientation if ((theClickCount < 0) && XCoordInBounds(x) && YCoordInBounds(y, mHungarrIsVertical)) mHungarrIsVertical = !mHungarrIsVertical; else if ((theClickCount > 0) && mMovingLine1.mDone && mMovingLine2.mDone && !mFilling) { //left click, and there's no lines moving: drop two new lines // Make sure the user didn't click on a planet which would instantly kill them FRect hungarrRect = FRect(mHungarrX, mHungarrY, IMAGE_HUNGARR_HORIZ->mWidth, IMAGE_HUNGARR_HORIZ->mHeight); for (int i = 0; i < mPlanets.size(); i++) { Planet* p = &mPlanets[i]; FRect planetRect = FRect(p->mX, p->mY, IMAGE_PLANETS->GetCelWidth(), IMAGE_PLANETS->GetCelHeight()); if (planetRect.Intersects(hungarrRect)) return; } mApp->PlaySample(SOUND_MAGZAP); // start the electrical shorting sound mShortSound->Play(true, false); mMovingLine1.mDone = mMovingLine2.mDone = false; mMovingLine1.mBroken = mMovingLine2.mBroken = false; int midX = IMAGE_HUNGARR_HORIZ->GetWidth() / 2; int midY = IMAGE_HUNGARR_HORIZ->GetHeight() / 2; //Align the XYs of the lines to the grid, and set the target coordinates to the //closest normal state tile. if (mHungarrIsVertical) { mMovingLine1.mIsVertical = mMovingLine2.mIsVertical = true; mMovingLine1.mX = mMovingLine2.mX = GetAlignedX(mHungarrX + midX); mMovingLine1.mY = mMovingLine2.mY = GetAlignedY(mHungarrY + midY); mMovingLine1.mHeight = 1; mMovingLine2.mHeight = 13; mMovingLine1.mWidth = mMovingLine2.mWidth = GRID_PIX_SIZE; mMovingLine1.mTargetY = mMovingLine2.mTargetY = mMovingLine1.mY; mMovingLine1.mTargetX = mMovingLine2.mTargetX = mMovingLine1.mX; // Make sure the target coords end at a tile that's normal. If not, keep moving them int row = GetRow(mMovingLine1.mTargetY); int col = GetCol(mMovingLine1.mTargetX); // Tile immediately below is not valid if (mGridState[row][col].mFillState != GRID_NORMAL) return; while ((row >= 0) && (mGridState[row][col].mFillState == GRID_NORMAL)) { mMovingLine1.mTargetY -= GRID_PIX_SIZE; --row; } // Make it end on the last valid tile. The loop above makes it leave // on an invalid tile mMovingLine1.mTargetY += GRID_PIX_SIZE; row = GetRow(mMovingLine2.mTargetY); col = GetCol(mMovingLine2.mTargetX); while ((row < GRID_HEIGHT) && (mGridState[row][col].mFillState == GRID_NORMAL)) { mMovingLine2.mTargetY += GRID_PIX_SIZE; ++row; } if (mMovingLine1.mTargetY > mMovingLine2.mTargetY) mMovingLine1.mDone = mMovingLine2.mDone = true; } else { mMovingLine1.mIsVertical = mMovingLine2.mIsVertical = false; mMovingLine1.mX = mMovingLine2.mX = GetAlignedX(mHungarrX + midX); mMovingLine1.mY = mMovingLine2.mY = GetAlignedY(mHungarrY + midY); mMovingLine1.mWidth = 1; mMovingLine2.mWidth = 13; mMovingLine1.mHeight = mMovingLine2.mHeight = GRID_PIX_SIZE; mMovingLine1.mTargetX = mMovingLine2.mTargetX = mMovingLine1.mX; mMovingLine1.mTargetY = mMovingLine2.mTargetY = mMovingLine1.mY; // Make sure the target coords end at a tile that's normal. If not, keep moving them int row = GetRow(mMovingLine1.mTargetY); int col = GetCol(mMovingLine1.mTargetX); // Tile immediately below is not valid...? if (mGridState[row][col].mFillState != GRID_NORMAL) return; while ((col >= 0) && (mGridState[row][col].mFillState == GRID_NORMAL)) { mMovingLine1.mTargetX -= GRID_PIX_SIZE; --col; } // Make it end on the last valid tile. The loop above makes it leave // on an invalid tile mMovingLine1.mTargetX += GRID_PIX_SIZE; row = GetRow(mMovingLine2.mTargetY); col = GetCol(mMovingLine2.mTargetX); while ((col < GRID_WIDTH) && (mGridState[row][col].mFillState == GRID_NORMAL)) { mMovingLine2.mTargetX += GRID_PIX_SIZE; ++col; } if (mMovingLine1.mTargetX > mMovingLine2.mTargetX) mMovingLine1.mDone = mMovingLine2.mDone = true; } } UpdateHungarrPosition(x, y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::UpdateHungarrPosition(int x, int y) { // Place the Hun-garr bitmap and the two lines that stick out of him // so that Hun-garr is centered on the mouse cursor int midX = IMAGE_HUNGARR_HORIZ->GetWidth() / 2; int midY = IMAGE_HUNGARR_HORIZ->GetHeight() / 2; if (YCoordInBounds(y, mHungarrIsVertical)) { mHungarrY = y - midY; mLine1Y = mHungarrY + (!mHungarrIsVertical ? 7 : -12); mLine2Y = mHungarrY + (!mHungarrIsVertical ? 7 : 35); } if (XCoordInBounds(x)) { mHungarrX = x - midX; mLine1X = mHungarrX + (!mHungarrIsVertical ? -13 : 8); mLine2X = mHungarrX + (!mHungarrIsVertical ? 36 : 9); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::CalculateFillRegions(void) { int topRow, botRow, leftCol, rightCol; // The basic idea is this: Find the CLOSEST edge to where the user clicks that // meets the following conditions: // 1. If Hun-garr is vertical, the edge must be as tall as the column created // by the two emitted lines (or more) and every grid piece must be normal // 2. If Hun-garr is horizontal, the edge must be as wide as the row created by // the two emitted lines (or more) and every grid piece must be normal // 3. If either of the lines were broken, we instead just fill in the single // line made by the non-broken line (the code won't execute if both are broken) if (mMovingLine1.mIsVertical) { topRow = GetRow(mMovingLine1.mTargetY); int col1 = GetCol(mMovingLine1.mTargetX); botRow = GetRow(mMovingLine2.mTargetY); if ((mMovingLine1.mBroken && !mMovingLine2.mBroken) || (!mMovingLine1.mBroken && mMovingLine2.mBroken)) { leftCol = col1; rightCol = col1 + 1; mFillDirection = FILL_RIGHT; topRow = mMovingLine1.mBroken ? GetRow(mMovingLine2.mY) : topRow; botRow = mMovingLine1.mBroken ? botRow : GetRow(mMovingLine2.mY); } else { int rightEdge, leftEdge; GetVerticalFillValues(col1, topRow, botRow, 1, &rightEdge); GetVerticalFillValues(col1, topRow, botRow, -1, &leftEdge); if ((rightEdge - col1) <= (col1 - leftEdge)) { leftCol = col1; rightCol = rightEdge + 1; mFillDirection = FILL_RIGHT; } else { leftCol = leftEdge; rightCol = col1 + 1; mFillDirection = FILL_LEFT; } } } else { leftCol = GetCol(mMovingLine1.mTargetX); rightCol = GetCol(mMovingLine2.mTargetX); int row1 = GetRow(mMovingLine1.mTargetY); if ((mMovingLine1.mBroken && !mMovingLine2.mBroken) || (!mMovingLine1.mBroken && mMovingLine2.mBroken)) { leftCol = mMovingLine1.mBroken ? GetCol(mMovingLine2.mX) : leftCol; rightCol = mMovingLine1.mBroken ? rightCol : GetCol(mMovingLine2.mX); topRow = row1; botRow = row1 + 1; mFillDirection = FILL_DOWN; } else { int topEdge, botEdge; GetHorizontalFillValues(row1, leftCol, rightCol, -1, &topEdge); GetHorizontalFillValues(row1, leftCol, rightCol, 1, &botEdge); if ((botEdge - row1) <= (row1 - topEdge)) { topRow = row1; botRow = botEdge + 1; mFillDirection = FILL_DOWN; } else { topRow = topEdge; botRow = row1 + 1; mFillDirection = FILL_UP; } } } //Make a rectangular fill region: every block in it will eventually be filled. // Then, for all grid pieces in that region, if they are in the normal state, // set them to the filling state and initialize their mFillRect's mFillRegion.mLeft = leftCol; mFillRegion.mRight = rightCol - 1; mFillRegion.mTop = topRow; mFillRegion.mBottom = botRow - 1; for (int y = topRow; y < botRow; y++) { for (int x = leftCol; x < rightCol; x++) { if (mGridState[y][x].mFillState == GRID_NORMAL) { mGridState[y][x].mFillState = GRID_FILLING; switch (mFillDirection) { case FILL_RIGHT: mGridState[y][x].mFillRect = FRect(GetColPix(x), GetRowPix(y), 0, GRID_PIX_SIZE); break; case FILL_LEFT: mGridState[y][x].mFillRect = FRect(GetColPix(x + 1), GetRowPix(y), 0, GRID_PIX_SIZE); break; case FILL_UP: mGridState[y][x].mFillRect = FRect(GetColPix(x), GetRowPix(y + 1), GRID_PIX_SIZE, 0); break; case FILL_DOWN: mGridState[y][x].mFillRect = FRect(GetColPix(x), GetRowPix(y), GRID_PIX_SIZE, 0); break; } } } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::FillRectF(Graphics* g, FRect fr) { Rect r = Rect((int)fr.mX, (int)fr.mY, (int)fr.mWidth, (int)fr.mHeight); g->FillRect(r); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::GetVerticalFillValues(int startCol, int topRow, int botRow, int dir, int* edge) { // If dir == -1, left, if 1, right // See function header for algorithm description bool done = false; int col = startCol; while (!done) { bool found = true; for (int y = topRow; y < botRow; y++) { if (mGridState[y][col].mFillState != GRID_FILLED) { found = false; break; } } if (!found) { if ( ((dir > 0) && (++col >= GRID_WIDTH)) || ((dir < 0) && (--col < 0)) ) { done = true; *edge = col + (dir > 0 ? -1 : 1); } } else { *edge = col; done = true; } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::GetHorizontalFillValues(int startRow, int leftCol, int rightCol, int dir, int* edge) { // If dir == -1, up, if 1, down // See function header for algorithm description bool done = false; int row = startRow; while (!done) { bool found = true; for (int x = leftCol; x < rightCol; x++) { if (mGridState[row][x].mFillState != GRID_FILLED) { found = false; break; } } if (!found) { if ( ((dir > 0) && (++row >= GRID_HEIGHT)) || ((dir < 0) && (--row < 0)) ) { done = true; *edge = row + (dir > 0 ? -1 : 1); } } else { *edge = row; done = true; } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::InitLevel(int level) { mLives += level - mLevel; mPopulationEaten = 0; mPlanetSpeed += 0.15f; mLevel = level; mPlanets.clear(); mFlashCount = 0; mPercentComplete = 0; mPlanetsEaten.clear(); mBonusText.clear(); mParticles.clear(); mFilling = false; // reset the grid state int i; for (i = 0; i < GRID_HEIGHT; i++) { for (int x = 0; x < GRID_WIDTH; x++) { mGridState[i][x].mFillRect = FRect(x * GRID_PIX_SIZE, GRID_START_Y + i * GRID_PIX_SIZE, 0, 0); mGridState[i][x].mFillState = GRID_NORMAL; } } // Start with 2 planets. Then add 1 every other level int numPlanets = 2 + (mLevel / 2); for (i = 0; i < numPlanets; i++) { Planet p; // Choose a random name and export p.mNameIdx = Rand() % NUM_PLANET_NAMES; p.mExportIdx = Rand() % NUM_PLANET_EXPORTS; // a random number I made up for the population. Increases by a random amount each level. p.mPopulation = (mLevel * 133602) + 748819; // Position it randomly within the confines of the grid p.mX = GRID_START_X + 20 + (Rand() % (GRID_END_X - GRID_START_X - 20)); p.mY = GRID_START_Y + 20 + (Rand() % (GRID_END_Y - GRID_START_Y - 20)); // Get a random angle for the planet to travel in. It's easier to do RAND on // degrees, so convert them to radians after choosing an angle float a = (Rand() % 360) * M_PI / 180.0f; p.mVX = mPlanetSpeed * cosf(a); p.mVY = -mPlanetSpeed * sinf(a); // don't let the speed be too close to 0 though, it's lame if the planet // bounces just straight vertically or horizontally if ((p.mVX >= -0.1) && (p.mVX <= 0.1)) p.mVX = 0.3f; if ((p.mVY >= -0.1) && (p.mVY <= 0.1)) p.mVY = 0.3f; // Set a random initial rotation angle and speed to rotate at. // All angle manipulation is in radians. p.mRotationAngle = (Rand() % 360) * M_PI / 180.0f; p.mRotateSpeed = (float)(Rand() % 100) / 1000.0f; // Choose a random image. There's 11 images, each is just 1 frame. p.mImgCol = Rand() % IMAGE_PLANETS->mNumCols; mPlanets.push_back(p); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool Board::MovePlanet(Planet* p, float theFrac) { // This is a pretty simple collision detection routine and is good enough for this // game. It's also a lot easier to understand than other more accurate but more // complex methods. The basic idea is to check the two blocks in the direction of // travel to see if they are solid or not, and if so, we reverse course, and // don't move the planet to that new coordinate. int w = IMAGE_PLANETS->GetCelWidth(); int h = IMAGE_PLANETS->GetCelHeight(); bool playSample = false; // Update rotation p->mRotationAngle += p->mRotateSpeed; // Don't move it yet...compute where it WOULD be if the move was valid float newx = p->mX + p->mVX * theFrac; float newy = p->mY + p->mVY * theFrac; // If moving right, we'll check the grid piece right of the // planet to see if we hit it. Otherwise, we'll just use the grid piece that maps to // where the new X coordinate is: float checkx = p->mVX > 0 ? newx + GRID_PIX_SIZE : newx; int col = GetCol(checkx); // We're going to check both the current row and row below it: int row = GetRow(p->mY); int nextrow = ValidRow(row + 1) ? row + 1 : row; if (ValidCol(col) && ValidRow(row)) { int state1 = mGridState[row][col].mFillState; int state2 = mGridState[nextrow][col].mFillState; if ((state1 == GRID_NORMAL) && (state2 == GRID_NORMAL) && (newx > GRID_START_X)) p->mX = newx; // valid grid space else if (((state1 == GRID_FILLING) || (state2 == GRID_FILLING)) && (newx > GRID_START_X)) { // planet entered a grid space that is in the process of being filled, so make it explode p->mExploding = true; GivePlanetBonus(p); return true; } else { // planet hit a filled in space, reverse the X velocity playSample = true; p->mVX = -p->mVX; } } else { // Not valid cases would be if the planet hit the edges of the board, where there // aren't any grid tiles. If so, just bounce it off the wall. playSample = true; p->mVX = -p->mVX; } // Now for the Y direction. The principal is the same as above. int checky = p->mVY > 0 ? (int)newy + GRID_PIX_SIZE : (int)newy; row = GetRow(checky); col = GetCol(p->mX); int nextcol = ValidCol(col + 1) ? col + 1 : col; if (ValidCol(col) && ValidRow(row)) { int state1 = mGridState[row][col].mFillState; int state2 = mGridState[row][nextcol].mFillState; if ((state1 == GRID_NORMAL) && (state2 == GRID_NORMAL) && (newy > GRID_START_Y)) p->mY = newy; else if (((state1 == GRID_FILLING) || (state2 == GRID_FILLING)) && (newy > GRID_START_Y)) { p->mExploding = true; GivePlanetBonus(p); return true; } else { playSample = true; p->mVY = -p->mVY; } } else { p->mVY = -p->mVY; playSample = true; } // When a planet hits a wall/filled in grid piece, bounce it and play a sound if (playSample) mApp->PlaySample(SOUND_PLANET_HIT); CheckPlanetBeamCollision(p); return false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::CheckPlanetBeamCollision(Planet* p) { // We're just going to do a rectangular collision check on each of the beams // and the given planet. Because the visible "beam" part of the image is smaller // than the image width/height, and the same goes for the planet too, you'll notice // that offsets are used to constrain the collision rectangles to make a more fair algorithm. FRect pr = FRect(p->mX + 4, p->mY + 4, 11, 11); FRect beam1Rect; if (!mMovingLine1.mIsVertical) beam1Rect = FRect(mMovingLine1.mX + 7, mMovingLine1.mY + 12, mMovingLine1.mWidth - 12, 8); else beam1Rect = FRect(mMovingLine1.mX + 12, mMovingLine1.mY + 10, 9, mMovingLine1.mHeight); // Only allow the user to lose 1 life max: if both beams break you don't lose 2. If the beam breaks, // set a flag and set its target to be its current location (indicating that it's done moving) if (pr.Intersects(beam1Rect)) { if (!mMovingLine1.mDone) { mMovingLine1.mBroken = true; mApp->PlaySample(SOUND_BEAM_HIT); if (!mMovingLine2.mBroken) LostLife(); if (!mMovingLine1.mIsVertical) mMovingLine1.mTargetX = mMovingLine1.mX = mMovingLine1.mX + mMovingLine1.mWidth; else mMovingLine1.mTargetY = mMovingLine1.mY = mMovingLine1.mY + mMovingLine1.mHeight; } else if (!mMovingLine1.mBroken && mMovingLine1.mDone && !mMovingLine2.mDone) { // bounce off of it if (mMovingLine1.mIsVertical) { p->mVX *= -1.0f; p->mX += p->mVX; } else { p->mVY *= -1.0f; p->mY += p->mVY; } } } FRect beam2Rect; if (!mMovingLine2.mIsVertical) beam2Rect = FRect(mMovingLine2.mX, mMovingLine2.mY + 12, mMovingLine2.mWidth - 7, 8); else beam2Rect = FRect(mMovingLine2.mX + 12, mMovingLine2.mY, 9, mMovingLine2.mHeight); if (pr.Intersects(beam2Rect)) { if (!mMovingLine2.mDone) { mMovingLine2.mBroken = true; mApp->PlaySample(SOUND_BEAM_HIT); if (!mMovingLine1.mBroken) LostLife(); if (!mMovingLine2.mIsVertical) mMovingLine2.mTargetX = mMovingLine2.mX; else mMovingLine2.mTargetY = mMovingLine2.mY; } else if (!mMovingLine2.mBroken && mMovingLine2.mDone && !mMovingLine1.mDone) { // bounce off of it if (mMovingLine2.mIsVertical) { p->mVX *= -1.0f; p->mX += p->mVX; } else { p->mVY *= -1.0f; p->mY += p->mVY; } } } if ((mMovingLine1.mDone && mMovingLine2.mDone) || (mMovingLine1.mBroken && mMovingLine2.mDone) || (mMovingLine2.mBroken && mMovingLine1.mDone)) mShortSound->Stop(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Pause(bool p) { if (p) { // Since when we're paused we don't update each frame, call // MarkDirty here so that we ensure the "PAUSED" overlay appears MarkDirty(); ++mPauseLevel; // Don't play the looping circuit sound mShortSound->Stop(); } else { if (--mPauseLevel == 0) { // If any of the lines are moving, re-play the shorting sound if (!mMovingLine1.mDone || !mMovingLine2.mDone) mShortSound->Play(true, false); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::KeyChar(char theChar) { if (theChar == ' ') Pause(mPauseLevel == 0); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::GivePlanetBonus(Planet* p) { mTotalPopulationEaten += p->mPopulation; mPopulationEaten += p->mPopulation; mLineSpeed += BEAM_INC_SPEED; if (mLineSpeed > MAX_BEAM_SPEED) mLineSpeed = MAX_BEAM_SPEED; ++mNumPlanetsEaten; SexyString pName = PLANET_NAME[p->mNameIdx]; SexyString pExport = PLANET_EXPORTS[p->mExportIdx]; int points = mLevel * 1000; AddBonusText(StrFormat(_S("%s: +%d"), pName.c_str(), points), p->mX, p->mY); mScore += points; mPlanetsEaten.push_back(pName); mPlanetsEaten.push_back(pExport.c_str()); mPlanetsEaten.push_back(CommaSeperate(p->mPopulation)); std::map::iterator it = mPlanetIdxCount.find(p->mNameIdx); if (it == mPlanetIdxCount.end()) mPlanetIdxCount[p->mNameIdx] = 1; else ++it->second; it = mExportIdxCount.find(p->mExportIdx); if (it == mExportIdxCount.end()) mExportIdxCount[p->mExportIdx] = 1; else ++it->second; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::UpdatePercentComplete(void) { if (mGameOverEffect->IsActive()) return; int total = GRID_WIDTH * GRID_HEIGHT; int actual = 0; for (int y = 0; y < GRID_HEIGHT; y++) for (int x = 0; x < GRID_WIDTH; x++) if (mGridState[y][x].mFillState == GRID_FILLED) ++actual; int newAmount = (int) (((float)actual / (float)total) * 100.0f); int pctCleared = newAmount - mPercentComplete; // Make the edges of the grid flash the larger the filled region was, but not // for more than 3 seconds. mFlashCount = pctCleared * 10; if (mFlashCount > 300) mFlashCount = 300; // Points are exponential, so the larger a fill region, the much larger the score int points = pctCleared * pctCleared * 20; mScore += points; if (points > 0) { mApp->PlaySample(SOUND_REGION_FILLED); AddBonusText(StrFormat(_S("+%d"), points)); } mPercentComplete = newAmount; if (mPercentComplete >= LEVELUP_PERCENT) { // Time to level up, set up the stats LevelupStats ls; ls.mLevelCompleted = mLevel; ls.mPercentComplete = mPercentComplete; ls.mPopulationEaten = mPopulationEaten; ls.mPlanetsEaten = mPlanetsEaten; // Award a bonus for extra region filling action if (mPercentComplete >= COMPLETION_BONUS_PCT) mScore += COMPLETION_BONUS * mLevel; mOptionsBtn->SetVisible(false); mLevelupEffect->Activate(ls); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddBonusText(SexyString t) { AddBonusText(t, mWidth / 2 - FONT_HUNGARR->StringWidth(t) / 2, (mHeight - GRID_START_Y) / 2 - FONT_HUNGARR->GetHeight() / 2); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddBonusText(SexyString t, float x, float y) { BonusText bt; bt.mText = t; bt.mX = x; bt.mY = y; mBonusText.push_back(bt); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::LostLife(void) { if (--mLives <= 0) { mLives = 0; // Game over. Set up the stats: mOptionsBtn->SetVisible(false); EndGameStats es; es.mLevel = mLevel; es.mNumPlanetsEaten = mNumPlanetsEaten; es.mPopulationConsumed = mTotalPopulationEaten; es.mScore = mScore; // Find which planet and export were consumed the most: int idx = -1; int count = 0; int i; for (i = 0; i < NUM_PLANET_NAMES; i++) { std::map::iterator it = mPlanetIdxCount.find(i); if (it != mPlanetIdxCount.end()) { if (it->second > count) { count = it->second; idx = i; } } } if (idx != -1) es.mFavoritePlanet = PLANET_NAME[idx]; else es.mFavoritePlanet = _S("N/A"); idx = -1; count = 0; for (i = 0; i < NUM_PLANET_EXPORTS; i++) { std::map::iterator it = mExportIdxCount.find(i); if (it != mExportIdxCount.end()) { if (it->second > count) { count = it->second; idx = i; } } } if (idx != -1) es.mFavoriteExport = PLANET_EXPORTS[idx]; else es.mFavoriteExport = _S("N/A"); // Fade out the music mApp->mMusicInterface->FadeOut(0, true); mShortSound->Stop(); mGameOverEffect->Activate(es); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::EmitSparks(void) { // This basically emits sparks between various angles, depending on // the orientation of the line. The angle values I had to play around with // until I found ones that I liked, and there's no magic secret formula for // coming up with them, unless you just know how to guess well. Again, // the Rand() function is easier dealt with using degrees, so we convert them // to radians after choosing an angle. Then, using some basic math, we compute // the separate XY velocities for the projectiles. In some cases, projectiles use // diferent velocities, and again, that was just due to trying to get the nicest look // and involved some playing around with to figure out. The offsets are to make the sparks // appear to come out of the bulbous part of the line. if (!mMovingLine1.mDone && !mMovingLine1.mBroken) { if (mMovingLine1.mIsVertical) { // between 90 and 180 degrees for left side emission float angle = (90 + (Rand() % 90)) * M_PI / 180.0f; float vx = cosf(angle) * 2.0f; float vy = -sinf(angle) * 2.0f; mParticles.push_back(Particle(mMovingLine1.mX + 5, mMovingLine1.mY + 8, vx, vy)); // between 0 and 90 degrees for right side emission angle = (Rand() % 90) * M_PI / 180.0f; vx = cosf(angle) * 2.0f; vy = -sinf(angle) * 2.0f; mParticles.push_back(Particle(mMovingLine1.mX + 5, mMovingLine1.mY + 8, vx, vy)); } else { // between 280 and 320 degrees for bottom side emission float angle = (280 + (Rand() % 40)) * M_PI / 180.0f; float vx = cosf(angle) * 4.0f; float vy = -sinf(angle) * 2.0f; mParticles.push_back(Particle(mMovingLine1.mX + 5, mMovingLine1.mY + 8, vx, vy)); // between 50 and 90 degrees for top side emission angle = (50 + (Rand() % 40)) * M_PI / 180.0f; vx = cosf(angle) * 4.0f; vy = -sinf(angle) * 3.0f; mParticles.push_back(Particle(mMovingLine1.mX + 5, mMovingLine1.mY + 8, vx, vy)); } } if (!mMovingLine2.mDone && !mMovingLine2.mBroken) { if (mMovingLine2.mIsVertical) { // between 50 and 90 degrees for left side emission float angle = (50 + (Rand() % 40)) * M_PI / 180.0f; float vx = cosf(angle) * 3.0f; float vy = -sinf(angle) * 4.0f; mParticles.push_back(Particle(mMovingLine2.mX + 1, mMovingLine2.mY + mMovingLine2.mHeight - 17, vx, vy)); // between 120 and 160 degrees for right side emission angle = (120 + (Rand() % 40)) * M_PI / 180.0f; vx = cosf(angle) * 2.0f; vy = -sinf(angle) * 4.0f; mParticles.push_back(Particle(mMovingLine2.mX + 1, mMovingLine2.mY + mMovingLine2.mHeight - 17, vx, vy)); } else { // between 90 and 140 degrees for top side emission float angle = (90 + (Rand() % 50)) * M_PI / 180.0f; float vx = cosf(angle) * 4.0f; float vy = -sinf(angle) * 3.0f; mParticles.push_back(Particle(mMovingLine2.mX + mMovingLine2.mWidth - 20, mMovingLine2.mY + 2, vx, vy)); // between 220 and 260 degrees for bottom side emission angle = (220 + (Rand() % 40)) * M_PI / 180.0f; vx = cosf(angle) * 4.0f; vy = -sinf(angle) * 4.0f; mParticles.push_back(Particle(mMovingLine2.mX + mMovingLine2.mWidth - 20, mMovingLine2.mY + 2, vx, vy)); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::OptionsDialogDone() { // If any of the lines are moving, re-play the shorting sound if (!mMovingLine1.mDone || !mMovingLine2.mDone) mShortSound->Play(true, false); Pause(false); // Give focus back to the board so that it processes keyboard input mApp->mWidgetManager->SetFocus(this); mApp->KillDialog(OptionsDialog::DIALOG_ID); } libtuxcap-1.4.0/tuxcap/hungarr/LevelupEffect.h0000644000175000017500000001704710641010442021244 0ustar inniyahinniyah////////////////////////////////////////////////////////////////////////// // LevelupEffect.h // // Does the level up effect, from the bouncing "LEVEL UP!" text to // the stats display and weird transition effects. ////////////////////////////////////////////////////////////////////////// #ifndef __LEVELUP_EFFECT_H__ #define __LEVELUP_EFFECT_H__ #include "Common.h" #include "Rect.h" namespace Sexy { class Graphics; ////////////////////////////////////////////////////////////////////////// // Represents a letter that bounces, used for the "LEVEL UP!" text. ////////////////////////////////////////////////////////////////////////// struct BouncyChar { SexyString mChar; // The character bouncing bool mDone; // Completed bouncing yet? float mX, mY; float mBounceSpeed; // How fast up or down it's bouncing, affected by "gravity" float mOldBounceSpeed; // The base value that mBounceSpeed started at. Gets reduced over time. BouncyChar(SexyString t, float x, float y, float s) {mChar = t; mX = x; mY = y; mBounceSpeed = mOldBounceSpeed = s; mDone = false;} }; ////////////////////////////////////////////////////////////////////////// // Contains stat info to display after completing a level. ////////////////////////////////////////////////////////////////////////// struct LevelupStats { int mPopulationEaten; int mPercentComplete; int mLevelCompleted; // Always 3 strings per planet: // Planet name, exports, population (comma delimited) std::vector mPlanetsEaten; }; class LevelupEffect { private: // States that the level up effect goes through enum { LEVELUP_TEXT, // Displaying the bouncy LEVEL UP! text CURTAIN_IN, // Moving the black "curtain" inward to cover up the level CURTAIN_OUT, // Moving the red "curtain" out after above to reveal the stats SHOWING_STATS, // Displaying level stats COVERING_STATS, // Doing the weird transitionary cover-up screen after clicking to continue FADE_OUT_STATS // Fading out the above screen }; std::vector mText; // The letters that spell LEVEL UP!, as BouncyChar structures LevelupStats mStats; // Stat info to display bool mActive; // If true, means we're doing the level up sequence bool mDone; // If done, means all finished and the next level can actually begin bool mStartNextLevel; // When true, indicates that the board should set up the next level so that it'll be there when we fade out int mHue; // For hue/saturation/luminence crazy weird flashing effect int mCurtainX; // X location of the black/red curtain edge (for the left curtain, the right is the same size) int mState; // One of the above nums // When doing the COVERING_STATS phase, this is how wide 1/2 of the filled in part of the screen is. The other half // is the same size. int mCoverWidth; int mStripHeight; // For the above, we make strips quickly appear, alternating up/down filling // Indicates whether the strips are increasing Y (so strip comes from top) or decreasing // (so strip comes from bottom) int mStripSizeChange; int mFadeOutAlpha; // Alpha amount for the final fade out effect ////////////////////////////////////////////////////////////////////////// // Function: Init // // Purpose: Sets up and initializes/resets all variables. ////////////////////////////////////////////////////////////////////////// void Init(); public: LevelupEffect(); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: // theFrac - Value from Board::UpdateF, used for smooth motion // ////////////////////////////////////////////////////////////////////////// void Update(float theFrac); ////////////////////////////////////////////////////////////////////////// // Draw ////////////////////////////////////////////////////////////////////////// void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Activate // Parameters: // ls - A stat structure containing the info for the past level // // Purpose: Begins the level up sequence ////////////////////////////////////////////////////////////////////////// void Activate(LevelupStats ls); ////////////////////////////////////////////////////////////////////////// // Function: DoneViewingStats // // Purpose: Called by Board when the user clicks the mouse button, // indicating that they want the stats screen to go away and have the // next level begin. ////////////////////////////////////////////////////////////////////////// void DoneViewingStats(); ////////////////////////////////////////////////////////////////////////// // Function: StartNextLevel // Returns: true or false, indicating if the next level can be started. // // Purpose: Called by the Board's Update method, this returns true // when the board should initialize the next level, so that when the // level up effect fades out, the next level will appear underneath it. // When the function returns true, it automatically sets internal variables // so that the next time the function is called, it will return false, // preventing the Board from accidentally initializing the same level // multiple times. After the next call to Activate, it is allowed to // return true again. // // Once the screen is totally filled after closing the stats display, // the Board is allowed to init the next level. ////////////////////////////////////////////////////////////////////////// bool StartNextLevel(); ////////////////////////////////////////////////////////////////////////// // Function: IsDone // Returns: true or false indicating if the entire sequence is done // // Purpose: Used to let the board know when playing of the next level // can begin. ////////////////////////////////////////////////////////////////////////// bool IsDone() {return mDone;} ////////////////////////////////////////////////////////////////////////// // Function: IsActive // Returns: true or false indicating if the sequence is running or not ////////////////////////////////////////////////////////////////////////// bool IsActive() {return mActive;} ////////////////////////////////////////////////////////////////////////// // Function: ShowingStats // Returns: true or false indicating if the stats display is visible ////////////////////////////////////////////////////////////////////////// bool ShowingStats() {return mState == SHOWING_STATS;} ////////////////////////////////////////////////////////////////////////// // Function: HideBoard // Returns: true or false indicating whether or not the board should // hide all of its display stuff, except for the starfield which always // displays. ////////////////////////////////////////////////////////////////////////// bool HideBoard() {return (mState == SHOWING_STATS) || (mState == CURTAIN_OUT) || (mState == COVERING_STATS);} ////////////////////////////////////////////////////////////////////////// // Function: HidePlanets // Returns: true or false indicating if just the planets should be // hidden. // // Purpose: Used to hide the planets but still allow the rest of the // game board to display. Used during the transtion to the stats // display screen. ////////////////////////////////////////////////////////////////////////// bool HidePlanets() {return IsActive() && (HideBoard() || (mState == LEVELUP_TEXT) || (mState == CURTAIN_IN));} }; } #endif //__LEVELUP_EFFECT_H__ libtuxcap-1.4.0/tuxcap/hungarr/LevelupEffect.cpp0000644000175000017500000003600610645766220021613 0ustar inniyahinniyah#include "LevelupEffect.h" #include "Board.h" #include "Res.h" #include "SexyAppBase.h" #include "Graphics.h" #include "Font.h" using namespace Sexy; const int STRIP_WIDTH = 20; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// LevelupEffect::LevelupEffect() { Init(); mActive = false; mCoverWidth = 0; mStripSizeChange = 60; mStripHeight = 0; mFadeOutAlpha = 255; mStartNextLevel = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void LevelupEffect::Init() { mText.clear(); ////////////////////////////////////////////////////////////////////////// // Each letter, starting with the 'L' in "LEVEL UP!", will drop, delayed // by a height of FONT_HUNGARR->GetHeight() pixels. Each letter will initially // drop at a rate of 5 pixels per update (500 pixels per second). Once they // reach their target Y coordinate (300), the speed will decrease and reverse // to make the letters bounce upward. Gravity is applied each frame, so eventually // the letters return back to Y of 300, where the speed is again decreased and // reversed until it drops below the threshhold speed of 0.1 pixels per update. ////////////////////////////////////////////////////////////////////////// float x = (GRID_END_X - GRID_START_X) / 2 - FONT_HUNGARR->StringWidth(_S("LEVEL UP!")) / 2; float y = FONT_HUNGARR->GetHeight(); float startingY = y; float ydec = y; float speed = 5.0f; mText.push_back(BouncyChar(_S("L"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("L")); y -= ydec; mText.push_back(BouncyChar(_S("E"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("E")); y -= ydec; mText.push_back(BouncyChar(_S("V"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("V")); y -= ydec; mText.push_back(BouncyChar(_S("E"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("E")); y -= ydec; mText.push_back(BouncyChar(_S("L"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("L ")); y -= ydec; mText.push_back(BouncyChar(_S("U"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("U")); y -= ydec; mText.push_back(BouncyChar(_S("P"), x, y, speed)); x += FONT_HUNGARR->StringWidth(_S("P")); y -= ydec; mText.push_back(BouncyChar(_S("!"), x, y, speed)); mDone = false; mHue = 0; mCurtainX = 0; mState = LevelupEffect::LEVELUP_TEXT; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void LevelupEffect::Activate(LevelupStats ls) { Init(); mActive = true; mStats = ls; gSexyAppBase->PlaySample(SOUND_LEVEL_UP1); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void LevelupEffect::Update(float theFrac) { // HSL is an alternative to specifying an RGB color format. // Using HSL lets us easily do the hyper blinking crazy weird // flashing effect commonly found in old games, such as Robotron. // Below, we increment the value by 7 per update. The &0xFF is an // easy way to clamp the value between 0 and 255 instead of having to // do a separate if (mHue > 255) mHue -= 255. This lets the value // rollover and keep cycling. mHue = (mHue + 7) & 0xFF; if (mState == LevelupEffect::LEVELUP_TEXT) { // Move all the letters, applying 0.15 pixels per update of // "gravity" to pull the letters down. Once reaching Y of 300, // the speed of the letters decreases by 0.75 and is reversed, making // them "bounce" in the up direction. Once this bounce speed drops below 0.1 // pixels per update, the letter is done bouncing. When all letters are done bouncing, // switch to the next state. bool allDone = true; for (int i = 0; i < mText.size(); i++) { BouncyChar* c = &mText[i]; if (c->mDone) continue; c->mY += c->mBounceSpeed; c->mBounceSpeed += 0.15f; if (c->mY >= 300) { c->mY = 300; c->mOldBounceSpeed -= 0.750f; if (c->mOldBounceSpeed <= 0.1f) { c->mDone = true; c->mOldBounceSpeed = 0; } else { allDone = false; c->mBounceSpeed = -c->mOldBounceSpeed; } } else allDone = false; } if (allDone) mState = LevelupEffect::CURTAIN_IN; } else if (mState == LevelupEffect::CURTAIN_IN) { // Moves the black rectangles ("curtains") inward to cover up the // previous level. We only move the left one. The right one is logically // just the same width but starting from the right of the screen instead // of the left. The curtain moves 25 pixels per update. Once it reaches // the center (and thus fully covers the screen), we switch to the next state. if ((mCurtainX += 25) >= gSexyAppBase->mWidth / 2) { mCurtainX = gSexyAppBase->mWidth / 2; mState = LevelupEffect::CURTAIN_OUT; gSexyAppBase->PlaySample(SOUND_LEVEL_UP2); } } else if (mState == LevelupEffect::CURTAIN_OUT) { // Now the curtain is red and slowly moves back out to reveal the // stats below it. This works just like above. if ((mCurtainX -= 2) <= 0) mState = LevelupEffect::SHOWING_STATS; } else if (mState == LevelupEffect::COVERING_STATS) { // This state begins when the user clicks the mouse to dismiss the // stats screen. We then make these strips quickly appear. Imagine // rectangles of width 20 coming in from the left and right of the screen. // The left one starts comign from the top left of the screen, the right // from the bottom right. These strips quickly expand to be screen height in size // and then move closer inward (by their width of 20) and reverse the direction // that they come in at. Once the strips have traveled to the center of the screen, // it's fully covered and we then move to the next state. After a strip becomes // the height of the screen, we update mCoverWidth, which is just simply the width // of the region fully filled in. Again, like with the curtain effects, we only // keep track of the left side, since the right moves the same amount and it's // easy to compute the right's offsets. if (mStripSizeChange > 0) { // Left strip is moving downward from Y of 0, right is moving up // from Y of app height if ((mStripHeight += mStripSizeChange) >= gSexyAppBase->mHeight) { // Left strip and right strip are now the height of the screen. // Reverse the direction they come in at and reset their heights. // Then, increment the width of the fully covered region by the // size of one of the strip's width. mStripSizeChange = -mStripSizeChange; mStripHeight = 0; if ((mCoverWidth += STRIP_WIDTH) >= gSexyAppBase->mWidth / 2) { // The screen is fully covered. Fade out. mStartNextLevel = true; mState = LevelupEffect::FADE_OUT_STATS; } } } else { if ((mStripHeight -= mStripSizeChange) >= gSexyAppBase->mHeight) { mStripSizeChange = -mStripSizeChange; mStripHeight = 0; if ((mCoverWidth += STRIP_WIDTH) >= gSexyAppBase->mWidth / 2) { mStartNextLevel = true; mState = LevelupEffect::FADE_OUT_STATS; } } } } else if (mState == LevelupEffect::FADE_OUT_STATS) { //Fade the screen out, with the next level appearing below it. if ((mFadeOutAlpha -= 2) <= 0) { mDone = true; mActive = false; } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void LevelupEffect::Draw(Graphics* g) { g->SetFont(FONT_HUNGARR); if (mState == LevelupEffect::LEVELUP_TEXT) { // This is how we convert an HSL value to an RGB value, which we have to // do to specify the color for the graphics object. The function HSLToRGB // takes as parameters: hue, saturation, luminance. We want to leave the // saturation at max and luminance at half for our particular example. // The returned value is ANDed with 0xFFFFFFFF to clamp the values for // the alpha, red, green, and blue to the valid region of 0 to 255. g->SetColor( (gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFFFF) ); for (int i = 0; i < mText.size(); i++) { BouncyChar* c = &mText[i]; g->DrawString(c->mChar, (int)c->mX, (int)c->mY); } } else if (mState == LevelupEffect::CURTAIN_IN) { // The righ tcurtain is just the same width as the left, but starts from the right // side instead of X of 0. g->SetColor(Color(0, 0, 0)); g->FillRect(0, 0, mCurtainX, gSexyAppBase->mHeight); g->FillRect(gSexyAppBase->mWidth - mCurtainX, 0, mCurtainX, gSexyAppBase->mHeight); } else if ((mState == LevelupEffect::SHOWING_STATS) || (mState == LevelupEffect::CURTAIN_OUT) || (mState == LevelupEffect::COVERING_STATS)) { // When just showing the stats normally, fading out the red curtain (to reveal the stats // beneath it), or covering up the stats with the effect triggered when the user clicks // to begin the next level, we display info on the user's performance from the last level. int y = 50; g->SetColor(gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFFFF); SexyString s = StrFormat(_S("LEVEL %d COMPLETE!"), mStats.mLevelCompleted); g->DrawString(s, gSexyAppBase->mWidth / 2 - FONT_HUNGARR->StringWidth(s) / 2, y); g->SetColor(Color::White); s = _S("POPULATION CONSUMED:"); int strWidth = FONT_HUNGARR->StringWidth(s); int rightX = strWidth + 100; y += 50; g->DrawString(s, 100, y); g->SetColor(Color(255, 0, 0)); g->DrawString(CommaSeperate(mStats.mPopulationEaten), rightX + 5, y); y += FONT_HUNGARR->GetHeight(); g->SetColor(Color::White); s = _S("SYSTEMS SUBJUGATED:"); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 0, 0)); g->DrawString(StrFormat(_S("%d%%"), mStats.mPercentComplete), rightX + 5, y); y += FONT_HUNGARR->GetHeight(); if (mStats.mPercentComplete >= COMPLETION_BONUS_PCT) { s = StrFormat(_S("%d%%+ BONUS:"), COMPLETION_BONUS_PCT); g->SetColor(Color::White); strWidth = FONT_HUNGARR->StringWidth(s); g->DrawString(s, rightX - strWidth, y); g->SetColor(Color(255, 0, 0)); g->DrawString(StrFormat(_S("%d"), COMPLETION_BONUS * mStats.mLevelCompleted), rightX + 5, y); } if (mStats.mPlanetsEaten.size() > 0) { y += 50; int third = gSexyAppBase->mWidth / 3; g->SetColor(Color(255, 255, 0)); s = _S("PLANET EATEN:"); g->DrawString(s, third / 2 - FONT_HUNGARR->StringWidth(s) / 2, y); s = _S("EXPORTS:"); g->DrawString(s, third + (third / 2 - FONT_HUNGARR->StringWidth(s) / 2), y); s = _S("POPULATION:"); g->DrawString(s, third*2 + (third / 2 - FONT_HUNGARR->StringWidth(s) / 2), y); y += FONT_HUNGARR->GetHeight(); // If the user ate too many planets to fit on screen, we'll just display "..." // to indicate that they ate a bunch but we just can't fit it all on screen. // In reality, it'd be best to either ensure that all the planets fit on screen, // or that there's some sort of scrolling mechanism to allow the user to view all their // stats. bool drawDotDotDot = false; for (int i = 0; i < mStats.mPlanetsEaten.size(); i += 3) { if (y >= gSexyAppBase->mHeight - FONT_HUNGARR->GetHeight() * 2) { drawDotDotDot = true; break; } g->SetColor(Color(255, 255, 255)); s = mStats.mPlanetsEaten[i]; g->DrawString(s, third / 2 - FONT_HUNGARR->StringWidth(s) / 2, y); g->SetColor(Color(128, 255, 0)); s = mStats.mPlanetsEaten[i+1]; g->DrawString(s, third + (third / 2 - FONT_HUNGARR->StringWidth(s) / 2), y); g->SetColor(Color(255, 128, 0)); s = mStats.mPlanetsEaten[i+2]; g->DrawString(s, third*2 + (third / 2 - FONT_HUNGARR->StringWidth(s) / 2), y); y += FONT_HUNGARR->GetHeight(); } if (drawDotDotDot) { g->SetColor(Color::White); g->DrawString(_S("..."), 5, y); } } g->SetColor(Color::White); s = _S("CLICK TO CONTINUE"); g->DrawString(s, gSexyAppBase->mWidth / 2 - FONT_HUNGARR->StringWidth(s) / 2, gSexyAppBase->mHeight - 20); } if (mState == LevelupEffect::CURTAIN_OUT) { // Draw a red curtain, whose alpha decreases as it withdrawls more. // This lets the stats display underneath the curtain while it moves. int alpha = mCurtainX > 255 ? 255 : mCurtainX; g->SetColor(Color(255, 0, 0, alpha)); g->FillRect(0, 0, mCurtainX, gSexyAppBase->mHeight); g->FillRect(gSexyAppBase->mWidth - mCurtainX, 0, mCurtainX, gSexyAppBase->mHeight); } if ((mState == LevelupEffect::COVERING_STATS) || (mState == LevelupEffect::FADE_OUT_STATS)) { // Both the states where we cover up the stats and fade them out are controlled here, // since they are functionally the same. Again, with the HSL we do the usual HSLToRGB // stuff. However, since the FADE_OUT_STATS state actually fades out the screen and // has an alpha value that decreases over time (mFadeOutAlpha), instead of always // setting the alpha to 255, we need to set the alpha to mFadeOutAlpha. To do this, // we AND with 0xFFFFFF instead of 0xFFFFFFFF. Then, we OR it with the alpha value // shifted left 24 bits. This then sticks the alpha value, which changes over time, // into our HSL color. As you may recall from previous demos, the actual color // structure is 32 bit, and looks like this in binary form: // AAAA RRRR GGGG BBBB Where A,R,G,B are alpha, red, green, blue. // // We draw the totally filled in regions separately, since they're easy. // The strips then are drawn differently depending on if they are moving up or down. // The left and right ones move oppositely. g->SetColor( (gSexyAppBase->HSLToRGB(mHue, 255, 128) & 0xFFFFFF) | (mFadeOutAlpha << 24) ); g->FillRect(0, 0, mCoverWidth, gSexyAppBase->mHeight); g->FillRect(gSexyAppBase->mWidth - mCoverWidth, 0, mCoverWidth, gSexyAppBase->mHeight); if (mStripSizeChange > 0) { g->FillRect(mCoverWidth, 0, STRIP_WIDTH, mStripHeight); g->FillRect(gSexyAppBase->mWidth - mCoverWidth - STRIP_WIDTH, gSexyAppBase->mHeight - mStripHeight, STRIP_WIDTH, mStripHeight); } else { g->FillRect(mCoverWidth, gSexyAppBase->mHeight - mStripHeight, STRIP_WIDTH, mStripHeight); g->FillRect(gSexyAppBase->mWidth - mCoverWidth - STRIP_WIDTH, 0, STRIP_WIDTH, mStripHeight); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void LevelupEffect::DoneViewingStats() { // The user clicked to dismiss the stats screen. Cover it up // and begin the transition to the next level. mState = LevelupEffect::COVERING_STATS; mCoverWidth = 0; mStripSizeChange = 90; mStripHeight = 0; mFadeOutAlpha = 255; mStartNextLevel = false; gSexyAppBase->PlaySample(SOUND_LEVEL_UP3); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool LevelupEffect::StartNextLevel() { // See function header for a complete description if (mStartNextLevel) { mStartNextLevel = false; gSexyAppBase->PlaySample(SOUND_LEVEL_UP4); return true; } return false; } libtuxcap-1.4.0/tuxcap/demo5/0000755000175000017500000000000011212652053015701 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/demo5/Res.h0000644000175000017500000000771010643254671016623 0ustar inniyahinniyah#ifndef __Res_H__ #define __Res_H__ namespace Sexy { class ResourceManager; class Image; class Font; Image* LoadImageById(ResourceManager *theManager, int theId); bool ExtractResourcesByName(ResourceManager *theManager, const char *theName); // Game Resources bool ExtractGameResources(ResourceManager *theMgr); extern Image* IMAGE_BG0; extern Image* IMAGE_BG1; extern Image* IMAGE_BG2; extern Image* IMAGE_BUTTON_DOWN; extern Image* IMAGE_BUTTON_NORMAL; extern Image* IMAGE_BUTTON_OVER; extern Image* IMAGE_CHECKBOX; extern Image* IMAGE_DIALOG_BOX; extern Image* IMAGE_DIALOG_BUTTON; extern Image* IMAGE_ROBOTROBOT; extern Image* IMAGE_SLIDER_THUMB; extern Image* IMAGE_SLIDER_TRACK; extern int SOUND_MUTATOR; extern int SOUND_TIMER; // Hungarr Resources bool ExtractHungarrResources(ResourceManager *theMgr); extern Image* IMAGE_ATOMIC_EXPLOSION; extern Image* IMAGE_BOMB_RADIAL_DEATH; extern Image* IMAGE_HUNGARR_BEAM_DOWN; extern Image* IMAGE_HUNGARR_BEAM_LEFT; extern Image* IMAGE_HUNGARR_BEAM_RIGHT; extern Image* IMAGE_HUNGARR_BEAM_UP; extern Image* IMAGE_HUNGARR_HORIZ; extern Image* IMAGE_HUNGARR_SMALL; extern Image* IMAGE_HUNGARR_VERT; extern Image* IMAGE_PARTICLE_LIGHTNING; extern Image* IMAGE_PLANETS; extern Image* IMAGE_SPARK; extern int SOUND_BEAM_HIT; extern int SOUND_BEAM_MOVING; extern int SOUND_BUTTON; extern int SOUND_EXPLOSION; extern int SOUND_GAME_OVER_CLICK; extern int SOUND_GAME_OVER_RESTART; extern int SOUND_GAME_OVER_STATS; extern int SOUND_GAME_OVER_TEXT; extern int SOUND_LEVEL_UP1; extern int SOUND_LEVEL_UP2; extern int SOUND_LEVEL_UP3; extern int SOUND_LEVEL_UP4; extern int SOUND_MAGZAP; extern int SOUND_PLANET; extern int SOUND_PLANET_HIT; extern int SOUND_REGION_FILLED; // Init Resources bool ExtractInitResources(ResourceManager *theMgr); extern Font* FONT_DEFAULT; extern Font* FONT_HUNGARR; extern Image* IMAGE_CUSTOM_DRAGGING; extern Image* IMAGE_CUSTOM_HAND; extern Image* IMAGE_CUSTOM_POINTER; extern Image* IMAGE_CUSTOM_TEXT; extern Image* IMAGE_HUNGARR_LOGO; // TitleScreen Resources bool ExtractTitleScreenResources(ResourceManager *theMgr); extern Image* IMAGE_LOADER_BAR; extern Image* IMAGE_LOADER_LOADINGTXT; extern int SOUND_CONTINUE; enum ResourceId { FONT_DEFAULT_ID, FONT_HUNGARR_ID, IMAGE_CUSTOM_POINTER_ID, IMAGE_CUSTOM_HAND_ID, IMAGE_CUSTOM_DRAGGING_ID, IMAGE_CUSTOM_TEXT_ID, IMAGE_HUNGARR_LOGO_ID, IMAGE_LOADER_BAR_ID, IMAGE_LOADER_LOADINGTXT_ID, SOUND_CONTINUE_ID, SOUND_MUTATOR_ID, SOUND_TIMER_ID, IMAGE_ROBOTROBOT_ID, IMAGE_CHECKBOX_ID, IMAGE_BG0_ID, IMAGE_BG1_ID, IMAGE_BG2_ID, IMAGE_BUTTON_DOWN_ID, IMAGE_BUTTON_OVER_ID, IMAGE_BUTTON_NORMAL_ID, IMAGE_DIALOG_BOX_ID, IMAGE_DIALOG_BUTTON_ID, IMAGE_SLIDER_TRACK_ID, IMAGE_SLIDER_THUMB_ID, IMAGE_HUNGARR_SMALL_ID, IMAGE_HUNGARR_BEAM_UP_ID, IMAGE_HUNGARR_BEAM_DOWN_ID, IMAGE_HUNGARR_BEAM_LEFT_ID, IMAGE_HUNGARR_BEAM_RIGHT_ID, IMAGE_HUNGARR_HORIZ_ID, IMAGE_HUNGARR_VERT_ID, IMAGE_ATOMIC_EXPLOSION_ID, IMAGE_BOMB_RADIAL_DEATH_ID, IMAGE_PLANETS_ID, IMAGE_SPARK_ID, IMAGE_PARTICLE_LIGHTNING_ID, SOUND_MAGZAP_ID, SOUND_BUTTON_ID, SOUND_PLANET_ID, SOUND_LEVEL_UP1_ID, SOUND_LEVEL_UP2_ID, SOUND_EXPLOSION_ID, SOUND_BEAM_HIT_ID, SOUND_PLANET_HIT_ID, SOUND_BEAM_MOVING_ID, SOUND_LEVEL_UP4_ID, SOUND_LEVEL_UP3_ID, SOUND_GAME_OVER_CLICK_ID, SOUND_GAME_OVER_STATS_ID, SOUND_GAME_OVER_RESTART_ID, SOUND_GAME_OVER_TEXT_ID, SOUND_REGION_FILLED_ID, RESOURCE_ID_MAX }; Image* GetImageById(int theId); Font* GetFontById(int theId); int GetSoundById(int theId); ResourceId GetIdByImage(Image *theImage); ResourceId GetIdByFont(Font *theFont); ResourceId GetIdBySound(int theSound); const char* GetStringIdById(int theId); ResourceId GetIdByStringId(const char *theStringId); } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/demo5/GameApp.cpp0000644000175000017500000004427311062533666017744 0ustar inniyahinniyah#include "GameApp.h" #include "TitleScreen.h" #include "Board.h" #include "DemoDialog.h" #include "WidgetManager.h" #include "Checkbox.h" // We will be accessing the resource manager in this demo, so include it's header #include "ResourceManager.h" #include "MusicInterface.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" #include "Dialog.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Demo 5"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Demo5"; // Set the application width/height in terms of pixels here. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F8. To toggle 3D on/off, press shift-F8. That is just // for testing purposes. //mAutoEnable3D = true; mBoard = NULL; mTitleScreen = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. Because our board might not have been // added (if you shut down the app before closing the loading screen), // only remove it if it isn't null. if (mBoard != NULL) mWidgetManager->RemoveWidget(mBoard); // Take a look at TitleScreen::ButtonDepress if you haven't already. // It explains a function called SafeDeleteWidget. Notice that we're // directly deleting the widget here: that is because when our app's // destructor is called, it's at the very end of the shutdown sequence // and the safe delete widget list will NOT be processed. Thus we // have to delete the memory manually. delete mBoard; // If you shut down the app before closing the loading screen, then // it will need to be removed here. The rational for the next two // steps is the same as for Board: if (mTitleScreen != NULL) mWidgetManager->RemoveWidget(mTitleScreen); delete mTitleScreen; // We should also free up all the resources that we loaded // for ALL the resource groups. Deleting a group that was // already deleted doesn't do anything, it's ignored. mResourceManager->DeleteResources("Init"); mResourceManager->DeleteResources("TitleScreen"); mResourceManager->DeleteResources("Game"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // We need to tell the resource manager to read in all the groups // and information from that main group we made, called ResourceManifest, // in the file "properties/resources.xml". The path/filename are // by default set up to load that file, so you must name it exactly as such. // This doesn't load any resources: it just parses the data and sets // things up for loading. LoadResourceManifest(); // Next, we want to load our absolutely necessary files that have to // be loaded before anything else can run. You'll notice in the resources.xml // file that we created a group called Init that contains these resources. // You may call it whatever you like. Let's load those resources now. // We do that by calling the LoadResources method of our mResourceManager // variable and specifying in quotes the name of the resource group to // load. This string is case sensitive. if (!mResourceManager->LoadResources("Init")) { mLoadingFailed = true; // This will display an informative error message indicating exactly // what went wrong in the resource loading process. ShowResourceError(true); return; } // Now we've loaded the resources, but we need to extract them. // Extraction is the phase that converts sound files to raw WAV // files, and sets up and initializes fonts and palletizes images. // The ResourceGen.exe program, when it generates C++ code for our // resources, also creates a function for EVERY resource group of the // form: ExtractResources, where is the exact name // of the resource group you made. In our case, we made an "Init" // group, so we have an ExtractInitResources method. You pass to it // the pointer to the resource manager. Because an error can occur // during this step, you should make sure to check for it. if (!ExtractInitResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // We also need to load our title screen graphics in, since you can't // display the title screen without any graphics. For an explanation of why // we placed this in a separate group from Init, see properties/resources.xml. // This code works exactly like the above did for the Init group. if (!mResourceManager->LoadResources("TitleScreen")) { mLoadingFailed = true; ShowResourceError(true); return; } if (!ExtractTitleScreenResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // Now let's create and add our title screen to the widget manager mTitleScreen = new TitleScreen(this); mTitleScreen->Resize(0, 0, mWidth, mHeight); // Let's let the title screen initialize it's widgets and data // before adding it to the widget manager: mTitleScreen->Init(); mWidgetManager->AddWidget(mTitleScreen); // Let's also load in some music to play. We use the mMusicInterface // member for all our music needs, which requires the BassMusicInterface.h // header to be loaded, since we use the library BASS to play our music. // We can load in WAV, OGG, or MP3 files. BASS also supports a number // of tracker formats, such as .it, .xm, .mod, etc. It also supports // a format called MO3, which is a compressed version of a tracker // file. For this example, we will use the MO3 from AstroPop. // Why? Cause it's ours and we won't get sued for using it. // We load our file manually, we do not use the resource manager for this. // The first parameter is the ID to associate the song with. Just as sounds // have IDs, so do music tracks. mMusicInterface->LoadMusic(0, "music/hungarr.ogg"); // Let's load another copy of the file. Why? In order to fade from one // track to another, we need two instances of the track on different // channels. Let's load it again and give it a different ID, 1. mMusicInterface->LoadMusic(1, "music/hungarr.ogg"); // Now we need to start playing a track. Because we are using an MO3 // and because the original format was a .it (Impulse Tracker) file, // there are actually multiple songs inside of it, differentiated // by various offsets. If you were just playing a single MP3 or OGG // or WAV file instead of a tracker file, you would ignore this // and use the default offset of 0 for the start of the song. // Because the person that made the song file was nice and // told us which offsets equated to which song pieces, I already // know the magic offset numbers. In this particular case, the // song for the intro screen is at offset 0, and the song // for the main game music is at offset 9. Our music artist // also was kind enough to put in tracker looping commands, // so you'll notice that the songs play over and over. A discussion // of tracker file formats is beyond the scope of this. Again, // if you are just playing a WAV/OGG/MP3, you use offset 0 (the default) // to indicate that you want to start playing from the start of the song. // // You can use PlayMusic to instantly play the track, or, like below, // you can use FadeIn to smoothly fade the song in. The first parameter // for both methods is the channel or song id that was used when the // track was first loaded (In our case, either 0 or 1 works). For both, // the second parameter is the offset to start playing at. Again, I just // happen to know that the intro song is at offset 0. For FadeIn, the // third parameter is how quickly to fade in, out of 1.0. The last parameter // for both indicates whether or not you want to loop. This is kind of weird, // but specify "false" to loop and "true" to not loop. mMusicInterface->FadeIn(0, 0, 0.0008, false); // We'll cover changing the music and sound volumes in a later demo. // Next, we need to know how many resources there are to load. // This is necessary so we can display our progress bar on the title screen // and make it be the appropriate length. There's a variable in SexyAppBase // called mNumLoadingThreadTasks which holds the number of resources to // load in the LoadingThreadProc function. You get the number of resources // in a given group with a call to the resource manager's GetNumResources function // for each of your groups that you are going to load: mNumLoadingThreadTasks = mResourceManager->GetNumResources("Game"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // For each of the groups that we want to load, // we first have to instruct the resource manager to begin the // loading phase and initialize its internal variables. // We do that with the StartLoadResources method and pass in the // exact string name of the group to begin loading: mResourceManager->StartLoadResources("Game"); // Now we need to load each individual resource. We will loop, // calling LoadNextResource at the start. When it returns true, // there are no more resources to load for the current group. // LoadNextResource knows what group to load from because // of the call to StartLoadResources above: while (mResourceManager->LoadNextResource()) { // The SexyAppBase variable, mCompletedLoadingThreadTasks, indicates the // total number of resources that have so far been loaded. This is used // to tell our loading screen the % progress we've made. See TitleScreen::Draw // for an example of how this is used. We need to increment this value // ourselves everytime we load a resource: mCompletedLoadingThreadTasks++; // If there was an error loading our resource, the resource manager // will tell us to shut down by setting mShutdown to true. If that // happened, immediately abort and return: if (mShutdown) return; // Remember in demos 1-3 how we had the Board class call MarkDirty // every update? Well, the title screen doesn't need to be such a hog. // The title screen only needs to repaint when its progress bar changes // size. The progress bar only changes size when a resource gets loaded. // Because the game app is the only one that knows when this happens, // the game app will be the one to tell the title screen that it's a // dirty, dirty widget and that it needs a good and proper repainting. // You COULD make an update method for the title screen and mark dirty // every frame. But because this consumes more CPU time, it will take // longer to load our resources. And since you want the loading time // to be as quick as possible, you should only repaint when you need to. mTitleScreen->MarkDirty(); } // Just like in our Init function, after loading resources we // need to extract them. Let's do that. Let's also ask the resource // manager if an error occurred in the above loop that we // didn't yet catch. We do that with the HadError method: if (mResourceManager->HadError() || !ExtractGameResources(mResourceManager)) { ShowResourceError(false); mLoadingFailed = true; return; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // We aren't going to make and add the Board class here like we // did in the previous demos. Instead, since we are done loading // everything, we're going to tell the title screen that // we're done and that it should unhide the continue link and let // the user enter the game. mTitleScreen->LoadingComplete(); // Remember: since we didn't give our title screen an Update method, // this class is responsible for telling it when to repaint. If we // don't mark it dirty, you won't see the hyperlink widget // appear. So mark it dirty now: mTitleScreen->MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::TitleScreenIsFinished() { mTitleScreen = NULL; mBoard = new Board(this); // Now that the title screen is done, we don't need its resources // wasting memory. Let's delete all of its resources. We do that // by calling DeleteResources and specifying the exact name of the // resource group we want to free up: mResourceManager->DeleteResources("TitleScreen"); mBoard->Resize(0, 0, mWidth, mHeight); mWidgetManager->AddWidget(mBoard); // This is a new step: We're going to tell the WidgetManager // that keyboard input and mouse wheel notifications should go to // the board object. This way, we'll be able to respond to keypresses: mWidgetManager->SetFocus(mBoard); // Let's fade out the intro song and fade in the main game music. // FadeOut works just like FadeIn did in Init() but with some // slightly different parameters. The first, is like with FadeIn and // PlayMusic, the channel or song id that you want to mess with. // The second indicates that the song fading out should stop when // done, if it is true. The final parameter indicates how fast // to fade out, and is from 0 to 1. mMusicInterface->FadeOut(0, true, 0.001); // Let's fade in the main game music. This is the same as in Init. // The only difference is we're using 1 instead of 0 for our song id. // Why? Well, channel/song id 0 is being used to fade out the // previously playing track, we can't use it to also fade in. // That's why we loaded another copy of the song into channel 1. // Again, as explained in Init, I happen to know that offset 9 // is the start of the main game music. mMusicInterface->FadeIn(1, 126, 0.0006, false); // We'll cover changing the music and sound volumes in our options dialog. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Dialog* GameApp::NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader, const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode) { // Rather than dupliate a lengthy explanation, check out the top of DemoDialog.cpp for a complete description // of what all the parameters and functions are. Dialog* d = new Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, theDialogId, isModal, StringToSexyStringFast(theDialogHeader), StringToSexyStringFast(theDialogLines), StringToSexyStringFast(theDialogFooter), theButtonMode); d->SetButtonFont(FONT_DEFAULT); d->SetLinesFont(FONT_DEFAULT); d->SetHeaderFont(FONT_DEFAULT); d->SetColor(Dialog::COLOR_HEADER, Color::Black); d->SetColor(Dialog::COLOR_LINES, Color::Black); d->mSpaceAfterHeader = 30; d->Resize(100, 100, 300, 250); return d; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::SwitchScreenMode(bool wantWindowed, bool is3d) { #if 0 // Let the app handle the actual details of this call... SexyAppBase::SwitchScreenMode(wantWindowed, is3d); #endif // We can see if the options dialog is up with a call to // GetDialog. You pass GetDialog the unique ID of the dialog box, // and if it exists it is returned to you, otherwise NULL is returned. DemoDialog* d = (DemoDialog*) GetDialog(DemoDialog::DIALOG_ID); // Set the checkbox state to our windowed state if ((d != NULL) && (d->mFSCheckbox != NULL)) d->mFSCheckbox->SetChecked(!wantWindowed); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::ButtonPress(int theId) { if (theId == DemoDialog::MESSAGE_BOX_ID + 2000) KillDialog(theId - 2000); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::SetFocusToBoard() { if (mBoard != NULL) mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/demo5/DemoDialog.cpp0000644000175000017500000004434210642176156020433 0ustar inniyahinniyah#include "DemoDialog.h" #include "Res.h" #include "GameApp.h" #include "SexyAppBase.h" #include "WidgetManager.h" #include "Font.h" #include "DialogButton.h" #include "Checkbox.h" // We're going to use a slider widget to control sound/music volume #include "Slider.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// // Let's do a little explanation of the parent Dialog class, shall we? // The first parameter we pass it is an image to use for the dialog box. // // This image has to have the property that its width and height be // divisible by 3. Why? For stretching/tiling, in case you want the // dialog box to be bigger than the actual image. The image can // be thought of as being divided into regions. The 4 corners // are drawn normally, and the remaining chunks (which comprise a third // of the image height or the image width) are tiled to allow for // the stretching of the dialog box. // // The image for the dialog button works the same way and must have // the same properties. Dialogs use a DialogButton class which is exactly // the same as a normal button class, except that they support tiling // the image if it is stretched larger than the original image is. // // The third parameter is the ID to use for the dialog box. // // The fourth indicates if the dialog is modal. If it is, then only the // dialog box and any widget above it (like its buttons) will receive // keyboard and mouse input. This is just like in Windows when a file // dialog appears and you can't click on the window of the application // below it. // // The fifth parameter is the header to use for the dialog box. // // The sixth parameter is the text to display in the body of the dialog // box. You can use the newline (\n) character for line breaks. // // The seventh parameter is optional, and is only used if the eigth // parameter is Dialog::BUTTONS_FOOTER. This is the text to display on // the footer (bottom) dialog button. // // The eigth parameter indicates what type of buttons are to display. // You can use BUTTONS_YES_NO or BUTTONS_OK_CANCEL for the standard // "Yes", "No" or "OK", "Cancel" options, BUTTONS_NONE for no buttons, // or BUTTONS_FOOTER for a single button that runs along the bottom. // Of course, you can change the labels on any of the buttons if you // like. // // The YES/OK/FOOTER buttons have a value of 2000 + the dialog's ID. // The NO/CANCEL buttons have a value of 3000 + the dialog's ID. ////////////////////////////////////////////////////////////////////////// DemoDialog::DemoDialog(std::string theHeader, std::string theBody) : Dialog(IMAGE_DIALOG_BOX, IMAGE_DIALOG_BUTTON, DemoDialog::DIALOG_ID, true, StringToSexyStringFast(theHeader), StringToSexyStringFast(theBody), _S("CLOSE"), Dialog::BUTTONS_FOOTER) { // We can set the rectangular region in which all text/buttons are to go // by changing the mContentInsets variable. The first parameter // is the distance from the left side of the dialog box, the second // is the distance from the top, third is distance from the right, // and fourth is distance from the bottom in which content // can be placed. mContentInsets = Insets(23, 20, 23, 20); // We can then set a value for how many pixels below the inset top // the text body should go: mSpaceAfterHeader = 30; // Let's also set the fonts to use for the header and the text. We should // use the SetXXXFont functions instead of directly modifying the font because // the dialog class makes a copy of the font and then deletes it in its destructor. // This is due to backwards compatibility with our old Java framework. SetHeaderFont(FONT_DEFAULT); SetLinesFont(FONT_DEFAULT); SetButtonFont(FONT_DEFAULT); // We can also change the color of the text SetColor(COLOR_HEADER, Color::Black); SetColor(COLOR_LINES, Color::Black); // Now let's create some sliders to control the music and sound volume with. // The first parameter is the image to use for the track of the slider. The // second is the image to use for the little movable "thumb" icon. // The third is the ID and the fourth is the widget who wants to listen to // the slider. mMusicVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, DemoDialog::MUSIC_SLIDER_ID, this); // Let's set the value of the music slider to what the current volume is. // SexyAppBase has a GetMusicVolume function that returns this amount. // But wait, we didn't get a SexyAppBase pointer passed into the constructor! // Don't worry. gSexyAppBase is externed in SexyAppBase.h and we can use that instead. mMusicVolumeSlider->SetValue(gSexyAppBase->GetMusicVolume()); mSfxVolumeSlider = new Slider(IMAGE_SLIDER_TRACK, IMAGE_SLIDER_THUMB, DemoDialog::SFX_SLIDER_ID, this); // Let's set the sound volume to the current volume, just like we did with the music slider mSfxVolumeSlider->SetValue(gSexyAppBase->GetSfxVolume()); // Let's make a button to show off how to use random numbers mRandomBtn = new DialogButton(IMAGE_DIALOG_BUTTON, DemoDialog::RANDOM_BTN_ID, this); mRandomBtn->mLabel = _S("Random #"); mRandomBtn->SetFont(FONT_DEFAULT); // To illustrate the mClip example, we'll use a button to toggle it. mClipBtn = new DialogButton(IMAGE_DIALOG_BUTTON, DemoDialog::CLIP_BTN_ID, this); mClipBtn->mLabel = _S("Clipping"); mClipBtn->SetFont(FONT_DEFAULT); m3DCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, DemoDialog::HARDWARE_CHECKBOX_ID, this); mFSCheckbox = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, DemoDialog::FS_CHECKBOX_ID, this); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// DemoDialog::~DemoDialog() { delete mMusicVolumeSlider; delete mSfxVolumeSlider; delete mRandomBtn; delete mClipBtn; delete m3DCheckbox; delete mFSCheckbox; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::Draw(Graphics* g) { Dialog::Draw(g); // Let's draw some labels for the sliders g->SetFont(FONT_DEFAULT); g->SetColor(Color::Black); // We draw the X/Y at the slider's X/Y but we subtract off the dialog box's // X/Y's from that. Why? The slider's XY's are in absolute screen coordinates, // as are the dialog boxes. But as you may recall from Board::Draw(), where // we explain graphics translation, once we get inside the draw loop of a // widget, the graphics object is already moved (translated) to the widget's // coordinates. Thus, in using the Graphics object, g, (0, 0) is located // at the top left corner of the widget (our dialog box). So we // just take the difference between the widget locations to produce the // actual location we want to drawour text at: g->DrawString(_S("Music volume:"), mMusicVolumeSlider->mX - mX, mMusicVolumeSlider->mY - mY - mMusicVolumeSlider->mHeight); g->DrawString(_S("Sound volume:"), mSfxVolumeSlider->mX - mX, mSfxVolumeSlider->mY - mY - mSfxVolumeSlider->mHeight); // Do the same for the checkboxes: g->DrawString(_S("3D Mode:"), m3DCheckbox->mX - mX, m3DCheckbox->mY - mY - m3DCheckbox->mHeight + 20); g->DrawString(_S("Full Screen:"), mFSCheckbox->mX - mX, mFSCheckbox->mY - mY - mFSCheckbox->mHeight + 20); // As an example of clipping and how to disable it, let's draw // a box and some text outside of the X/Y/Width/Height of this // dialog box. You'll notice that when mClip is true (default), // that anything drawn outside the bounds of the widget is clipped, or // ignored. When mClip is false, no clipping is performed and we // can draw anywhere. g->SetColor(Color(255, 0, 0, 128)); // Draw a box in the bottom right g->FillRect(mWidth, mHeight, 100, 100); // Draw one in the top left g->FillRect(-100, -100, 100, 100); g->SetColor(Color::Black); g->DrawString(_S("Top left"), -90, -20); g->DrawString(_S("Bottom right"), mWidth + 10, mHeight + 20); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::Update() { Dialog::Update(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::AddedToManager(WidgetManager* theWidgetManager) { Dialog::AddedToManager(theWidgetManager); theWidgetManager->AddWidget(mMusicVolumeSlider); theWidgetManager->AddWidget(mSfxVolumeSlider); theWidgetManager->AddWidget(mRandomBtn); theWidgetManager->AddWidget(mClipBtn); int checkWidth = IMAGE_CHECKBOX->GetWidth() / 2; m3DCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); m3DCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mFSCheckbox->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mFSCheckbox->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); // Let's set the initial checked state of the 3d checkbox to true if the // user has 3D support enabled. We determine that via a call to Is3DAccelerated m3DCheckbox->mChecked = gSexyAppBase->Is3DAccelerated(); // We can check if the app is fullscreen by examining the mIsWindowed variable: mFSCheckbox->mChecked = !gSexyAppBase->mIsWindowed; theWidgetManager->AddWidget(m3DCheckbox); theWidgetManager->AddWidget(mFSCheckbox); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::RemovedFromManager(WidgetManager* theWidgetManager) { Dialog::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mMusicVolumeSlider); theWidgetManager->RemoveWidget(mSfxVolumeSlider); theWidgetManager->RemoveWidget(mRandomBtn); theWidgetManager->RemoveWidget(mClipBtn); theWidgetManager->RemoveWidget(m3DCheckbox); theWidgetManager->RemoveWidget(mFSCheckbox); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::Resize(int theX, int theY, int theWidth, int theHeight) { Dialog::Resize(theX, theY, theWidth, theHeight); // Layout the music slider so that it's left aligned with the // boundary we set for the content insets. We'll make the slider fill the width // of the content region (it'll be stretched if the base image isn't // wide enough) too. mMusicVolumeSlider->Resize(theX + mContentInsets.mLeft, theY + 140, mWidth - mContentInsets.mLeft - mContentInsets.mRight, IMAGE_SLIDER_THUMB->GetHeight()); // Let's align the sound effect slider in the same way but using a different method. // We know that we want the SFX slider to have the same X, width, and height, and // to be just a few pixels below the music slider. Instead of having to mess around // with the settings like we did above, we can use the layout (LAY_) flags instead. // The first parameter is an ORed list of layout parameters and should be // pretty self explanatory. You can find more in Widget.h. // The second parameter is the widget to use as the reference. // The rest are any extra padding to use for left/top/width/height related // layout flags. As you can see, we wanted 60 pixels added to the top of // our sound effect slider. mSfxVolumeSlider->Layout(LAY_SameLeft | LAY_Below | LAY_SameWidth | LAY_SameHeight, mMusicVolumeSlider, 0, 40, 0, 0); // Place the button that will show off random number generation under the sound effect // slider. But let's only make it take up 1/2 of the width of the slider // and be only as tall as the original button image: mRandomBtn->Layout(LAY_SameLeft | LAY_SameTop, mSfxVolumeSlider, 0, 40, 0, 0); mRandomBtn->Resize(mRandomBtn->mX, mRandomBtn->mY, mSfxVolumeSlider->mWidth / 2, IMAGE_DIALOG_BUTTON->mHeight); // And let's place the clipping toggle button to its right mClipBtn->Layout(LAY_Right | LAY_SameTop | LAY_SameWidth | LAY_SameHeight, mRandomBtn, 0, 0, 0, 0); // Place the 3D checkbox under the random button: m3DCheckbox->Layout(LAY_SameLeft | LAY_Below, mRandomBtn, 0, 40, 0, 0); m3DCheckbox->Resize(m3DCheckbox->mX, m3DCheckbox->mY, IMAGE_CHECKBOX->mWidth / 2, IMAGE_CHECKBOX->mHeight); // And the fullscreen box to the right of the 3d one. Except, let's use // the mClipBtn's X coordinate to align with: mFSCheckbox->Layout(LAY_SameTop | LAY_SameWidth | LAY_SameHeight, m3DCheckbox); mFSCheckbox->Layout(LAY_SameLeft, mClipBtn); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::SliderVal(int theId, double theVal) { if (theId == DemoDialog::MUSIC_SLIDER_ID) { // Let's set the music volume to whatever the slider position is gSexyAppBase->SetMusicVolume(theVal); } else if (theId == DemoDialog::SFX_SLIDER_ID) { // Set the sound value gSexyAppBase->SetSfxVolume(theVal); // A good idea is to play a "ding" or some similar sound when // the thumb is released, to indicate to the user what the current // sound volume is (since sounds might not be continuously playing, // unlike the music). We check for this by seeing if the mDragging // variable is true or not. if (!mSfxVolumeSlider->mDragging) gSexyAppBase->PlaySample(SOUND_TIMER); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::ButtonDepress(int theId) { Dialog::ButtonDepress(theId); if (theId == mRandomBtn->mId) { // Let's get a random integer. The Rand() function is declared // in Common.h and returns a value from 0 to SEXY_RAND_MAX (2,147,483,647) int r = Rand(); // Now let's change the text of the dialog box: mDialogLines = StrFormat(_S("Random number: %d"), r); } else if (theId == mClipBtn->mId) { // Toggle mClip. If mClip is off, we can draw outside the X/Y/width/height of // our dialog box. mClip = !mClip; if (mClip) mClipBtn->mLabel = _S("Clipping"); else mClipBtn->mLabel = _S("No clipping"); } // Previously, before framework 1.2, the line below looked like: // else if (theId == 2000 + mId) // With the 1.2 changes, there's just 1 slight incompatibility. // If the DialogListener for a dialog your app (by default), and // you don't implement your own DialogButton(De)press method (see V12Demo for // more info on this), and instead are trapping button presses within ButtonDepress // inside the dialog itself, then instead of the button ID being 2000 or 3000 + mId, // it's just ID_YES/ID_OK for ok/cancel/1-button dialog, and ID_NO/ID_CANCEL for no/cancel 2nd button. // Hence we changed our check to look for ID_YES, which is our default single close button at the bottom of this // dialog. else if (theId == ID_YES) { // Close button pressed. Tell the app to remove ourselves. This // will automatically safe delete the dialog at a later time. // Let's apply the 3D and fullscreen mode settings first though. // We call SwitchScreenMode. The first parameter is whether or not to run // windowed (false means fullscreen), the second is whether or not to do 3d. gSexyAppBase->SwitchScreenMode(!mFSCheckbox->mChecked, m3DCheckbox->mChecked); gSexyAppBase->KillDialog(this); // Set focus back to the board ((GameApp*)gSexyAppBase)->SetFocusToBoard(); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void DemoDialog::CheckboxChecked(int theId, bool checked) { // We'll wait until the dialog box is closed before actually applying any effects, // since it's rather jarring if as soon as a user clicks the 3d or fullscreen // toggle buttons to change right then and there. if (theId == m3DCheckbox->mId) { if (checked) { // Turn on 3D acceleration. But we need to check if the user is // even allowed to have it on. Some cards are just not compatible // with the framework (less than 8MB RAM for instance): if (!gSexyAppBase->Is3DAccelerationSupported()) { // It's not supported. Don't let the checkbox get checked. // Display an error dialog to the user to let them know why this happened. // The reason we don't use a Popup or Windows-based message box here is because // if the user was in full screen mode, they might not see the error message. Using // a game dialog box is the safest way to warn them. m3DCheckbox->SetChecked(false); gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("Not Supported"), _S("Hardware acceleration can not be enabled on this computer. \nYour\ video card does not meet the minimum requirements for this game."), _S("OK"), Dialog::BUTTONS_FOOTER); } else if(!gSexyAppBase->Is3DAccelerationRecommended()) { // We can also check if 3D acceleration is not recommended for this computer // with a call to Is3DAccelerationRecommended. This allows the user to override // the default setting, but with a warning that it might not work or might cause // problems. Some cards fail the detection process but wind up being OK to use. gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("Warning"), _S("Your video card may not fully support this feature.\n\ If you experience slower performance, please disable Hardware Acceleration."), _S("OK"), Dialog::BUTTONS_FOOTER); } } } else if (theId == mFSCheckbox->mId) { // Believe it or not, some people are not allowed to play in windowed mode. // You can only run in windowed mode if your desktop is 16 or 32 bit, and // if the resolution of their desktop is GREATER THAN the resolution of the // game. It doesn't make sense to run a 800x600 game windowed when your desktop // is 800x600 or less. // We can determine if the user is not allowed to run in windowed mode by // checking the value of SexyAppBase's mForceFullScreen variable. if (gSexyAppBase->mForceFullscreen && !checked) { gSexyAppBase->DoDialog(DemoDialog::MESSAGE_BOX_ID, true, _S("No Windowed Mode"), _S("Windowed mode is only available if your desktop is running in\n\ either 16 bit or 32 bit color mode, which it is not."), _S("OK"), Dialog::BUTTONS_FOOTER); // re-check the box to indicate that fullscreen is still the selected mode: mFSCheckbox->SetChecked(true); } } } libtuxcap-1.4.0/tuxcap/demo5/TitleScreen.cpp0000644000175000017500000002110610641010425020622 0ustar inniyahinniyah#include "TitleScreen.h" #include "GameApp.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" #include "Font.h" #include "Graphics.h" #include "Image.h" #include "WidgetManager.h" #include "Rect.h" #include "HyperlinkWidget.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::TitleScreen(GameApp *pApp) { mApp = pApp; mContinueLink = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::~TitleScreen() { delete mContinueLink; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Init(void) { // A hyperlink widget is basically the same thing as a button widget // but with some slight differences. It is meant to emulate the look // and feel of an internet hyperlink. We create the widget the // same way we created a button widget in Demo3, specifying that // this class is to listen to the widget events. mContinueLink = new HyperlinkWidget(1, this); // We need to set the font to use. In previous demos, we had // a variable inside of GameApp that held the font. Now that we're // using the resource manager, we'll use the main (and only) one // that we declared from there. Remember how we named it FONT_DEFAULT? // Well, you can use that name exactly now to reference it. mContinueLink->SetFont(FONT_DEFAULT); // Like the button widget, we can set the text to display: mContinueLink->mLabel = _S("CLICK TO CONTINUE"); // And like the button widget, we can set the default and over colors. // We don't use the SetColor method though, we just directly // set mColor and mOverColor: mContinueLink->mColor = Color(255, 255, 255); mContinueLink->mOverColor = Color(0, 255, 0); mContinueLink->mUnderlineSize = 1; // We're not going to place the widget just yet. Why? Well, // the TitleScreen hasn't been added to the widget manager. // We'll wait until the AddedToManager method is called before // adding it, just like in Demo3. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::AddedToManager(WidgetManager *theWidgetManager) { Widget::AddedToManager(theWidgetManager); // Just like with the button widget from Demo3, we're going to add our // hyperlink widget in this method. However, we want the link to be // invisible at first. Why? Well, while we're loading our resources, // we don't want the user to be able to just start the game. We want // them to wait until it's all loaded and ready to go. Once everything // is loaded, then we'll make it visible and let them click to play. // We do that with the SetVisible command: mContinueLink->SetVisible(false); // Just making it invisible isn't enough. Technically the user could // still click on it even though they can't see it. We have to // disable the widget to prevent it from receiving input: mContinueLink->SetDisabled(true); // Let's resize it to be at the bottom of the screen, and to be exactly // the width/height of the lable that we set. Again, we use our friend // the Resize function. However, note that we're setting the height to // be a bit larger than that of the string. That's because the underline // part of the hyperlink widget (whose thickness can be controlled via mUnderlineSize) // draws a little below the string. If you didn't make the height a little // larger, the line would be clipped and thus wouldn't be visible. int labelWidth = FONT_DEFAULT->StringWidth(mContinueLink->mLabel); int labelHeight = FONT_DEFAULT->GetHeight(); mContinueLink->Resize( mWidth / 2 - labelWidth / 2, mHeight - labelHeight - 40, labelWidth, labelHeight+4); // Almost done. Let's make it so that when the user mouses over the widget, // that the cursor changes from the standard Windows arrow to a hand icon. // We do that by setting the variable mDoFinger to true. This instructs the // WidgetManager to chagne the cursor to the hand/finger icon when the mouse // is inside the widget's bounds, and to reset it back to the arrow when it // is not. Note that ALL widgets have this functionality. mContinueLink->mDoFinger = true; // And finally, we add the widget just like we added the button widget // from demo 3 and the Board widget. theWidgetManager->AddWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::RemovedFromManager(WidgetManager *theWidgetManager) { // This is just like what we did in Board in Demo3. // Let our parent class know about the removal, and get rid // of our hyperlink widget. Widget::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Draw(Graphics *g) { // Instead of having to say Color(0, 0, 0) or Color(255, 255, 255) // for black/white, you can use Color::Black and Color::White. g->SetColor(Color::Black); g->FillRect(0, 0, mWidth, mHeight); // We want to draw our loader bar to indicate the progress made in // loading all our resources. As you recalll, GameApp::LoadingThreadProc is // the thread that is actually loading everything. The app has a function, // GetLoadingThreadProgress, that returns a value from 0.0 to 1.0 indicating // the % complete it is. We will multiply this % complete by the width // of our progress bar, so that we give the illusion of a growing bar. int loaderBarWidth = IMAGE_LOADER_BAR->GetWidth(); int drawWidth = (int) (mApp->GetLoadingThreadProgress() * (double)loaderBarWidth); if (drawWidth > 0) { // As you may recall from Demo3 where we drew the frames of animation // for the lightning image, the DrawImage call can take a source rectangle // which indicates what chunk of the original image we want to draw. // In our case, we want to start from from the upper left corner of // the loader bar, but we only want to draw "drawWidth" wide. This will // give the illusion that the progress bar is expanding as the resources // are loaded in. g->DrawImage(IMAGE_LOADER_BAR, mWidth / 2 - loaderBarWidth / 2, 400, Rect(0, 0, drawWidth, IMAGE_LOADER_BAR->GetHeight())); } // If our hyperlink widget is false, let's instead draw some // "Loading" text (er, actually in this case it's an image) where // it is located. if (mContinueLink->mVisible == false) g->DrawImage(IMAGE_LOADER_LOADINGTXT, mContinueLink->mX - 10, mContinueLink->mY - 80); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::LoadingComplete() { // Since the app told us that we're done loading all our resources, // let's unhide and enable our continue link so the user can start // playing. mContinueLink->SetVisible(true); mContinueLink->SetDisabled(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::ButtonDepress(int theId) { if (theId == 1) { // Our hyperlink widget was pressed. We want to remove ourselves // and the hyperlink widget, and tell the app to display the // main board and get the game started. // You might be thinking, "If I delete the title screen and // hyperlink, won't I crash the program?" Yes, you will. That's // why we aren't going to delete them using "delete". We're going // to use SexyAppBase's SafeDeleteWidget method. This places the // widget in a queue that is processed after all widgets and data // get processed, and is then deleted at a time that is safe // and appropriate. We still have to remove ourself and the // hyperlink widget from the WidgetManager. We can easily access // the WidgetManager, as it is a public variable in our game app. mApp->mWidgetManager->RemoveWidget(this); mApp->mWidgetManager->RemoveWidget(mContinueLink); mApp->SafeDeleteWidget(this); mApp->SafeDeleteWidget(mContinueLink); mContinueLink = NULL; // Now let's tell the game app that it's ok to add the board widget: mApp->TitleScreenIsFinished(); } } libtuxcap-1.4.0/tuxcap/demo5/CMakeLists.txt0000644000175000017500000000404010762446645020460 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp TitleScreen.cpp DemoDialog.cpp Board.cpp GameApp.cpp Res.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../demo_5") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/demo5/Board.h0000644000175000017500000001655010641010426017105 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// #include "Widget.h" #include "ButtonListener.h" // Because we're going to be learning about some new widgets, we // need to include some more listener classes so we can respond to each one. #include "EditListener.h" #include "CheckboxListener.h" #include "ListListener.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { class Graphics; class GameApp; class ButtonWidget; class WidgetManager; class Image; struct ParallaxLayer { float mX; float mY; Image* mImage; }; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public ButtonListener { private: GameApp* mApp; ButtonWidget* mButton; // And in this demo, we're going to do some parallax scrolling whenever // the arrow keys are pressed. struct ParallaxLayer mLayer[3]; public: // And let's finally use some enums for our widgets enum { OPTIONS_BUTTON_ID }; ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: KeyDown // Parameters: // theKey - A KEYCODE_ value from Keycodes.h that represents the // key pressed. // // Returns: none // // Purpose: When a key is pressed, this method is called. This method // differs from KeyChar (described below) in that you can detect non-ASCII // keys with it, as well as ASCII. ////////////////////////////////////////////////////////////////////////// virtual void KeyDown(KeyCode theKey); ////////////////////////////////////////////////////////////////////////// // Function: KeyChar // Parameters: // theChar - The ASCII character that was pressed. // // Returns: none. // // Purpose: Unlike KeyDown, this method only takes ASCII characters // as input. It's common to use KeyChar for your normal ASCII processing // needs, and KeyDown for your extended keyboard key needs. We're not // actually going to do anything with KeyChar in this code. It's displayed // here though to illustrate the differences between KeyDown and to // help explain its usage. ////////////////////////////////////////////////////////////////////////// //virtual void KeyChar(char theChar); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/demo5/GameApp.h0000644000175000017500000001613710641010426017371 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; // We're going to be responsible for creating and adding the title screen widget class TitleScreen; // We're going to learn about making and using dialog boxes in this demo class Dialog; class GameApp : public SexyAppBase { private: Board* mBoard; TitleScreen* mTitleScreen; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); ////////////////////////////////////////////////////////////////////////// // Function: TitleScreenIsFinished // Parameters: none // Returns: none // // Purpose: Called by the TitleScreen widget when it is about to close // down, this indicates that we should now add the board widget and // start the game. ////////////////////////////////////////////////////////////////////////// void TitleScreenIsFinished(); ////////////////////////////////////////////////////////////////////////// // Function: NewDialog // Parameters: // theDialogId - Unique ID to give this dialog box // isModal - If true, only itself and widgets above it receive // input events. // theDialogHeader - String to display in the header part of the dialog box // theDialogLines - String to use for the body of the dialog. May use // \n characters to indicate new lines. // theDialogFooter - If the button mode is BUTTONS_FOOTER, this is the text // to use for the button, otherwise ignored. // theButtonMode - One of 3 settings: Dialog::BUTTONS_YES_NO creates two // "Yes" "No" buttons, Dialog::BUTTONS_OK_CANCEL creates two // "OK" "Cancel" buttons, Dialog::BUTTONS_FOOTER creates one // button with the text from theDialogFooter. // // Returns: A new dialog pointer for use by SexyAppBase's DoDialog method. // // Purpose: SexyAppBase contains a convenience function, DoDialog, that relies on // this overriden function. DoDialog calls NewDialog which instructs it how to make // a dialog box. You should use DoDialog to create and add your dialog boxes. // The reason for this function is to allow for customized dialog boxes and to avoid // having to have a gigantic function with every possible parameter to pass to the Dialog's // constructor. ////////////////////////////////////////////////////////////////////////// virtual Dialog* NewDialog(int theDialogId, bool isModal, const std::string& theDialogHeader, const std::string& theDialogLines, const std::string& theDialogFooter, int theButtonMode); ////////////////////////////////////////////////////////////////////////// // Function: SwitchScreenMode // Parameters: // wantWindowed - True indicates that the game should be in windowed mode // is3d - True indicates that 3D acceleration should be turned on // // Returns: none // // Purpose: Take a look at DemoDialog. In it, you can toggle whether or not // the game is fullscreen. What if though, the user presses ALT-ENTER to force // the game to be windowed/fullscreen while that dialog is up? The fullscreen // checkbox should update to reflect the current windowed state. It's a little // thing to do but if you don't wind up doing it, it can be a bit wonky // for the user if the checkbox state gets out of sync with the resolution and // could wind up irritating them. ////////////////////////////////////////////////////////////////////////// virtual void SwitchScreenMode(bool wantWindowed, bool is3d); ////////////////////////////////////////////////////////////////////////// // Function: ButtonPress: // Parameters: // theId - ID of the button pressed // // Returns: none // // Purpose: Called when the button is pressed, but before the mouse is // released (which would instead generate a ButtonDepress event). ////////////////////////////////////////////////////////////////////////// virtual void ButtonPress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: SetFocusToBoard // // Parameters: none // Returns: none // // Purpose: When a dialog box closes, this is called to set keyboard focus // to the board widget. ////////////////////////////////////////////////////////////////////////// void SetFocusToBoard(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/demo5/Res.cpp0000644000175000017500000003023310643254671017152 0ustar inniyahinniyah#include "Res.h" #include "ResourceManager.h" using namespace Sexy; #pragma warning(disable:4311 4312) static bool gNeedRecalcVariableToIdMap = false; bool Sexy::ExtractResourcesByName(ResourceManager *theManager, const char *theName) { if (strcmp(theName,"Game")==0) return ExtractGameResources(theManager); if (strcmp(theName,"Hungarr")==0) return ExtractHungarrResources(theManager); if (strcmp(theName,"Init")==0) return ExtractInitResources(theManager); if (strcmp(theName,"TitleScreen")==0) return ExtractTitleScreenResources(theManager); return false; } Sexy::ResourceId Sexy::GetIdByStringId(const char *theStringId) { typedef std::map MyMap; static MyMap aMap; if(aMap.empty()) { for(int i=0; isecond; } // Game Resources Image* Sexy::IMAGE_BG0; Image* Sexy::IMAGE_BG1; Image* Sexy::IMAGE_BG2; Image* Sexy::IMAGE_BUTTON_DOWN; Image* Sexy::IMAGE_BUTTON_NORMAL; Image* Sexy::IMAGE_BUTTON_OVER; Image* Sexy::IMAGE_CHECKBOX; Image* Sexy::IMAGE_DIALOG_BOX; Image* Sexy::IMAGE_DIALOG_BUTTON; Image* Sexy::IMAGE_ROBOTROBOT; Image* Sexy::IMAGE_SLIDER_THUMB; Image* Sexy::IMAGE_SLIDER_TRACK; int Sexy::SOUND_MUTATOR; int Sexy::SOUND_TIMER; bool Sexy::ExtractGameResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_BG0 = aMgr.GetImageThrow("IMAGE_BG0"); IMAGE_BG1 = aMgr.GetImageThrow("IMAGE_BG1"); IMAGE_BG2 = aMgr.GetImageThrow("IMAGE_BG2"); IMAGE_BUTTON_DOWN = aMgr.GetImageThrow("IMAGE_BUTTON_DOWN"); IMAGE_BUTTON_NORMAL = aMgr.GetImageThrow("IMAGE_BUTTON_NORMAL"); IMAGE_BUTTON_OVER = aMgr.GetImageThrow("IMAGE_BUTTON_OVER"); IMAGE_CHECKBOX = aMgr.GetImageThrow("IMAGE_CHECKBOX"); IMAGE_DIALOG_BOX = aMgr.GetImageThrow("IMAGE_DIALOG_BOX"); IMAGE_DIALOG_BUTTON = aMgr.GetImageThrow("IMAGE_DIALOG_BUTTON"); IMAGE_ROBOTROBOT = aMgr.GetImageThrow("IMAGE_ROBOTROBOT"); IMAGE_SLIDER_THUMB = aMgr.GetImageThrow("IMAGE_SLIDER_THUMB"); IMAGE_SLIDER_TRACK = aMgr.GetImageThrow("IMAGE_SLIDER_TRACK"); SOUND_MUTATOR = aMgr.GetSoundThrow("SOUND_MUTATOR"); SOUND_TIMER = aMgr.GetSoundThrow("SOUND_TIMER"); } catch(ResourceManagerException&) { return false; } return true; } // Hungarr Resources Image* Sexy::IMAGE_ATOMIC_EXPLOSION; Image* Sexy::IMAGE_BOMB_RADIAL_DEATH; Image* Sexy::IMAGE_HUNGARR_BEAM_DOWN; Image* Sexy::IMAGE_HUNGARR_BEAM_LEFT; Image* Sexy::IMAGE_HUNGARR_BEAM_RIGHT; Image* Sexy::IMAGE_HUNGARR_BEAM_UP; Image* Sexy::IMAGE_HUNGARR_HORIZ; Image* Sexy::IMAGE_HUNGARR_SMALL; Image* Sexy::IMAGE_HUNGARR_VERT; Image* Sexy::IMAGE_PARTICLE_LIGHTNING; Image* Sexy::IMAGE_PLANETS; Image* Sexy::IMAGE_SPARK; int Sexy::SOUND_BEAM_HIT; int Sexy::SOUND_BEAM_MOVING; int Sexy::SOUND_BUTTON; int Sexy::SOUND_EXPLOSION; int Sexy::SOUND_GAME_OVER_CLICK; int Sexy::SOUND_GAME_OVER_RESTART; int Sexy::SOUND_GAME_OVER_STATS; int Sexy::SOUND_GAME_OVER_TEXT; int Sexy::SOUND_LEVEL_UP1; int Sexy::SOUND_LEVEL_UP2; int Sexy::SOUND_LEVEL_UP3; int Sexy::SOUND_LEVEL_UP4; int Sexy::SOUND_MAGZAP; int Sexy::SOUND_PLANET; int Sexy::SOUND_PLANET_HIT; int Sexy::SOUND_REGION_FILLED; bool Sexy::ExtractHungarrResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_ATOMIC_EXPLOSION = aMgr.GetImageThrow("IMAGE_ATOMIC_EXPLOSION"); IMAGE_BOMB_RADIAL_DEATH = aMgr.GetImageThrow("IMAGE_BOMB_RADIAL_DEATH"); IMAGE_HUNGARR_BEAM_DOWN = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_DOWN"); IMAGE_HUNGARR_BEAM_LEFT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_LEFT"); IMAGE_HUNGARR_BEAM_RIGHT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_RIGHT"); IMAGE_HUNGARR_BEAM_UP = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_UP"); IMAGE_HUNGARR_HORIZ = aMgr.GetImageThrow("IMAGE_HUNGARR_HORIZ"); IMAGE_HUNGARR_SMALL = aMgr.GetImageThrow("IMAGE_HUNGARR_SMALL"); IMAGE_HUNGARR_VERT = aMgr.GetImageThrow("IMAGE_HUNGARR_VERT"); IMAGE_PARTICLE_LIGHTNING = aMgr.GetImageThrow("IMAGE_PARTICLE_LIGHTNING"); IMAGE_PLANETS = aMgr.GetImageThrow("IMAGE_PLANETS"); IMAGE_SPARK = aMgr.GetImageThrow("IMAGE_SPARK"); SOUND_BEAM_HIT = aMgr.GetSoundThrow("SOUND_BEAM_HIT"); SOUND_BEAM_MOVING = aMgr.GetSoundThrow("SOUND_BEAM_MOVING"); SOUND_BUTTON = aMgr.GetSoundThrow("SOUND_BUTTON"); SOUND_EXPLOSION = aMgr.GetSoundThrow("SOUND_EXPLOSION"); SOUND_GAME_OVER_CLICK = aMgr.GetSoundThrow("SOUND_GAME_OVER_CLICK"); SOUND_GAME_OVER_RESTART = aMgr.GetSoundThrow("SOUND_GAME_OVER_RESTART"); SOUND_GAME_OVER_STATS = aMgr.GetSoundThrow("SOUND_GAME_OVER_STATS"); SOUND_GAME_OVER_TEXT = aMgr.GetSoundThrow("SOUND_GAME_OVER_TEXT"); SOUND_LEVEL_UP1 = aMgr.GetSoundThrow("SOUND_LEVEL_UP1"); SOUND_LEVEL_UP2 = aMgr.GetSoundThrow("SOUND_LEVEL_UP2"); SOUND_LEVEL_UP3 = aMgr.GetSoundThrow("SOUND_LEVEL_UP3"); SOUND_LEVEL_UP4 = aMgr.GetSoundThrow("SOUND_LEVEL_UP4"); SOUND_MAGZAP = aMgr.GetSoundThrow("SOUND_MAGZAP"); SOUND_PLANET = aMgr.GetSoundThrow("SOUND_PLANET"); SOUND_PLANET_HIT = aMgr.GetSoundThrow("SOUND_PLANET_HIT"); SOUND_REGION_FILLED = aMgr.GetSoundThrow("SOUND_REGION_FILLED"); } catch(ResourceManagerException&) { return false; } return true; } // Init Resources Font* Sexy::FONT_DEFAULT; Font* Sexy::FONT_HUNGARR; Image* Sexy::IMAGE_CUSTOM_DRAGGING; Image* Sexy::IMAGE_CUSTOM_HAND; Image* Sexy::IMAGE_CUSTOM_POINTER; Image* Sexy::IMAGE_CUSTOM_TEXT; Image* Sexy::IMAGE_HUNGARR_LOGO; bool Sexy::ExtractInitResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { FONT_DEFAULT = aMgr.GetFontThrow("FONT_DEFAULT"); FONT_HUNGARR = aMgr.GetFontThrow("FONT_HUNGARR"); IMAGE_CUSTOM_DRAGGING = aMgr.GetImageThrow("IMAGE_CUSTOM_DRAGGING"); IMAGE_CUSTOM_HAND = aMgr.GetImageThrow("IMAGE_CUSTOM_HAND"); IMAGE_CUSTOM_POINTER = aMgr.GetImageThrow("IMAGE_CUSTOM_POINTER"); IMAGE_CUSTOM_TEXT = aMgr.GetImageThrow("IMAGE_CUSTOM_TEXT"); IMAGE_HUNGARR_LOGO = aMgr.GetImageThrow("IMAGE_HUNGARR_LOGO"); } catch(ResourceManagerException&) { return false; } return true; } // TitleScreen Resources Image* Sexy::IMAGE_LOADER_BAR; Image* Sexy::IMAGE_LOADER_LOADINGTXT; int Sexy::SOUND_CONTINUE; bool Sexy::ExtractTitleScreenResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_LOADER_BAR = aMgr.GetImageThrow("IMAGE_LOADER_BAR"); IMAGE_LOADER_LOADINGTXT = aMgr.GetImageThrow("IMAGE_LOADER_LOADINGTXT"); SOUND_CONTINUE = aMgr.GetSoundThrow("SOUND_CONTINUE"); } catch(ResourceManagerException&) { return false; } return true; } static void* gResources[] = { &FONT_DEFAULT, &FONT_HUNGARR, &IMAGE_CUSTOM_POINTER, &IMAGE_CUSTOM_HAND, &IMAGE_CUSTOM_DRAGGING, &IMAGE_CUSTOM_TEXT, &IMAGE_HUNGARR_LOGO, &IMAGE_LOADER_BAR, &IMAGE_LOADER_LOADINGTXT, &SOUND_CONTINUE, &SOUND_MUTATOR, &SOUND_TIMER, &IMAGE_ROBOTROBOT, &IMAGE_CHECKBOX, &IMAGE_BG0, &IMAGE_BG1, &IMAGE_BG2, &IMAGE_BUTTON_DOWN, &IMAGE_BUTTON_OVER, &IMAGE_BUTTON_NORMAL, &IMAGE_DIALOG_BOX, &IMAGE_DIALOG_BUTTON, &IMAGE_SLIDER_TRACK, &IMAGE_SLIDER_THUMB, &IMAGE_HUNGARR_SMALL, &IMAGE_HUNGARR_BEAM_UP, &IMAGE_HUNGARR_BEAM_DOWN, &IMAGE_HUNGARR_BEAM_LEFT, &IMAGE_HUNGARR_BEAM_RIGHT, &IMAGE_HUNGARR_HORIZ, &IMAGE_HUNGARR_VERT, &IMAGE_ATOMIC_EXPLOSION, &IMAGE_BOMB_RADIAL_DEATH, &IMAGE_PLANETS, &IMAGE_SPARK, &IMAGE_PARTICLE_LIGHTNING, &SOUND_MAGZAP, &SOUND_BUTTON, &SOUND_PLANET, &SOUND_LEVEL_UP1, &SOUND_LEVEL_UP2, &SOUND_EXPLOSION, &SOUND_BEAM_HIT, &SOUND_PLANET_HIT, &SOUND_BEAM_MOVING, &SOUND_LEVEL_UP4, &SOUND_LEVEL_UP3, &SOUND_GAME_OVER_CLICK, &SOUND_GAME_OVER_STATS, &SOUND_GAME_OVER_RESTART, &SOUND_GAME_OVER_TEXT, &SOUND_REGION_FILLED, NULL }; Image* Sexy::LoadImageById(ResourceManager *theManager, int theId) { return (*((Image**)gResources[theId]) = theManager->LoadImage(GetStringIdById(theId))); } Image* Sexy::GetImageById(int theId) { return *(Image**)gResources[theId]; } Font* Sexy::GetFontById(int theId) { return *(Font**)gResources[theId]; } int Sexy::GetSoundById(int theId) { return *(int*)gResources[theId]; } static Sexy::ResourceId GetIdByVariable(const void *theVariable) { typedef std::map MyMap; static MyMap aMap; if(gNeedRecalcVariableToIdMap) { gNeedRecalcVariableToIdMap = false; aMap.clear(); for(int i=0; isecond; } Sexy::ResourceId Sexy::GetIdByImage(Image *theImage) { return GetIdByVariable(theImage); } Sexy::ResourceId Sexy::GetIdByFont(Font *theFont) { return GetIdByVariable(theFont); } Sexy::ResourceId Sexy::GetIdBySound(int theSound) { return GetIdByVariable((void*)theSound); } const char* Sexy::GetStringIdById(int theId) { switch(theId) { case FONT_DEFAULT_ID: return "FONT_DEFAULT"; case FONT_HUNGARR_ID: return "FONT_HUNGARR"; case IMAGE_CUSTOM_POINTER_ID: return "IMAGE_CUSTOM_POINTER"; case IMAGE_CUSTOM_HAND_ID: return "IMAGE_CUSTOM_HAND"; case IMAGE_CUSTOM_DRAGGING_ID: return "IMAGE_CUSTOM_DRAGGING"; case IMAGE_CUSTOM_TEXT_ID: return "IMAGE_CUSTOM_TEXT"; case IMAGE_HUNGARR_LOGO_ID: return "IMAGE_HUNGARR_LOGO"; case IMAGE_LOADER_BAR_ID: return "IMAGE_LOADER_BAR"; case IMAGE_LOADER_LOADINGTXT_ID: return "IMAGE_LOADER_LOADINGTXT"; case SOUND_CONTINUE_ID: return "SOUND_CONTINUE"; case SOUND_MUTATOR_ID: return "SOUND_MUTATOR"; case SOUND_TIMER_ID: return "SOUND_TIMER"; case IMAGE_ROBOTROBOT_ID: return "IMAGE_ROBOTROBOT"; case IMAGE_CHECKBOX_ID: return "IMAGE_CHECKBOX"; case IMAGE_BG0_ID: return "IMAGE_BG0"; case IMAGE_BG1_ID: return "IMAGE_BG1"; case IMAGE_BG2_ID: return "IMAGE_BG2"; case IMAGE_BUTTON_DOWN_ID: return "IMAGE_BUTTON_DOWN"; case IMAGE_BUTTON_OVER_ID: return "IMAGE_BUTTON_OVER"; case IMAGE_BUTTON_NORMAL_ID: return "IMAGE_BUTTON_NORMAL"; case IMAGE_DIALOG_BOX_ID: return "IMAGE_DIALOG_BOX"; case IMAGE_DIALOG_BUTTON_ID: return "IMAGE_DIALOG_BUTTON"; case IMAGE_SLIDER_TRACK_ID: return "IMAGE_SLIDER_TRACK"; case IMAGE_SLIDER_THUMB_ID: return "IMAGE_SLIDER_THUMB"; case IMAGE_HUNGARR_SMALL_ID: return "IMAGE_HUNGARR_SMALL"; case IMAGE_HUNGARR_BEAM_UP_ID: return "IMAGE_HUNGARR_BEAM_UP"; case IMAGE_HUNGARR_BEAM_DOWN_ID: return "IMAGE_HUNGARR_BEAM_DOWN"; case IMAGE_HUNGARR_BEAM_LEFT_ID: return "IMAGE_HUNGARR_BEAM_LEFT"; case IMAGE_HUNGARR_BEAM_RIGHT_ID: return "IMAGE_HUNGARR_BEAM_RIGHT"; case IMAGE_HUNGARR_HORIZ_ID: return "IMAGE_HUNGARR_HORIZ"; case IMAGE_HUNGARR_VERT_ID: return "IMAGE_HUNGARR_VERT"; case IMAGE_ATOMIC_EXPLOSION_ID: return "IMAGE_ATOMIC_EXPLOSION"; case IMAGE_BOMB_RADIAL_DEATH_ID: return "IMAGE_BOMB_RADIAL_DEATH"; case IMAGE_PLANETS_ID: return "IMAGE_PLANETS"; case IMAGE_SPARK_ID: return "IMAGE_SPARK"; case IMAGE_PARTICLE_LIGHTNING_ID: return "IMAGE_PARTICLE_LIGHTNING"; case SOUND_MAGZAP_ID: return "SOUND_MAGZAP"; case SOUND_BUTTON_ID: return "SOUND_BUTTON"; case SOUND_PLANET_ID: return "SOUND_PLANET"; case SOUND_LEVEL_UP1_ID: return "SOUND_LEVEL_UP1"; case SOUND_LEVEL_UP2_ID: return "SOUND_LEVEL_UP2"; case SOUND_EXPLOSION_ID: return "SOUND_EXPLOSION"; case SOUND_BEAM_HIT_ID: return "SOUND_BEAM_HIT"; case SOUND_PLANET_HIT_ID: return "SOUND_PLANET_HIT"; case SOUND_BEAM_MOVING_ID: return "SOUND_BEAM_MOVING"; case SOUND_LEVEL_UP4_ID: return "SOUND_LEVEL_UP4"; case SOUND_LEVEL_UP3_ID: return "SOUND_LEVEL_UP3"; case SOUND_GAME_OVER_CLICK_ID: return "SOUND_GAME_OVER_CLICK"; case SOUND_GAME_OVER_STATS_ID: return "SOUND_GAME_OVER_STATS"; case SOUND_GAME_OVER_RESTART_ID: return "SOUND_GAME_OVER_RESTART"; case SOUND_GAME_OVER_TEXT_ID: return "SOUND_GAME_OVER_TEXT"; case SOUND_REGION_FILLED_ID: return "SOUND_REGION_FILLED"; default: return ""; } } libtuxcap-1.4.0/tuxcap/demo5/DemoDialog.h0000644000175000017500000001646710641010426020071 0ustar inniyahinniyah////////////////////////////////////////////////////////////////////////// // DemoDialog.h // // This class demonstrates how to create a customized dialog box. // Most games will want to use custom implementations of the dialog // class if they want to go beyond the simple yes/no/ok ones. // // Basically, all we want to do is implement custom drawing and updating // code, as well as do some little things when we get added/removed from // the widget manager and handle button presses slightly differently. // // IMPORTANT: Make sure to read the comments in the .CPP file for the // Dialog constructor as they contain important information. ////////////////////////////////////////////////////////////////////////// #ifndef __DEMO_DIALOG_H__ #define __DEMO_DIALOG_H__ #include "Dialog.h" // This lets us receive slider events #include "SliderListener.h" #include "CheckboxListener.h" namespace Sexy { class Graphics; // We're going to use slider widgets to control audio volume class Slider; // This is the same as a normal button, but it automatically tiles // the butotn image if we make the widget too large class DialogButton; class Checkbox; class DemoDialog : public Dialog, public SliderListener, public CheckboxListener { protected: Slider* mMusicVolumeSlider; Slider* mSfxVolumeSlider; DialogButton* mRandomBtn; // Click this for a random number DialogButton* mClipBtn; // Click this to toggle clipping public: // Alright, fine, we'll use some constants for our widgets! enum { MUSIC_SLIDER_ID, SFX_SLIDER_ID, RANDOM_BTN_ID, CLIP_BTN_ID, FS_CHECKBOX_ID, HARDWARE_CHECKBOX_ID, MESSAGE_BOX_ID, DIALOG_ID }; // For ease of accessing, we're going to make our checkboxes public, // as the GameApp class will need to query their states as well as // possibly alter the FSCheckbox's state. Checkbox* m3DCheckbox; // Toggle 3D enhanced mode Checkbox* mFSCheckbox; // Toggle fullscreen mode public: ////////////////////////////////////////////////////////////////////////// // Function: DemoDialog // Parameters: // theHeader - A string to use for the dialog box header // theBody - A string to use for the body of the text. May use // \n characters to denote new line. // // Returns: none // // Purpose: Creates a new dialog box. You can specify a custom header // and content with the two parameters. ////////////////////////////////////////////////////////////////////////// DemoDialog(std::string theHeader, std::string theBody); virtual ~DemoDialog(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS). ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: Resize // Parameters: // theX - X coordinate to place the dialog at // theY - Y coordinate to place the dialog at // theWidth - Width of the dialog box // theHeight - Height of the dialog box // // Returns: none // // Purpose: Resizes and places the dialog box. We'll also // make sure to position any widgets appropriately based on the new // dimensions. ////////////////////////////////////////////////////////////////////////// virtual void Resize(int theX, int theY, int theWidth, int theHeight); ////////////////////////////////////////////////////////////////////////// // Function: SliderVal // Parameters: // theId - ID of the slider object that generated this message // theVal - The value of the slider, i.e. where the thumb image // is located. Leftmost is 0, rightmost is mVal in the slider widget. // // Returns: none // // Purpose: Whenever the thumb image on a slider is moved, this event is // generated. The value passed in ranges from 0 to the maximum value on // the slider, which is set in the slider's mVal variable. ////////////////////////////////////////////////////////////////////////// virtual void SliderVal(int theId, double theVal); ////////////////////////////////////////////////////////////////////////// // Function: CheckboxChecked // Parameters: // theId - Integer ID of the checkbox widget sending this message // checked - Boolean indicating if the widget is checked or not // // Returns: none // // Purpose: Whenever a checkbox widget is checked or unchecked, this // method is called. ////////////////////////////////////////////////////////////////////////// void CheckboxChecked(int theId, bool checked); }; } #endif libtuxcap-1.4.0/tuxcap/demo5/TitleScreen.h0000644000175000017500000001042510641010426020272 0ustar inniyahinniyah#ifndef __TITLE_SCREEN_H__ #define __TITLE_SCREEN_H__ #include "Widget.h" #include "ButtonListener.h" namespace Sexy { class GameApp; class Graphics; class WidgetManager; class HyperlinkWidget; // If you forgot about the ButtonListener class, you should review Demo3. // The hyperlink widget is essentially the same thing as a button widget, // and emits the same messages that a button does. Thus, to act on its // messages we derive from the ButtonListener class. class TitleScreen : public Widget, public ButtonListener { private: GameApp* mApp; HyperlinkWidget* mContinueLink; public: ////////////////////////////////////////////////////////////////////////// // Function: TitleScreen // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// TitleScreen(GameApp* pApp); virtual ~TitleScreen(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Called BEFORE the title screen is added to the widget manager // by GameApp. This initializes some things like the images used for // our hyperlink widget. ////////////////////////////////////////////////////////////////////////// void Init(void); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager. This is where // we'll do all our display routines for the loading screen. ////////////////////////////////////////////////////////////////////////// void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: LoadingComplete // Parameters: none // Returns: none // // Purpose: Called manually by GameApp when we are done loading all // resources, to let the title screen know that it should unhide and // enable the continue link, so the user can start playing the game. ////////////////////////////////////////////////////////////////////////// void LoadingComplete(); }; } #endif //__TITLE_SCREEN_H__ libtuxcap-1.4.0/tuxcap/demo5/main.cpp0000644000175000017500000000022710641010426017327 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/demo5/Board.cpp0000644000175000017500000002777310665636771017500 0ustar inniyahinniyah#include "Board.h" #include "GameApp.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" // You should remember these files from the previous demos #include "Graphics.h" #include "Color.h" #include "Rect.h" #include "ButtonWidget.h" #include "WidgetManager.h" #include "ImageFont.h" #include "Image.h" // Our example dialog box #include "DemoDialog.h" #if 0 // And for our performance profiling example, we first have to define SEXY_PERF_ENABLED // before including PerfTimer.h: #define SEXY_PERF_ENABLED #include "PerfTimer.h" // On GNU/Linux use Valgrind to detect memory leaks instead // Lastly, for our example of how to catch memory leaks, we first // enable leak detection with a #define in EACH of the files we want // to find leaks in, then include the memory management file. // IT IS VERY IMPORTANT THAT THIS DEFINE AND INCLUDE BE DONE AFTER ALL // OTHER FILE INCLUDES OR ELSE IT WILL CAUSE LINKER AND COMPILER ERRORS! // Memory leaks will automatically be dumped to "mem_leaks.txt" when // the app is closed. #define SEXY_MEMTRACE #include "memmgr.h" #endif // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; mButton = NULL; // Set up our parallaxing layers for (int i = 0; i < 3; i++) { mLayer[i].mX = 0; // Get the image for this layer. You'll notice in our resource // file that we named the layers IMAGE_BG0, IMAGE_BG1, IMAGE_BG2. // Instead of having to manually type in the layer names for each one, // we can use some convenience routines from our generated Res.h/.cpp // resource files. First step: make a string of the ID of the image we want // to access: std::string imageStringID = StrFormat("IMAGE_BG%d", i); // what we need to do now is get the integer ID for our resource // that has the same name as imageStringID. int id = GetIdByStringId(imageStringID.c_str()); // Now that we have the integer ID, we can request the actual // image data with it. We do that with GetImageById: mLayer[i].mImage = GetImageById(id); // Set the Y coordinate of the background layer so that it's // base is at the bottom of the screen. Because the Board hasn't // been resized or added to the manager yet, it's own mHeight and // mWidth are at the default of 0, 0. But not to worry, we set the // overall game's width/height in GameApp's constructor, so we // can just use those variables instead: mLayer[i].mY = (float)(mApp->mHeight - mLayer[i].mImage->GetHeight()); } // We will ON PURPOSE leak memory as an example of how to track // such things in your program. Review the comments at the top of this // file about memory leak detection: int* aLeakedInteger = new int; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete mButton; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // As an example of how to profile things, we're going to profile // the update and draw functions. Clearly, profiling this almost // empty function isn't too useful, but the point is to show you // HOW to profile multiple things and how to view the results. // You tell the profiler that you want it to begin with the // statement below, passing in a string indicating WHAT you're // profiling. The string can be anything. Enabled debug keys by // pressing CTRL-ALT-D and then press F2 to enabled/disable profiling. #if 0 SEXY_PERF_BEGIN("Start_Of_Update"); #endif Widget::Update(); MarkDirty(); // And you mark the end of a profiling section with // SEXY_PER_END, passing in the same string you passed to // SEXY_PERF_BEGIN. #if 0 SEXY_PERF_END("Start_Of_Update"); #endif } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::KeyDown(KeyCode theKey) { // If the user presses the right or left arrow keys, let's // scroll the layers: if (theKey == KEYCODE_RIGHT) { for (int i = 0; i < 3; i++) { // When the X coordinate has moved leftward (negative) by // the image's width or more, we reset the X coordinate back to // 0. Since we tile an image to the left and right of // this center image, the user won't see the snapping back to 0. mLayer[i].mX -= 1.0f * (i + 1); if (mLayer[i].mX <= -mLayer[i].mImage->GetWidth()) mLayer[i].mX = 0; } } else if (theKey == KEYCODE_LEFT) { for (int i = 0; i < 3; i++) { // This is the opposite of above, but notice that we're checking // to see if the X coordinate is >= the width of the image, and not the // width of the application. That's because some of the layers are wider // than the screen: 960 wide, when the game is 640 wide. If we checked // against the game width instead, we'd get this odd flicker appearing // because the tiling would be off. You can try it and see the effect. mLayer[i].mX += 1.0f * (i + 1); if (mLayer[i].mX >= mLayer[i].mImage->GetWidth()) mLayer[i].mX = 0; } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // As an example of how to profile things, we're going to profile // the update and draw functions. // You tell the profiler that you want it to begin with the // statement below, passing in a string indicating WHAT you're // profiling. The string can be anything. Enabled debug keys by // pressing CTRL-ALT-D and then press F2 to enabled/disable profiling. #if 0 SEXY_PERF_BEGIN("Start_Of_Draw"); #endif // Clear the screen to black g->SetColor(Color(0, 0, 0)); g->FillRect(0, 0, mWidth, mHeight); for (int i = 0; i < 3; i++) { int imgWidth = mLayer[i].mImage->GetWidth(); // Let's learn about Graphics translation. Normally, you draw your image // at a given XY by passing the coordinates to DrawImage. As an alternative, // you can "translate" the Graphics object (change its XY drawing offset) // and then just draw your image at 0, 0. Think of the Graphics object by // default as always being at 0, 0. By translating it, you move that // to whereever you like. The usefulness is in saving extra typing, // as well as some other features that come into play when scrolling // large worlds with many objects. For each of the background layers, // let's move the graphics object to its base XY location: g->TranslateF(mLayer[i].mX, mLayer[i].mY); // Something else to know about translation is that it is the method // used when drawing widgets. For every widget, the Graphics object // is translated to its own X, Y coordinate. Thus, when drawing // in the widget's class, you should always draw as if the top left // corner of the widget itself was 0, 0. Since all along we've been making // our Board widget the size of the screen, this hasn't been something we've // had to care about. But as you'll see in the dialog box example, it's something // we have to take into consideration. Normally, you can't draw outside the // X, Y, width, height of a widget. However, as you'll also see, you can // change that to allow drawing anywhere you want. // Remember how in previous demos we mentioned that it's common to use the // smoother DrawImageF functions instead of DrawImage if the user has 3D // acceleration enabled? Let's do that know. We can check if hardware acceleration // is on or not with a call to SexyAppBase's Is3DAccelerated: if (mApp->Is3DAccelerated()) { // Because we translated the graphics object, we can just draw our layers // offset by the image width. Had we not translated the graphics object, here // is the code we would have had to use instead: // g->DrawImageF(mLayer[i].mImage, mLayer[i].mX - imgWidth, mLayer[i].mY); // g->DrawImageF(mLayer[i].mImage, mLayer[i].mX, mLayer[i].mY); // g->DrawImageF(mLayer[i].mImage, mLayer[i].mX + imgWidth, mLayer[i].mY); g->DrawImageF(mLayer[i].mImage, (float)-imgWidth, 0.0f); g->DrawImageF(mLayer[i].mImage, 0.0f, 0.0f); g->DrawImageF(mLayer[i].mImage, (float)imgWidth, 0.0f); } else { // non-hardware accelerated g->DrawImage(mLayer[i].mImage, -imgWidth, 0); g->DrawImage(mLayer[i].mImage, 0, 0); g->DrawImage(mLayer[i].mImage, imgWidth, 0); } // You should remember to put the Graphics object back to where it was // before you translated it, otherwise all subsequent drawing commands will // be offset by that amount. g->TranslateF(-mLayer[i].mX, -mLayer[i].mY); } // And you mark the end of a profiling section with // SEXY_PER_END, passing in the same string you passed to // SEXY_PERF_BEGIN. #if 0 SEXY_PERF_END("Start_Of_Draw"); #endif } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); // You should remember how to create buttons from Demo3. If not, // go back and review. mButton = new ButtonWidget(Board::OPTIONS_BUTTON_ID, this); mButton->SetFont(FONT_DEFAULT); mButton->mLabel = _S("Click Me!"); // This time, let's use some images for our button. // mOverImage is the image to use when the mouse cursor is over the button. // mDownImage is the image to use when a mouse button is held down on it // mButtonImage is the default image to use // If we wanted to, we could specify a disabled image as well. mButton->mOverImage = IMAGE_BUTTON_OVER; mButton->mDownImage = IMAGE_BUTTON_DOWN; mButton->mButtonImage = IMAGE_BUTTON_NORMAL; mButton->mDoFinger = true; mButton->Resize(56, 5, IMAGE_BUTTON_NORMAL->GetWidth(), IMAGE_BUTTON_NORMAL->GetHeight()); theWidgetManager->AddWidget(mButton); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); // We should now also remove any widgets we are responsible for. theWidgetManager->RemoveWidget(mButton); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::ButtonDepress(int theId) { // As another PURPOSEFUL example of detecting memory leaks, let's // cause a leak here as well so you can see how the leak detection works. // Again, this is on purpose to illustrate a point. struct ParallaxLayer* aLeakedParallaxLayer = new struct ParallaxLayer; if (theId == Board::OPTIONS_BUTTON_ID) { // Let's open our options dialog box. Everything works the same // except that instead of using the WidgetManager's AddWidget function, // we use a special AddDialog method. The first parameter is the ID // of the dialog box, the second is the dialog box itself. // In this case, we don't need to maintain a pointer to the dialog box // to delete later. It will automatically be cleaned up when the // dialog box is closed via the KillDialog command (see DemoDialog). DemoDialog* dlg = new DemoDialog("Header", "Hello! I am a dialog box."); dlg->Resize(50, 50, 300, 400); mApp->AddDialog(DemoDialog::DIALOG_ID, dlg); } } libtuxcap-1.4.0/tuxcap/include/0000755000175000017500000000000011212652053016313 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/include/SexyVector.h0000644000175000017500000000533310736754547020630 0ustar inniyahinniyah#ifndef __SEXYVECTOR_H__ #define __SEXYVECTOR_H__ #include namespace Sexy { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class SexyVector2 { public: float x,y; public: SexyVector2() : x(0), y(0) { } SexyVector2(float theX, float theY) : x(theX), y(theY) { } float Dot(const SexyVector2 &v) const { return x*v.x + y*v.y; } SexyVector2 operator+(const SexyVector2 &v) const { return SexyVector2(x+v.x, y+v.y); } SexyVector2 operator-(const SexyVector2 &v) const { return SexyVector2(x-v.x, y-v.y); } SexyVector2 operator-() const { return SexyVector2(-x, -y); } SexyVector2 operator*(float t) const { return SexyVector2(t*x, t*y); } SexyVector2 operator/(float t) const { return SexyVector2(x/t, y/t); } void operator+=(const SexyVector2 &v) { x+=v.x; y+=v.y; } void operator-=(const SexyVector2 &v) { x-=v.x; y-=v.y; } void operator*=(float t) { x*=t; y*=t; } void operator/=(float t) { x/=t; y/=t; } bool operator==(const SexyVector2 &v) { return x==v.x && y==v.y; } bool operator!=(const SexyVector2 &v) { return x!=v.x || y!=v.y; } float Magnitude() const { return sqrtf(x*x + y*y); } float MagnitudeSquared() const { return x*x+y*y; } SexyVector2 Normalize() const { float aMag = Magnitude(); return aMag!=0 ? (*this)/aMag : *this; } SexyVector2 Perp() const { return SexyVector2(-y, x); } float Angle(const SexyVector2 *v) const { if(v) { SexyVector2 s=*this, t=*v; s.Normalize(); t.Normalize(); return acosf(s.Dot(t)); } else return atan2f(y, x); } }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class SexyVector3 { public: float x,y,z; public: SexyVector3() : x(0), y(0), z(0) { } SexyVector3(float theX, float theY, float theZ) : x(theX), y(theY), z(theZ) { } float Dot(const SexyVector3 &v) const { return x*v.x + y*v.y + z*v.z; } SexyVector3 Cross(const SexyVector3 &v) const { return SexyVector3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x); } SexyVector3 operator+(const SexyVector3 &v) const { return SexyVector3(x+v.x, y+v.y, z+v.z); } SexyVector3 operator-(const SexyVector3 &v) const { return SexyVector3(x-v.x, y-v.y, z-v.z); } SexyVector3 operator*(float t) const { return SexyVector3(t*x, t*y, t*z); } SexyVector3 operator/(float t) const { return SexyVector3(x/t, y/t, z/t); } float Magnitude() const { return sqrtf(x*x + y*y + z*z); } SexyVector3 Normalize() const { float aMag = Magnitude(); return aMag!=0 ? (*this)/aMag : *this; } }; }; #endif libtuxcap-1.4.0/tuxcap/include/NativeDisplay.h0000644000175000017500000000110111202747625021242 0ustar inniyahinniyah#ifndef __NATIVEDISPLAY_H__ #define __NATIVEDISPLAY_H__ #include "Common.h" namespace Sexy { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class NativeDisplay { public: int mRGBBits; uint32_t mRedMask; uint32_t mGreenMask; uint32_t mBlueMask; int mRedBits; int mGreenBits; int mBlueBits; int mRedShift; int mGreenShift; int mBlueShift; public: NativeDisplay(); virtual ~NativeDisplay(); }; } #endif libtuxcap-1.4.0/tuxcap/include/DDImage.h0000644000175000017500000001110711202747625017727 0ustar inniyahinniyah#ifndef __DDIMAGE_H__ #define __DDIMAGE_H__ #include "MemoryImage.h" #include "SDL.h" namespace Sexy { class DDInterface; #if 0 class SysFont; #endif class DDImage : public MemoryImage { protected: #if 0 friend class SysFont; #endif void DeleteAllNonSurfaceData(); public: DDInterface* mDDInterface; SDL_Surface* mSurface; #if 0 DDSURFACEDESC mLockedSurfaceDesc; #endif bool mSurfaceSet; bool mNoLock; bool mVideoMemory; bool mFirstPixelTrans; bool mWantDDSurface; bool mDrawToBits; int mLockCount; private: void Init(); public: virtual void ReInit(); virtual void SetVideoMemory(bool wantVideoMemory); SDL_Surface* GetSurface(); bool GenerateDDSurface(); void DeleteDDSurface(); #if 0 virtual void RehupFirstPixelTrans(); #endif virtual void BitsChanged(); virtual void CommitBits(); virtual void NormalFillRect(const Rect& theRect, const Color& theColor); virtual void AdditiveFillRect(const Rect& theRect, const Color& theColor); virtual void NormalBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); virtual void AdditiveBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); virtual void NormalDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); virtual void AdditiveDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); virtual void NormalDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); virtual void AdditiveDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); virtual void NormalBltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); virtual void AdditiveBltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); virtual void FillScanLinesWithCoverage(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode, const unsigned char* theCoverage, int theCoverX, int theCoverY, int theCoverWidth, int theCoverHeight); static bool Check3D(DDImage *theImage); static bool Check3D(Image *theImage); public: DDImage(); DDImage(DDInterface* theDDInterface); virtual ~DDImage(); virtual bool LockSurface(); virtual bool UnlockSurface(); virtual void SetSurface(SDL_Surface* theSurface); virtual void Create(int theWidth, int theHeight); virtual uint32_t* GetBits(); virtual bool PolyFill3D(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty, bool comvex); virtual void FillRect(const Rect& theRect, const Color& theColor, int theDrawMode); virtual void DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode); virtual void BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode); virtual void BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY); virtual void StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch); virtual void BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend); virtual void BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend); virtual void BltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode); virtual void StretchBltMirror(Image* theImage, const Rect& theDestRectOrig, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch); virtual bool Palletize(); virtual void PurgeBits(); virtual void DeleteNativeData(); virtual void DeleteExtraBuffers(); }; } #endif //__DDIMAGE_H__ libtuxcap-1.4.0/tuxcap/include/Widget.h0000644000175000017500000001117010654427540017721 0ustar inniyahinniyah#ifndef __WIDGET_H__ #define __WIDGET_H__ #include "Common.h" #include "Color.h" #include "Insets.h" #include "Graphics.h" #include "KeyCodes.h" #include "WidgetContainer.h" namespace Sexy { class WidgetManager; typedef std::vector ColorVector; class Widget : public WidgetContainer { public: bool mVisible; bool mMouseVisible; bool mDisabled; bool mHasFocus; bool mIsDown; bool mIsOver; bool mHasTransparencies; ColorVector mColors; Insets mMouseInsets; bool mDoFinger; bool mWantsFocus; Widget* mTabPrev; Widget* mTabNext; static bool mWriteColoredString; // controls whether ^color^ works in calls to WriteString void WidgetRemovedHelper(); public: Widget(); virtual ~Widget(); virtual void OrderInManagerChanged(); virtual void SetVisible(bool isVisible); virtual void SetColors(int theColors[][3], int theNumColors); virtual void SetColors(int theColors[][4], int theNumColors); virtual void SetColor(int theIdx, const Color& theColor); virtual const Color& GetColor(int theIdx); virtual Color GetColor(int theIdx, const Color& theDefaultColor); virtual void SetDisabled(bool isDisabled); virtual void ShowFinger(bool on); virtual void Resize(int theX, int theY, int theWidth, int theHeight); virtual void Resize(const Rect& theRect); virtual void Move(int theNewX, int theNewY); virtual bool WantsFocus(); virtual void Draw(Graphics* g); // Already translated virtual void DrawOverlay(Graphics* g); virtual void DrawOverlay(Graphics* g, int thePriority); virtual void Update(); virtual void UpdateF(float theFrac); virtual void GotFocus(); virtual void LostFocus(); virtual void KeyChar(SexyChar theChar); virtual void KeyDown(KeyCode theKey); virtual void KeyUp(KeyCode theKey); virtual void MouseEnter(); virtual void MouseLeave(); virtual void MouseMove(int x, int y); virtual void MouseDown(int x, int y, int theClickCount); virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseUp(int x, int y); virtual void MouseUp(int x, int y, int theClickCount); virtual void MouseUp(int x, int y, int theBtnNum, int theClickCount); virtual void MouseDrag(int x, int y); virtual void MouseWheel(int theDelta); virtual bool IsPointVisible(int x, int y); //////// Helper functions virtual Rect WriteCenteredLine(Graphics* g, int anOffset, const SexyString& theLine); virtual Rect WriteCenteredLine(Graphics* g, int anOffset, const SexyString& theLine, Color theColor1, Color theColor2, const Point& theShadowOffset = Point(1,2)); virtual int WriteString(Graphics* g, const SexyString& theString, int theX, int theY, int theWidth = -1, int theJustification = -1, bool drawString = true, int theOffset = 0, int theLength = -1); virtual int WriteWordWrapped(Graphics* g, const Rect& theRect, const SexyString& theLine, int theLineSpacing, int theJustification); virtual int GetWordWrappedHeight(Graphics* g, int theWidth, const SexyString& theLine, int aLineSpacing); virtual int GetNumDigits(int theNumber); virtual void WriteNumberFromStrip(Graphics* g, int theNumber, int theX, int theY, Image* theNumberStrip, int aSpacing); virtual bool Contains(int theX, int theY); virtual Rect GetInsetRect(); void DeferOverlay(int thePriority = 0); //////// Layout functions int Left() { return mX; } int Top() { return mY; } int Right() { return mX + mWidth; } int Bottom() { return mY + mHeight; } int Width() { return mWidth; } int Height() { return mHeight; } void Layout(int theLayoutFlags, Widget *theRelativeWidget, int theLeftPad = 0, int theTopPad = 0, int theWidthPad = 0, int theHeightPad = 0); }; /////// Layout flags used in Widget::Layout method enum LayoutFlags { LAY_SameWidth = 0x0001, LAY_SameHeight = 0x0002, LAY_SetLeft = 0x0010, LAY_SetTop = 0x0020, LAY_SetWidth = 0x0040, LAY_SetHeight = 0x0080, LAY_Above = 0x0100, LAY_Below = 0x0200, LAY_Right = 0x0400, LAY_Left = 0x0800, LAY_SameLeft = 0x1000, LAY_SameRight = 0x2000, LAY_SameTop = 0x4000, LAY_SameBottom = 0x8000, LAY_GrowToRight = 0x10000, LAY_GrowToLeft = 0x20000, LAY_GrowToTop = 0x40000, LAY_GrowToBottom = 0x80000, LAY_HCenter = 0x100000, LAY_VCenter = 0x200000, LAY_Max = 0x400000, LAY_SameSize = LAY_SameWidth | LAY_SameHeight, LAY_SameCorner = LAY_SameLeft | LAY_SameTop, LAY_SetPos = LAY_SetLeft | LAY_SetTop, LAY_SetSize = LAY_SetWidth | LAY_SetHeight }; } #endif //__WIDGET_H__ libtuxcap-1.4.0/tuxcap/include/MI_BltRotated_Additive.inc0000644000175000017500000000442211202747625023263 0ustar inniyahinniyah{ double aCos = cos(theRot); double aSin = sin(theRot); int aCosLong = (int) (aCos * 0x10000); int aSinLong = (int) (aSin * 0x10000); #ifdef OPTIMIZE_SOFTWARE_DRAWING int aRotCenterXLong = (int)(theRotCenterX * 0x10000); int aRotCenterYLong = (int)(theRotCenterY * 0x10000); #endif uint32_t* aDestPixelsRow = GetBits() + ((int)aDestRect.mY * mWidth) + (int)aDestRect.mX; int aDestPixelsPitch = mWidth; if (theColor == Color::White) { #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ uint32_t dest = *aDestPixels;\ int a = a1+a2+a3+a4; \ if(a==0) /* transparent */ \ aDestPixels++;\ else \ { \ uint32_t r = aMaxTable[((((src1&0xFF0000)*a1) + ((src2&0xFF0000)*a2) + ((src3&0xFF0000)*a3) + ((src4&0xFF0000)*a4))>>24) + ((dest&0xFF0000)>>16)]; \ uint32_t g = aMaxTable[((((src1&0x00FF00)*a1) + ((src2&0x00FF00)*a2) + ((src3&0x00FF00)*a3) + ((src4&0x00FF00)*a4))>>16) + ((dest&0x00FF00)>>8)]; \ uint32_t b = aMaxTable[((((src1&0x0000FF)*a1) + ((src2&0x0000FF)*a2) + ((src3&0x0000FF)*a3) + ((src4&0x0000FF)*a4))>>8) + (dest&0x0000FF)]; \ \ *aDestPixels++ = (dest & 0xFF000000) | (r<<16) | (g<<8) | b; \ } \ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ uint32_t dest = *aDestPixels;\ int a = a1+a2+a3+a4; \ if(a==0) /* transparent */ \ aDestPixels++; \ else \ { \ uint32_t destPixel = *aDestPixels; \ \ uint32_t r = aMaxTable[((((((src1&0xFF0000)*a1) + ((src2&0xFF0000)*a2) + ((src3&0xFF0000)*a3) + ((src4&0xFF0000)*a4))>>24)*cr)>>8) + ((dest&0xFF0000)>>16)]; \ uint32_t g = aMaxTable[(((((src1&0x00FF00)*a1) + ((src2&0x00FF00)*a2) + ((src3&0x00FF00)*a3) + ((src4&0x00FF00)*a4))*cg)>>24) + ((dest&0x00FF00)>>8)]; \ uint32_t b = aMaxTable[(((((src1&0x0000FF)*a1) + ((src2&0x0000FF)*a2) + ((src3&0x0000FF)*a3) + ((src4&0x0000FF)*a4))*cb)>>16) + (dest&0x0000FF)]; \ \ *aDestPixels++ = (dest & 0xFF000000) | (r<<16) | (g<<8) | b; \ }\ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } } libtuxcap-1.4.0/tuxcap/include/KeyCodes.h0000644000175000017500000000672710775711737020230 0ustar inniyahinniyah#ifndef __KEYCODES_INCLUDED__ #define __KEYCODES_INCLUDED__ #include "Common.h" #include "SDL_keysym.h" #define KEYCODE_RIGHT SDLK_RIGHT #define KEYCODE_LEFT SDLK_LEFT #define KEYCODE_RETURN SDLK_RETURN #define KEYCODE_SPACE SDLK_SPACE #define KEYCODE_BACK SDLK_BACKSPACE #define KEYCODE_TAB SDLK_TAB #define KEYCODE_ESCAPE SDLK_ESCAPE #define KEYCODE_RSHIFT SDLK_RSHIFT #define KEYCODE_LSHIFT SDLK_LSHIFT #define KEYCODE_UP SDLK_UP #define KEYCODE_DOWN SDLK_DOWN namespace Sexy { #if 0 typedef enum KeyCode { KEYCODE_UNKNOWN = SDLK_UNKNOWN, KEYCODE_RIGHT = SDLK_RIGHT, KEYCODE_LEFT = SDLK_LEFT, KEYCODE_RETURN = SDLK_RETURN, KEYCODE_ESCAPE = SDLK_ESCAPE, KEYCODE_LBUTTON = 0x01, KEYCODE_RBUTTON = 0x02, KEYCODE_CANCEL = 0x03, KEYCODE_MBUTTON = 0x04, KEYCODE_BACK = 0x08, KEYCODE_TAB = 0x09, KEYCODE_CLEAR = 0x0C, KEYCODE_SHIFT = 0x10, KEYCODE_CONTROL = 0x11, KEYCODE_MENU = 0x12, KEYCODE_PAUSE = 0x13, KEYCODE_CAPITAL = 0x14, KEYCODE_KANA = 0x15, KEYCODE_HANGEUL = 0x15, KEYCODE_HANGUL = 0x15, KEYCODE_JUNJA = 0x17, KEYCODE_FINAL = 0x18, KEYCODE_HANJA = 0x19, KEYCODE_KANJI = 0x19, KEYCODE_CONVERT = 0x1C, KEYCODE_NONCONVERT = 0x1D, KEYCODE_ACCEPT = 0x1E, KEYCODE_MODECHANGE = 0x1F, KEYCODE_SPACE = 0x20, KEYCODE_PRIOR = 0x21, KEYCODE_NEXT = 0x22, KEYCODE_END = 0x23, KEYCODE_HOME = 0x24, KEYCODE_UP = 0x26, KEYCODE_DOWN = 0x28, KEYCODE_SELECT = 0x29, KEYCODE_PRINT = 0x2A, KEYCODE_EXECUTE = 0x2B, KEYCODE_SNAPSHOT = 0x2C, KEYCODE_INSERT = 0x2D, KEYCODE_DELETE = 0x2E, KEYCODE_HELP = 0x2F, KEYCODE_ASCIIBEGIN = 0x30, KEYCODE_ASCIIEND = 0x5A, KEYCODE_LWIN = 0x5B, KEYCODE_RWIN = 0x5C, KEYCODE_APPS = 0x5D, KEYCODE_NUMPAD0 = 0x60, KEYCODE_NUMPAD1 = 0x61, KEYCODE_NUMPAD2 = 0x62, KEYCODE_NUMPAD3 = 0x63, KEYCODE_NUMPAD4 = 0x64, KEYCODE_NUMPAD5 = 0x65, KEYCODE_NUMPAD6 = 0x66, KEYCODE_NUMPAD7 = 0x67, KEYCODE_NUMPAD8 = 0x68, KEYCODE_NUMPAD9 = 0x69, KEYCODE_MULTIPLY = 0x6A, KEYCODE_ADD = 0x6B, KEYCODE_SEPARATOR = 0x6C, KEYCODE_SUBTRACT = 0x6D, KEYCODE_DECIMAL = 0x6E, KEYCODE_DIVIDE = 0x6F, KEYCODE_F1 = 0x70, KEYCODE_F2 = 0x71, KEYCODE_F3 = 0x72, KEYCODE_F4 = 0x73, KEYCODE_F5 = 0x74, KEYCODE_F6 = 0x75, KEYCODE_F7 = 0x76, KEYCODE_F8 = 0x77, KEYCODE_F9 = 0x78, KEYCODE_F10 = 0x79, KEYCODE_F11 = 0x7A, KEYCODE_F12 = 0x7B, KEYCODE_F13 = 0x7C, KEYCODE_F14 = 0x7D, KEYCODE_F15 = 0x7E, KEYCODE_F16 = 0x7F, KEYCODE_F17 = 0x80, KEYCODE_F18 = 0x81, KEYCODE_F19 = 0x82, KEYCODE_F20 = 0x83, KEYCODE_F21 = 0x84, KEYCODE_F22 = 0x85, KEYCODE_F23 = 0x86, KEYCODE_F24 = 0x87, KEYCODE_NUMLOCK = 0x90, KEYCODE_SCROLL = 0x91, KEYCODE_ASCIIBEGIN2 = 0xA1, //ASCII + 0x80 KEYCODE_ASCIIEND2 = 0xE0 }; #endif KeyCode GetKeyCodeFromName(const std::string& theKeyName); const std::string GetKeyNameFromCode(const KeyCode& theKeyCode); } #endif //__KEYCODES_INCLUDED__ libtuxcap-1.4.0/tuxcap/include/MTRand.h0000644000175000017500000000141011202747625017616 0ustar inniyahinniyah#ifndef __MTRAND_H__ #define __MTRAND_H__ #include namespace Sexy { #define MTRAND_N 624 class MTRand { uint32_t mt[MTRAND_N]; /* the array for the state vector */ int mti; public: MTRand(const std::string& theSerialData); MTRand(uint32_t seed); MTRand(); void SRand(const std::string& theSerialData); void SRand(uint32_t seed); uint32_t NextNoAssert(); uint32_t Next(); uint32_t NextNoAssert(uint32_t range); uint32_t Next(uint32_t range); float NextNoAssert(float range); float Next( float range ); std::string Serialize(); static void SetRandAllowed(bool allowed); }; struct MTAutoDisallowRand { MTAutoDisallowRand() { MTRand::SetRandAllowed(false); } ~MTAutoDisallowRand() { MTRand::SetRandAllowed(true); } }; } #endif //__MTRAND_H__ libtuxcap-1.4.0/tuxcap/include/ButtonWidget.h0000644000175000017500000000361510641010426021105 0ustar inniyahinniyah#ifndef __BUTTONWIDGET_H__ #define __BUTTONWIDGET_H__ #include "Widget.h" namespace Sexy { class Image; class ButtonListener; class Font; class ButtonWidget : public Widget { public: enum { BUTTON_LABEL_LEFT = -1, BUTTON_LABEL_CENTER, BUTTON_LABEL_RIGHT }; enum { COLOR_LABEL, COLOR_LABEL_HILITE, COLOR_DARK_OUTLINE, COLOR_LIGHT_OUTLINE, COLOR_MEDIUM_OUTLINE, COLOR_BKG, NUM_COLORS }; int mId; SexyString mLabel; int mLabelJustify; Font* mFont; Image* mButtonImage; Image* mOverImage; Image* mDownImage; Image* mDisabledImage; Rect mNormalRect; Rect mOverRect; Rect mDownRect; Rect mDisabledRect; bool mInverted; bool mBtnNoDraw; bool mFrameNoDraw; ButtonListener* mButtonListener; double mOverAlpha; double mOverAlphaSpeed; double mOverAlphaFadeInSpeed; bool HaveButtonImage(Image *theImage, const Rect &theRect); virtual void DrawButtonImage(Graphics *g, Image *theImage, const Rect &theRect, int x, int y); public: ButtonWidget(int theId, ButtonListener* theButtonListener); virtual ~ButtonWidget(); virtual void SetFont(Font* theFont); virtual bool IsButtonDown(); virtual void Draw(Graphics* g); virtual void SetDisabled(bool isDisabled); virtual void MouseEnter(); virtual void MouseLeave(); virtual void MouseMove(int theX, int theY); virtual void MouseDown(int theX, int theY, int theClickCount) { Widget::MouseDown(theX, theY, theClickCount); } virtual void MouseDown(int theX, int theY, int theBtnNum, int theClickCount); virtual void MouseUp(int theX, int theY) { Widget::MouseUp(theX, theY); } virtual void MouseUp(int theX, int theY, int theClickCount) { Widget::MouseUp(theX, theY, theClickCount); } virtual void MouseUp(int theX, int theY, int theBtnNum, int theClickCount); virtual void Update(); }; } #endif //__BUTTONWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/DDI_Additive.inc0000644000175000017500000001645411202747625021242 0ustar inniyahinniyah{ aMemoryImage->CommitBits(); // RECT aDestRect = {theX, theY, theX + theSrcRect.mWidth, theY + theSrcRect.mHeight}; // RECT aSrcRect = {theSrcRect.mX, theSrcRect.mY, theSrcRect.mX + theSrcRect.mWidth, theSrcRect.mY + theSrcRect.mHeight}; if (!LockSurface()) return; uchar* aSrcRLAdditiveData = aMemoryImage->GetRLAdditiveData(mDDInterface); if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theY * mSurface->pitch/2) + theX; uchar* aRLAdditiveDataRow = aSrcRLAdditiveData + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; int aMaxR = (1<mRedBits) - 1; int aMaxG = (1<mGreenBits) - 1; int aMaxB = (1<mBlueBits) - 1; int aRedShift = mDDInterface->mRedShift; int aGreenShift = mDDInterface->mGreenShift; int aBlueShift = mDDInterface->mBlueShift; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; if (theColor == Color::White) { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAdditiveData = aRLAdditiveDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAdditiveData; if (rl > aSpanLeft) rl = aSpanLeft; if ((src & 0xFFFFFF) == 0) // A run of black { aSrcPixels += rl; aDestPixels _PLUSEQUALS rl; } else { for (int i = 0; i < rl; i++) { src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) + (src & aRMask)) >> aRedShift]; int g = aMaxGreenTable[((dest & aGMask) + (src & aGMask)) >> aGreenShift]; int b = aMaxBlueTable[((dest & aBMask) + (src & aBMask)) >> aBlueShift]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } } aRLAdditiveData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAdditiveDataRow += theImage->mWidth; } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAdditiveData = aRLAdditiveDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAdditiveData; if (rl > aSpanLeft) rl = aSpanLeft; if ((src & 0xFFFFFF) == 0) // A run of black { aSrcPixels += rl; aDestPixels _PLUSEQUALS rl; } else { for (int i = 0; i < rl; i++) { src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + ((((src & aRMask) >> aRedShift) * cr) >> 8)]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + ((((src & aGMask) >> aGreenShift) * cg) >> 8)]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + ((((src & aBMask) >> aBlueShift) * cb) >> 8)]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } } aRLAdditiveData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAdditiveDataRow += theImage->mWidth; } } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theY * mSurface->pitch/4) + theX; uchar* aRLAdditiveDataRow = aSrcRLAdditiveData + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; int aMaxR = (1<mRedBits) - 1; int aMaxG = (1<mGreenBits) - 1; int aMaxB = (1<mBlueBits) - 1; int aRedShift = mDDInterface->mRedShift; int aGreenShift = mDDInterface->mGreenShift; int aBlueShift = mDDInterface->mBlueShift; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; if (theColor == Color::White) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; uchar* aRLAdditiveData = aRLAdditiveDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAdditiveData; if (rl > aSpanLeft) rl = aSpanLeft; if ((src & 0xFFFFFF) == 0) // A run of black { aSrcPixels += rl; aDestPixels _PLUSEQUALS rl; } else { for (int i = 0; i < rl; i++) { src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) + (src & aRMask)) >> aRedShift]; int g = aMaxGreenTable[((dest & aGMask) + (src & aGMask)) >> aGreenShift]; int b = aMaxBlueTable[((dest & aBMask) + (src & aBMask)) >> aBlueShift]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } } aRLAdditiveData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; aRLAdditiveDataRow += theImage->mWidth; } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; uchar* aRLAdditiveData = aRLAdditiveDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAdditiveData; if (rl > aSpanLeft) rl = aSpanLeft; if ((src & 0xFFFFFF) == 0) // A run of black { aSrcPixels += rl; aDestPixels _PLUSEQUALS rl; } else { for (int i = 0; i < rl; i++) { src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + ((((src & aRMask) >> aRedShift) * cr) >> 8)]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + ((((src & aGMask) >> aGreenShift) * cg) >> 8)]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + ((((src & aBMask) >> aBlueShift) * cb) >> 8)]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } } aRLAdditiveData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; aRLAdditiveDataRow += theImage->mWidth; } } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/Physics.h0000644000175000017500000002520511202747625020123 0ustar inniyahinniyah/* Sexy Chipmunk, a physics engine for the PopCap Games Framework using Scott Lembcke's excellent chipmunk physics library */ /* Copyright (c) 2007-2008 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef __SEXYPHYSICS_H__ #define __SEXYPHYSICS_H__ #include #include #include #include #include #include "chipmunk.h" #include "PhysicsListener.h" #include "SexyVector.h" #include typedef __u32 uint32_t; namespace Sexy { class CollisionPoint; class PhysicsObject; class Joint; class Physics { friend class PhysicsObject; public: Physics(); ~Physics(); void Init(); bool IsInitialized(){return space != 0;} void SetGravity(const SexyVector2& gravity); void SetDamping(cpFloat damping); void SetIterations(int iter); void ResizeStaticHash(float dimension, int count); void ResizeActiveHash(float dimension, int count); void Update(); void Draw(Graphics* g); void Clear(); void SetSteps(int steps); void SetDelta(float delta) { this->delta = delta; } PhysicsObject* CreateObject(cpFloat mass, cpFloat inertia); PhysicsObject* CreateStaticObject(); void DestroyObject(PhysicsObject* object); bool IsValidObject(PhysicsObject* object) const; void SetPhysicsListener(PhysicsListener* p) { listener = p; } void RegisterCollisionType(uint32_t type_a, uint32_t type_b = 0); void UnregisterCollisionType(uint32_t type_a, uint32_t type_b = 0); std::vector& GetPhysicsObjects() { return objects;} //help functions void ApplySpringForce(PhysicsObject* obj1, PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2, float rest_length, float spring, float damping); Joint CreatePinJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2); Joint CreateSlideJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2, float min, float max); Joint CreatePivotJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& pivot); void RemoveJoint(const Joint& joint); void RemoveJoint(const PhysicsObject* obj1, const PhysicsObject* obj2); void RemoveJoints(const PhysicsObject* obj); bool IsJoined(const PhysicsObject* obj1, const PhysicsObject* obj2) const; std::vector > GetJoints(const PhysicsObject* obj1, const PhysicsObject* obj2) const; std::vector > GetJoints(const PhysicsObject* obj1) const; std::vector > GetJoints() const; std::set GetJoinedPhysicsObjects(const PhysicsObject* obj1) const; static cpFloat ComputeMomentForPoly(cpFloat moment, int numVerts, SexyVector2* vectors, const SexyVector2& offset) { return cpMomentForPoly(moment, numVerts, (cpVect*)vectors, cpv(offset.x, offset.y)); } static cpFloat ComputeMomentForCircle(cpFloat moment, cpFloat r1, cpFloat r2, const SexyVector2& offset) { return cpMomentForCircle(moment, r1, r2, cpv(offset.x, offset.y)); } static SexyVector2 RotateVector(const SexyVector2& v1, const SexyVector2& v2) { cpVect r = cpvrotate(cpv(v1.x,v1.y), cpv(v2.x,v2.y)); return SexyVector2(r.x,r.y); } static SexyVector2 SumCollisionImpulses(int numContacts, CollisionPoint* contacts); static SexyVector2 SumCollisionImpulsesWithFriction(int numContacts, CollisionPoint* contacts); private: cpSpace* space; int steps; cpFloat delta; std::vector objects; std::vector joints; PhysicsListener* listener; void AddUniqueJoint(std::vector >* v, const SexyVector2& start, const SexyVector2& end) const; const std::vector GetJointsOfObject(const PhysicsObject* obj) const; void RemoveJoint(const cpJoint* joint); static void AllCollisions(void* ptr, void* data); static void HashQuery(void* ptr, void* data); static int CollFunc(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data); static PhysicsObject* FindObject(std::vector* objects, cpBody* body, cpShape* shape); static PhysicsObject* FindObject(std::vector* objects, cpShape* shape); typedef struct typed_data { Graphics* graphics; std::vector* objects; PhysicsListener* listener; } TypedData; }; class PhysicsObject { private: PhysicsObject():body(NULL), physics(NULL), is_static(false){} PhysicsObject(cpFloat mass, cpFloat inertia, Physics* physics, bool is_static=false); ~PhysicsObject(); friend class Physics; friend class CollisionObject; cpBody* body; std::vector shapes; Physics* physics; int colliding_shape_index; public: bool is_static; //body functions void SetMass(cpFloat m) { cpBodySetMass(body, m); } void SetMoment(cpFloat i) { cpBodySetMoment(body, i); } void SetAngle(cpFloat a) { cpBodySetAngle(body, a); } void ResetForces() { cpBodyResetForces(body);} void SetAngularVelocity(cpFloat w); void SetVelocity(const SexyVector2& v); void SetPosition(const SexyVector2&p) { body->p = cpv(p.x,p.y);} void UpdatePosition(); void UpdateVelocity(); void ApplyImpulse(const SexyVector2& j, const SexyVector2& r) { cpBodyApplyImpulse(body, cpv(j.x,j.y), cpv(r.x,r.y)); } void ApplyForce(const SexyVector2& f, const SexyVector2& r) { cpBodyApplyForce(body, cpv(f.x,f.y), cpv(r.x,r.y)); } float GetAngle() const; SexyVector2 GetRotation() const; SexyVector2 GetPosition() const; SexyVector2 GetVelocity() const; //shape functions void AddCircleShape(cpFloat radius, const SexyVector2& offset, cpFloat elasticity, cpFloat friction); void AddSegmentShape(const SexyVector2& begin, const SexyVector2& end, cpFloat radius, cpFloat elasticity, cpFloat friction); void AddPolyShape(int numVerts, SexyVector2* vectors, const SexyVector2& offset, cpFloat elasticity, cpFloat friction); void SetCollisionType(unsigned int type, int shape_index=0); void SetGroup(unsigned int group, int shape_index=0); void SetLayers(unsigned int layers, int shape_index=0); void SetData(void* data, int shape_index=0); unsigned int GetCollisionType(int shape_index=0) const; unsigned int GetGroup(int shape_index=0) const; unsigned int GetLayers(int shape_index=0) const; void* GetData(int shape_index=0) const; int GetNumberVertices(int shape_index=0) const; SexyVector2 GetVertex(int vertex_index, int shape_index=0) const; SexyVector2 GetSegmentShapeBegin(int shape_index=0) const; SexyVector2 GetSegmentShapeEnd(int shape_index=0) const; float GetSegmentShapeRadius(int shape_index=0) const; float GetCircleShapeRadius(int shape_index=0) const; SexyVector2 GetCircleShapeCenter(int shape_index=0) const; int GetShapeType(int shape_index=0) const; int GetNumberOfShapes() const; int GetCollidingShapeIndex() const; enum SHAPE_TYPE { CIRCLE_SHAPE = CP_CIRCLE_SHAPE, SEGMENT_SHAPE, POLY_SHAPE, NR_SHAPE_TYPES }; }; class CollisionPoint { public: CollisionPoint(const SexyVector2& point,const SexyVector2& normal, float distance): point(point),normal(normal), distance(distance){} ~CollisionPoint(){} SexyVector2 point; SexyVector2 normal; float distance; // Calculated by cpArbiterPreStep(). SexyVector2 r1, r2; float nMass, tMass, bounce; // Persistant contact information. float jnAcc, jtAcc, jBias; float bias; // Hash value used to (mostly) uniquely identify a contact. uint32_t hash; }; class CollisionObject { public: CollisionObject(PhysicsObject* object1, PhysicsObject* object2, const CollisionPoint* points, int num_points, float normal_coef = 1.0f): object1(object1), object2(object2), points(points), num_points(num_points), normal_coef(normal_coef){} ~CollisionObject(){} PhysicsObject* object1; PhysicsObject* object2; const CollisionPoint* points; int num_points; float normal_coef; }; class Joint { private: Joint(cpJoint* joint, PhysicsObject* obj1, PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2): joint(joint), object1(obj1), object2(obj2), anchor1(anchor1), anchor2(anchor2){} Joint(cpJoint* joint, PhysicsObject* obj1, PhysicsObject* obj2, const SexyVector2& pivot): joint(joint), object1(obj1), object2(obj2), pivot(pivot){} friend class Physics; cpJoint* joint; PhysicsObject* object1; PhysicsObject* object2; SexyVector2 anchor1; SexyVector2 anchor2; SexyVector2 pivot; public: ~Joint(){} const PhysicsObject* GetPhysicsObject1() { return object1; } const PhysicsObject* GetPhysicsObject2() { return object2; } const SexyVector2* GetAnchor1() { if (joint->type == CP_PIN_JOINT || joint->type == CP_SLIDE_JOINT) return &anchor1; return NULL; } const SexyVector2* GetAnchor2() { if (joint->type == CP_PIN_JOINT || joint->type == CP_SLIDE_JOINT) return &anchor2; return NULL; } const SexyVector2* GetPivot() { if (joint->type == CP_PIVOT_JOINT) return &pivot; return NULL; } }; }; #endif libtuxcap-1.4.0/tuxcap/include/MI_BltRotated.inc0000644000175000017500000000635111202747625021455 0ustar inniyahinniyah{ double aCos = cos(theRot); double aSin = sin(theRot); int aCosLong = (int) (aCos * 0x10000); int aSinLong = (int) (aSin * 0x10000); uint32_t* aDestPixelsRow = GetBits() + ((int)aDestRect.mY * mWidth) + (int)aDestRect.mX; int aDestPixelsPitch = mWidth; if (theColor == Color::White) { #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ int a = a1+a2+a3+a4; \ if(a==0) /* transparent */ \ aDestPixels++; \ else \ { \ uint32_t r = (((((src1&0xFF0000)*a1)) + (((src2&0xFF0000)*a2)) + (((src3&0xFF0000)*a3)) + (((src4&0xFF0000)*a4)))&0xFF000000); \ uint32_t g = (((((src1&0x00FF00)*a1)) + (((src2&0x00FF00)*a2)) + (((src3&0x00FF00)*a3)) + (((src4&0x00FF00)*a4)))&0x00FF0000); \ uint32_t b = (((((src1&0x0000FF)*a1)) + (((src2&0x0000FF)*a2)) + (((src3&0x0000FF)*a3)) + (((src4&0x0000FF)*a4)))&0x0000FF00); \ if(a > 250) /* opaque */ \ *aDestPixels++ = 0xFF000000 | (r>>8) | (g>>8) | (b>>8);\ else /* blend */ \ {\ uint32_t destPixel = *aDestPixels; \ uint32_t da = destPixel >> 24;\ \ uint32_t dr = (((destPixel&0xFF0000)*da)>>8) & 0xFF0000;\ uint32_t dg = (((destPixel&0x00FF00)*da)>>8) & 0x00FF00;\ uint32_t db = (((destPixel&0x0000FF)*da)>>8) & 0x0000FF;\ \ int finalAlpha = 256 - (((256 - a)*(256 - da))>>8);\ r = ((r + (256-a)*dr)/finalAlpha) & 0xFF0000;\ g = ((g + (256-a)*dg)/finalAlpha) & 0x00FF00;\ b = ((b + (256-a)*db)/finalAlpha) & 0x0000FF;\ \ *aDestPixels++ = ((finalAlpha-1)<<24) | r | g | b; \ }\ } \ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } else { int ca = theColor.mAlpha; int cr = theColor.mRed + 1; int cg = theColor.mGreen + 1; int cb = theColor.mBlue + 1; #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ a1 = (a1*ca)>>8; a2 = (a2*ca)>>8; a3 = (a3*ca)>>8; a4 = (a4*ca)>>8; \ int a = a1+a2+a3+a4; \ \ if(a==0) /* transparent */ \ aDestPixels++; \ else \ { \ uint32_t r = (cr * (((((src1&0xFF0000)*a1)) + (((src2&0xFF0000)*a2)) + (((src3&0xFF0000)*a3)) + (((src4&0xFF0000)*a4)))>>8)) & 0xFF000000 ; \ uint32_t g = ((((((src1&0x00FF00)*a1)) + (((src2&0x00FF00)*a2)) + (((src3&0x00FF00)*a3)) + (((src4&0x00FF00)*a4)))&0x00FF0000) * cg) & 0xFF000000; \ uint32_t b = ((((((src1&0x0000FF)*a1)) + (((src2&0x0000FF)*a2)) + (((src3&0x0000FF)*a3)) + (((src4&0x0000FF)*a4)))&0x0000FF00) * cb) & 0x00FF0000; \ if(a > 250) /* opaque */ \ *aDestPixels++ = 0xFF000000 | (r>>8) | (g>>16) | (b>>16);\ else /* blend */ \ {\ uint32_t destPixel = *aDestPixels; \ uint32_t da = destPixel >> 24;\ \ uint32_t dr = (((destPixel&0xFF0000)*da)>>8) & 0xFF0000;\ uint32_t dg = (((destPixel&0x00FF00)*da)>>8) & 0x00FF00;\ uint32_t db = (((destPixel&0x0000FF)*da)>>8) & 0x0000FF;\ \ int finalAlpha = 256 - (((256 - a)*(256 - da))>>8);\ r = ((r + (256-a)*dr)/finalAlpha) & 0xFF0000;\ g = (((g>>8) + (256-a)*dg)/finalAlpha) & 0x00FF00;\ b = (((b>>8) + (256-a)*db)/finalAlpha) & 0x0000FF;\ \ *aDestPixels++ = ((finalAlpha-1)<<24) | r | g | b; \ }\ } \ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } } libtuxcap-1.4.0/tuxcap/include/SDLMixerSoundManager.h0000644000175000017500000000541710737636302022440 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef __SDLMixerSoundMANAGER_H__ #define __SDLMixerSoundMANAGER_H__ #include "SoundManager.h" #include "SDL_mixer.h" #ifndef WIN32 #define HWND void* #endif namespace Sexy { class SDLMixerSoundInstance; class SDLMixerSoundManager : public SoundManager { friend class SDLMixerSoundInstance; protected: Mix_Chunk* mSourceSounds[MAX_SOURCE_SOUNDS]; float mBaseVolumes[MAX_SOURCE_SOUNDS]; int mBasePans[MAX_SOURCE_SOUNDS]; float mBasePitches[MAX_SOURCE_SOUNDS]; SDLMixerSoundInstance* mPlayingSounds[MAX_CHANNELS]; float mMasterVolume; Uint32 mLastReleaseTick; protected: int FindFreeChannel(); void ReleaseFreeChannels(); public: SDLMixerSoundManager(); virtual ~SDLMixerSoundManager(); virtual bool Initialized(); virtual bool LoadSound(unsigned int theSfxID, const std::string& theFilename); virtual int LoadSound(const std::string& theFilename); virtual void ReleaseSound(unsigned int theSfxID); virtual int GetFreeSoundId(); virtual int GetNumSounds(); virtual void SetVolume(double theVolume); virtual bool SetBaseVolume(unsigned int theSfxID, double theBaseVolume); virtual bool SetBasePan(unsigned int theSfxID, int theBasePan); virtual bool SetBasePitch(unsigned int theSfxID, float theBasePitch); virtual SoundInstance* GetSoundInstance(unsigned int theSfxID); virtual void ReleaseSounds(); virtual void ReleaseChannels(); virtual double GetMasterVolume(); virtual void SetMasterVolume(double theVolume); virtual void Flush(); virtual void SetCooperativeWindow(HWND theHWnd, bool isWindowed); virtual void StopAllSounds(); }; } #endif //__SDLMIXERSoundMANAGER_H__ libtuxcap-1.4.0/tuxcap/include/DDI_BltRotated_Additive.inc0000644000175000017500000000760211202747625023361 0ustar inniyahinniyah{ double aCos = cos(theRot); double aSin = sin(theRot); int aCosLong = (int) (aCos * 0x10000); int aSinLong = (int) (aSin * 0x10000); #ifdef OPTIMIZE_SOFTWARE_DRAWING int aRotCenterXLong = (int)(theRotCenterX * 0x10000); int aRotCenterYLong = (int)(theRotCenterY * 0x10000); #endif if (!LockSurface()) return; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; int aRedShift = mDDInterface->mRedShift; int aGreenShift = mDDInterface->mGreenShift; int aBlueShift = mDDInterface->mBlueShift; int aRedRightShift = 32 - mDDInterface->mRedBits; int aGreenRightShift = 24 - mDDInterface->mGreenBits; int aBlueRightShift = 16 - mDDInterface->mBlueBits; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + ((int)aDestRect.mY * mSurface->pitch/2) + (int)aDestRect.mX; int aDestPixelsPitch = mSurface->pitch/2; //TODO: if (theColor == Color::White) { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; #define DEST_PIXEL_TYPE ushort #define WRITE_PIXEL\ {\ ushort dest = *aDestPixels;\ \ int r = aMaxRedTable[((dest & aRMask)>>aRedShift) + \ ((((((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> aRedRightShift) * cr) >> 8)];\ int g = aMaxGreenTable[((dest & aGMask)>>aGreenShift) + \ (((((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) * cg) >> (aGreenRightShift + 8))];\ int b = aMaxBlueTable[((dest & aBMask)>>aBlueShift) + \ (((((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) * cb) >> (aBlueRightShift + 8))];\ \ *(aDestPixels++) = \ (r << aRedShift) | \ (g << aGreenShift) | \ (b << aBlueShift); \ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } /*else { }*/ } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + ((int)aDestRect.mY * mSurface->pitch/4) + (int)aDestRect.mX; int aDestPixelsPitch = mSurface->pitch/4; //if (theColor == Color::White) { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ uint32_t dest = *aDestPixels;\ \ int r = aMaxRedTable[((dest & aRMask)>>aRedShift) + \ ((((((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> aRedRightShift) * cr) >> 8)];\ int g = aMaxGreenTable[((dest & aGMask)>>aGreenShift) + \ (((((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) * cg) >> (aGreenRightShift + 8))];\ int b = aMaxBlueTable[((dest & aBMask)>>aBlueShift) + \ (((((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) * cb) >> (aBlueRightShift + 8))];\ \ *(aDestPixels++) = \ (r << aRedShift) | \ (g << aGreenShift) | \ (b << aBlueShift);\ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/MI_NormalBlt.inc0000644000175000017500000001410411202747625021276 0ustar inniyahinniyah{ uint32_t* aDestPixelsRow = ((uint32_t*) GetBits()) + (theY * mWidth) + theX; if ((mHasAlpha) || (mHasTrans) || (theColor != Color::White)) { if (theColor == Color::White) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; EACH_ROW; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 24; if (a != 0) { int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; int oma = 256 - a; // TODO: To avoid rounding problems for fully opaque pixels use (a+1) instead of a in the code below since we are dividing by 256 *(aDestPixels++) = (aNewDestAlpha << 24) | #ifdef OPTIMIZE_SOFTWARE_DRAWING ((((dest & 0xFF00FF) * oma >> 8) + ((src & 0xFF00FF) * a >> 8)) & 0xFF00FF) | ((((dest & 0x00FF00) * oma >> 8) + ((src & 0x00FF00) * a >> 8)) & 0x00FF00); #else ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * a) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * a) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((src & 0xFF0000) * a) >> 8) & 0xFF0000); #endif } else aDestPixels++; } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } else { int ca = theColor.mAlpha; int cr = theColor.mRed; int cg = theColor.mGreen; int cb = theColor.mBlue; #ifdef OPTIMIZE_SOFTWARE_DRAWING bool performNormalBlit = true; if (cr == cg && cg == cb) { performNormalBlit = false; for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; EACH_ROW; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = ((src >> 24) * ca) / 255; if (a != 0) { int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; int oma = 256 - a; *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0xFF00FF) * oma >> 8) + ((((src & 0xFF00FF) * cr >> 8) & 0xFF00FF) * a >> 8)) & 0xFF00FF) | ((((dest & 0x00FF00) * oma >> 8) + ((src & 0x00FF00) * cr * a >> 16)) & 0x00FF00); } else aDestPixels++; } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } if (performNormalBlit) #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; EACH_ROW; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = ((src >> 24) * ca) / 255; if (a != 0) { int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; int oma = 256 - a; *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * a * cb) >> 16) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * a * cg) >> 16) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((((src & 0xFF0000) * a) >> 8) * cr) >> 8) & 0xFF0000); } else aDestPixels++; } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } } } else { uchar* aSrcRLAlphaData = aSrcMemoryImage->GetRLAlphaData(); uchar* aRLAlphaDataRow = aSrcRLAlphaData + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; EACH_ROW; uchar* aRLAlphaData = aRLAlphaDataRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = READ_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int oma = 256 - (src >> 24); if (oma == 1) // Fully opaque { for (int i = 0; i < rl; i++) *aDestPixels++ = NEXT_SRC_COLOR; } else if (oma == 256) // Fully transparent { aDestPixels += rl; aSrcPtr += rl; } else // Partially transparent { #ifdef OPTIMIZE_SOFTWARE_DRAWING int a = 256 - oma; aSrcPtr++; uint32_t dest = *aDestPixels; *(aDestPixels++) = (0xFF000000) | ((((dest & 0xFF00FF) * oma >> 8) + ((src & 0xFF00FF) * a >> 8)) & 0xFF00FF) | ((((dest & 0x00FF00) * oma >> 8) + ((src & 0x00FF00) * a >> 8)) & 0x00FF00); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int a = (src >> 24); int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels++) = (0xFF000000) | ((((dest & 0xFF00FF) * oma >> 8) + ((src & 0xFF00FF) * a >> 8)) & 0xFF00FF) | ((((dest & 0x00FF00) * oma >> 8) + ((src & 0x00FF00) * a >> 8)) & 0x00FF00); } #else int a = 256 - oma; aSrcPtr++; uint32_t dest = *aDestPixels; *(aDestPixels++) = (0xFF000000) | ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * a) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * a) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((src & 0xFF0000) * a) >> 8) & 0xFF0000); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int a = (src >> 24); int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels++) = (0xFF000000) | ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * a) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * a) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((src & 0xFF0000) * a) >> 8) & 0xFF0000); } #endif } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } } libtuxcap-1.4.0/tuxcap/include/CursorWidget.h0000644000175000017500000000054210654432207021114 0ustar inniyahinniyah#ifndef __CURSORWIDGET_H__ #define __CURSORWIDGET_H__ #include "Widget.h" #include "Point.h" namespace Sexy { class Image; class CursorWidget : public Widget { public: Image* mImage; public: CursorWidget(); virtual void Draw(Graphics* g); void SetImage(Image* theImage); Point GetHotspot(); }; } #endif //__CURSORWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/Ratio.h0000644000175000017500000000253710641010426017546 0ustar inniyahinniyah#ifndef __RATIO_H__ #define __RATIO_H__ namespace Sexy { struct Ratio { Ratio(); Ratio(int theNumerator, int theDenominator); void Set(int theNumerator, int theDenominator); bool operator==(const Ratio& theRatio) const; bool operator!=(const Ratio& theRatio) const; bool operator<(const Ratio& theRatio) const; int operator*(int theInt) const; int operator/(int theInt) const; int mNumerator; int mDenominator; }; inline bool Ratio::operator==(const Ratio& theRatio) const { return mNumerator == theRatio.mNumerator && mDenominator == theRatio.mDenominator; } inline bool Ratio::operator!=(const Ratio& theRatio) const { return ! (*this == theRatio); } inline bool Ratio::operator<(const Ratio& theRatio) const { return (mNumerator*theRatio.mDenominator/mDenominator < theRatio.mNumerator) || (mNumerator < theRatio.mNumerator*mDenominator/theRatio.mDenominator); } inline int Ratio::operator*(int theInt) const { return theInt * mNumerator / mDenominator; } inline int Ratio::operator/(int theInt) const { return theInt * mDenominator / mNumerator; } inline int operator*(int theInt, const Ratio& theRatio) { return theInt * theRatio.mNumerator / theRatio.mDenominator; } inline int operator/(int theInt, const Ratio& theRatio) { return theInt * theRatio.mDenominator / theRatio.mNumerator; } } #endif libtuxcap-1.4.0/tuxcap/include/ScrollbarWidget.h0000644000175000017500000000444710641010426021561 0ustar inniyahinniyah// ScrollbarWidget.h: interface for the ScrollbarWidget class. // ////////////////////////////////////////////////////////////////////// #ifndef __SCROLLBARWIDGET_H__ #define __SCROLLBARWIDGET_H__ #include "Widget.h" #include "ButtonListener.h" namespace Sexy { class ScrollListener; class ScrollbuttonWidget; class ScrollbarWidget : public Widget, public ButtonListener { public: enum { UPDATE_MODE_IDLE =0, UPDATE_MODE_PGUP, UPDATE_MODE_PGDN }; public: ScrollbuttonWidget *mUpButton; ScrollbuttonWidget *mDownButton; bool mInvisIfNoScroll; public: int mId; double mValue; double mMaxValue; double mPageSize; bool mHorizontal; bool mPressedOnThumb; int mMouseDownThumbPos; int mMouseDownX; int mMouseDownY; int mUpdateMode; int mUpdateAcc; int mButtonAcc; int mLastMouseX; int mLastMouseY; ScrollListener* mScrollListener; public: ScrollbarWidget(int theId, ScrollListener *theScrollListener); virtual ~ScrollbarWidget(); virtual void SetInvisIfNoScroll(bool invisIfNoScroll); virtual void SetMaxValue(double theNewMaxValue); virtual void SetPageSize(double theNewPageSize); virtual void SetValue(double theNewValue); virtual void SetHorizontal(bool isHorizontal); virtual void ResizeScrollbar(int theX, int theY, int theWidth, int theHeight); virtual bool AtBottom(); virtual void GoToBottom(); virtual void DrawThumb(Graphics *g, int theX, int theY, int theWidth, int theHeight); virtual int GetTrackSize(); virtual int GetThumbSize(); virtual int GetThumbPosition(); virtual void Draw(Graphics *g); virtual void ClampValue(); virtual void SetThumbPosition(int thePosition); virtual void ButtonPress(int theId); virtual void ButtonDepress(int theId); virtual void ButtonDownTick(int theId); virtual void Update(); virtual int ThumbCompare(int x, int y); virtual void MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); } virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseUp(int x, int y) { Widget::MouseUp(x, y); } virtual void MouseUp(int x, int y, int theBtnNum, int theClickCount); virtual void MouseDrag(int x, int y); }; } #endif // __SCROLLBARWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/AudiereSoundInstance.h0000644000175000017500000000277610766713353022572 0ustar inniyahinniyah/* Original Audiere Sound Instance class by Rheenen 2005 */ #ifndef __AudiereSoundINSTANCE_H__ #define __AudiereSoundINSTANCE_H__ #include "SoundInstance.h" #include "audiere.h" using namespace audiere; namespace Sexy { class AudiereSoundManager; class AudiereSoundInstance : public SoundInstance { friend class AudiereSoundManager; protected: AudiereSoundManager* mAudiereSoundManagerP; OutputStreamPtr mStream; bool mAutoRelease; bool mReleased; float mBasePan; float mBaseVolume; float mBasePitch; float mPan; float mVolume; float mPitch; bool mHasPlayed; protected: void RehupVolume(); void RehupPan(); void RehupPitch(); public: AudiereSoundInstance(AudiereSoundManager* theSoundManager, SampleSourcePtr theSourceSound); virtual ~AudiereSoundInstance(); virtual void Release(); virtual void SetBaseVolume(double theBaseVolume); //0.0 to 1.0 virtual void SetBasePan(int theBasePan); //-100 to +100 virtual void AdjustBasePitch(float thePitch); //+0.5 to +2.0 relative to normal playing speed virtual void SetVolume(double theVolume); //0.0 to 1.0 virtual void SetPan(int thePosition); //-100 to +100 = left to right virtual void AdjustPitch(double thePitch); //+0.5 to +2.0 relative to normal playing speed virtual bool Play(bool looping, bool autoRelease); virtual void Stop(); virtual bool IsPlaying(); virtual bool IsReleased(); virtual double GetVolume(); }; } #endif //__AudiereSoundINSTANCE_H__ libtuxcap-1.4.0/tuxcap/include/TextWidget.h0000644000175000017500000000343510654432207020567 0ustar inniyahinniyah#ifndef __TEXTWIDGET_H__ #define __TEXTWIDGET_H__ #include "Widget.h" #include "ScrollListener.h" namespace Sexy { class ScrollbarWidget; class Font; typedef std::vector SexyStringVector; typedef std::vector IntVector; class TextWidget : public Widget, public ScrollListener { public: Font* mFont; ScrollbarWidget* mScrollbar; SexyStringVector mLogicalLines; SexyStringVector mPhysicalLines; IntVector mLineMap; double mPosition; double mPageSize; bool mStickToBottom; int mHiliteArea[2][2]; int mMaxLines; public: TextWidget(); virtual SexyStringVector GetLines(); virtual void SetLines(SexyStringVector theNewLines); virtual void Clear(); virtual void DrawColorString(Graphics* g, const SexyString& theString, int x, int y, bool useColors); virtual void DrawColorStringHilited(Graphics* g, const SexyString& theString, int x, int y, int theStartPos, int theEndPos); virtual int GetStringIndex(const SexyString& theString, int thePixel); virtual int GetColorStringWidth(const SexyString& theString); virtual void Resize(int theX, int theY, int theWidth, int theHeight); virtual Color GetLastColor(const SexyString& theString); virtual void AddToPhysicalLines(int theIdx, const SexyString& theLine); virtual void AddLine(const SexyString& theString); virtual bool SelectionReversed(); virtual void GetSelectedIndices(int theLineIdx, int* theIndices); virtual void Draw(Graphics* g); virtual void ScrollPosition(int theId, double thePosition); virtual void GetTextIndexAt(int x, int y, int* thePosArray); virtual SexyString GetSelection(); virtual void MouseDown(int x, int y, int theClickCount); virtual void MouseDrag(int x, int y); virtual void KeyDown(KeyCode theKey); }; } #endif //__TEXTWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/DDI_FastStretch.inc0000644000175000017500000001343211202747625021734 0ustar inniyahinniyah{ if (!LockSurface()) return; int aFPSrcY = (int)(theSrcRect.mY * 0x10000); int anAddX = (int)((theSrcRect.mWidth * 0x10000) / theDestRect.mWidth); int anAddY = (int)((theSrcRect.mHeight * 0x10000) / theDestRect.mHeight); if (theColor == Color::White) { if (mSurface->format->BitsPerPixel == 16) { //FIXME replace with Uint32 and Uint16 ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/2) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)(theSrcRect.mX * 0x10000); ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++, aFPSrcX += anAddX) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; int a = src >> 24; if (a != 0) { int oma = 256 - a; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma)) >> 8) & aRMask) + (((((dest & aGMask) * oma)) >> 8) & aGMask) + (((((dest & aBMask) * oma)) >> 8) & aBMask); } else aDestPixels _PLUSPLUS; } aDestPixelsRow += mSurface->pitch/2; aFPSrcY += anAddY; } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/4) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)(theSrcRect.mX * 0x10000); uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++, aFPSrcX += anAddX) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; int a = src >> 24; if (a != 0) { int oma = 256 - a; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma)) >> 8) & aRMask) + (((((dest & aGMask) * oma)) >> 8) & aGMask) + (((((dest & aBMask) * oma)) >> 8) & aBMask); } else aDestPixels _PLUSPLUS; } aDestPixelsRow += mSurface->pitch/4; aFPSrcY += anAddY; } } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/2) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)(theSrcRect.mX * 0x10000); ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++, aFPSrcX += anAddX) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; int a = ((src >> 24) * ca) / 255; if (a != 0) { int oma = 256 - a; *(aDestPixels _PLUSPLUS) = (((((dest & aRMask) * oma) + ((src & aRMask) * cr)) >> 8) & aRMask) + (((((dest & aGMask) * oma) + ((src & aGMask) * cg)) >> 8) & aGMask) + (((((dest & aBMask) * oma) + ((src & aBMask) * cb)) >> 8) & aBMask); } else aDestPixels _PLUSPLUS; } aDestPixelsRow += mSurface->pitch/2; aFPSrcY += anAddY; } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/4) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)(theSrcRect.mX * 0x10000); uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++, aFPSrcX += anAddX) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; int a = ((src >> 24) * ca) / 255; int oma = 256 - a; if (a != 0) { int oma = 256 - a; *(aDestPixels _PLUSPLUS) = (((((dest & aRMask) * oma) + ((src & aRMask) * cr)) >> 8) & aRMask) + (((((dest & aGMask) * oma) + ((src & aGMask) * cg)) >> 8) & aGMask) + (((((dest & aBMask) * oma) + ((src & aBMask) * cb)) >> 8) & aBMask); } else aDestPixels _PLUSPLUS; } aDestPixelsRow += mSurface->pitch/4; aFPSrcY += anAddY; } } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/SoundManager.h0000644000175000017500000000231610641010432021043 0ustar inniyahinniyah#ifndef __SOUNDMANAGER_H__ #define __SOUNDMANAGER_H__ #include "Common.h" #ifndef WIN32 #define HWND void* #endif namespace Sexy { class SoundInstance; #define MAX_SOURCE_SOUNDS 256 #define MAX_CHANNELS 32 class SoundManager { public: SoundManager() {} virtual ~SoundManager() {} virtual bool Initialized() = 0; virtual bool LoadSound(unsigned int theSfxID, const std::string& theFilename) = 0; virtual int LoadSound(const std::string& theFilename) = 0; virtual void ReleaseSound(unsigned int theSfxID) = 0; virtual void SetVolume(double theVolume) = 0; virtual bool SetBaseVolume(unsigned int theSfxID, double theBaseVolume) = 0; virtual bool SetBasePan(unsigned int theSfxID, int theBasePan) = 0; virtual SoundInstance* GetSoundInstance(unsigned int theSfxID) = 0; virtual void ReleaseSounds() = 0; virtual void ReleaseChannels() = 0; virtual double GetMasterVolume() = 0; virtual void SetMasterVolume(double theVolume) = 0; virtual void Flush() = 0; virtual void SetCooperativeWindow(HWND theHWnd, bool isWindowed) = 0; virtual void StopAllSounds() = 0; virtual int GetFreeSoundId() = 0; virtual int GetNumSounds() = 0; }; } #endif //__SOUNDMANAGER_H__ libtuxcap-1.4.0/tuxcap/include/Common.h0000644000175000017500000001745711202747625017743 0ustar inniyahinniyah#ifndef __SEXYAPPFRAMEWORK_COMMON_H__ #define __SEXYAPPFRAMEWORK_COMMON_H__ #include #include #include #include #include #include #include #include #include #include "SDL.h" #include "SDL_keysym.h" #if SDL_BYTEORDER == SDL_LIL_ENDIAN const Uint32 SDL_rmask = 0x000000FF; const Uint32 SDL_gmask = 0x0000FF00; const Uint32 SDL_bmask = 0x00FF0000; const Uint32 SDL_amask = 0xFF000000; #else const Uint32 SDL_rmask = 0xFF000000; const Uint32 SDL_gmask = 0x00FF0000; const Uint32 SDL_bmask = 0x0000FF00; const Uint32 SDL_amask = 0x000000FF; #endif //FIXME map popcap keycodes to sdl #define KeyCode SDLKey //#define USE_AUDIERE #ifdef _USE_WIDE_STRING #define sexystricmp wcscasecmp typedef std::wstring SexyString; #define _S(x) L ##x #if 0 #include "ModVal.h" #define sexystrncmp wcsncmp #define sexystrcmp wcscmp #define sexysscanf swscanf #define sexyatoi _wtoi #define sexystrcpy wcscpy #define SexyStringToStringFast(x) WStringToString(x) #define SexyStringToWStringFast(x) (x) #define StringToSexyStringFast(x) StringToWString(x) #define WStringToSexyStringFast(x) (x) #ifndef SEXYFRAMEWORK_NO_REDEFINE_WIN_API // Redefine the functions and structs we need to be wide-string #undef CreateWindowEx #undef RegisterClass #undef MessageBox #undef ShellExecute #undef GetTextExtentPoint32 #undef RegisterWindowMessage #undef CreateMutex #undef DrawTextEx #undef TextOut #define CreateWindowEx CreateWindowExW #define RegisterClass RegisterClassW #define WNDCLASS WNDCLASSW #define MessageBox MessageBoxW #define ShellExecute ShellExecuteW #define GetTextExtentPoint32 GetTextExtentPoint32W #define RegisterWindowMessage RegisterWindowMessageW #define CreateMutex CreateMutexW #define DrawTextEx DrawTextExW #define TextOut TextOutW #endif #endif #else typedef std::string SexyString; #define _S(x) x #define sexystrncmp strncmp #define sexystrcmp strcmp #define sexystricmp strcasecmp #define sexysscanf sscanf #define sexyatoi atoi #define sexystrcpy strcpy #define SexyStringToStringFast(x) (x) #define SexyStringToWStringFast(x) StringToWString(x) #define StringToSexyStringFast(x) (x) #define WStringToSexyStringFast(x) WStringToString(x) #endif #define LONG_BIGE_TO_NATIVE(l) (((l >> 24) & 0xFF) | ((l >> 8) & 0xFF00) | ((l << 8) & 0xFF0000) | ((l << 24) & 0xFF000000)) #define WORD_BIGE_TO_NATIVE(w) (((w >> 8) & 0xFF) | ((w << 8) & 0xFF00)) #define LONG_LITTLEE_TO_NATIVE(l) (l) #define WORD_LITTLEE_TO_NATIVE(w) (w) #define LENGTH(anyarray) (sizeof(anyarray) / sizeof(anyarray[0])) typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; //typedef unsigned long ulong; //typedef long long int64; typedef std::map DefinesMap; typedef std::map WStringWStringMap; typedef SexyString::value_type SexyChar; #define HAS_SEXYCHAR namespace Sexy { const uint32_t SEXY_RAND_MAX = 0x7FFFFFFF; extern bool gDebug; int Rand(); int Rand(int range); float Rand(float range); void SRand(uint32_t theSeed); extern std::string vformat(const char* fmt, va_list argPtr); extern std::string StrFormat(const char* fmt ...); std::string GetAppDataFolder(); void SetAppDataFolder(const std::string& thePath); std::string GetAppResourceFolder(); void SetAppResourceFolder(const std::string& thePath); std::vector GetFilesInDir(const std::string& theDir); std::string GetPathFrom(const std::string& theRelPath, const std::string& theDir); std::string GetFileDir(const std::string& thePath, bool withSlash = false); std::string GetFileName(const std::string& thePath, bool noExtension = false); std::string RemoveTrailingSlash(const std::string& theDirectory); std::string BuildIniName(std::string copy, const std::string& theSubstitute); std::string ReplaceBackSlashes(std::string copy); void MkDir(const std::string& theDir); bool AllowAllAccess(const std::string& theFileName); bool FileExists(const std::string& theFileName); bool CreateFile(const std::string& theFileName); std::string GetFullPath(const std::string& theRelPath); std::string GetCurDir(); #if 0 bool Deltree(const std::string& thePath); std::string AddTrailingSlash(const std::string& theDirectory, bool backSlash = false); time_t GetFileDate(const std::string& theFileName); std::string Trim(const std::string& theString); std::wstring Trim(const std::wstring& theString); extern std::wstring StrFormat(const wchar_t* fmt ...); extern std::wstring vformat(const wchar_t* fmt, va_list argPtr); #endif std::string Upper(const std::string& theData); std::wstring Upper(const std::wstring& theData); std::string Lower(const std::string& theData); std::wstring Lower(const std::wstring& theData); std::string StringToUpper(const std::string& theString); std::wstring StringToUpper(const std::wstring& theString); std::string URLEncode(const std::string& theString); std::string StringToLower(const std::string& theString); std::wstring StringToLower(const std::wstring& theString); std::wstring StringToWString(const std::string &theString); std::string WStringToString(const std::wstring &theString); SexyString StringToSexyString(const std::string& theString); SexyString WStringToSexyString(const std::wstring& theString); std::string SexyStringToString(const SexyString& theString); std::wstring SexyStringToWString(const SexyString& theString); bool StringToInt(const std::string theString, int* theIntVal); bool StringToDouble(const std::string theString, double* theDoubleVal); bool StringToInt(const std::wstring theString, int* theIntVal); bool StringToDouble(const std::wstring theString, double* theDoubleVal); int StrFindNoCase(const char *theStr, const char *theFind); bool StrPrefixNoCase(const char *theStr, const char *thePrefix, int maxLength = 10000000); SexyString CommaSeperate(int theValue); std::string Evaluate(const std::string& theString, const DefinesMap& theDefinesMap); std::string XMLDecodeString(const std::string& theString); std::string XMLEncodeString(const std::string& theString); std::wstring XMLDecodeString(const std::wstring& theString); std::wstring XMLEncodeString(const std::wstring& theString); inline void inlineUpper(std::string &theData) { //std::transform(theData.begin(), theData.end(), theData.begin(), toupper); int aStrLen = (int) theData.length(); for (int i = 0; i < aStrLen; i++) { theData[i] = toupper(theData[i]); } } #if 0 inline void inlineUpper(std::wstring &theData) { //std::transform(theData.begin(), theData.end(), theData.begin(), toupper); int aStrLen = (int) theData.length(); for (int i = 0; i < aStrLen; i++) { theData[i] = towupper(theData[i]); } } #endif inline void inlineLower(std::string &theData) { std::transform(theData.begin(), theData.end(), theData.begin(), tolower); } inline void inlineLower(std::wstring &theData) { std::transform(theData.begin(), theData.end(), theData.begin(), tolower); } inline void inlineLTrim(std::string &theData, const std::string& theChars = " \t\r\n") { theData.erase(0, theData.find_first_not_of(theChars)); } inline void inlineLTrim(std::wstring &theData, const std::wstring& theChars = L" \t\r\n") { theData.erase(0, theData.find_first_not_of(theChars)); } inline void inlineRTrim(std::string &theData, const std::string& theChars = " \t\r\n") { theData.resize(theData.find_last_not_of(theChars) + 1); } inline void inlineTrim(std::string &theData, const std::string& theChars = " \t\r\n") { inlineRTrim(theData, theChars); inlineLTrim(theData, theChars); } struct StringLessNoCase { bool operator()(const std::string &s1, const std::string &s2) const { return strcasecmp(s1.c_str(),s2.c_str())<0; } }; } #endif //__SEXYAPPFRAMEWORK_COMMON_H__ libtuxcap-1.4.0/tuxcap/include/PropertiesParser.h0000644000175000017500000000153410645717035022013 0ustar inniyahinniyah#ifndef __SEXYAPPFRAMEWORK_NO_PROPERTIES_PARSER__ #ifndef __PROPERTIESPARSER_H__ #define __PROPERTIESPARSER_H__ #include "SexyAppBase.h" namespace Sexy { class XMLParser; class PropertiesParser { public: SexyAppBase* mApp; XMLParser* mXMLParser; SexyString mError; bool mHasFailed; protected: void Fail(const SexyString& theErrorText); bool ParseSingleElement(SexyString* theString); bool ParseStringArray(StringVector* theStringVector); bool ParseProperties(); bool DoParseProperties(); public: PropertiesParser(SexyAppBase* theApp); virtual ~PropertiesParser(); bool ParsePropertiesFile(const std::string& theFilename); bool ParsePropertiesBuffer(const Buffer& theBuffer); SexyString GetErrorText(); }; } #endif //__PROPERTIESPARSER_H__ #endif // __SEXYAPPFRAMEWORK_NO_PROPERTIES_PARSER__ libtuxcap-1.4.0/tuxcap/include/MusicInterface.h0000644000175000017500000000237210641010426021366 0ustar inniyahinniyah#ifndef __MUSICINTERFACE_H__ #define __MUSICINTERFACE_H__ #include "Common.h" namespace Sexy { class MusicInterface { public: public: MusicInterface(); virtual ~MusicInterface(); virtual bool LoadMusic(int theSongId, const std::string& theFileName); virtual void PlayMusic(int theSongId, int theOffset = 0, bool noLoop = false); virtual void StopMusic(int theSongId); virtual void PauseMusic(int theSongId); virtual void ResumeMusic(int theSongId); virtual void StopAllMusic(); virtual void UnloadMusic(int theSongId); virtual void UnloadAllMusic(); virtual void PauseAllMusic(); virtual void ResumeAllMusic(); virtual void FadeIn(int theSongId, int theOffset = -1, double theSpeed = 0.002, bool noLoop = false); virtual void FadeOut(int theSongId, bool stopSong = true, double theSpeed = 0.004); virtual void FadeOutAll(bool stopSong = true, double theSpeed = 0.004); virtual void SetSongVolume(int theSongId, double theVolume); virtual void SetSongMaxVolume(int theSongId, double theMaxVolume); virtual bool IsPlaying(int theSongId); virtual void SetVolume(double theVolume); virtual void SetMusicAmplify(int theSongId, double theAmp); virtual void Update(); }; } #endif //__MUSICINTERFACE_H__ libtuxcap-1.4.0/tuxcap/include/Graphics.h0000644000175000017500000001654410641010426020233 0ustar inniyahinniyah#ifndef __GRAPHICS_H__ #define __GRAPHICS_H__ #include "Common.h" #include "Rect.h" #include "Color.h" #include "Image.h" #include "TriVertex.h" namespace Sexy { class Font; class SexyMatrix3; class Transform; const int MAX_TEMP_SPANS = 8192; struct Edge { double mX; double mDX; int i; double b; }; class Graphics; class GraphicsState { public: static Image mStaticImage; Image* mDestImage; float mTransX; float mTransY; float mScaleX; float mScaleY; float mScaleOrigX; float mScaleOrigY; Rect mClipRect; Color mColor; Font* mFont; int mDrawMode; bool mColorizeImages; bool mFastStretch; bool mWriteColoredString; bool mLinearBlend; bool mIs3D; public: void CopyStateFrom(const GraphicsState* theState); }; typedef std::list GraphicsStateList; class Graphics : public GraphicsState { public: enum { DRAWMODE_NORMAL, DRAWMODE_ADDITIVE }; Edge* mPFActiveEdgeList; int mPFNumActiveEdges; static const Point* mPFPoints; int mPFNumVertices; GraphicsStateList mStateStack; protected: static int PFCompareInd(const void* u, const void* v); static int PFCompareActive(const void* u, const void* v); void PFDelete(int i); void PFInsert(int i, int y); void DrawImageTransformHelper(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x, float y, bool useFloat); public: Graphics(const Graphics& theGraphics); Graphics(Image* theDestImage = NULL); virtual ~Graphics(); void PushState(); void PopState(); Graphics* Create(); void SetFont(Font* theFont); Font* GetFont(); void SetColor(const Color& theColor); const Color& GetColor(); void SetDrawMode(int theDrawMode); int GetDrawMode(); void SetColorizeImages(bool colorizeImages); bool GetColorizeImages(); void SetFastStretch(bool fastStretch); bool GetFastStretch(); void SetLinearBlend(bool linear); // for DrawImageMatrix, DrawImageTransform, etc... bool GetLinearBlend(); void FillRect(int theX, int theY, int theWidth, int theHeight); void FillRect(const Rect& theRect); void DrawRect(int theX, int theY, int theWidth, int theHeight); void DrawRect(const Rect& theRect); void ClearRect(int theX, int theY, int theWidth, int theHeight); void ClearRect(const Rect& theRect); void DrawString(const SexyString& theString, int theX, int theY); private: bool DrawLineClipHelper(double* theStartX, double* theStartY, double *theEndX, double* theEndY); public: void DrawLine(int theStartX, int theStartY, int theEndX, int theEndY); void DrawLineAA(int theStartX, int theStartY, int theEndX, int theEndY); void PolyFill(const Point *theVertexList, int theNumVertices, bool convex = false); void PolyFillAA(const Point *theVertexList, int theNumVertices, bool convex = false); void DrawImage(Image* theImage, int theX, int theY); void DrawImage(Image* theImage, int theX, int theY, const Rect& theSrcRect); void DrawImage(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect); void DrawImage(Image* theImage, int theX, int theY, int theStretchedWidth, int theStretchedHeight); void DrawImageF(Image* theImage, float theX, float theY); void DrawImageF(Image* theImage, float theX, float theY, const Rect& theSrcRect); void DrawImageMirror(Image* theImage, int theX, int theY, bool mirror = true); void DrawImageMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, bool mirror = true); void DrawImageMirror(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, bool mirror = true); void DrawImageRotated(Image* theImage, int theX, int theY, double theRot, const Rect *theSrcRect = NULL); void DrawImageRotated(Image* theImage, int theX, int theY, double theRot, int theRotCenterX, int theRotCenterY, const Rect *theSrcRect = NULL); void DrawImageRotatedF(Image* theImage, float theX, float theY, double theRot, const Rect *theSrcRect = NULL); void DrawImageRotatedF(Image* theImage, float theX, float theY, double theRot, float theRotCenterX, float theRotCenterY, const Rect *theSrcRect = NULL); void DrawImageMatrix(Image* theImage, const SexyMatrix3 &theMatrix, float x = 0, float y = 0); void DrawImageMatrix(Image* theImage, const SexyMatrix3 &theMatrix, const Rect &theSrcRect, float x = 0, float y = 0); void DrawImageTransform(Image* theImage, const Transform &theTransform, float x = 0, float y = 0); void DrawImageTransform(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x = 0, float y = 0); void DrawImageTransformF(Image* theImage, const Transform &theTransform, float x = 0, float y = 0); void DrawImageTransformF(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x = 0, float y = 0); void DrawTriangleTex(Image *theTexture, const TriVertex &v1, const TriVertex &v2, const TriVertex &v3); void DrawTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles); void DrawImageCel(Image* theImageStrip, int theX, int theY, int theCel); void DrawImageCel(Image* theImageStrip, const Rect& theDestRect, int theCel); void DrawImageCel(Image* theImageStrip, int theX, int theY, int theCelCol, int theCelRow); void DrawImageCel(Image* theImageStrip, const Rect& theDestRect, int theCelCol, int theCelRow); void DrawImageAnim(Image* theImageAnim, int theX, int theY, int theTime); void ClearClipRect(); void SetClipRect(int theX, int theY, int theWidth, int theHeight); void SetClipRect(const Rect& theRect); void ClipRect(int theX, int theY, int theWidth, int theHeight); void ClipRect(const Rect& theRect); void Translate(int theTransX, int theTransY); void TranslateF(float theTransX, float theTransY); // In progress: Only affects DrawImage void SetScale(float theScaleX, float theScaleY, float theOrigX, float theOrigY); int StringWidth(const SexyString& theString); void DrawImageBox(const Rect& theDest, Image* theComponentImage); void DrawImageBox(const Rect& theSrc, const Rect& theDest, Image* theComponentImage); int WriteString(const SexyString& theString, int theX, int theY, int theWidth = -1, int theJustification = 0, bool drawString = true, int theOffset = 0, int theLength = -1, int theOldColor = -1); int WriteWordWrapped(const Rect& theRect, const SexyString& theLine, int theLineSpacing = -1, int theJustification = -1, int *theMaxWidth = NULL, int theMaxChars = -1, int* theLastWidth = NULL); int DrawStringColor(const SexyString& theString, int theX, int theY, int theOldColor = -1); //works like DrawString but can have color tags like ^ff0000^. int DrawStringWordWrapped(const SexyString& theLine, int theX, int theY, int theWrapWidth = 10000000, int theLineSpacing = -1, int theJustification = -1, int *theMaxWidth = NULL); //works like DrawString but also word wraps int GetWordWrappedHeight(int theWidth, const SexyString& theLine, int theLineSpacing = -1, int *theMaxWidth = NULL); bool Is3D() { return mIs3D; } }; class GraphicsAutoState { public: Graphics* mG; public: GraphicsAutoState(Graphics* theG) : mG(theG) { mG->PushState(); } ~GraphicsAutoState() { mG->PopState(); } }; } #endif //__GRAPHICS_H__ libtuxcap-1.4.0/tuxcap/include/MI_AdditiveBlt.inc0000644000175000017500000000634411202747625021606 0ustar inniyahinniyah{ uint32_t* aDestPixelsRow = ((uint32_t*) GetBits()) + (theY * mWidth) + theX; SRC_TYPE* aSrcPixelsRow = aSrcBits + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; if (theColor == Color::White) { if (aSrcMemoryImage->mHasAlpha) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPtr = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = (src&0xFF000000)>>24; int r = aMaxTable[((dest & 0xFF0000) + (((src & 0xFF0000)*a)>>8)) >> 16]; int g = aMaxTable[((dest & 0x00FF00) + (((src & 0x00FF00)*a)>>8)) >> 8 ]; int b = aMaxTable[((dest & 0x0000FF) + (((src & 0x0000FF)*a)>>8)) ]; *(aDestPixels++) = (dest & 0xFF000000) | (r << 16) | (g << 8) | (b); } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } else { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPtr = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxTable[((dest & 0xFF0000) + (src & 0xFF0000)) >> 16]; int g = aMaxTable[((dest & 0x00FF00) + (src & 0x00FF00)) >> 8 ]; int b = aMaxTable[((dest & 0x0000FF) + (src & 0x0000FF)) ]; *(aDestPixels++) = (dest & 0xFF000000) | (r << 16) | (g << 8) | (b); } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; if (aSrcMemoryImage->mHasAlpha) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPtr = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = (src&0xFF000000)>>24; int r = aMaxTable[((dest & 0xFF0000) + (((((src & 0xFF0000) * cr) >> 8)*a)>>8)) >> 16]; int g = aMaxTable[((dest & 0x00FF00) + (((((src & 0x00FF00) * cg) >> 8)*a)>>8)) >> 8]; int b = aMaxTable[((dest & 0x0000FF) + (((((src & 0x0000FF) * cb) >> 8)*a)>>8)) ]; *(aDestPixels++) = (dest & 0xFF000000) | (r << 16) | (g << 8) | (b); } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } else { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPtr = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int r = aMaxTable[((dest & 0xFF0000) + (((src & 0xFF0000) * cr) >> 8)) >> 16]; int g = aMaxTable[((dest & 0x00FF00) + (((src & 0x00FF00) * cg) >> 8)) >> 8]; int b = aMaxTable[((dest & 0x0000FF) + (((src & 0x0000FF) * cb) >> 8)) ]; *(aDestPixels++) = (dest & 0xFF000000) | (r << 16) | (g << 8) | (b); } aDestPixelsRow += mWidth; aSrcPixelsRow += theImage->mWidth; } } } } libtuxcap-1.4.0/tuxcap/include/XMLWriter.h0000644000175000017500000000401610654427540020334 0ustar inniyahinniyah// XMLWriter.h: interface for the XMLWriter class by James Poag // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_XMLWRITER_H__3DB6D22D_A120_4738_B622_06E90FAED4E4__INCLUDED_) #define AFX_XMLWRITER_H__3DB6D22D_A120_4738_B622_06E90FAED4E4__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #pragma warning(disable:4786) #pragma warning(disable:4503) #include #include "XMLParser.h" #if 0 #include "../SexyAppFramework/PerfTimer.h" #endif namespace Sexy { class XMLWriter { protected: std::string mFileName; std::string mErrorText; int mLineNum; FILE* mFile; bool mHasFailed; bool mAllowComments; bool mOpenAttributes; std::stack mSectionStack; std::stack mWarningStack; protected: bool CheckFileOpen(); bool ValidateElementNodeName(const std::string& theNodeName); void Fail(const std::string& theErrorText); void Warn(const std::string& theWarning); void Init(); public: XMLWriter(); virtual ~XMLWriter(); static bool AddAttribute(XMLElement* theElement, const std::string& aAttributeKey, const std::string& aAttributeValue); bool WriteAttribute(const std::string& aAttributeKey, const std::string& aAttributeValue); bool WriteAttribute(const std::string& aAttributeKey, const float& aAttributeValue); bool WriteAttribute(const std::string& aAttributeKey, const int& aAttributeValue); void Comment(const std::string& theComment); bool StartElement(const std::string &theElementName); bool StartElement(XMLElement *theElement); bool StopElement(); bool OpenFile(const std::string& theFilename); bool CloseFile(); std::string GetErrorText(); int GetCurrentLineNum(); std::string GetFileName(); inline void AllowComments(bool doAllow) { mAllowComments = doAllow; } bool HasFailed(); }; }; #endif // !defined(AFX_XMLWRITER_H__3DB6D22D_A120_4738_B622_06E90FAED4E4__INCLUDED_) libtuxcap-1.4.0/tuxcap/include/DDI_FastStretch_Additive.inc0000644000175000017500000001467611202747625023560 0ustar inniyahinniyah{ if (!LockSurface()) return; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; int aRedShift = mSurface->format->Rshift; int aGreenShift = mSurface->format->Gshift; int aBlueShift = mSurface->format->Bshift; int aFPSrcY = (int)theSrcRect.mY * 0x10000; int anAddX = ((int)theSrcRect.mWidth * 0x10000) / theDestRect.mWidth; int anAddY = ((int)theSrcRect.mHeight * 0x10000) / theDestRect.mHeight; if (theColor == Color::White) { if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/2) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)theSrcRect.mX * 0x10000; ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; if (src != 0) { int r = aMaxRedTable[((dest & aRMask) + (src & aRMask)) >> aRedShift]; int g = aMaxGreenTable[((dest & aGMask) + (src & aGMask)) >> aGreenShift]; int b = aMaxBlueTable[((dest & aBMask) + (src & aBMask)) >> aBlueShift]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } else aDestPixels _PLUSPLUS; aFPSrcX += anAddX; } aDestPixelsRow += mSurface->pitch/2; aFPSrcY += anAddY; } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/4) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)theSrcRect.mX * 0x10000; uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; if (src != 0) { int r = aMaxRedTable[((dest & aRMask) + (src & aRMask)) >> aRedShift]; int g = aMaxGreenTable[((dest & aGMask) + (src & aGMask)) >> aGreenShift]; int b = aMaxBlueTable[((dest & aBMask) + (src & aBMask)) >> aBlueShift]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } else aDestPixels _PLUSPLUS; aFPSrcX += anAddX; } aDestPixelsRow += mSurface->pitch/4; aFPSrcY += anAddY; } } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/2) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)theSrcRect.mX * 0x10000; ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; if (src != 0) { int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + ((((src & aRMask) >> aRedShift) * cr) >> 8)]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + ((((src & aGMask) >> aGreenShift) * cg) >> 8)]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + ((((src & aBMask) >> aBlueShift) * cb) >> 8)]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } else aDestPixels _PLUSPLUS; aFPSrcX += anAddX; } aDestPixelsRow += mSurface->pitch/2; aFPSrcY += anAddY; } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theDestRect.mY * mSurface->pitch/4) + theDestRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; for (int y = 0; y < theDestRect.mHeight; y++) { int aFPSrcX = (int)theSrcRect.mX * 0x10000; uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixelsRow = aSrcBits + (aSrcMemoryImage->mWidth * (aFPSrcY >> 16)); for (int x = 0; x < theDestRect.mWidth; x++) { SRC_TYPE* aSrcPixels = aSrcPixelsRow + (aFPSrcX >> 16); uint32_t src = READ_COLOR(aSrcPixels); uint32_t dest = *aDestPixels; if (src != 0) { int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + ((((src & aRMask) >> aRedShift) * cr) >> 8)]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + ((((src & aGMask) >> aGreenShift) * cg) >> 8)]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + ((((src & aBMask) >> aBlueShift) * cb) >> 8)]; *(aDestPixels _PLUSPLUS) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } else aDestPixels _PLUSPLUS; aFPSrcX += anAddX; } aDestPixelsRow += mSurface->pitch/4; aFPSrcY += anAddY; } } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/Buffer.h0000644000175000017500000000334011202747625017706 0ustar inniyahinniyah#ifndef __BUFFER_H__ #define __BUFFER_H__ #include #include "Common.h" namespace Sexy { typedef std::vector ByteVector; class Buffer { public: ByteVector mData; int mDataBitSize; mutable int mReadBitPos; mutable int mWriteBitPos; public: Buffer(); virtual ~Buffer(); void SeekFront() const; void Clear(); void FromWebString(const std::string& theString); void WriteByte(uchar theByte); void WriteNumBits(int theNum, int theBits); static int GetBitsRequired(int theNum, bool isSigned); void WriteBoolean(bool theBool); void WriteShort(short theShort); void WriteLong(int32_t theLong); void WriteString(const std::string& theString); void WriteUTF8String(const std::wstring& theString); void WriteLine(const std::string& theString); void WriteBuffer(const ByteVector& theBuffer); void WriteBytes(const uchar* theByte, int theCount); void SetData(const ByteVector& theBuffer); void SetData(uchar* thePtr, int theCount); std::string ToWebString() const; std::wstring UTF8ToWideString() const; uchar ReadByte() const; int ReadNumBits(int theBits, bool isSigned) const; bool ReadBoolean() const; short ReadShort() const; int32_t ReadLong() const; std::string ReadString() const; std::wstring ReadUTF8String() const; std::string ReadLine() const; void ReadBytes(uchar* theData, int theLen) const; void ReadBuffer(ByteVector* theByteVector) const; const uchar* GetDataPtr() const; int GetDataLen() const; int GetDataLenBits() const; uint32_t GetCRC32(uint32_t theSeed = 0) const; bool AtEnd() const; bool PastEnd() const; }; } #endif //__BUFFER_H__ libtuxcap-1.4.0/tuxcap/include/Insets.h0000644000175000017500000000046010641010426017726 0ustar inniyahinniyah#ifndef __INSETS_H__ #define __INSETS_H__ namespace Sexy { class Insets { public: int mLeft; int mTop; int mRight; int mBottom; public: Insets(); Insets(int theLeft, int theTop, int theRight, int theBottom); Insets(const Insets& theInsets); }; } #endif //__INSETS_H__ libtuxcap-1.4.0/tuxcap/include/NaturalCubicSpline.h0000644000175000017500000001043210662644453022230 0ustar inniyahinniyah/////////////////////////////////////////////////////////////// // // Written By: James Poag // // http://sexyfaq.jamespoag.com // /////////////////////////////////////////////////////////////// // // Cubic Class, RegenerateSpline, and RegenrateClosedSpline // written by Tim Lambert. // // http://www.cse.unsw.edu.au/~lambert/ // // Thanks to Brian "Ace" Rothstein For pointing me to Tim. // // Special Thanks to Paul Hamilton. // http://www.mooktowngames.com // http://mooktown.blogspot.com // /////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // Usage ////////////////////////////////////////////////////////////// // // Use AddPoint() to create a Spline. 3 or more points are // required to create a cubic spline. // // Think of the spline as a long straight line. Addressing // a Point on the line with a single distance variable. The // Spline will return 2D coordinates for the position passed // into 'GetPointAt'. 'GetTangentAt' reports the direction // of travel. Use 'atan2' to turn the tangent into a rotation. // // The rest of the functions are used in creating and refining // the Spline in an editor // ////////////////////////////////////////////////////////////// #include #include "Point.h" namespace Sexy { class Graphics; class XMLWriter; class XMLElement; class XMLParser; }; class Cubic { float a,b,c,d; /* a + b*u + c*u^2 +d*u^3 */ public: Cubic(float a, float b, float c, float d){ this->a = a; this->b = b; this->c = c; this->d = d; } ~Cubic(){}; /** evaluate cubic */ public: float eval(float u) { return (((d*u) + c)*u + b)*u + a; } float tangent(float u){ return ((3*d*u) + 2*c)*u + b; } }; class NaturalCubicSpline { protected: std::vector mYCubics; std::vector mXCubics; std::vector mXCoords; std::vector mYCoords; std::vector mPoints; std::vector mSpline; std::vector mSplineSegmentLengths; virtual void RegenerateSpline(std::vector& theInput, std::vector& theOutput); virtual void RegenerateClosedSpline(std::vector& theInput, std::vector& theOutput); virtual float GetMinUFromLineAB(Sexy::FPoint A, Sexy::FPoint B, Sexy::Point C); virtual float GetMinDistanceFromLineAB(Sexy::FPoint A, Sexy::FPoint B, Sexy::Point C); float mArcLength; unsigned int mGranularity; bool mClosed; public: NaturalCubicSpline(void); virtual ~NaturalCubicSpline(void); // Drawing Functions virtual void Draw(Sexy::Graphics* g); //Example on how to draw virtual void DrawControlPoint(Sexy::Graphics* g, int theControlPointId, int theWidth); virtual void DrawSplineSegment(Sexy::Graphics* g, int theSplineSegmentId); // The main functions virtual void AddPoint(Sexy::Point thePoint); virtual void RegenerateSplines(); // You Shouldn't have to call this. virtual Sexy::Point GetPointAt(float theDistanceOnTheSpline); virtual Sexy::FPoint GetTangentAt(float theLength); // ADT functions virtual int GetNumControlPoints(){return (int)mPoints.size();}; virtual int GetNumSplineSegments(){return (int)mXCubics.size();}; virtual float GetArcLength(){return mArcLength;}; virtual void SetClosed(bool bClosed){mClosed = bClosed; RegenerateSplines();}; virtual bool isClosed(){return mClosed;}; virtual int GetGranularity(){return mGranularity;}; virtual void SetGranularity(int theGranularity){mGranularity = theGranularity; RegenerateSplines();}; // For Curve Refinement virtual void BisectSegment(int theSplineSegmentId); virtual void DeleteControlPoint(int theControlPointId); virtual void ClearAllPoints(); // Picking Helper Functions virtual float GetClosestPointOnSegmentToPoint(Sexy::Point thePoint); virtual int GetControlPointIdNear(Sexy::Point thePoint); virtual int GetSegmentIdNear(Sexy::Point thePoint); virtual Sexy::Point GetControlPoint(int theControlPointId); virtual void SetControlPoint(int theControlPointId, Sexy::Point thePoint); //Serialization virtual void Serialize(Sexy::XMLWriter* theWriter); virtual void Serialize(Sexy::XMLParser* theParser, Sexy::XMLElement* theNode); virtual void SaveToFile(std::string theFileName); virtual void OpenFile(std::string theFileName); }; libtuxcap-1.4.0/tuxcap/include/DDI_NormalBlt_Volatile.inc0000644000175000017500000001213211202747625023227 0ustar inniyahinniyah{ if (mNoLock) return; // Special path that avoids generating cached native alpha data if (!LockSurface()) return; if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theY * mSurface->pitch/2) + theX; SRC_TYPE* aSrcPixelsRow = aSrcBits + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; #ifdef OPTIMIZE_SOFTWARE_DRAWING bool performNormalBlit = true; if (gOptimizeSoftwareDrawing) // we know the ordering of the bit masks. { if (aGMask == 0x7E0) { performNormalBlit = false; for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 27; src = ((src & 0xFC00) << 11) + ((src >> 8) & 0xF800) + ((src >> 3) & 0x1F); dest = (dest | (dest << 16)) & 0x7E0F81F; dest += ((src - dest) * a) >> 5; dest &= 0x7E0F81F; *(aDestPixels++) = dest | (dest >> 16); } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; } } else if (aGMask == 0x3E0) { performNormalBlit = false; for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 27; src = ((src & 0xF800) << 10) + ((src >> 9) & 0x7C00) + ((src >> 3) & 0x1F); dest = (dest | (dest << 16)) & 0x3E07C1F; dest += ((src - dest) * a) >> 5; // 1*d - a*d = (1-a)*d = oma*d :) dest &= 0x3E07C1F; *(aDestPixels++) = dest | (dest >> 16); } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; } } } if (performNormalBlit) #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 24; int oma = 256 - a; *(aDestPixels++) = (((((dest & aBMask) * oma) + (((src & 0x000000FF) * a * aBMask) >> 8) + aBRoundAdd) >> 8) & aBMask) + (((((dest & aGMask) * oma) + ((((src & 0x0000FF00) >> 8) * a * aGMask) >> 8) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aRMask) * oma) + ((((src & 0x00FF0000) >> 16) * a * aRMask) >> 8) + aRRoundAdd) >> 8) & aRMask); } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; } } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theY * mSurface->pitch/4) + theX; SRC_TYPE* aSrcPixelsRow = aSrcBits + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; #ifdef OPTIMIZE_SOFTWARE_DRAWING if (gOptimizeSoftwareDrawing) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 24; uint32_t srctmp = src & 0xFF00FF; uint32_t desttmp = dest & 0xFF00FF; desttmp = (desttmp + (((srctmp - desttmp) * a) >> 8)) & 0xFF00FF; src &= 0x00FF00; dest &= 0x00FF00; dest = (dest + (((src - dest) * a) >> 8)) & 0x00FF00; *(aDestPixels++) = dest | desttmp; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; } } else #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; SRC_TYPE* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = *aDestPixels; int a = src >> 24; int oma = 256 - a; *(aDestPixels++) = (((((dest & aBMask) * oma) + ((((src & 0x000000FF) * a) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask) + (((((dest & aGMask) * oma) + (((((src & 0x0000FF00) >> 8) * a) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aRMask) * oma) + (((((src & 0x00FF0000) >> 16) * a) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask); } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; } } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/SDLMixerSoundInstance.h0000644000175000017500000000503010675772655022636 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef __SDLMixerSoundINSTANCE_H__ #define __SDLMixerSoundINSTANCE_H__ #include "SoundInstance.h" namespace Sexy { class SDLMixerSoundManager; class SDLMixerSoundInstance : public SoundInstance { friend class SDLMixerSoundManager; protected: SDLMixerSoundManager* mSDLMixerSoundManagerP; Mix_Chunk* mSample; int mChannel; bool mAutoRelease; bool mReleased; float mBasePan; float mBaseVolume; float mBasePitch; float mPan; float mVolume; float mPitch; bool mHasPlayed; protected: void RehupVolume(); void RehupPan(); void RehupPitch(); public: SDLMixerSoundInstance(SDLMixerSoundManager* theSoundManager, int channel, Mix_Chunk* theSourceSound); virtual ~SDLMixerSoundInstance(); virtual void Release(); virtual void SetBaseVolume(double theBaseVolume); //0.0 to 1.0 virtual void SetBasePan(int theBasePan); //-100 to +100 virtual void AdjustBasePitch(float thePitch); //+0.5 to +2.0 relative to normal playing speed virtual void SetVolume(double theVolume); //0.0 to 1.0 virtual void SetPan(int thePosition); //-100 to +100 = left to right virtual void AdjustPitch(double thePitch); //+0.5 to +2.0 relative to normal playing speed virtual bool Play(bool looping, bool autoRelease); virtual void Stop(); virtual bool IsPlaying(); virtual bool IsReleased(); virtual double GetVolume(); }; } #endif //__SDLMixerSoundINSTANCE_H__ libtuxcap-1.4.0/tuxcap/include/DDInterface.h0000644000175000017500000000605511202747625020613 0ustar inniyahinniyah#ifndef __DDINTERFACE_H__ #define __DDINTERFACE_H__ #include "Common.h" #include "NativeDisplay.h" #include "Rect.h" #include "Ratio.h" #include "SDL.h" #ifndef WIN32 #define HWND void* #endif #if 0 #include "CritSect.h" #endif namespace Sexy { class SexyAppBase; class DDImage; class Image; class MemoryImage; class D3DInterface; #if 0 class D3DTester; #endif typedef std::set DDImageSet; class DDInterface : public NativeDisplay { public: enum { RESULT_OK = 0, RESULT_FAIL = 1, RESULT_DD_CREATE_FAIL = 2, RESULT_SURFACE_FAIL = 3, RESULT_EXCLUSIVE_FAIL = 4, RESULT_DISPCHANGE_FAIL = 5, RESULT_INVALID_COLORDEPTH = 6, RESULT_3D_FAIL = 7 }; SexyAppBase* mApp; D3DInterface* mD3DInterface; #if 0 D3DTester* mD3DTester; CritSect mCritSect; LPDIRECTDRAW mDD; LPDIRECTDRAW7 mDD7; #endif //FIXME eliminate SDL_Surface* mPrimarySurface; SDL_Surface* mSecondarySurface; SDL_Surface* mDrawSurface; bool mIs3D; int mWidth; int mHeight; Ratio mAspect; int mDesktopWidth; int mDesktopHeight; Ratio mDesktopAspect; bool mIsWidescreen; int mDisplayWidth; int mDisplayHeight; Ratio mDisplayAspect; Rect mPresentationRect; int mFullscreenBits; uint32_t mRefreshRate; uint32_t mMillisecondsPerFrame; int mScanLineFailCount; int* mRedAddTable; int* mGreenAddTable; int* mBlueAddTable; uint32_t mRedConvTable[256]; uint32_t mGreenConvTable[256]; uint32_t mBlueConvTable[256]; bool mInitialized; HWND mHWnd; SDL_Surface* mOldCursorArea; bool mIsWindowed; DDImage* mScreenImage; DDImageSet mDDImageSet; bool mVideoOnlyDraw; uint32_t mInitCount; int mCursorWidth; int mCursorHeight; int mCursorX; int mCursorY; Image* mCursorImage; bool mHasOldCursorArea; DDImage* mOldCursorAreaImage; std::string mErrorString; public: int CreateSurface(SDL_Surface** theSurface, int width, int height, bool mVideoMemory); #if 0 bool CopyBitmap(LPDIRECTDRAWSURFACE theSurface, HBITMAP TheBitmap, int theX, int theY, int theWidth, int theHeight); #endif uint32_t GetColorRef(uint32_t theRGB); void AddDDImage(DDImage* theDDImage); void RemoveDDImage(DDImage* theDDImage); void Remove3DData(MemoryImage* theImage); // for 3d texture cleanup void Cleanup(); void SetVideoOnlyDraw(bool videoOnly); bool Redraw(Rect* theClipRect = NULL); void RestoreOldCursorArea(); void DrawCursor(); #if 0 bool GotDXError(HRESULT theResult, const char *theContext = ""); void ClearSurface(LPDIRECTDRAWSURFACE theSurface); bool Do3DTest(HWND theHWND); #endif public: DDInterface(SexyAppBase* theApp); virtual ~DDInterface(); static std::string ResultToString(int theResult); DDImage* GetScreenImage(); int Init(HWND theWindow, bool IsWindowed); void RemapMouse(int& theX, int& theY); bool SetCursorImage(Image* theImage); }; } #endif //__DDINTERFACE_H__ libtuxcap-1.4.0/tuxcap/include/TriVertex.h0000644000175000017500000000134110737636302020431 0ustar inniyahinniyah#ifndef __TRIVERTEX_H__ #define __TRIVERTEX_H__ #include "SDL.h" namespace Sexy { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class TriVertex { public: float x,y,u,v; Uint32 color; //ARGB (0 = use color specified in function call) public: TriVertex() { color = 0; } TriVertex(float theX, float theY) : x(theX), y(theY) { color = 0; } TriVertex(float theX, float theY, float theU, float theV) : x(theX), y(theY), u(theU), v(theV) { color = 0; } TriVertex(float theX, float theY, float theU, float theV, Uint32 theColor) : x(theX), y(theY), u(theU), v(theV), color(theColor) { } }; } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/include/SharedImage.h0000644000175000017500000000165310641010432020634 0ustar inniyahinniyah#ifndef __SHARED_IMAGE_H__ #define __SHARED_IMAGE_H__ #include "Common.h" namespace Sexy { class Image; class DDImage; class MemoryImage; class SharedImage { public: DDImage* mImage; int mRefCount; SharedImage(); }; typedef std::map, SharedImage> SharedImageMap; class SharedImageRef { public: SharedImage* mSharedImage; MemoryImage* mUnsharedImage; bool mOwnsUnshared; public: SharedImageRef(); SharedImageRef(const SharedImageRef& theSharedImageRef); SharedImageRef(SharedImage* theSharedImage); ~SharedImageRef(); void Release(); SharedImageRef& operator=(const SharedImageRef& theSharedImageRef); SharedImageRef& operator=(SharedImage* theSharedImage); SharedImageRef& operator=(MemoryImage* theUnsharedImage); MemoryImage* operator->(); operator Image*(); operator MemoryImage*(); operator DDImage*(); }; } #endif //__SHARED_IMAGE_H__ libtuxcap-1.4.0/tuxcap/include/Slider.h0000644000175000017500000000144110641010426017703 0ustar inniyahinniyah#ifndef __SLIDER_H__ #define __SLIDER_H__ #include "Widget.h" namespace Sexy { class SliderListener; class Slider : public Widget { public: SliderListener* mListener; double mVal; int mId; Image* mTrackImage; Image* mThumbImage; bool mDragging; int mRelX; int mRelY; bool mHorizontal; public: Slider(Image* theTrackImage, Image* theThumbImage, int theId, SliderListener* theListener); virtual void SetValue(double theValue); virtual bool HasTransparencies(); virtual void Draw(Graphics* g); virtual void MouseMove(int x, int y); virtual void MouseDown(int x, int y, int theClickCount); virtual void MouseDrag(int x, int y); virtual void MouseUp(int x, int y); virtual void MouseLeave(); }; } #endif //__SLIDER_H__ libtuxcap-1.4.0/tuxcap/include/ParticlePhysicsSystem.h0000644000175000017500000000605110743475610023013 0ustar inniyahinniyah/* Physics enabled particle engine derived from HGE's particle engine, see directory hgeparticle for HGE's files and copyright notices*/ /* Copyright (c) 2008 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef _PARTICLEPHYSICSSYSTEM_H_ #define _PARTICLEPHYSICSSYSTEM_H_ #include "Physics.h" #include "hgeparticle.h" using namespace HGE; namespace Sexy { class ParticlePhysicsSystem: public hgeParticleSystem { public: ~ParticlePhysicsSystem() { for(int i=0; iDestroyObject(particles[i].ph_object); } } ParticlePhysicsSystem(const char *filename, DDImage *sprite, Physics* physics, float fps=0.0f, bool parseMetaData = true, bool old_format=true): hgeParticleSystem(filename, sprite, fps, parseMetaData, old_format), physics(physics), collision_type(124769), collision_group(214964){} ParticlePhysicsSystem(hgeParticleSystemInfo *psi, Physics* physics, float fps=0.0f): hgeParticleSystem(psi, fps), physics(physics), collision_type(124769), collision_group(214964){} ParticlePhysicsSystem(const ParticlePhysicsSystem &ps):hgeParticleSystem(ps) { physics = ps.physics; collision_type = ps.collision_type; collision_group = ps.collision_group; } ParticlePhysicsSystem(const hgeParticleSystem &ps, Physics* physics):hgeParticleSystem(ps), physics(physics), collision_type(124769), collision_group(214964){} void _update(float fDeltaTime); void SetCollisionType(unsigned int type) { collision_type = type; } void SetCollisionGroup(unsigned int group) { collision_group = group; } unsigned int GetCollisionType() const { return collision_type; } unsigned int GetCollisionGroup() const { return collision_group; } private: Physics* physics; unsigned int collision_type; unsigned int collision_group; }; } #endif /* _PARTICLEPHYSICSSYSTEM_H_ */ libtuxcap-1.4.0/tuxcap/include/DialogButton.h0000644000175000017500000000064110641010432021052 0ustar inniyahinniyah#ifndef __DIALOGBUTTON_H__ #define __DIALOGBUTTON_H__ #include "ButtonWidget.h" namespace Sexy { class DialogButton : public ButtonWidget { public: Image* mComponentImage; int mTranslateX, mTranslateY; int mTextOffsetX, mTextOffsetY; public: DialogButton(Image* theComponentImage, int theId, ButtonListener* theListener); virtual void Draw(Graphics* g); }; } #endif //__DIALOGBUTTON_H__ libtuxcap-1.4.0/tuxcap/include/ImageLib.h0000644000175000017500000000165211202747625020152 0ustar inniyahinniyah#ifndef __IMAGELIB_H__ #define __IMAGELIB_H__ #include namespace ImageLib { class Image { public: int mWidth; int mHeight; uint32_t* mBits; public: Image(); Image(int width, int height); virtual ~Image(); int GetWidth(); int GetHeight(); uint32_t* GetBits(); }; #if 0 bool WriteJPEGImage(const std::string& theFileName, Image* theImage); bool WritePNGImage(const std::string& theFileName, Image* theImage); bool WriteTGAImage(const std::string& theFileName, Image* theImage); bool WriteBMPImage(const std::string& theFileName, Image* theImage); #endif extern int gAlphaComposeColor; extern bool gAutoLoadAlpha; extern bool gIgnoreJPEG2000Alpha; // I've noticed alpha in jpeg2000's that shouldn't have alpha so this defaults to true Image* GetImage(std::string theFileName, bool lookForAlphaImage = true); void InitJPEG2000(); void CloseJPEG2000(); } #endif //__IMAGELIB_H__ libtuxcap-1.4.0/tuxcap/include/SexyMatrix.h0000644000175000017500000000417010641010432020575 0ustar inniyahinniyah#ifndef __SEXYMATRIX_H__ #define __SEXYMATRIX_H__ #include "SexyVector.h" namespace Sexy { /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class SexyMatrix3 { public: union { float m[3][3]; struct { float m00, m01, m02; float m10, m11, m12; float m20, m21, m22; }; }; public: SexyMatrix3(); void ZeroMatrix(); void LoadIdentity(); SexyVector2 operator*(const SexyVector2 &theVec) const; SexyVector3 operator*(const SexyVector3 &theVec) const; SexyMatrix3 operator*(const SexyMatrix3 &theMat) const; const SexyMatrix3& operator*=(const SexyMatrix3 &theMat); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class SexyTransform2D : public SexyMatrix3 { public: SexyTransform2D(); SexyTransform2D(bool loadIdentity); SexyTransform2D(const SexyMatrix3& theMatrix); const SexyTransform2D& operator=(const SexyMatrix3 &theMat); void Translate(float tx, float ty); // Rotate has been replaced by RotateRad. // NOTE: If you had Rotate(angle) you should now use RotateRad(-angle). // This is to make positive rotations go counter-clockwise when using screen coordinates. void RotateRad(float rot); void RotateDeg(float rot); void Scale(float sx, float sy); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class Transform { protected: mutable SexyTransform2D mMatrix; mutable bool mNeedCalcMatrix; void MakeComplex(); void CalcMatrix() const; public: bool mComplex, mHaveRot, mHaveScale; float mTransX1, mTransY1, mTransX2, mTransY2; float mScaleX, mScaleY; float mRot; public: Transform(); void Reset(); void Translate(float tx, float ty); void RotateRad(float rot); void RotateDeg(float rot); void Scale(float sx, float sy); const SexyTransform2D& GetMatrix() const; }; } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/include/WidgetContainer.h0000644000175000017500000000471611202747625021573 0ustar inniyahinniyah#ifndef __WIDGETCONTAINER_H__ #define __WIDGETCONTAINER_H__ #include "Common.h" #include "Rect.h" #include "Flags.h" namespace Sexy { class Graphics; class Widget; class WidgetManager; typedef std::list WidgetList; class WidgetContainer { public: WidgetList mWidgets; WidgetManager* mWidgetManager; WidgetContainer* mParent; bool mUpdateIteratorModified; WidgetList::iterator mUpdateIterator; uint32_t mLastWMUpdateCount; int mUpdateCnt; bool mDirty; int mX; int mY; int mWidth; int mHeight; bool mHasAlpha; bool mClip; FlagsMod mWidgetFlagsMod; int mPriority; int mZOrder; public: Widget* GetWidgetAtHelper(int x, int y, int theFlags, bool* found, int* theWidgetX, int* theWidgetY); bool IsBelowHelper(Widget* theWidget1, Widget* theWidget2, bool* found); void InsertWidgetHelper(const WidgetList::iterator &where, Widget *theWidget); public: WidgetContainer(); virtual ~WidgetContainer(); virtual Rect GetRect(); virtual bool Intersects(WidgetContainer* theWidget); virtual void AddWidget(Widget* theWidget); virtual void RemoveWidget(Widget* theWidget); virtual bool HasWidget(Widget* theWidget); virtual void DisableWidget(Widget* theWidget); virtual void RemoveAllWidgets(bool doDelete = false, bool recursive = false); virtual void SetFocus(Widget* theWidget); virtual bool IsBelow(Widget* theWidget1, Widget* theWidget2); virtual void MarkAllDirty(); virtual void BringToFront(Widget* theWidget); virtual void BringToBack(Widget* theWidget); virtual void PutBehind(Widget* theWidget, Widget* theRefWidget); virtual void PutInfront(Widget* theWidget, Widget* theRefWidget); virtual Point GetAbsPos(); // relative to top level virtual void MarkDirty(); virtual void MarkDirtyFull(); virtual void MarkDirtyFull(WidgetContainer* theWidget); virtual void MarkDirty(WidgetContainer* theWidget); virtual void AddedToManager(WidgetManager* theWidgetManager); virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void Update(); virtual void UpdateAll(ModalFlags* theFlags); virtual void UpdateF(float theFrac); virtual void UpdateFAll(ModalFlags* theFlags, float theFrac); virtual void Draw(Graphics* g); virtual void DrawAll(ModalFlags* theFlags, Graphics* g); virtual void SysColorChangedAll(); virtual void SysColorChanged(); }; }; #endif //__WIDGETCONTAINER_H__ libtuxcap-1.4.0/tuxcap/include/DialogListener.h0000644000175000017500000000044310641010432021364 0ustar inniyahinniyah#ifndef __DIALOGLISTENER_H__ #define __DIALOGLISTENER_H__ namespace Sexy { class DialogListener { public: virtual void DialogButtonPress(int theDialogId, int theButtonId) {} virtual void DialogButtonDepress(int theDialogId, int theButtonId) {} }; } #endif // __DIALOGLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/HyperlinkWidget.h0000644000175000017500000000067710641010426021604 0ustar inniyahinniyah#ifndef __HYPERLINKWIDGET_H__ #define __HYPERLINKWIDGET_H__ #include "ButtonWidget.h" namespace Sexy { class HyperlinkWidget : public ButtonWidget { public: Color mColor; Color mOverColor; int mUnderlineSize; int mUnderlineOffset; public: HyperlinkWidget(int theId, ButtonListener* theButtonListener); void Draw(Graphics* g); void MouseEnter(); void MouseLeave(); }; } #endif //__HYPERLINKWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/DDI_FastBlt_NoAlpha.inc0000644000175000017500000000357511202747625022452 0ustar inniyahinniyah{ if (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theY * mSurface->pitch/2) + theX; if (aMemoryImage->mHasTrans) { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t aSrc = NEXT_SRC_COLOR; if (aSrc>>24 != 0) *(aDestPixels++) = (ushort) aSrc; else aDestPixels++; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; } } else { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { *(aDestPixels++) = (ushort) NEXT_SRC_COLOR; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; } } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theY * mSurface->pitch/4) + theX; if (aMemoryImage->mHasTrans) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { uint32_t aSrc = NEXT_SRC_COLOR; if (aSrc>>24 != 0) *(aDestPixels++) = aSrc; else aDestPixels++; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; } } else { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; aSrcPixels = aSrcPixelsRow; for (int x = 0; x < theSrcRect.mWidth; x++) { *(aDestPixels++) = NEXT_SRC_COLOR; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; } } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/SoundInstance.h0000644000175000017500000000134510641010432021236 0ustar inniyahinniyah#ifndef __SOUNDINSTANCE_H__ #define __SOUNDINSTANCE_H__ #include "Common.h" namespace Sexy { class SoundInstance { public: SoundInstance() {} virtual ~SoundInstance() {} virtual void Release() = 0; virtual void SetBaseVolume(double theBaseVolume) = 0; virtual void SetBasePan(int theBasePan) = 0; virtual void AdjustPitch(double theNumSteps) = 0; virtual void SetVolume(double theVolume) = 0; virtual void SetPan(int thePosition) = 0; //-hundredth db to +hundredth db = left to right virtual bool Play(bool looping, bool autoRelease) = 0; virtual void Stop() = 0; virtual bool IsPlaying() = 0; virtual bool IsReleased() = 0; virtual double GetVolume() = 0; }; } #endif //__SOUNDINSTANCE_H__ libtuxcap-1.4.0/tuxcap/include/Font.h0000644000175000017500000000173410641010426017374 0ustar inniyahinniyah#ifndef __FONT_H__ #define __FONT_H__ #include "Common.h" #include "Rect.h" #include "Color.h" namespace Sexy { class Graphics; class Font { public: int mAscent; int mAscentPadding; // How much space is above the avg uppercase char int mHeight; int mLineSpacingOffset; // This plus height should get added between lines public: Font(); Font(const Font& theFont); virtual ~Font(); virtual int GetAscent(); virtual int GetAscentPadding(); virtual int GetDescent(); virtual int GetHeight(); virtual int GetLineSpacingOffset(); virtual int GetLineSpacing(); virtual int StringWidth(const SexyString& theString); virtual int CharWidth(SexyChar theChar); virtual int CharWidthKern(SexyChar theChar, SexyChar thePrevChar); virtual void DrawString(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect& theClipRect); virtual Font* Duplicate() = 0; }; } #endif //__FONT_H__ libtuxcap-1.4.0/tuxcap/include/DescParser.h0000644000175000017500000000472210641010426020521 0ustar inniyahinniyah#ifndef __DESCPARSER_H__ #define __DESCPARSER_H__ #include "Common.h" namespace Sexy { class DataElement { public: bool mIsList; public: DataElement(); virtual ~DataElement(); virtual DataElement* Duplicate() = 0; }; class SingleDataElement : public DataElement { public: std::string mString; public: SingleDataElement(); SingleDataElement(const std::string theString); virtual ~SingleDataElement(); virtual DataElement* Duplicate(); }; typedef std::vector ElementVector; class ListDataElement : public DataElement { public: ElementVector mElementVector; public: ListDataElement(); ListDataElement(const ListDataElement& theListDataElement); virtual ~ListDataElement(); ListDataElement& operator=(const ListDataElement& theListDataElement); virtual DataElement* Duplicate(); }; typedef std::map DataElementMap; typedef std::vector StringVector; typedef std::vector IntVector; typedef std::vector DoubleVector; class DescParser { public: enum { CMDSEP_SEMICOLON = 1, CMDSEP_NO_INDENT = 2 }; public: int mCmdSep; std::string mError; int mCurrentLineNum; std::string mCurrentLine; DataElementMap mDefineMap; public: virtual bool Error(const std::string& theError); virtual DataElement* Dereference(const std::string& theString); bool IsImmediate(const std::string& theString); std::string Unquote(const std::string& theQuotedString); bool GetValues(ListDataElement* theSource, ListDataElement* theValues); std::string DataElementToString(DataElement* theDataElement); bool DataToString(DataElement* theSource, std::string* theString); bool DataToInt(DataElement* theSource, int* theInt); bool DataToStringVector(DataElement* theSource, StringVector* theStringVector); bool DataToList(DataElement* theSource, ListDataElement* theValues); bool DataToIntVector(DataElement* theSource, IntVector* theIntVector); bool DataToDoubleVector(DataElement* theSource, DoubleVector* theDoubleVector); bool ParseToList(const std::string& theString, ListDataElement* theList, bool expectListEnd, int* theStringPos); bool ParseDescriptorLine(const std::string& theDescriptorLine); // You must implement this one virtual bool HandleCommand(const ListDataElement& theParams) = 0; public: DescParser(); virtual ~DescParser(); bool LoadDescriptor(const std::string& theFileName); }; } #endif //__DESCPARSER_H__ libtuxcap-1.4.0/tuxcap/include/SWTri.h0000644000175000017500000007272511202747625017522 0ustar inniyahinniyah#ifndef __SWTRI_H__ #define __SWTRI_H__ #include "Color.h" #include "MemoryImage.h" #include "Rect.h" #include "SexyMatrix.h" namespace Sexy { class SWHelper { public: struct XYZStruct { float mX; float mY; float mU; float mV; int32_t mDiffuse; }; struct SWVertex { int x, y; int a, r, g, b; int u, v; }; struct SWTextureInfo { const unsigned int * pTexture; unsigned int vShift, uMask, vMask; int pitch; unsigned int endpos; int height; }; struct SWDiffuse { unsigned int a, r, g, b; }; //typedef long long signed64; public: // For drawing static void SWDrawShape(XYZStruct *theVerts, int theNumVerts, MemoryImage *theImage, const Color &theColor, int theDrawMode, const Rect &theClipRect, void *theSurface, int thePitch, int thePixelFormat, bool blend, bool vertexColor); static void SWDrawTriangle(bool textured, bool talpha, bool mod_argb, bool global_argb, SWVertex * pVerts, unsigned int * pFrameBuffer, const unsigned int pitch, const SWTextureInfo * textureInfo, SWDiffuse & globalDiffuse, int thePixelFormat, bool blend); }; typedef void(*DrawTriFunc)(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); void SWTri_AddAllDrawTriFuncs(); void SWTri_AddDrawTriFunc(bool textured, bool talpha, bool mod_argb, bool global_argb, int thePixelFormat, bool blend, DrawTriFunc theFunc); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); extern void DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse); } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/include/D3DInterface.h0000644000175000017500000001540110737636302020672 0ustar inniyahinniyah#ifndef __D3DINTERFACE_H__ #define __D3DINTERFACE_H__ #include "Common.h" #include "MemoryImage.h" #include "SexyMatrix.h" #include "SDL.h" #include "SDL_opengl.h" namespace Sexy { class DDInterface; class SexyMatrix3; class TriVertex; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // The following flags apply to to the mD3DFlags member of MemoryImage enum D3DImageFlags { D3DImageFlag_MinimizeNumSubdivisions = 0x0001, // subdivide image into fewest possible textures (may use more memory) D3DImageFlag_Use64By64Subdivisions = 0x0002, // good to use with image strips so the entire texture isn't pulled in when drawing just a piece D3DImageFlag_UseA4R4G4B4 = 0x0004, // images with not too many color gradients work well in this format D3DImageFlag_UseA8R8G8B8 = 0x0008 // non-alpha images will be stored as R5G6B5 by default so use this option if you want a 32-bit non-alpha image }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct TextureDataPiece { GLuint mTexture; int mWidth,mHeight; }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// enum PixelFormat { PixelFormat_Unknown = 0x0000, PixelFormat_A8R8G8B8 = 0x0001, PixelFormat_A4R4G4B4 = 0x0002, PixelFormat_R5G6B5 = 0x0004, PixelFormat_Palette8 = 0x0008 }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct TextureData { public: typedef std::vector TextureVector; TextureVector mTextures; #if 0 LPDIRECTDRAWPALETTE mPalette; #endif int mWidth,mHeight; int mTexVecWidth, mTexVecHeight; int mTexPieceWidth, mTexPieceHeight; int mBitsChangedCount; int mTexMemSize; float mMaxTotalU, mMaxTotalV; PixelFormat mPixelFormat; Uint32 mImageFlags; TextureData(); ~TextureData(); void ReleaseTextures(); void CreateTextureDimensions(MemoryImage *theImage); GLuint GetTexture(int x, int y, int &width, int &height, float &u1, float &v1, float &u2, float &v2); GLuint GetTextureF(float x, float y, float &width, float &height, float &u1, float &v1, float &u2, float &v2); void CreateTextures(MemoryImage *theImage); void CheckCreateTextures(MemoryImage *theImage); void Blt(float theX, float theY, const Rect& theSrcRect, const Color& theColor); void BltTransformed(const SexyMatrix3 &theTrans, const Rect& theSrcRect, const Color& theColor, const Rect *theClipRect = NULL, float theX = 0, float theY = 0, bool center = false); void BltTriangles(const TriVertex theVertices[][3], int theNumTriangles, Uint32 theColor, float tx = 0, float ty = 0); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class D3DInterface { public: #if 0 HWND mHWnd; LPDIRECTDRAW7 mDD; LPDIRECT3D7 mD3D; LPDIRECT3DDEVICE7 mD3DDevice; D3DVIEWPORT7 mD3DViewport; #endif int mWidth; int mHeight; GLuint custom_cursor_texture; SDL_Surface* mDDSDrawSurface; SDL_Surface* mZBuffer; bool mSceneBegun; bool mIsWindowed; typedef std::set ImageSet; ImageSet mImageSet; typedef std::list TransformStack; TransformStack mTransformStack; static std::string mErrorString; protected: void UpdateViewport(); bool InitD3D(); void SetupDrawMode(int theDrawMode, const Color &theColor, Image *theImage); #if 0 static HRESULT CALLBACK PixelFormatsCallback(LPDDPIXELFORMAT theFormat, LPVOID lpContext); #endif public: D3DInterface(); virtual ~D3DInterface(); void Cleanup(); void PushTransform(const SexyMatrix3 &theTransform, bool concatenate = true); void PopTransform(); bool PreDraw(); void Flush(); void RemoveMemoryImage(MemoryImage *theImage); void FillOldCursorAreaTexture(GLint x, GLint y); void BltOldCursorArea(GLfloat x, GLfloat y, const Color& theColor); bool CreateImageTexture(MemoryImage *theImage); bool RecoverBits(MemoryImage* theImage); void SetCurTexture(MemoryImage *theImage); void Blt(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode, bool linearFilter = false); void BltClipF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect *theClipRect, const Color& theColor, int theDrawMode); void BltMirror(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode, bool linearFilter = false); void StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect* theClipRect, const Color &theColor, int theDrawMode, bool fastStretch, bool mirror = false); void BltRotated(Image* theImage, float theX, float theY, const Rect* theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY, const Rect& theSrcRect); void BltTransformed(Image* theImage, const Rect* theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, const SexyMatrix3 &theTransform, bool linearFilter, float theX = 0, float theY = 0, bool center = false); void DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); void FillRect(const Rect& theRect, const Color& theColor, int theDrawMode); void DrawTriangle(const TriVertex &p1, const TriVertex &p2, const TriVertex &p3, const Color &theColor, int theDrawMode); void DrawTriangleTex(const TriVertex &p1, const TriVertex &p2, const TriVertex &p3, const Color &theColor, int theDrawMode, Image *theTexture, bool blend = true); void DrawTrianglesTex(const TriVertex theVertices[][3], int theNumTriangles, const Color &theColor, int theDrawMode, Image *theTexture, float tx = 0, float ty = 0, bool blend = true); void DrawTrianglesTexStrip(const TriVertex theVertices[], int theNumTriangles, const Color &theColor, int theDrawMode, Image *theTexture, float tx = 0, float ty = 0, bool blend = true); void FillPoly(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty); bool InitFromDDInterface(DDInterface *theInterface); #if 0 static void MakeDDPixelFormat(PixelFormat theFormatType, DDPIXELFORMAT* theFormat); static PixelFormat GetDDPixelFormat(LPDDPIXELFORMAT theFormat); static bool CheckDXError(HRESULT theError, const char *theMsg=""); #endif }; } #endif //__D3DINTERFACE_H__ libtuxcap-1.4.0/tuxcap/include/ButtonListener.h0000644000175000017500000000101010641010426021432 0ustar inniyahinniyah#ifndef __BUTTONLISTENER_H__ #define __BUTTONLISTENER_H__ namespace Sexy { class ButtonListener { public: virtual void ButtonPress(int theId) {} virtual void ButtonPress(int theId, int theClickCount) { ButtonPress(theId); } virtual void ButtonDepress(int theId) {} virtual void ButtonDownTick(int theId) {} virtual void ButtonMouseEnter(int theId) {} virtual void ButtonMouseLeave(int theId) {} virtual void ButtonMouseMove(int theId, int theX, int theY) {} }; } #endif //__BUTTONLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/GENERIC_DrawLineAA.inc0000644000175000017500000000533011202747625022063 0ustar inniyahinniyah{ if (!(dx == 0 || dy == 0)) { PIXEL_TYPE* aDestPixels = &aBits[aY0*STRIDE + aX0]; uint32_t anErrAcc = 0x10000 - (uint32_t)((1.0f - fabsf(theStartX - aX0))*(1.0f - fabsf(theStartY - aY0)) * 0x10000); if (dx >= dy) // mostly horizontal { //uint32_t anErrAdj = (((uint32_t)dy << 16) / (uint32_t)dx); uint32_t anErrAdj = (uint32_t)(dyd / dxd * 0x10000); uchar aWeight = 255 - (uchar)(anErrAcc >> 8); uchar aWeight2 = (aWeight ^ 0xFF); int a = CALC_WEIGHT_A(aWeight); PIXEL_TYPE dest = *aDestPixels; if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels); } while (--dx) { anErrAcc += anErrAdj; if (anErrAcc >= 0x10000) { anErrAcc &= 0xFFFF; aDestPixels += STRIDE; aY0++; } aDestPixels += aXinc; uchar aWeight = 255 - (uchar)(anErrAcc >> 8); uchar aWeight2 = (aWeight ^ 0xFF); dest = *aDestPixels; a = CALC_WEIGHT_A(aWeight); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels); } if (aY0 < mHeight-1) { dest = *(aDestPixels+STRIDE); a = CALC_WEIGHT_A(aWeight2); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels+STRIDE); } } } } else // mostly vertical { //uint32_t anErrAdj = (uint32_t)(((uint32_t)dx << 16) / (uint32_t)dy); uint32_t anErrAdj = (uint32_t)(dxd / dyd * 0x10000); uchar aWeight = 255 - (uchar)(anErrAcc >> 8); uchar aWeight2 = (aWeight ^ 0xFF); PIXEL_TYPE dest = *aDestPixels; int a = CALC_WEIGHT_A(aWeight); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels); } while (--dy) { anErrAcc += anErrAdj; if (anErrAcc >= 0x10000) { anErrAcc &= 0xFFFF; aDestPixels += aXinc; aX0 += aXinc; } aDestPixels += STRIDE; uchar aWeight = 255 - (uchar)(anErrAcc >> 8); uchar aWeight2 = (aWeight ^ 0xFF); dest = *aDestPixels; int a = CALC_WEIGHT_A(aWeight); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels); } if (aX0 < STRIDE-1) { dest = *(aDestPixels+aXinc); a = CALC_WEIGHT_A(aWeight2); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels+aXinc); } } } } aDestPixels = &aBits[aY1*STRIDE + aX1]; uchar aWeight = 255 - (uchar)(anErrAcc >> 8); uchar aWeight2 = (aWeight ^ 0xFF); PIXEL_TYPE dest = *aDestPixels; int a = CALC_WEIGHT_A(aWeight); if (a != 0) { int oma = 256 - a; BLEND_PIXEL(aDestPixels); } } } libtuxcap-1.4.0/tuxcap/include/ListWidget.h0000644000175000017500000000502210641010426020537 0ustar inniyahinniyah#ifndef __LISTWIDGET_H__ #define __LISTWIDGET_H__ #include "ScrollListener.h" #include "Widget.h" namespace Sexy { typedef std::vector SexyStringVector; typedef std::vector ColorVector; class ScrollbarWidget; class ListListener; class Font; class ListWidget : public Widget, public ScrollListener { public: enum { JUSTIFY_LEFT =0, JUSTIFY_CENTER, JUSTIFY_RIGHT }; enum { COLOR_BKG =0, COLOR_OUTLINE, COLOR_TEXT, COLOR_HILITE, COLOR_SELECT, COLOR_SELECT_TEXT, }; public: int mId; Font* mFont; ScrollbarWidget* mScrollbar; int mJustify; SexyStringVector mLines; ColorVector mLineColors; double mPosition; double mPageSize; int mHiliteIdx; int mSelectIdx; ListListener* mListListener; ListWidget* mParent; ListWidget* mChild; bool mSortFromChild; bool mDrawOutline; int mMaxNumericPlaces; int mItemHeight; bool mDrawSelectWhenHilited; bool mDoFingerWhenHilited; void SetHilite(int theHiliteIdx, bool notifyListener = false); public: ListWidget(int theId, Font *theFont, ListListener *theListListener); virtual ~ListWidget(); virtual void RemovedFromManager(WidgetManager *theManager); virtual SexyString GetSortKey(int theIdx); virtual void Sort(bool ascending); virtual SexyString GetStringAt(int theIdx); virtual void Resize(int theX, int theY, int theWidth, int theHeight); virtual int AddLine(const SexyString& theLine, bool alphabetical); virtual void SetLine(int theIdx, const SexyString& theString); virtual int GetLineCount(); virtual int GetLineIdx(const SexyString& theLine); virtual void SetColor(const SexyString& theLine, const Color& theColor); virtual void SetColor(int theIdx, const Color& theColor); virtual void SetLineColor(int theIdx, const Color& theColor); virtual void RemoveLine(int theIdx); virtual void RemoveAll(); virtual int GetOptimalWidth(); virtual int GetOptimalHeight(); virtual void OrderInManagerChanged(); virtual void Draw(Graphics *g); virtual void ScrollPosition(int theId, double thePosition); virtual void MouseMove(int x, int y); virtual void MouseWheel(int theDelta); virtual void MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); } virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseLeave(); virtual void SetSelect(int theSelectIdx); }; } #endif // __LISTWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/Image.h0000644000175000017500000001000310641010426017475 0ustar inniyahinniyah#ifndef __IMAGE_H__ #define __IMAGE_H__ #include "Common.h" #include "Color.h" #include "Rect.h" #include "Point.h" namespace Sexy { struct Span { int mY; int mX; int mWidth; }; enum AnimType { AnimType_None, AnimType_Once, AnimType_PingPong, AnimType_Loop }; struct AnimInfo { AnimType mAnimType; int mFrameDelay; // 1/100s int mNumCels; std::vector mPerFrameDelay; std::vector mFrameMap; int mTotalAnimTime; AnimInfo(); void SetPerFrameDelay(int theFrame, int theTime); void Compute(int theNumCels, int theBeginFrameTime = 0, int theEndFrameTime = 0); int GetPerFrameCel(int theTime); int GetCel(int theTime); }; class Graphics; class SexyMatrix3; #if 0 class SysFont; #endif class TriVertex; class Image { #if 0 friend class Sexy::SysFont; #endif public: bool mDrawn; std::string mFilePath; int mWidth; int mHeight; // for image strips int mNumRows; int mNumCols; // for animations AnimInfo *mAnimInfo; public: Image(); Image(const Image& theImage); virtual ~Image(); int GetWidth(); int GetHeight(); int GetCelWidth(); // returns the width of just 1 cel in a strip of images int GetCelHeight(); // like above but for vertical strips int GetAnimCel(int theTime); // use animinfo to return appropriate cel to draw at the time Rect GetAnimCelRect(int theTime); Rect GetCelRect(int theCel); // Gets the rectangle for the given cel at the specified row/col Rect GetCelRect(int theCol, int theRow); // Same as above, but for an image with both multiple rows and cols void CopyAttributes(Image *from); Graphics* GetGraphics(); virtual bool PolyFill3D(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty, bool convex); virtual void FillRect(const Rect& theRect, const Color& theColor, int theDrawMode); virtual void DrawRect(const Rect& theRect, const Color& theColor, int theDrawMode); virtual void ClearRect(const Rect& theRect); virtual void DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void FillScanLines(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode); virtual void FillScanLinesWithCoverage(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode, const unsigned char* theCoverage, int theCoverX, int theCoverY, int theCoverWidth, int theCoverHeight); virtual void Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode); virtual void BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode); virtual void BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY); virtual void StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch); virtual void BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend); virtual void BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend); virtual void BltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode); virtual void StretchBltMirror(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch); }; } #endif //__IMAGE_H__ libtuxcap-1.4.0/tuxcap/include/Quantize.h0000644000175000017500000000037011202747625020275 0ustar inniyahinniyah#ifndef __QUANTIZE_H__ #define __QUANTIZE_H__ #include "Common.h" namespace Sexy { bool Quantize8Bit(const uint32_t* theSrcBits, int theWidth, int theHeight, uchar* theDestColorIndices, uint32_t* theDestColorTable); } #endif //__QUANTIZE_H__ libtuxcap-1.4.0/tuxcap/include/EditListener.h0000644000175000017500000000074010737636302021072 0ustar inniyahinniyah#ifndef __EDITLISTENER_H__ #define __EDITLISTENER_H__ #include "Common.h" #include "SDL_keysym.h" namespace Sexy { class EditListener { public: virtual void EditWidgetText(int theId, const SexyString& theString) {}; virtual bool AllowKey(int theId, SDLKey theKey) { return true; } virtual bool AllowChar(int theId, SexyChar theChar) { return true; } virtual bool AllowText(int theId, const SexyString& theText) { return true; } }; } #endif //__EDITLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/PhysicsListener.h0000644000175000017500000000331510760515321021621 0ustar inniyahinniyah/* Sexy Chipmunk, a physics engine for the PopCap Games Framework using Scott Lembcke's excellent chipmunk physics library */ /* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifndef __SEXYPHYSICSLISTENER_H__ #define __SEXYPHYSICSLISTENER_H__ namespace Sexy { class PhysicsObject; class CollisionObject; class Graphics; class PhysicsListener { public: virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g){} virtual void HandleCollision(CollisionObject* col){} virtual bool HandleTypedCollision(CollisionObject* col){ return true; } virtual void BeforePhysicsStep(){} virtual void AfterPhysicsStep(){} }; }; #endif libtuxcap-1.4.0/tuxcap/include/XMLParser.h0000644000175000017500000000432210641010426020277 0ustar inniyahinniyah#ifndef __XMLPARSER_H__ #define __XMLPARSER_H__ #include "Common.h" #if 0 #include "PerfTimer.h" #endif //struct PFILE; namespace Sexy { class XMLParam { public: std::string mKey; std::string mValue; }; typedef std::map XMLParamMap; typedef std::list XMLParamMapIteratorList; typedef std::vector XMLParserBuffer; class XMLElement { public: enum { TYPE_NONE, TYPE_START, TYPE_END, TYPE_ELEMENT, TYPE_INSTRUCTION, TYPE_COMMENT }; public: int mType; SexyString mSection; SexyString mValue; SexyString mInstruction; XMLParamMap mAttributes; XMLParamMapIteratorList mAttributeIteratorList; // stores attribute iterators in their original order }; class XMLParser { protected: std::string mFileName; SexyString mErrorText; int mLineNum; FILE* mFile; bool mHasFailed; bool mAllowComments; XMLParserBuffer mBufferedText; SexyString mSection; bool (XMLParser::*mGetCharFunc)(wchar_t* theChar, bool* error); bool mForcedEncodingType; bool mFirstChar; bool mByteSwap; protected: void Fail(const SexyString& theErrorText); void Init(); bool AddAttribute(XMLElement* theElement, const SexyString& aAttributeKey, const SexyString& aAttributeValue); bool GetAsciiChar(wchar_t* theChar, bool* error); bool GetUTF8Char(wchar_t* theChar, bool* error); bool GetUTF16Char(wchar_t* theChar, bool* error); bool GetUTF16LEChar(wchar_t* theChar, bool* error); bool GetUTF16BEChar(wchar_t* theChar, bool* error); public: enum XMLEncodingType { ASCII, UTF_8, UTF_16, UTF_16_LE, UTF_16_BE }; public: XMLParser(); virtual ~XMLParser(); void SetEncodingType(XMLEncodingType theEncoding); bool OpenFile(const std::string& theFilename); void SetStringSource(const std::wstring& theString); void SetStringSource(const std::string& theString); bool NextElement(XMLElement* theElement); SexyString GetErrorText(); int GetCurrentLineNum(); std::string GetFileName(); inline void AllowComments(bool doAllow) { mAllowComments = doAllow; } bool HasFailed(); bool EndOfFile(); }; }; #endif //__XMLPARSER_H__ libtuxcap-1.4.0/tuxcap/include/SexyAppBase.h0000644000175000017500000004531111202747625020665 0ustar inniyahinniyah#ifndef __SEXYAPPBASE_H__ #define __SEXYAPPBASE_H__ #include #include #include #include #include #include "SDL.h" #include "SDL_thread.h" #include "ButtonListener.h" #include "DialogListener.h" #include "Common.h" #include "Rect.h" #include "Color.h" #include "NativeDisplay.h" #include "SharedImage.h" #include "Buffer.h" #if 0 #include "CritSect.h" #endif #include "Ratio.h" #ifndef WIN32 #define HWND void* enum { REG_SZ, REG_DWORD, REG_BINARY, HKEY_CURRENT_USER }; typedef int HKEY; #endif namespace ImageLib { class Image; }; namespace Sexy { class WidgetManager; class Image; class Widget; class MemoryImage; typedef std::set MemoryImageSet; typedef std::map StringSexyStringMap; class SoundManager; class MusicInterface; class DDInterface; class DDImage; class ResourceManager; class Dialog; typedef std::map DialogMap; typedef std::list DialogList; #if 0 class HTTPTransfer; typedef std::list WindowsMessageList; typedef std::map HandleToIntMap; #endif class WidgetSafeDeleteInfo { public: int mUpdateAppDepth; Widget* mWidget; }; typedef std::list WidgetSafeDeleteList; typedef std::vector StringVector; typedef std::map StringStringVectorMap; typedef std::map StringStringMap; typedef std::map StringWStringMap; typedef std::map StringBoolMap; typedef std::map StringIntMap; typedef std::map StringDoubleMap; enum { CURSOR_POINTER, CURSOR_HAND, CURSOR_DRAGGING, CURSOR_TEXT, CURSOR_CIRCLE_SLASH, CURSOR_SIZEALL, CURSOR_SIZENESW, CURSOR_SIZENS, CURSOR_SIZENWSE, CURSOR_SIZEWE, CURSOR_WAIT, CURSOR_NONE, CURSOR_CUSTOM, NUM_CURSORS }; enum { DEMO_MOUSE_POSITION, DEMO_ACTIVATE_APP, DEMO_SIZE, DEMO_KEY_DOWN, DEMO_KEY_UP, DEMO_KEY_CHAR, DEMO_CLOSE, DEMO_MOUSE_ENTER, DEMO_MOUSE_EXIT, DEMO_LOADING_COMPLETE, DEMO_REGISTRY_GETSUBKEYS, DEMO_REGISTRY_READ, DEMO_REGISTRY_WRITE, DEMO_REGISTRY_ERASE, DEMO_FILE_EXISTS, DEMO_FILE_READ, DEMO_FILE_WRITE, DEMO_HTTP_RESULT, DEMO_SYNC, DEMO_ASSERT_STRING_EQUAL, DEMO_ASSERT_INT_EQUAL, DEMO_MOUSE_WHEEL, DEMO_HANDLE_COMPLETE, DEMO_VIDEO_DATA, DEMO_IDLE = 31 }; enum { FPS_ShowFPS, FPS_ShowCoords, Num_FPS_Types }; enum { UPDATESTATE_MESSAGES, UPDATESTATE_PROCESS_1, UPDATESTATE_PROCESS_2, UPDATESTATE_PROCESS_DONE }; class SexyAppBase : public ButtonListener, public DialogListener { protected: std::map mRegistry; bool WriteRegistryToIni(const std::string& IniFile); bool ReadRegistryFromIni(const std::string& IniFile); public: Uint32 mRandSeed; SDL_Surface* surface; std::string mCompanyName; std::string mFullCompanyName; std::string mProdName; std::string mRegKey; std::string mChangeDirTo; int mRelaxUpdateBacklogCount; // app doesn't try to catch up for this many frames int mPreferredX; int mPreferredY; int mWidth; int mHeight; int mFullscreenBits; double mMusicVolume; double mSfxVolume; double mDemoMusicVolume; double mDemoSfxVolume; bool mNoSoundNeeded; bool mWantFMod; bool mCmdLineParsed; bool mSkipSignatureChecks; bool mStandardWordWrap; bool mbAllowExtendedChars; bool mOnlyAllowOneCopyToRun; bool mBetaValidate; bool mSEHOccured; bool mShutdown; bool mExitToTop; bool mIsWindowed; bool mIsPhysWindowed; bool mFullScreenWindow; // uses ChangeDisplaySettings to run fullscreen with mIsWindowed true bool mForceFullscreen; bool mForceWindowed; bool mInitialized; bool mProcessInTimer; bool mIsScreenSaver; bool mAllowMonitorPowersave; bool mNoDefer; bool mFullScreenPageFlip; bool mTabletPC; bool mAlphaDisabled; bool mReadFromRegistry; bool mIsOpeningURL; bool mShutdownOnURLOpen; std::string mOpeningURL; std::string mRegisterLink; std::string mProductVersion; double mUnmutedMusicVolume; double mUnmutedSfxVolume; int mMuteCount; int mAutoMuteCount; bool mDemoMute; bool mMuteOnLostFocus; bool mCleanupSharedImages; int mNonDrawCount; int mFrameTime; bool mIsDrawing; bool mLastDrawWasEmpty; bool mHasPendingDraw; double mPendingUpdatesAcc; double mUpdateFTimeAcc; int mSleepCount; int mDrawCount; int mUpdateCount; int mUpdateAppState; int mUpdateAppDepth; double mUpdateMultiplier; bool mPaused; int mFastForwardToUpdateNum; bool mFastForwardToMarker; bool mFastForwardStep; int mStepMode; // 0 = off, 1 = step, 2 = waiting for step int mCursorNum; bool mMouseIn; bool mRunning; bool mActive; bool mMinimized; bool mPhysMinimized; bool mIsDisabled; bool mHasFocus; int mDrawTime; int mFPSFlipCount; int mFPSDirtyCount; int mFPSTime; int mFPSCount; bool mShowFPS; int mShowFPSMode; int mScreenBltTime; bool mAutoStartLoadingThread; bool mLoadingThreadStarted; bool mLoadingThreadCompleted; bool mLoaded; bool mYieldMainThread; bool mLoadingFailed; bool mSysCursor; bool mCustomCursorsEnabled; bool mCustomCursorDirty; bool mLastShutdownWasGraceful; bool mIsWideWindow; int mNumLoadingThreadTasks; int mCompletedLoadingThreadTasks; std::string mWindowIconBMP; // For recording/playback of program control #if 0 bool mRecordingDemoBuffer; bool mPlayingDemoBuffer; bool mManualShutdown; std::string mDemoPrefix; std::string mDemoFileName; #endif int mDemoLength; int mLastDemoMouseX; int mLastDemoMouseY; int mLastDemoUpdateCnt; bool mDemoNeedsCommand; bool mDemoIsShortCmd; int mDemoCmdNum; int mDemoCmdOrder; int mDemoCmdBitPos; bool mDemoLoadingComplete; int mCurHandleNum; typedef std::pair DemoMarker; typedef std::list DemoMarkerList; DemoMarkerList mDemoMarkerList; bool mDebugKeysEnabled; bool mEnableMaximizeButton; bool mCtrlDown; bool mAltDown; int mSyncRefreshRate; bool mVSyncUpdates; bool mVSyncBroken; int mVSyncBrokenCount; bool mWaitForVSync; bool mSoftVSyncWait; bool mUserChanged3DSetting; bool mAutoEnable3D; bool mTest3D; bool mWidescreenAware; bool mEnableWindowAspect; StringWStringMap mStringProperties; StringBoolMap mBoolProperties; StringIntMap mIntProperties; StringDoubleMap mDoubleProperties; StringStringVectorMap mStringVectorProperties; Uint32 mPrimaryThreadId; SDL_mutex* mMutex; SDL_Cursor* mHandCursor; SDL_Cursor* mDraggingCursor; SDL_Cursor* mArrowCursor; Uint32 mLastTimeCheck; Uint32 mLastTime; Uint32 mLastUserInputTick; Uint32 mLastTimerTime; Uint32 mLastDrawTick; Uint32 mNextDrawTick; WidgetSafeDeleteList mSafeDeleteList; Uint32 mVSyncBrokenTestStartTick; Uint32 mVSyncBrokenTestUpdates; DDInterface* mDDInterface; uchar mAdd8BitMaxTable[512]; WidgetManager* mWidgetManager; Uint32 mTimeLoaded; SexyString mTitle; Image* mCursorImages[NUM_CURSORS]; uint32_t mFPSStartTick; Buffer mDemoBuffer; MemoryImageSet mMemoryImageSet; SharedImageMap mSharedImageMap; HWND mHWnd; HWND mInvisHWnd; uint mNotifyGameMessage; Rect mScreenBounds; SoundManager* mSoundManager; MusicInterface* mMusicInterface; DialogMap mDialogMap; DialogList mDialogList; #if 0 CritSect mCritSect; HCURSOR mOverrideCursor; DWORD mOpeningURLTime; DWORD mLastBigDelayTime; HandleToIntMap mHandleToIntMap; // For waiting on handles DWORD mMinVidMemory3D; DWORD mRecommendedVidMemory3D; LONG mOldWndProc; #endif Ratio mWindowAspect; ResourceManager* mResourceManager; virtual void Init(); SexyAppBase(); virtual ~SexyAppBase(); virtual void Shutdown(); virtual void Start(); void SetCursor(int theCursorNum); virtual void SafeDeleteWidget(Widget* theWidget); void AddMemoryImage(MemoryImage* theMemoryImage); void RemoveMemoryImage(MemoryImage* theMemoryImage); void WaitForLoadingThread(); virtual void LoadingThreadProc(); virtual SharedImageRef GetSharedImage(const std::string& theFileName, const std::string& theVariant = "", bool* isNew = NULL); virtual void PlaySample(int theSoundNum); virtual void PlaySample(int theSoundNum, int thePan); virtual double GetMasterVolume(); virtual double GetMusicVolume(); virtual double GetSfxVolume(); virtual bool IsMuted(); virtual void SetMasterVolume(double theVolume); virtual void SetMusicVolume(double theVolume); virtual void SetSfxVolume(double theVolume); virtual void Mute(bool autoMute = false); virtual void Unmute(bool autoMute = false); virtual MusicInterface* CreateMusicInterface(); DDImage* CopyImage(Image* theImage, const Rect& theRect); DDImage* CopyImage(Image* theImage); virtual DDImage* GetImage(const std::string& theFileName, bool commitBits = true); DDImage* CreateCrossfadeImage(Image* theImage1, const Rect& theRect1, Image* theImage2, const Rect& theRect2, double theFadeFactor); void ColorizeImage(Image* theImage, const Color& theColor); DDImage* CreateColorizedImage(Image* theImage, const Color& theColor); void MirrorImage(Image* theImage); void FlipImage(Image* theImage); void RotateImageHue(Sexy::MemoryImage *theImage, int theDelta); uint32_t HSLToRGB(int h, int s, int l); uint32_t RGBToHSL(int r, int g, int b); void HSLToRGB(const uint32_t* theSource, uint32_t* theDest, int theSize); void RGBToHSL(const uint32_t* theSource, uint32_t* theDest, int theSize); void PrecacheAdditive(MemoryImage* theImage); void PrecacheAlpha(MemoryImage* theImage); void PrecacheNative(MemoryImage* theImage); virtual void MakeWindow(); bool Is3DAccelerated(); virtual double GetLoadingThreadProgress(); bool FileExists(const std::string& theFileName); bool ReadBufferFromFile(const std::string& theFileName, Buffer* theBuffer, bool dontWriteToDemo = false);//UNICODE bool WriteBufferToFile(const std::string& theFileName, const Buffer* theBuffer); virtual Dialog* NewDialog(int theDialogId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode); virtual Dialog* DoDialog(int theDialogId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode); virtual Dialog* GetDialog(int theDialogId); virtual void AddDialog(int theDialogId, Dialog* theDialog); virtual void AddDialog(Dialog* theDialog); virtual bool KillDialog(Dialog* theDialog); virtual bool KillDialog(int theDialogId, bool removeWidget, bool deleteWidget); virtual bool KillDialog(int theDialogId); virtual int GetDialogCount(); virtual void DialogButtonPress(int theDialogId, int theButtonId); virtual void DialogButtonDepress(int theDialogId, int theButtonId); virtual void ModalOpen(); virtual void ModalClose(); virtual void GotFocus(); virtual void LostFocus(); virtual bool UpdateAppStep(bool* updated); virtual void SetAlphaDisabled(bool isDisabled); void Set3DAcclerated(bool is3D, bool reinit = true); virtual void HandleGameAlreadyRunning(); virtual void SwitchScreenMode(); virtual void SwitchScreenMode(bool wantWindowed); virtual void SwitchScreenMode(bool wantWindowed, bool is3d, bool force = false); bool Is3DAccelerationSupported(); bool Is3DAccelerationRecommended(); void SetCursorImage(int theCursorNum, Image* theImage); int GetCursor(); void EnableCustomCursors(bool enabled); // Registry access methods bool RegistryGetSubKeys(const std::string& theKeyName, StringVector* theSubKeys); bool RegistryReadString(const std::string& theValueName, std::string* theString); bool RegistryReadInteger(const std::string& theValueName, int* theValue); bool RegistryReadBoolean(const std::string& theValueName, bool* theValue); bool RegistryReadData(const std::string& theValueName, uchar* theValue, uint32_t* theLength); bool RegistryEraseKey(const SexyString& theKeyName); void RegistryEraseValue(const SexyString& theValueName); bool RegistryWriteString(const std::string& theValueName, const std::string& theString); bool RegistryWriteInteger(const std::string& theValueName, int theValue); bool RegistryWriteBoolean(const std::string& theValueName, bool theValue); bool RegistryWriteData(const std::string& theValueName, const uchar* theValue, uint32_t theLength); virtual void WriteToRegistry(); virtual void ReadFromRegistry(); SexyString GetString(const std::string& theId); SexyString GetString(const std::string& theId, const SexyString& theDefault); void SetWindowIconBMP(const std::string& icon); virtual void Done3dTesting(); virtual std::string NotifyCrashHook(); // return file name that you want to upload // Properties access methods bool LoadProperties(const std::string& theFileName, bool required, bool checkSig); bool LoadProperties(); bool GetBoolean(const std::string& theId); bool GetBoolean(const std::string& theId, bool theDefault); int GetInteger(const std::string& theId); int GetInteger(const std::string& theId, int theDefault); double GetDouble(const std::string& theId); double GetDouble(const std::string& theId, double theDefault); StringVector GetStringVector(const std::string& theId); void SetBoolean(const std::string& theId, bool theValue); void SetInteger(const std::string& theId, int theValue); void SetDouble(const std::string& theId, double theValue); void SetString(const std::string& theId, const std::wstring& theValue); virtual bool CheckSignature(const Buffer& theBuffer, const std::string& theFileName); protected: // Registry helpers bool RegistryRead(const std::string& theValueName, uint32_t* theType, uchar* theValue, uint32_t* theLength); bool RegistryReadKey(const std::string& theValueName, uint32_t* theType, uchar* theValue, uint32_t* theLength, HKEY theMainKey = HKEY_CURRENT_USER); bool RegistryWrite(const std::string& theValueName, uint32_t theType, const uchar* theValue, uint32_t theLength); virtual bool DoUpdateFrames(); virtual void DoUpdateFramesF(float theFrac); virtual void LoadingThreadCompleted(); virtual void UpdateFrames(); virtual bool DrawDirtyStuff(); void UpdateFTimeAcc(); virtual bool Process(bool allowSleep = true); void ProcessSafeDeleteList(); static int LoadingThreadProcStub(void *theArg); void StartLoadingThread(); virtual void PreDDInterfaceInitHook(); virtual void DeleteNativeImageData(); virtual void PostDDInterfaceInitHook(); virtual void PreDisplayHook(); bool WriteBytesToFile(const std::string& theFileName, const void *theData, uint32_t theDataLen); void RestoreScreenResolution(); void DoExit(int theCode); virtual bool ChangeDirHook(const char *theIntendedPath); virtual void InitPropertiesHook(); virtual void InitHook(); virtual void DeleteExtraImageData(); virtual void ReInitImages(); void Remove3DData(MemoryImage* theMemoryImage); virtual void EnforceCursor(); virtual void PreTerminate(); #if 0 void RehupFocus(); void ClearKeysDown(); // Loading thread methods void TakeScreenshot(); void DumpProgramInfo(); void ShowMemoryUsage(); // Demo recording helpers void ProcessDemo(); public: // Common overrides: virtual void GetSEHWebParams(DefinesMap* theDefinesMap); // Demo access methods bool PrepareDemoCommand(bool required); void WriteDemoTimingBlock(); void WriteDemoBuffer(); bool ReadDemoBuffer(std::string &theError);//UNICODE void DemoSyncBuffer(Buffer* theBuffer); void DemoSyncString(std::string* theString); void DemoSyncInt(int* theInt); void DemoSyncBool(bool* theBool); void DemoAssertStringEqual(const std::string& theString); void DemoAssertIntEqual(int theInt); void DemoAddMarker(const std::string& theString); void DemoRegisterHandle(HANDLE theHandle); void DemoWaitForHandle(HANDLE theHandle); bool DemoCheckHandle(HANDLE theHandle); // File access methods bool EraseFile(const std::string& theFileName); virtual bool IsAltKeyUsed(WPARAM wParam); virtual int MsgBox(const std::string &theText, const std::string &theTitle = "Message", int theFlags = MB_OK); virtual int MsgBox(const std::wstring &theText, const std::wstring &theTitle = L"Message", int theFlags = MB_OK); // Public methods virtual void BeginPopup(); virtual void EndPopup(); virtual void Popup(const std::string& theString); virtual void Popup(const std::wstring& theString); virtual void LogScreenSaverError(const std::string &theError); virtual void URLOpenFailed(const std::string& theURL); virtual void URLOpenSucceeded(const std::string& theURL); virtual bool OpenURL(const std::string& theURL, bool shutdownOnOpen = false); virtual std::string GetProductVersion(const std::string& thePath); virtual void SEHOccured(); virtual std::string GetGameSEHInfo(); virtual void DoParseCmdLine(); virtual void ParseCmdLine(const std::string& theCmdLine); virtual void HandleCmdLineParam(const std::string& theParamName, const std::string& theParamValue); virtual void HandleNotifyGameMessage(int theType, int theParam); // for HWND_BROADCAST of mNotifyGameMessage (0-1000 are reserved for SexyAppBase for theType) void CopyToClipboard(const std::string& theString); std::string GetClipboard(); virtual bool DebugKeyDown(int theKey); virtual bool DebugKeyDownAsync(int theKey, bool ctrlDown, bool altDown); virtual void CloseRequestAsync(); void DemoSyncRefreshRate(); // Misc methods bool IsScreenSaver(); virtual bool AppCanRestore(); #endif void CleanSharedImages(); // Resource access methods void LoadResourceManifest(); void ShowResourceError(bool doExit = false); int InitDDInterface(); void ClearUpdateBacklog(bool relaxForASecond = false); virtual void DoMainLoop(); virtual bool UpdateApp(); virtual void Redraw(Rect* theClipRect); virtual void ShutdownHook(); }; extern SexyAppBase* gSexyAppBase; }; #endif //__SEXYAPPBASE_H__ libtuxcap-1.4.0/tuxcap/include/Point.h0000644000175000017500000000245410641010432017554 0ustar inniyahinniyah#ifndef __POINT_H__ #define __POINT_H__ #include "Common.h" namespace Sexy { template class TPoint { public: _T mX; _T mY; public: TPoint(_T theX, _T theY) : mX(theX), mY(theY) { } TPoint(const TPoint<_T>& theTPoint) : mX(theTPoint.mX), mY(theTPoint.mY) { } TPoint() : mX(0), mY(0) { } inline bool operator==(const TPoint& p) { return ((p.mX == mX) && (p.mY == mY)); } inline bool operator!=(const TPoint& p) { return ((p.mX != mX) || (p.mY != mY)); } TPoint operator+(const TPoint& p) const {return TPoint(mX+p.mX, mY+p.mY);} TPoint operator-(const TPoint& p) const {return TPoint(mX-p.mX, mY-p.mY);} TPoint operator*(const TPoint& p) const {return TPoint(mX*p.mX, mY*p.mY);} TPoint operator/(const TPoint& p) const {return TPoint(mX/p.mX, mY/p.mY);} TPoint& operator+=(const TPoint& p) {mX+=p.mX; mY+=p.mY; return *this;} TPoint& operator-=(const TPoint& p) {mX-=p.mX; mY-=p.mY; return *this;} TPoint& operator*=(const TPoint& p) {mX*=p.mX; mY*=p.mY; return *this;} TPoint& operator/=(const TPoint& p) {mX/=p.mX; mY/=p.mY; return *this;} TPoint operator*(_T s) const {return TPoint(mX*s, mY*s);} TPoint operator/(_T s) const {return TPoint(mX/s, mY/s);} }; typedef TPoint Point; typedef TPoint FPoint; }; #endif //__POINT_H__ libtuxcap-1.4.0/tuxcap/include/ScrollbuttonWidget.h0000644000175000017500000000105110641010432022311 0ustar inniyahinniyah#ifndef __SCROLLBUTTONWIDGET_H__ #define __SCROLLBUTTONWIDGET_H__ #include "ButtonWidget.h" namespace Sexy { class ButtonListener; class ScrollbuttonWidget : public ButtonWidget { public: bool mHorizontal; // mType is a new way of doing things (1 = up, 2 = down, 3 = left, 4 = right). // This overrides mHorizontal and mId. int mType; public: ScrollbuttonWidget(int theId, ButtonListener *theButtonListener, int theType = 0); virtual ~ScrollbuttonWidget(); void Draw(Graphics *g); }; } #endif //__SCROLLBUTTONWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/SDLMain.h0000644000175000017500000000046310742156504017725 0ustar inniyahinniyah/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject @end libtuxcap-1.4.0/tuxcap/include/ImageFont.h0000644000175000017500000001022310723361572020344 0ustar inniyahinniyah#ifndef __IMAGEFONT_H__ #define __IMAGEFONT_H__ #include "Font.h" #include "DescParser.h" #include "SharedImage.h" namespace Sexy { class SexyAppBase; class Image; class CharData { public: Rect mImageRect; Point mOffset; char mKerningOffsets[256]; int mWidth; int mOrder; public: CharData(); }; class FontData; class FontLayer { public: FontData* mFontData; StringVector mRequiredTags; StringVector mExcludedTags; CharData mCharData[256]; Color mColorMult; Color mColorAdd; SharedImageRef mImage; int mDrawMode; Point mOffset; int mSpacing; int mMinPointSize; int mMaxPointSize; int mPointSize; int mAscent; int mAscentPadding; // How much space is above the avg uppercase char int mHeight; // int mDefaultHeight; // Max height of font character image rects int mLineSpacingOffset; // This plus height should get added between lines int mBaseOrder; public: FontLayer(FontData* theFontData); FontLayer(const FontLayer& theFontLayer); }; typedef std::list FontLayerList; typedef std::map FontLayerMap; typedef std::list RectList; class FontData : public DescParser { public: bool mInitialized; int mRefCount; SexyAppBase* mApp; int mDefaultPointSize; uchar mCharMap[256]; FontLayerList mFontLayerList; FontLayerMap mFontLayerMap; std::string mSourceFile; std::string mFontErrorHeader; public: virtual bool Error(const std::string& theError); bool GetColorFromDataElement(DataElement *theElement, Color &theColor); bool DataToLayer(DataElement* theSource, FontLayer** theFontLayer); virtual bool HandleCommand(const ListDataElement& theParams); public: FontData(); virtual ~FontData(); void Ref(); void DeRef(); bool Load(SexyAppBase* theSexyApp, const std::string& theFontDescFileName); bool LoadLegacy(Image* theFontImage, const std::string& theFontDescFileName); }; class ActiveFontLayer { public: FontLayer* mBaseFontLayer; Image* mScaledImage; bool mOwnsImage; Rect mScaledCharImageRects[256]; public: ActiveFontLayer(); ActiveFontLayer(const ActiveFontLayer& theActiveFontLayer); virtual ~ActiveFontLayer(); }; typedef std::list ActiveFontLayerList; class RenderCommand { public: Image* mImage; int mDest[2]; int mSrc[4]; int mMode; Color mColor; RenderCommand* mNext; }; typedef std::multimap RenderCommandMap; class ImageFont : public Font { public: FontData* mFontData; int mPointSize; StringVector mTagVector; bool mActiveListValid; ActiveFontLayerList mActiveLayerList; double mScale; bool mForceScaledImagesWhite; public: virtual void GenerateActiveFontLayers(); virtual void DrawStringEx(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect* theClipRect, RectList* theDrawnAreas, int* theWidth); public: ImageFont(SexyAppBase* theSexyApp, std::string theFontDescFileName); ImageFont(Image *theFontImage); // for constructing your own image font without a file descriptor ImageFont(const ImageFont& theImageFont); virtual ~ImageFont(); // Deprecated ImageFont(Image* theFontImage, const std::string& theFontDescFileName); //ImageFont(const ImageFont& theImageFont, Image* theImage); virtual int CharWidth(char theChar); virtual int CharWidthKern(char theChar, char thePrevChar); virtual int StringWidth(const SexyString& theString); virtual void DrawString(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect& theClipRect); virtual Font* Duplicate(); virtual void SetPointSize(int thePointSize); virtual int GetPointSize(); virtual void SetScale(double theScale); virtual int GetDefaultPointSize(); virtual bool AddTag(const std::string& theTagName); virtual bool RemoveTag(const std::string& theTagName); virtual bool HasTag(const std::string& theTagName); virtual std::string GetDefine(const std::string& theName); virtual void Prepare(); }; } #endif //__IMAGEFONT_H__ libtuxcap-1.4.0/tuxcap/include/Dialog.h0000644000175000017500000000567010641010432017665 0ustar inniyahinniyah#ifndef __DIALOG_H__ #define __DIALOG_H__ #include "Widget.h" #include "ButtonListener.h" namespace Sexy { class DialogListener; class ButtonWidget; class DialogButton; class Font; extern SexyString DIALOG_YES_STRING; extern SexyString DIALOG_NO_STRING; extern SexyString DIALOG_OK_STRING; extern SexyString DIALOG_CANCEL_STRING; typedef std::vector StringVector; class Dialog : public Widget, public ButtonListener { public: enum { BUTTONS_NONE, BUTTONS_YES_NO, BUTTONS_OK_CANCEL, BUTTONS_FOOTER }; enum { ID_YES = 1000, ID_NO = 1001, ID_OK = 1000, ID_CANCEL = 1001, ID_FOOTER = 1000 }; enum { COLOR_HEADER = 0, COLOR_LINES, COLOR_FOOTER, COLOR_BUTTON_TEXT, COLOR_BUTTON_TEXT_HILITE, COLOR_BKG, COLOR_OUTLINE, NUM_COLORS }; DialogListener* mDialogListener; Image* mComponentImage; DialogButton* mYesButton; DialogButton* mNoButton; int mNumButtons; SexyString mDialogHeader; SexyString mDialogFooter; SexyString mDialogLines; int mButtonMode; Font* mHeaderFont; Font* mLinesFont; int mTextAlign; int mLineSpacingOffset; int mButtonHeight; Insets mBackgroundInsets; Insets mContentInsets; int mSpaceAfterHeader; bool mDragging; int mDragMouseX; int mDragMouseY; int mId; bool mIsModal; int mResult; int mButtonHorzSpacing; int mButtonSidePadding; public: void EnsureFonts(); public: Dialog(Image* theComponentImage, Image* theButtonComponentImage, int theId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode); //UNICODE virtual ~Dialog(); virtual void SetButtonFont(Font* theFont); virtual void SetHeaderFont(Font* theFont); virtual void SetLinesFont(Font* theFont); virtual void SetColor(int theIdx, const Color& theColor); virtual int GetPreferredHeight(int theWidth); virtual void Draw(Graphics* g); virtual void AddedToManager(WidgetManager* theWidgetManager); virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void OrderInManagerChanged(); virtual void Resize(int theX, int theY, int theWidth, int theHeight); virtual void MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); } virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseDrag(int x, int y); virtual void MouseUp(int x, int y) { Widget::MouseUp(x, y); } virtual void MouseUp(int x, int y, int theClickCount) { Widget::MouseUp(x, y, theClickCount); } virtual void MouseUp(int x, int y, int theBtnNum, int theClickCount); virtual void Update(); virtual bool IsModal(); virtual int WaitForResult(bool autoKill = true); virtual void ButtonPress(int theId); virtual void ButtonDepress(int theId); virtual void ButtonDownTick(int theId); }; } #endif //__DIALOG_H__ libtuxcap-1.4.0/tuxcap/include/WidgetManager.h0000644000175000017500000000704111202747625021215 0ustar inniyahinniyah#ifndef __WIDGETMANAGER_H__ #define __WIDGETMANAGER_H__ #include "Common.h" #include "WidgetContainer.h" #include "SDL_keysym.h" namespace Sexy { class Widget; class Image; class MemoryImage; class SexyAppBase; class Graphics; typedef std::list WidgetList; enum { WIDGETFLAGS_UPDATE = 1, WIDGETFLAGS_MARK_DIRTY = 2, WIDGETFLAGS_DRAW = 4, WIDGETFLAGS_CLIP = 8, WIDGETFLAGS_ALLOW_MOUSE = 16, WIDGETFLAGS_ALLOW_FOCUS = 32, }; class PreModalInfo { public: Widget* mBaseModalWidget; Widget* mPrevBaseModalWidget; Widget* mPrevFocusWidget; FlagsMod mPrevBelowModalFlagsMod; }; typedef std::list PreModalInfoList; typedef std::vector > DeferredOverlayVector; class WidgetManager : public WidgetContainer { public: Widget* mDefaultTab; Graphics* mCurG; SexyAppBase* mApp; MemoryImage* mImage; MemoryImage* mTransientImage; bool mLastHadTransients; Widget* mPopupCommandWidget; DeferredOverlayVector mDeferredOverlayWidgets; int mMinDeferredOverlayPriority; bool mHasFocus; Widget* mFocusWidget; Widget* mLastDownWidget; Widget* mOverWidget; Widget* mBaseModalWidget; FlagsMod mLostFocusFlagsMod; FlagsMod mBelowModalFlagsMod; FlagsMod mDefaultBelowModalFlagsMod; PreModalInfoList mPreModalInfoList; Rect mMouseDestRect; Rect mMouseSourceRect; bool mMouseIn; int mLastMouseX; int mLastMouseY; int mDownButtons; int mActualDownButtons; int mLastInputUpdateCnt; //FIXME SDL does this for us so use it bool mKeyDown[SDLK_LAST]; int mLastDownButtonId; int mWidgetFlags; protected: int GetWidgetFlags(); void MouseEnter(Widget* theWidget); void MouseLeave(Widget* theWidget); protected: void SetBaseModal(Widget* theWidget, const FlagsMod& theBelowFlagsMod); public: WidgetManager(SexyAppBase* theApplet); virtual ~WidgetManager(); void FreeResources(); void AddBaseModal(Widget* theWidget, const FlagsMod& theBelowFlagsMod); void AddBaseModal(Widget* theWidget); void RemoveBaseModal(Widget* theWidget); void Resize(const Rect& theMouseDestRect, const Rect& theMouseSourceRect); void DisableWidget(Widget* theWidget); Widget* GetAnyWidgetAt(int x, int y, int* theWidgetX, int* theWidgetY); Widget* GetWidgetAt(int x, int y, int* theWidgetX, int* theWidgetY); void SetFocus(Widget* aWidget); void GotFocus(); void LostFocus(); void InitModalFlags(ModalFlags* theModalFlags); void DrawWidgetsTo(Graphics* g); void DoMouseUps(Widget* theWidget, uint32_t theDownCode); void DoMouseUps(); void DeferOverlay(Widget* theWidget, int thePriority); void FlushDeferredOverlayWidgets(int theMaxPriority); bool DrawScreen(); bool UpdateFrame(); bool UpdateFrameF(float theFrac); void SetPopupCommandWidget(Widget* theList); void RemovePopupCommandWidget(); void MousePosition(int x, int y); void RehupMouse(); void RemapMouse(int& theX, int& theY); bool MouseUp(int x, int y, int theClickCount); bool MouseDown(int x, int y, int theClickCount); bool MouseMove(int x, int y); bool MouseDrag(int x, int y); bool MouseExit(int x, int y); void MouseWheel(int theDelta); bool KeyChar(SexyChar theChar); bool KeyDown(KeyCode key); bool KeyUp(KeyCode key); bool IsLeftButtonDown(); bool IsMiddleButtonDown(); bool IsRightButtonDown(); }; } #endif // __WIDGETMANAGER_H__ libtuxcap-1.4.0/tuxcap/include/MI_GetRLAlphaData.inc0000644000175000017500000000160610641010426022110 0ustar inniyahinniyah{ uchar* aWPtr = mRLAlphaData; if (mWidth==1) { memset(aWPtr,1,mHeight); } else { for (int aRow = 0; aRow < mHeight; aRow++) { int aRCount = 1; int aRLCount = 1; int anAVal = NEXT_SRC_COLOR >> 24; int aLastAClass = (anAVal == 0) ? 0 : (anAVal == 255) ? 1 : 2; while (aRCount < mWidth) { aRCount++; anAVal = NEXT_SRC_COLOR >> 24; int aThisAClass = (anAVal == 0) ? 0 : (anAVal == 255) ? 1 : 2; if ((aThisAClass != aLastAClass) || (aRCount == mWidth)) { if (aThisAClass == aLastAClass) aRLCount++; for (int i = aRLCount; i > 0; i--) { if (i >= 255) *aWPtr++ = 255; else *aWPtr++ = i; } if ((aRCount == mWidth) && (aThisAClass != aLastAClass)) *aWPtr++ = 1; aLastAClass = aThisAClass; aRLCount = 1; } else { aRLCount++; } } } } } libtuxcap-1.4.0/tuxcap/include/EditWidget.h0000644000175000017500000000525310641010426020517 0ustar inniyahinniyah#ifndef __EDITWIDGET_H__ #define __EDITWIDGET_H__ #include "Widget.h" namespace Sexy { class Font; class EditListener; class EditWidget : public Widget { public: enum { COLOR_BKG, COLOR_OUTLINE, COLOR_TEXT, COLOR_HILITE, COLOR_HILITE_TEXT, NUM_COLORS }; int mId; SexyString mString; SexyString mPasswordDisplayString; Font* mFont; struct WidthCheck { Font *mFont; int mWidth; }; typedef std::list WidthCheckList; WidthCheckList mWidthCheckList; EditListener* mEditListener; bool mShowingCursor; bool mDrawSelOverride; // set this to true to draw selected text even when not in focus bool mHadDoubleClick; // Used to fix a bug with double clicking to hilite a word after the widget manager started calling mouse drag before mouse down/up events int mCursorPos; int mHilitePos; int mBlinkAcc; int mBlinkDelay; int mLeftPos; int mMaxChars; int mMaxPixels; SexyChar mPasswordChar; SexyString mUndoString; int mUndoCursor; int mUndoHilitePos; int mLastModifyIdx; protected: virtual void ProcessKey(SDLKey theKey, SexyChar theChar); SexyString& GetDisplayString(); virtual void HiliteWord(); void UpdateCaretPos(); public: virtual void SetFont(Font* theFont, Font* theWidthCheckFont = NULL); virtual void SetText(const SexyString& theText, bool leftPosToZero = true); virtual bool IsPartOfWord(SexyChar theChar); virtual int GetCharAt(int x, int y); virtual void Resize(int theX, int theY, int theWidth, int theHeight); virtual void Draw(Graphics* g); // Already translated; virtual void Update(); virtual void MarkDirty(); virtual bool WantsFocus(); virtual void GotFocus(); virtual void LostFocus(); virtual void FocusCursor(bool bigJump); virtual void KeyDown(SDLKey theKey); virtual void KeyChar(SexyChar theChar); virtual void MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); } virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseUp(int x, int y) { Widget::MouseUp(x, y); } virtual void MouseUp(int x, int y, int theClickCount) { Widget::MouseUp(x, y, theClickCount); } virtual void MouseUp(int x, int y, int theBtnNum, int theClickCount); virtual void MouseDrag(int x, int y); virtual void MouseEnter(); virtual void MouseLeave(); void ClearWidthCheckFonts(); void AddWidthCheckFont(Font *theFont, int theMaxPixels = -1); // defaults to mMaxPixels void EnforceMaxPixels(); public: EditWidget(int theId, EditListener* theEditListener); virtual ~EditWidget(); }; } #endif //__EDITWIDGET_H__ libtuxcap-1.4.0/tuxcap/include/ScrollListener.h0000644000175000017500000000032510641010426021425 0ustar inniyahinniyah#ifndef __SCROLLLISTENER_H__ #define __SCROLLLISTENER_H__ namespace Sexy { class ScrollListener { public: virtual void ScrollPosition(int theId, double thePosition) {}; }; } #endif // __SCROLLLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/Color.h0000644000175000017500000000170611202747625017557 0ustar inniyahinniyah#ifndef __COLOR_H__ #define __COLOR_H__ #include "Common.h" namespace Sexy { #pragma pack(push,1) struct SexyRGBA {unsigned char b,g,r,a;}; #pragma pack(pop) class Color { public: int mRed; int mGreen; int mBlue; int mAlpha; static Color Black; static Color White; public: Color(); Color(int theColor); Color(int theColor, int theAlpha); Color(int theRed, int theGreen, int theBlue); Color(int theRed, int theGreen, int theBlue, int theAlpha); Color(const SexyRGBA &theColor); Color(const uchar* theElements); Color(const int* theElements); int GetRed() const; int GetGreen() const; int GetBlue() const; int GetAlpha() const; uint32_t ToInt() const; SexyRGBA ToRGBA() const; int& operator[](int theIdx); int operator[](int theIdx) const; }; bool operator==(const Color& theColor1, const Color& theColor2); bool operator!=(const Color& theColor1, const Color& theColor2); } #endif //__COLOR_H__ libtuxcap-1.4.0/tuxcap/include/CheckboxListener.h0000644000175000017500000000032310641010426021713 0ustar inniyahinniyah#ifndef __CHECKBOX_LISTENER__ #define __CHECKBOX_LISTENER__ namespace Sexy { class CheckboxListener { public: virtual void CheckboxChecked(int theId, bool checked) {} }; } #endif //__CHECKBOX_LISTENER__ libtuxcap-1.4.0/tuxcap/include/SDLMixerMusicInterface.h0000644000175000017500000000553210737636302022754 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* To be able to use midi, install package freepats which contains midi instruments */ #ifndef __SDLMIXERMUSICINTERFACE_H__ #define __SDLMIXERMUSICINTERFACE_H__ #include "MusicInterface.h" #include "SDL_mixer.h" #ifndef WIN32 #define HWND void* #endif namespace Sexy { class SexyAppBase; class SDLMixerMusicInfo { public: Mix_Music* music; float mVolume; bool mStopOnFade; bool mRepeats; int mPosition; bool mIsActive; public: SDLMixerMusicInfo(); }; typedef std::map SDLMixerMusicMap; class SDLMixerMusicInterface : public MusicInterface { public: SDLMixerMusicMap mMusicMap; float mMasterVolume; int mCurrentMusic; public: SDLMixerMusicInterface(HWND theHWnd); virtual ~SDLMixerMusicInterface(); virtual bool LoadMusic(int theSongId, const std::string& theFileName); virtual void PlayMusic(int theSongId, int theOffset = 0, bool noLoop = false); virtual void StopMusic(int theSongId); virtual void PauseMusic(int theSongId); virtual void ResumeMusic(int theSongId); virtual void StopAllMusic(); virtual void UnloadMusic(int theSongId); virtual void UnloadAllMusic(); virtual void PauseAllMusic(); virtual void ResumeAllMusic(); virtual void FadeIn(int theSongId, int theOffset = -1, double theSpeed = 0.002, bool noLoop = false); virtual void FadeOut(int theSongId, bool stopSong = true, double theSpeed = 0.004); virtual void FadeOutAll(bool stopSong = true, double theSpeed = 0.004); virtual void SetSongVolume(int theSongId, double theVolume); virtual bool IsPlaying(int theSongId); virtual void SetVolume(double theVolume); virtual void Update(); void DeactivateAllMusic(); }; } #endif //__SDLMIXERMUSICINTERFACE_H__ libtuxcap-1.4.0/tuxcap/include/Rect.h0000644000175000017500000000463010641010426017361 0ustar inniyahinniyah#ifndef __TRectANGLE_H__ #define __TRectANGLE_H__ #include "Common.h" #include "Point.h" #include namespace Sexy { template class TRect { public: _T mX; _T mY; _T mWidth; _T mHeight; public: TRect(_T theX, _T theY, _T theWidth, _T theHeight) : mX(theX), mY(theY), mWidth(theWidth), mHeight(theHeight) { } TRect(const TRect<_T>& theTRect) : mX(theTRect.mX), mY(theTRect.mY), mWidth(theTRect.mWidth), mHeight(theTRect.mHeight) { } TRect() : mX(0), mY(0), mWidth(0), mHeight(0) { } bool Intersects(const TRect<_T>& theTRect) const { return !((theTRect.mX + theTRect.mWidth <= mX) || (theTRect.mY + theTRect.mHeight <= mY) || (theTRect.mX >= mX + mWidth) || (theTRect.mY >= mY + mHeight)); } TRect<_T> Intersection(const TRect<_T>& theTRect) const { _T x1 = std::max(mX, theTRect.mX); _T x2 = std::min(mX + mWidth, theTRect.mX + theTRect.mWidth); _T y1 = std::max(mY, theTRect.mY); _T y2 = std::min(mY + mHeight, theTRect.mY + theTRect.mHeight); if (((x2 - x1) < 0) || ((y2 - y1) < 0)) return TRect<_T>(0,0,0,0); else return TRect<_T>(x1, y1, x2 - x1, y2 - y1); } TRect<_T> Union(const TRect<_T>& theTRect) { _T x1 = min(mX, theTRect.mX); _T x2 = max(mX + mWidth, theTRect.mX + theTRect.mWidth); _T y1 = min(mY, theTRect.mY); _T y2 = max(mY + mHeight, theTRect.mY + theTRect.mHeight); return TRect<_T>(x1, y1, x2 - x1, y2 - y1); } bool Contains(_T theX, _T theY) const { return ((theX >= mX) && (theX < mX + mWidth) && (theY >= mY) && (theY < mY + mHeight)); } bool Contains(const TPoint<_T>& thePoint) const { return ((thePoint.mX >= mX) && (thePoint.mX < mX + mWidth) && (thePoint.mY >= mY) && (thePoint.mY < mY + mHeight)); } void Offset(_T theX, _T theY) { mX += theX; mY += theY; } void Offset(const TPoint<_T>& thePoint) { mX += thePoint.mX; mY += thePoint.mY; } TRect Inflate(_T theX, _T theY) { mX -= theX; mWidth += theX*2; mY -= theY; mHeight += theY*2; return *this; } bool operator==(const TRect<_T>& theRect) const { return (mX == theRect.mX) && (mY == theRect.mY) && (mWidth == theRect.mWidth) && (mHeight == theRect.mHeight); } #if 0 RECT ToRECT() const { RECT aRect = {mX, mY, mX + mWidth, mY + mHeight}; return aRect; } #endif }; typedef TRect Rect; typedef TRect FRect; typedef TRect fRect; }; #endif //__TRectANGLE_H__ libtuxcap-1.4.0/tuxcap/include/Checkbox.h0000644000175000017500000000166210641010426020214 0ustar inniyahinniyah#ifndef __CHECKBOX_H__ #define __CHECKBOX_H__ #include "Widget.h" namespace Sexy { class CheckboxListener; class Image; class Checkbox : public Widget { protected: CheckboxListener* mListener; public: int mId; bool mChecked; Image* mUncheckedImage; Image* mCheckedImage; Rect mCheckedRect; Rect mUncheckedRect; Color mOutlineColor; // These are only used if no image is specified Color mBkgColor; Color mCheckColor; public: virtual void SetChecked(bool checked, bool tellListener = true); virtual bool IsChecked(); virtual void MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); } virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void Draw(Graphics* g); public: Checkbox(Image* theUncheckedImage, Image* theCheckedImage, int theId, CheckboxListener* theCheckboxListener); }; } #endif //__CHECKBOX_H__ libtuxcap-1.4.0/tuxcap/include/Flags.h0000644000175000017500000000243610641010426017522 0ustar inniyahinniyah#ifndef __FLAGS_H__ #define __FLAGS_H__ namespace Sexy { class FlagsMod { public: int mAddFlags; int mRemoveFlags; public: FlagsMod() { mAddFlags = 0; mRemoveFlags = 0; } }; inline void ModFlags(int& theFlags, const FlagsMod& theFlagMod) { theFlags = (theFlags | theFlagMod.mAddFlags) & ~theFlagMod.mRemoveFlags; } inline int GetModFlags(int theFlags, const FlagsMod& theFlagMod) { return (theFlags | theFlagMod.mAddFlags) & ~theFlagMod.mRemoveFlags; } class ModalFlags { public: int mOverFlags; int mUnderFlags; bool mIsOver; public: void ModFlags(const FlagsMod& theFlagsMod) { Sexy::ModFlags(mOverFlags, theFlagsMod); Sexy::ModFlags(mUnderFlags, theFlagsMod); } int GetFlags() { return mIsOver ? mOverFlags : mUnderFlags; } }; class AutoModalFlags { public: ModalFlags* mModalFlags; int mOldOverFlags; int mOldUnderFlags; public: AutoModalFlags(ModalFlags* theModalFlags, const FlagsMod& theFlagMod) { mModalFlags = theModalFlags; mOldOverFlags = theModalFlags->mOverFlags; mOldUnderFlags = theModalFlags->mUnderFlags; theModalFlags->ModFlags(theFlagMod); } ~AutoModalFlags() { mModalFlags->mOverFlags = mOldOverFlags; mModalFlags->mUnderFlags = mOldUnderFlags; } }; } #endif //__FLAGS_H__ libtuxcap-1.4.0/tuxcap/include/ListListener.h0000644000175000017500000000050610641010426021103 0ustar inniyahinniyah#ifndef __LISTLISTENER_H__ #define __LISTLISTENER_H__ namespace Sexy { class ListListener { public: virtual void ListClicked(int theId, int theIdx, int theClickCount) {} virtual void ListClosed(int theId) {} virtual void ListHiliteChanged(int theId, int theOldIdx, int theNewIdx) {} }; } #endif //__LISTLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/SliderListener.h0000644000175000017500000000031210641010426021405 0ustar inniyahinniyah#ifndef __SLIDERLISTENER_H__ #define __SLIDERLISTENER_H__ namespace Sexy { class SliderListener { public: virtual void SliderVal(int theId, double theVal) {}; }; } #endif //__SLIDERLISTENER_H__ libtuxcap-1.4.0/tuxcap/include/DDI_AlphaBlt.inc0000644000175000017500000003753711202747625021205 0ustar inniyahinniyahif (mSurface->format->BitsPerPixel == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theY * mSurface->pitch/2) + theX; uchar* aRLAlphaDataRow = aSrcRLAlphaData + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (theColor == Color::White) { #ifdef OPTIMIZE_SOFTWARE_DRAWING if (aGMask == 0x7E0) // 5-6-5 optimizations { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int oma = 256 - (src >> 24); if (oma == 1) // Fully opaque { for (int i = 0; i < rl; i++) *aDestPixels _PLUSPLUS = NEXT_SRC_COLOR; } else if (oma == 256) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { oma >>= 3; aSrcPixels++; uint32_t dest = (((*aDestPixels | (*aDestPixels << 16)) & 0x7E0F81F) * oma >> 5) & 0x7E0F81F; *(aDestPixels _PLUSPLUS) = src + (dest | (dest >> 16)); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int oma = (256 - (src >> 24)) >> 3; uint32_t dest = (((*aDestPixels | (*aDestPixels << 16)) & 0x7E0F81F) * oma >> 5) & 0x7E0F81F; *(aDestPixels _PLUSPLUS) = src + (dest | (dest >> 16)); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } else if (aGMask == 0x3E0) // 5-5-5 optimizations { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int oma = 256 - (src >> 24); if (oma == 1) // Fully opaque { for (int i = 0; i < rl; i++) *aDestPixels _PLUSPLUS = NEXT_SRC_COLOR; } else if (oma == 256) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { oma >>= 3; aSrcPixels++; uint32_t dest = (((*aDestPixels | (*aDestPixels << 16)) & 0x3E07C1F) * oma >> 5) & 0x3E07C1F; *(aDestPixels _PLUSPLUS) = src + (dest | (dest >> 16)); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int oma = (256 - (src >> 24)) >> 3; uint32_t dest = (((*aDestPixels | (*aDestPixels << 16)) & 0x3E07C1F) * oma >> 5) & 0x3E07C1F; *(aDestPixels _PLUSPLUS) = src + (dest | (dest >> 16)); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } else #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int oma = 256 - (src >> 24); if (oma == 1) // Fully opaque { for (int i = 0; i < rl; i++) *aDestPixels _PLUSPLUS = NEXT_SRC_COLOR; } else if (oma == 256) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { aSrcPixels++; uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma) ) >> 8) & aRMask) + (((((dest & aGMask) * oma) ) >> 8) & aGMask) + (((((dest & aBMask) * oma) ) >> 8) & aBMask); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int oma = 256 - (src >> 24); uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma) ) >> 8) & aRMask) + (((((dest & aGMask) * oma) ) >> 8) & aGMask) + (((((dest & aBMask) * oma) ) >> 8) & aBMask); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; #ifdef OPTIMIZE_SOFTWARE_DRAWING bool performNormalBlit = true; if (cr == cg && cg == cb) { if (aGMask == 0x7E0) { performNormalBlit = false; cr >>= 3; for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int a = src >> 24; if ((a == 255) && (ca == 255)) // Fully opaque { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = (((( (src & 0xFFFF) | (src << 16)) & 0x7E0F81F) * cr) >> 5) & 0x7E0F81F; *(aDestPixels _PLUSPLUS) = dest | (dest >> 16); } } else if (a == 0) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; a = ((src >> 24) * ca) / 255; int oma = (256 - a) >> 3; uint32_t dest = (*aDestPixels | (*aDestPixels << 16)) & 0x7E0F81F; src &= 0xFFFF; src = ( (src & 0xFFFF) | (src << 16)) & 0x7E0F81F; dest = ((dest * oma + src * cr) >> 5) & 0x7E0F81F; *(aDestPixels _PLUSPLUS) = dest | (dest >> 16); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } else if (aGMask == 0x3E0) { performNormalBlit = false; cr >>= 3; for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int a = src >> 24; if ((a == 255) && (ca == 255)) // Fully opaque { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; uint32_t dest = (((( (src & 0xFFFF) | (src << 16)) & 0x3E07C1F) * cr) >> 5) & 0x3E07C1F; *(aDestPixels _PLUSPLUS) = dest | (dest >> 16); } } else if (a == 0) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; a = ((src >> 24) * ca) / 255; int oma = (256 - a) >> 3; uint32_t dest = (*aDestPixels | (*aDestPixels << 16)) & 0x3E07C1F; src &= 0xFFFF; src = ( (src & 0xFFFF) | (src << 16)) & 0x3E07C1F; dest = ((dest * oma + src * cr) >> 5) & 0x3E07C1F; *(aDestPixels _PLUSPLUS) = (dest | (dest >> 16)); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } } if (performNormalBlit) #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int a = src >> 24; if ((a == 255) && (ca == 255)) // Fully opaque { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; *(aDestPixels _PLUSPLUS) = (((((src & aRMask) * cr) ) >> 8) & aRMask) + (((((src & aGMask) * cg) ) >> 8) & aGMask) + (((((src & aBMask) * cb) ) >> 8) & aBMask); } } else if (a == 0) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; a = ((src >> 24) * ca) / 255; int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = (((((dest & aRMask) * oma) + ((src & aRMask) * cr) ) >> 8) & aRMask) + (((((dest & aGMask) * oma) + ((src & aGMask) * cg) ) >> 8) & aGMask) + (((((dest & aBMask) * oma) + ((src & aBMask) * cb) ) >> 8) & aBMask); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/2; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theY * mSurface->pitch/4) + theX; uchar* aRLAlphaDataRow = aSrcRLAlphaData + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (theColor == Color::White) { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int oma = 256 - (src >> 24); if (oma == 1) // Fully opaque { for (int i = 0; i < rl; i++) *aDestPixels _PLUSPLUS = NEXT_SRC_COLOR; } else if (oma == 256) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { #ifdef OPTIMIZE_SOFTWARE_DRAWING aSrcPixels++; int oma = 256 - (src >> 24); uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + ((((dest & 0xFF00FF) * oma) >> 8) & 0xFF00FF) + ((((dest & 0x00FF00) * oma) >> 8) & 0x00FF00); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int oma = 256 - (src >> 24); uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + ((((dest & 0xFF00FF) * oma) >> 8) & 0xFF00FF) + ((((dest & 0x00FF00) * oma) >> 8) & 0x00FF00); } #else aSrcPixels++; uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma)) >> 8) & aRMask) + (((((dest & aGMask) * oma)) >> 8) & aGMask) + (((((dest & aBMask) * oma)) >> 8) & aBMask); for (int i = 1; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; int oma = 256 - (src >> 24); uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = src + (((((dest & aRMask) * oma)) >> 8) & aRMask) + (((((dest & aGMask) * oma)) >> 8) & aGMask) + (((((dest & aBMask) * oma)) >> 8) & aBMask); } #endif } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } else { int ca = theColor.mAlpha; int cr = (theColor.mRed * ca) / 255; int cg = (theColor.mGreen * ca) / 255; int cb = (theColor.mBlue * ca) / 255; #ifdef OPTIMIZE_SOFTWARE_DRAWING bool performNormalBlit = true; if (cr == cg && cg == cb) { performNormalBlit = false; for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int a = src >> 24; if ((a == 255) && (ca == 255)) // Fully opaque { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; *(aDestPixels _PLUSPLUS) = ((((src & 0xFF00FF) * cr) >> 8) & 0xFF00FF) + ((((src & 0x00FF00) * cr) >> 8) & 0x00FF00); } } else if (a == 0) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; a = ((src >> 24) * ca) / 255; int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = ((((dest & 0xFF00FF) * oma + (src & 0xFF00FF) * cr) >> 8) & 0xFF00FF) + ((((dest & 0x00FF00) * oma + (src & 0x00FF00) * cr) >> 8) & 0x00FF00); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } if (performNormalBlit) #endif { for (int y = 0; y < theSrcRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; uchar* aRLAlphaData = aRLAlphaDataRow; aSrcPixels = aSrcPixelsRow; for (int aSpanLeft = theSrcRect.mWidth; aSpanLeft > 0; ) { uint32_t src = PEEK_SRC_COLOR; uchar rl = *aRLAlphaData; if (rl > aSpanLeft) rl = aSpanLeft; int a = src >> 24; if ((a == 255) && (ca == 255)) // Fully opaque { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; *(aDestPixels _PLUSPLUS) = (((((src & aRMask) * cr)) >> 8) & aRMask) + (((((src & aGMask) * cg)) >> 8) & aGMask) + (((((src & aBMask) * cb)) >> 8) & aBMask); } } else if (a == 0) // Fully transparent { aDestPixels _PLUSEQUALS rl; aSrcPixels += rl; } else // Partially transparent { for (int i = 0; i < rl; i++) { uint32_t src = NEXT_SRC_COLOR; a = ((src >> 24) * ca) / 255; int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels _PLUSPLUS) = (((((dest & aRMask) * oma) + ((src & aRMask) * cr)) >> 8) & aRMask) + (((((dest & aGMask) * oma) + ((src & aGMask) * cg)) >> 8) & aGMask) + (((((dest & aBMask) * oma) + ((src & aBMask) * cb)) >> 8) & aBMask); } } aRLAlphaData += rl; aSpanLeft -= rl; } aDestPixelsRow += mSurface->pitch/4; aSrcPixelsRow += theImage->mWidth; aRLAlphaDataRow += theImage->mWidth; } } } } libtuxcap-1.4.0/tuxcap/include/AudiereSoundManager.h0000644000175000017500000000344610766713353022373 0ustar inniyahinniyah/* Original Audiere Sound Manager by Rheenen 2005 */ #ifndef __AudiereSoundMANAGER_H__ #define __AudiereSoundMANAGER_H__ #include "SoundManager.h" #include "audiere.h" #include "SDL.h" #ifndef WIN32 #define HWND void* #endif using namespace audiere; namespace Sexy { class AudiereSoundInstance; class AudiereSoundManager : public SoundManager { friend class AudiereSoundInstance; protected: SampleSourcePtr mSourceSounds[MAX_SOURCE_SOUNDS]; float mBaseVolumes[MAX_SOURCE_SOUNDS]; int mBasePans[MAX_SOURCE_SOUNDS]; float mBasePitches[MAX_SOURCE_SOUNDS]; AudiereSoundInstance* mPlayingSounds[MAX_CHANNELS]; float mMasterVolume; Uint32 mLastReleaseTick; protected: int FindFreeChannel(); void ReleaseFreeChannels(); public: AudioDevicePtr mDevice; public: AudiereSoundManager(); virtual ~AudiereSoundManager(); virtual bool Initialized(); virtual bool LoadSound(unsigned int theSfxID, const std::string& theFilename); virtual int LoadSound(const std::string& theFilename); virtual void ReleaseSound(unsigned int theSfxID); virtual int GetFreeSoundId(); virtual int GetNumSounds(); virtual void SetVolume(double theVolume); virtual bool SetBaseVolume(unsigned int theSfxID, double theBaseVolume); virtual bool SetBasePan(unsigned int theSfxID, int theBasePan); virtual bool SetBasePitch(unsigned int theSfxID, float theBasePitch); virtual SoundInstance* GetSoundInstance(unsigned int theSfxID); virtual void ReleaseSounds(); virtual void ReleaseChannels(); virtual double GetMasterVolume(); virtual void SetMasterVolume(double theVolume); virtual void Flush(); virtual void SetCooperativeWindow(HWND theHWnd, bool isWindowed); virtual void StopAllSounds(); }; } #endif //__AudiereSoundMANAGER_H__ libtuxcap-1.4.0/tuxcap/include/MI_SlowStretchBlt.inc0000644000175000017500000001743111202747625022335 0ustar inniyahinniyah{ uint32_t* aDestBits = GetBits(); int aSrcRowWidth = aSrcMemoryImage->GetWidth(); int aSrcXI = (int) floor(theSrcRect.mX); int aSrcYI = (int) floor(theSrcRect.mY); int aSrcWidthI = (int) ceil(theSrcRect.mWidth + (theSrcRect.mX - aSrcXI)); int aSrcHeightI = (int) ceil(theSrcRect.mHeight + (theSrcRect.mY - aSrcYI)); if (aSrcXI<0) aSrcXI = 0; if (aSrcYI<0) aSrcYI = 0; if (aSrcXI + aSrcWidthI > theImage->mWidth) aSrcWidthI = theImage->mWidth - aSrcXI; if (aSrcYI + aSrcHeightI > theImage->mHeight) aSrcHeightI = theImage->mHeight - aSrcYI; if (aSrcWidthI<=0 || aSrcHeightI<=0) return; int aTempDestWidth = theDestRect.mWidth+4; int aTempDestHeight = theDestRect.mHeight+4; // For holding horizontally resized pixels not vertically (yet) uint32_t* aNewHorzPixels = new uint32_t[aTempDestWidth*aSrcHeightI*4]; uint32_t* aNewHorzPixelsEnd = aNewHorzPixels + (aTempDestWidth*aSrcHeightI*4); memset(aNewHorzPixels, 0, aTempDestWidth*aSrcHeightI*4*4); int aSrcImageWidth = theImage->GetWidth(); if (theSrcRect.mWidth >= theDestRect.mWidth) { double aDestXFactor = theDestRect.mWidth / theSrcRect.mWidth; double aDestXOffset = 1.0 + (aSrcXI - theSrcRect.mX) * aDestXFactor; // Shrinking for (int aSrcX = 0; aSrcX < aSrcWidthI; aSrcX++) { double aDestX1 = aDestXFactor * aSrcX + aDestXOffset; double aDestX2 = aDestX1 + aDestXFactor; int aDestXI1 = (int) aDestX1; int aDestXI2 = (int) aDestX2; SRC_TYPE* s1 = &aSrcBits[aSrcYI*aSrcRowWidth + aSrcXI+aSrcX]; if (aDestXI1 == aDestXI2) { uint32_t* d = &aNewHorzPixels[aDestXI1*4]; int aFactor = (int) (257 * aDestXFactor); for (int aSrcY = 0; aSrcY < aSrcHeightI; aSrcY++) { uint32_t pixel = READ_COLOR(s1); *d++ += aFactor * ((pixel ) & 0xFF); *d++ += aFactor * ((pixel >> 8) & 0xFF); *d++ += aFactor * ((pixel >> 16) & 0xFF); *d++ += aFactor * ((pixel >> 24) & 0xFF); assert(d <= aNewHorzPixelsEnd); d += aTempDestWidth*4 - 4; s1 += aSrcRowWidth; } } else { int aFactor1 = (int) (257 * (aDestXI2 - aDestX1)); int aFactor2 = (int) (257 * (aDestX2 - aDestXI2)); uint32_t* d = &aNewHorzPixels[aDestXI1*4]; for (int aSrcY = 0; aSrcY < aSrcHeightI; aSrcY++) { uint32_t pixel = READ_COLOR(s1); *d++ += aFactor1 * ((pixel ) & 0xFF); *d++ += aFactor1 * ((pixel >> 8) & 0xFF); *d++ += aFactor1 * ((pixel >> 16) & 0xFF); *d++ += aFactor1 * ((pixel >> 24) & 0xFF); *d++ += aFactor2 * ((pixel ) & 0xFF); *d++ += aFactor2 * ((pixel >> 8) & 0xFF); *d++ += aFactor2 * ((pixel >> 16) & 0xFF); *d++ += aFactor2 * ((pixel >> 24) & 0xFF); assert(d <= aNewHorzPixelsEnd); d += aTempDestWidth*4 - 8; s1 += aSrcRowWidth; } } } } else { double aSrcXFactor; if (theDestRect.mWidth != 1) aSrcXFactor = (theSrcRect.mWidth - 1) / (theDestRect.mWidth - 1); else aSrcXFactor = (theSrcRect.mWidth) / (theDestRect.mWidth); for (int aDestX = 1; aDestX < aTempDestWidth-1; aDestX++) { uint32_t* d = &aNewHorzPixels[aDestX*4]; double aSrcX = (aDestX - 1)*aSrcXFactor + theSrcRect.mX; int aSrcXI = (int) aSrcX; int aFactor1 = (int) (257 * (1.0 - (aSrcX - aSrcXI))); int aFactor2 = (int) (257 - aFactor1); SRC_TYPE* s = &aSrcBits[aSrcYI*aSrcRowWidth+aSrcXI]; for (int aDestY = 0; aDestY < aSrcHeightI; aDestY++) { uint32_t pixel1 = READ_COLOR(s++); uint32_t pixel2 = READ_COLOR(s); *d++ = (aFactor1 * ((pixel1 ) & 0xFF)) + (aFactor2 * ((pixel2 ) & 0xFF)); *d++ = (aFactor1 * ((pixel1 >> 8) & 0xFF)) + (aFactor2 * ((pixel2 >> 8) & 0xFF)); *d++ = (aFactor1 * ((pixel1 >> 16) & 0xFF)) + (aFactor2 * ((pixel2 >> 16) & 0xFF)); *d++ = (aFactor1 * ((pixel1 >> 24) & 0xFF)) + (aFactor2 * ((pixel2 >> 24) & 0xFF)); assert(d <= aNewHorzPixelsEnd); d += aTempDestWidth*4 - 4; s += aSrcRowWidth - 1; } } } uint32_t* aNewPixels = new uint32_t[aTempDestWidth*aTempDestHeight*4]; uint32_t* aNewPixelsEnd = aNewPixels + (aTempDestWidth*aTempDestHeight*4); memset(aNewPixels, 0, aTempDestWidth*aTempDestHeight*4*4); // Now resize vertically if (theSrcRect.mHeight >= theDestRect.mHeight) { double aDestYFactor = theDestRect.mHeight / theSrcRect.mHeight; double aDestYOffset = 1.0 + (aSrcYI - theSrcRect.mY) * aDestYFactor; for (int aSrcY = 0; aSrcY < aSrcHeightI; aSrcY++) { double aDestY1 = aDestYFactor * aSrcY + aDestYOffset; double aDestY2 = aDestY1 + aDestYFactor; int aDestYI1 = (int) floor(aDestY1); int aDestYI2 = (int) floor(aDestY2); uint32_t* s = &aNewHorzPixels[aSrcY*aTempDestWidth*4]; if (aDestYI1 == aDestYI2) { uint32_t* d = &aNewPixels[aDestYI1*aTempDestWidth*4]; int aFactor = (int) (256 * aDestYFactor); for (int aSrcX = 0; aSrcX < aTempDestWidth; aSrcX++) { *d++ += aFactor * *s++; *d++ += aFactor * *s++; *d++ += aFactor * *s++; *d++ += aFactor * *s++; } assert(d <= aNewPixelsEnd); } else { int aFactor1 = (int) (256 * (aDestYI2 - aDestY1)); int aFactor2 = (int) (256 * (aDestY2 - aDestYI2)); uint32_t* d1 = &aNewPixels[aDestYI1*aTempDestWidth*4]; uint32_t* d2 = &aNewPixels[aDestYI2*aTempDestWidth*4]; for (int aSrcX = 0; aSrcX < aTempDestWidth; aSrcX++) { *d1++ += aFactor1 * *s; *d2++ += aFactor2 * *s++; *d1++ += aFactor1 * *s; *d2++ += aFactor2 * *s++; *d1++ += aFactor1 * *s; *d2++ += aFactor2 * *s++; *d1++ += aFactor1 * *s; *d2++ += aFactor2 * *s++; } assert(d1 <= aNewPixelsEnd); assert(d2 <= aNewPixelsEnd); } } } else { double aSrcYFactor; if (theDestRect.mHeight != 1) aSrcYFactor = (theSrcRect.mHeight - 1) / (theDestRect.mHeight - 1); else aSrcYFactor = (theSrcRect.mHeight) / (theDestRect.mHeight); for (int aDestY = 1; aDestY < theDestRect.mHeight + 1; aDestY++) { uint32_t* d = &aNewPixels[(aDestY*aTempDestWidth+1)*4]; double aSrcY = (aDestY-1)*aSrcYFactor + (theSrcRect.mY - ((int) theSrcRect.mY)); int aSrcYI = (int) aSrcY; int aFactor1 = (int) (256 * (1.0 - (aSrcY - aSrcYI))); int aFactor2 = 256 - aFactor1; uint32_t* s1 = &aNewHorzPixels[(aSrcYI*aTempDestWidth+1)*4]; uint32_t* s2; if (aSrcYI == aSrcHeightI - 1) s2 = s1; else s2 = &aNewHorzPixels[((aSrcYI+1)*aTempDestWidth+1)*4]; for (int aDestX = 1; aDestX < aTempDestWidth-1; aDestX++) { *d++ = (aFactor1 * *s1++) + (aFactor2 * *s2++); *d++ = (aFactor1 * *s1++) + (aFactor2 * *s2++); *d++ = (aFactor1 * *s1++) + (aFactor2 * *s2++); *d++ = (aFactor1 * *s1++) + (aFactor2 * *s2++); } } } for (int y = 0; y < theDestRect.mHeight; y++) { uint32_t* aDestPixels = &aDestBits[(theDestRect.mY+y)*mWidth+theDestRect.mX]; for (int x = 0; x < theDestRect.mWidth; x++) { uint32_t *p = &aNewPixels[((y+1)*aTempDestWidth+x+1)*4]; int b = (*p++) >> 16; int g = (*p++) >> 16; int r = (*p++) >> 16; int a = (*p++) >> 16; /*aDestBits[(theDestRect.mY+y)*mWidth+theDestRect.mX+x] = (r) | (g << 8) | (b << 16) | (a << 24);*/ if (a != 0) { uint32_t dest = *aDestPixels; int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; int oma = 256 - a; assert(aDestPixels < aDestEnd); *(aDestPixels++) = (aNewDestAlpha << 24) | (((((dest & 0x0000FF) * oma) >> 8) & 0x0000FF) + (((b * a) >> 8))) | (((((dest & 0x00FF00) * oma) >> 8) & 0x00FF00) + (((g * a) >> 8) << 8)) | (((((dest & 0xFF0000) * oma) >> 8) & 0xFF0000) + (((r * a) >> 8) << 16)); } else aDestPixels++; } } delete[] aNewPixels; delete[] aNewHorzPixels; } libtuxcap-1.4.0/tuxcap/include/ResourceManager.h0000644000175000017500000001343211202747625021562 0ustar inniyahinniyah#ifndef __SEXY_RESOURCEMANAGER_H__ #define __SEXY_RESOURCEMANAGER_H__ #include "Common.h" #include "Image.h" #include "SexyAppBase.h" #include #include namespace ImageLib { class Image; }; namespace Sexy { class XMLParser; class XMLElement; class Image; class SoundInstance; class SexyAppBase; class Font; typedef std::map StringToStringMap; typedef std::map XMLParamMap; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// class ResourceManager { protected: enum ResType { ResType_Image, ResType_Sound, ResType_Font }; struct BaseRes { ResType mType; std::string mId; std::string mResGroup; std::string mPath; XMLParamMap mXMLAttributes; bool mFromProgram; virtual ~BaseRes() {} virtual void DeleteResource() { } }; struct ImageRes : public BaseRes { SharedImageRef mImage; std::string mAlphaImage; std::string mAlphaGridImage; std::string mVariant; bool mAutoFindAlpha; bool mPalletize; bool mA4R4G4B4; bool mA8R8G8B8; bool mDDSurface; bool mPurgeBits; bool mMinimizeSubdivisions; int mRows; int mCols; uint32_t mAlphaColor; AnimInfo mAnimInfo; ImageRes() { mType = ResType_Image; } virtual void DeleteResource(); }; struct SoundRes : public BaseRes { int mSoundId; double mVolume; int mPanning; SoundRes() { mType = ResType_Sound; } virtual void DeleteResource(); }; struct FontRes : public BaseRes { Font *mFont; Image *mImage; std::string mImagePath; std::string mTags; // For SysFonts bool mSysFont; bool mBold; bool mItalic; bool mUnderline; bool mShadow; int mSize; FontRes() { mType = ResType_Font; } virtual void DeleteResource(); }; typedef std::map ResMap; typedef std::list ResList; typedef std::map ResGroupMap; std::set mLoadedGroups; ResMap mImageMap; ResMap mSoundMap; ResMap mFontMap; XMLParser* mXMLParser; std::string mError; bool mHasFailed; SexyAppBase* mApp; std::string mCurResGroup; std::string mDefaultPath; std::string mDefaultIdPrefix; bool mAllowMissingProgramResources; bool mAllowAlreadyDefinedResources; // for reparsing file while running bool mHadAlreadyDefinedError; ResGroupMap mResGroupMap; ResList* mCurResGroupList; ResList::iterator mCurResGroupListItr; bool Fail(const std::string& theErrorText); virtual bool ParseCommonResource(XMLElement &theElement, BaseRes *theRes, ResMap &theMap); virtual bool ParseSoundResource(XMLElement &theElement); virtual bool ParseImageResource(XMLElement &theElement); virtual bool ParseFontResource(XMLElement &theElement); virtual bool ParseSetDefaults(XMLElement &theElement); virtual bool ParseResources(); bool DoParseResources(); void DeleteMap(ResMap &theMap); virtual void DeleteResources(ResMap &theMap, const std::string &theGroup); bool LoadAlphaGridImage(ImageRes *theRes, DDImage *theImage); bool LoadAlphaImage(ImageRes *theRes, DDImage *theImage); virtual bool DoLoadImage(ImageRes *theRes); virtual bool DoLoadFont(FontRes* theRes); virtual bool DoLoadSound(SoundRes* theRes); int GetNumResources(const std::string &theGroup, ResMap &theMap); public: ResourceManager(SexyAppBase *theApp); virtual ~ResourceManager(); bool ParseResourcesFile(const std::string& theFilename); bool ReparseResourcesFile(const std::string& theFilename); std::string GetErrorText(); bool HadError(); bool IsGroupLoaded(const std::string &theGroup); int GetNumImages(const std::string &theGroup); int GetNumSounds(const std::string &theGroup); int GetNumFonts(const std::string &theGroup); int GetNumResources(const std::string &theGroup); virtual bool LoadNextResource(); virtual void ResourceLoadedHook(BaseRes *theRes); virtual void StartLoadResources(const std::string &theGroup); virtual bool LoadResources(const std::string &theGroup); bool ReplaceImage(const std::string &theId, Image *theImage); bool ReplaceSound(const std::string &theId, int theSound); bool ReplaceFont(const std::string &theId, Font *theFont); void DeleteImage(const std::string &theName); SharedImageRef LoadImage(const std::string &theName); void DeleteFont(const std::string &theName); Font* LoadFont(const std::string &theName); SharedImageRef GetImage(const std::string &theId); int GetSound(const std::string &theId); Font* GetFont(const std::string &theId); // Returns all the XML attributes associated with the image const XMLParamMap& GetImageAttributes(const std::string &theId); // These throw a ResourceManagerException if the resource is not found virtual SharedImageRef GetImageThrow(const std::string &theId); virtual int GetSoundThrow(const std::string &theId); virtual Font* GetFontThrow(const std::string &theId); void SetAllowMissingProgramImages(bool allow); virtual void DeleteResources(const std::string &theGroup); void DeleteExtraImageBuffers(const std::string &theGroup); const ResList* GetCurResGroupList() {return mCurResGroupList;} std::string GetCurResGroup() {return mCurResGroup;} void DumpCurResGroup(std::string& theDestStr); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct ResourceManagerException : public std::exception { std::string what; ResourceManagerException(const std::string &theWhat) : what(theWhat) { } ~ResourceManagerException() throw (){} ; }; } #endif //__PROPERTIESPARSER_H__ libtuxcap-1.4.0/tuxcap/include/AudiereLoader.h0000644000175000017500000000035110766713353021206 0ustar inniyahinniyah/* Original AudiereLoader by Rheenen 2005 */ #ifndef __AudiereLOADER_H__ #define __AudiereLOADER_H__ #include "audiere.h" audiere::AudioDevicePtr getAudiereDevice(void); audiere::MIDIDevicePtr getAudiereMIDIDevice(void); #endif libtuxcap-1.4.0/tuxcap/include/AudiereMusicInterface.h0000644000175000017500000000345010766713353022704 0ustar inniyahinniyah/* Original Audiere Music Interface by Rheenen 2005 */ #ifndef __AudiereMUSICINTERFACE_H__ #define __AudiereMUSICINTERFACE_H__ #include "MusicInterface.h" #include "audiere.h" #ifndef WIN32 #define HWND void* #endif using namespace audiere; namespace Sexy { class SexyAppBase; class AudiereMusicInfo { public: OutputStreamPtr mStream; MIDIStreamPtr mMIDIStream; float mVolume; float mVolumeAdd; float mVolumeCap; bool mStopOnFade; bool mRepeats; int mPosition; public: AudiereMusicInfo(); }; typedef std::map AudiereMusicMap; class AudiereMusicInterface : public MusicInterface { public: AudioDevicePtr mDevice; MIDIDevicePtr mMIDIDevice; AudiereMusicMap mMusicMap; float mMasterVolume; public: AudiereMusicInterface(HWND theHWnd); virtual ~AudiereMusicInterface(); virtual bool LoadMusic(int theSongId, const std::string& theFileName); virtual void PlayMusic(int theSongId, int theOffset = 0, bool noLoop = false); virtual void StopMusic(int theSongId); virtual void PauseMusic(int theSongId); virtual void ResumeMusic(int theSongId); virtual void StopAllMusic(); virtual void UnloadMusic(int theSongId); virtual void UnloadAllMusic(); virtual void PauseAllMusic(); virtual void ResumeAllMusic(); virtual void FadeIn(int theSongId, int theOffset = -1, double theSpeed = 0.002, bool noLoop = false); virtual void FadeOut(int theSongId, bool stopSong = true, double theSpeed = 0.004); virtual void FadeOutAll(bool stopSong = true, double theSpeed = 0.004); virtual void SetSongVolume(int theSongId, double theVolume); virtual bool IsPlaying(int theSongId); virtual void SetVolume(double theVolume); virtual void Update(); }; } #endif //__AudiereMUSICINTERFACE_H__ libtuxcap-1.4.0/tuxcap/include/MI_GetNativeAlphaData.inc0000644000175000017500000000177711202747625023046 0ustar inniyahinniyah{ uint32_t* anAlphaData = new uint32_t[mWidth*mHeight]; if (theNumBits == 16) { for (int i = 0; i < mWidth*mHeight; i++) { uint32_t val = NEXT_SRC_COLOR; int anAlpha = val >> 24; int r = ((val >> 16) & 0xFF) * anAlpha >> 8; int g = ((val >> 8 ) & 0xFF) * anAlpha >> 8; int b = ((val ) & 0xFF) * anAlpha >> 8; anAlphaData[i] = ((((r * theRMask) >> 8) & theRMask) | (((g * theGMask) >> 8) & theGMask) | (((b * theBMask) >> 8) & theBMask) | (anAlpha << 24)); } } else if (theNumBits == 32) { for (int i = 0; i < mWidth*mHeight; i++) { uint32_t val = NEXT_SRC_COLOR; int anAlpha = val >> 24; int r = (((val >> 16) & 0xFF) * anAlpha) >> 8; int g = (((val >> 8 ) & 0xFF) * anAlpha) >> 8; int b = (((val ) & 0xFF) * anAlpha) >> 8; anAlphaData[i] = (((r * theRMask) >> 8) & theRMask) | (((g * theGMask) >> 8) & theGMask) | (((b * theBMask) >> 8) & theBMask) | (anAlpha << 24); } } mNativeAlphaData = anAlphaData; } libtuxcap-1.4.0/tuxcap/include/BltRotatedHelper.inc0000644000175000017500000001762711202747625022240 0ustar inniyahinniyah#define EACH_ROW\ for (int y = 0; y < aDestRect.mHeight; y++, aDestPixelsRow += aDestPixelsPitch)\ {\ float aBaseX = ((int)aDestRect.mX) + 0 - theRotCenterX - theX;\ float aBaseY = ((int)aDestRect.mY) + y - theRotCenterY - theY;\ \ int aU = (int) ((aCos*(aBaseX) - aSin*(aBaseY) + theRotCenterX) * 0x10000);\ int aV = (int) ((aCos*(aBaseY) + aSin*(aBaseX) + theRotCenterY) * 0x10000);\ \ DEST_PIXEL_TYPE* aDestPixels = aDestPixelsRow;\ \ int aLeft = 0;\ int aRight = (int)aDestRect.mWidth - 1;\ \ int aUInt = (aU >> 16);\ int aVInt = (aV >> 16);\ \ if (aCosLong <= -0x0001)\ {\ if (aUInt<0)\ continue;\ \ int anEdgeLeft = ((theSrcRect.mWidth << 16) - 0x27FFF - aU) / aCosLong;\ if (anEdgeLeft >= aLeft)\ aLeft = anEdgeLeft;\ \ int anEdgeRight = (0x07FFF - aU) / aCosLong;\ if (anEdgeRight < aRight)\ aRight = anEdgeRight;\ }\ else if (aCosLong >= 0x0001)\ {\ if (aUInt >= theSrcRect.mWidth-1)\ continue;\ \ int anEdgeLeft = (0x10000 - aU) / aCosLong;\ if (anEdgeLeft > aLeft)\ aLeft = anEdgeLeft;\ \ int anEdgeRight = ((theSrcRect.mWidth << 16) - 0x17FFF - aU) / aCosLong;\ if (anEdgeRight < aRight)\ aRight = anEdgeRight;\ }\ else if ((aU < 0) || (aU >= (theSrcRect.mWidth - 1) << 16))\ continue;\ \ if (aSinLong <= -0x0001)\ {\ if (aVInt<0)\ continue;\ \ int anEdgeLeft = ((theSrcRect.mHeight << 16) - 0x27FFF - aV) / aSinLong;\ if (anEdgeLeft > aLeft)\ aLeft = anEdgeLeft;\ \ int anEdgeRight = (0x0000 - aV) / aSinLong;\ if (anEdgeRight < aRight)\ aRight = anEdgeRight;\ }\ else if (aSinLong >= 0x0001)\ {\ if (aVInt >= theSrcRect.mHeight-1)\ continue;\ \ int anEdgeLeft = (0x10000 - aV) / aSinLong;\ if (anEdgeLeft > aLeft)\ aLeft = anEdgeLeft;\ \ int anEdgeRight = ((theSrcRect.mHeight << 16) - 0x17FFF - aV) / aSinLong;\ if (anEdgeRight < aRight)\ aRight = anEdgeRight;\ }\ else if ((aV < 0) || (aV >= (theSrcRect.mHeight - 1) << 16))\ continue;\ \ aU += aLeft * aCosLong;\ aV += aLeft * aSinLong;\ aDestPixels += aLeft;\ \ int aWidth = theImage->mWidth; #define END_ROW } { #if defined(OPTIMIZE_SOFTWARE_DRAWING) && defined(WRITE_PIXEL_OPTIMIZED) if (gOptimizeSoftwareDrawing) { if (aNumBits == 16) { #ifdef WRITE_PIXEL_OPTIMIZED_565 if (aGMask == 0x7E0) // 5-6-5 { EACH_ROW for (int x = aLeft; x <= aRight; x++) { int aUInt = (aU >> 16); int aVInt = (aV >> 16); SRC_TYPE* srcptr = aSrcBits + (aVInt * aWidth) + aUInt; int aUFactor = (aU & 0xFFFE) + 1; // aUFactor needs to be between 1 and 0xFFFF to avoid overflow int aVFactor = (aV & 0xFFFE) + 1; // ditto for aVFactor uint32_t src1 = READ_COLOR(srcptr); uint32_t src2 = READ_COLOR(srcptr+1); uint32_t src3 = READ_COLOR(srcptr+theImage->mWidth); uint32_t src4 = READ_COLOR(srcptr+1+theImage->mWidth); int a1 = ((src1 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a2 = ((src2 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a3 = ((src3 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a4 = ((src4 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; WRITE_PIXEL_OPTIMIZED_565; aU += aCosLong; aV += aSinLong; } END_ROW } #endif #ifdef WRITE_PIXEL_OPTIMIZED_555 #ifdef WRITE_PIXEL_OPTIMIZED_565 else #endif if (aGMask == 0x3E0) // 5-5-5 { EACH_ROW for (int x = aLeft; x <= aRight; x++) { int aUInt = (aU >> 16); int aVInt = (aV >> 16); SRC_TYPE* srcptr = aSrcBits + (aVInt * aWidth) + aUInt; int aUFactor = (aU & 0xFFFE) + 1; // aUFactor needs to be between 1 and 0xFFFF to avoid overflow int aVFactor = (aV & 0xFFFE) + 1; // ditto for aVFactor uint32_t src1 = READ_COLOR(srcptr); uint32_t src2 = READ_COLOR(srcptr+1); uint32_t src3 = READ_COLOR(srcptr+theImage->mWidth); uint32_t src4 = READ_COLOR(srcptr+1+theImage->mWidth); int a1 = ((src1 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a2 = ((src2 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a3 = ((src3 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a4 = ((src4 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; WRITE_PIXEL_OPTIMIZED_555; aU += aCosLong; aV += aSinLong; } END_ROW } #endif #if defined(WRITE_PIXEL_OPTIMIZED_555) || defined(WRITE_PIXEL_OPTIMIZED_565) else #endif { EACH_ROW for (int x = aLeft; x <= aRight; x++) { int aUInt = (aU >> 16); int aVInt = (aV >> 16); SRC_TYPE* srcptr = aSrcBits + (aVInt * aWidth) + aUInt; int aUFactor = (aU & 0xFFFE) + 1; // aUFactor needs to be between 1 and 0xFFFF to avoid overflow int aVFactor = (aV & 0xFFFE) + 1; // ditto for aVFactor uint32_t src1 = READ_COLOR(srcptr); uint32_t src2 = READ_COLOR(srcptr+1); uint32_t src3 = READ_COLOR(srcptr+theImage->mWidth); uint32_t src4 = READ_COLOR(srcptr+1+theImage->mWidth); int a1 = ((src1 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a2 = ((src2 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a3 = ((src3 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a4 = ((src4 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; WRITE_PIXEL; aU += aCosLong; aV += aSinLong; } END_ROW } } else if (aNumBits == 32) { EACH_ROW for (int x = aLeft; x <= aRight; x++) { int aUInt = (aU >> 16); int aVInt = (aV >> 16); SRC_TYPE* srcptr = aSrcBits + (aVInt * aWidth) + aUInt; int aUFactor = (aU & 0xFFFE) + 1; // aUFactor needs to be between 1 and 0xFFFF to avoid overflow int aVFactor = (aV & 0xFFFE) + 1; // ditto for aVFactor uint32_t src1 = READ_COLOR(srcptr); uint32_t src2 = READ_COLOR(srcptr+1); uint32_t src3 = READ_COLOR(srcptr+theImage->mWidth); uint32_t src4 = READ_COLOR(srcptr+1+theImage->mWidth); int a1 = ((src1 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a2 = ((src2 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a3 = ((src3 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a4 = ((src4 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; WRITE_PIXEL_OPTIMIZED; aU += aCosLong; aV += aSinLong; } END_ROW } } else { #endif EACH_ROW for (int x = aLeft; x <= aRight; x++) { int aUInt = (aU >> 16); int aVInt = (aV >> 16); SRC_TYPE* srcptr = aSrcBits + (aVInt * aWidth) + aUInt; int aUFactor = (aU & 0xFFFE) + 1; // aUFactor needs to be between 1 and 0xFFFF to avoid overflow int aVFactor = (aV & 0xFFFE) + 1; // ditto for aVFactor uint32_t src1 = READ_COLOR(srcptr); uint32_t src2 = READ_COLOR(srcptr+1); uint32_t src3 = READ_COLOR(srcptr+theImage->mWidth); uint32_t src4 = READ_COLOR(srcptr+1+theImage->mWidth); int a1 = ((src1 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a2 = ((src2 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a3 = ((src3 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a4 = ((src4 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; WRITE_PIXEL; aU += aCosLong; aV += aSinLong; } END_ROW #if defined(OPTIMIZE_SOFTWARE_DRAWING) && defined(WRITE_PIXEL_OPTIMIZED) } #endif } libtuxcap-1.4.0/tuxcap/include/DDI_BltRotated.inc0000644000175000017500000001716511202747625021555 0ustar inniyahinniyah{ double aCos = cos(theRot); double aSin = sin(theRot); int aCosLong = (int) (aCos * 0x10000); int aSinLong = (int) (aSin * 0x10000); if (!LockSurface()) return; int aRedShift = mDDInterface->mRedShift; int aGreenShift = mDDInterface->mGreenShift; int aBlueShift = mDDInterface->mBlueShift; int aRedRightShift = 32 - mDDInterface->mRedBits; int aGreenRightShift = 24 - mDDInterface->mGreenBits; int aBlueRightShift = 16 - mDDInterface->mBlueBits; int aNumBits = mSurface->format->BitsPerPixel; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (aNumBits == 16) { ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + ((int)aDestRect.mY * mSurface->pitch/2) + (int)aDestRect.mX; int aDestPixelsPitch = mSurface->pitch/2; if (theColor == Color::White) { #define DEST_PIXEL_TYPE ushort #define WRITE_PIXEL\ {\ ushort dest = *aDestPixels;\ int oma = 256 - (a1 + a2 + a3 + a4);\ *(aDestPixels++) = \ (((((dest & aBMask) * oma) >> 8) & aBMask) + \ (((((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) >> aBlueRightShift) << aBlueShift)) | \ (((((dest & aGMask) * oma) >> 8) & aGMask) + \ (((((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) >> aGreenRightShift) << aGreenShift)) | \ (((((dest & aRMask) * oma) >> 8) & aRMask) + \ (((((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> aRedRightShift) << aRedShift)); \ } #define WRITE_PIXEL_OPTIMIZED_565\ {\ uint32_t dest = (*aDestPixels | (*aDestPixels << 16)) & 0x7E0F81F;\ int oma = (256 - (a1 + a2 + a3 + a4)) >> 3;\ uint32_t src_b = ((src1 & 0xFF00FF) * a1 + (src2 & 0xFF00FF) * a2 + (src3 & 0xFF00FF) * a3 + (src4 & 0xFF00FF) * a4) & 0xFF00FF00;\ src_b = ((((src1 & 0xFF00) * a1 + (src2 & 0xFF00) * a2 + (src3 & 0xFF00) * a3 + (src4 & 0xFF00) * a4) & 0xFF0000) | src_b) >> 8;\ uint32_t s = ((src_b & 0xfc00) << 11) + (src_b >> 8 & 0xf800) + (src_b >> 3 & 0x1f);\ dest = ((dest * oma >> 5) & 0x7E0F81F) + s;\ *(aDestPixels++) = dest | (dest >> 16);\ } #define WRITE_PIXEL_OPTIMIZED_555\ {\ uint32_t dest = (*aDestPixels | (*aDestPixels << 16)) & 0x3E07C1F;\ int oma = (256 - (a1 + a2 + a3 + a4)) >> 3;\ uint32_t src_b = ((src1 & 0xFF00FF) * a1 + (src2 & 0xFF00FF) * a2 + (src3 & 0xFF00FF) * a3 + (src4 & 0xFF00FF) * a4) & 0xFF00FF00;\ src_b = ((((src1 & 0xFF00) * a1 + (src2 & 0xFF00) * a2 + (src3 & 0xFF00) * a3 + (src4 & 0xFF00) * a4) & 0xFF0000) | src_b) >> 8;\ uint32_t s = ((src_b & 0xf800) << 10) + (src_b >> 9 & 0x7c00) + (src_b >> 3 & 0x1f);\ dest = ((dest * oma >> 5) & 0x3E07C1F) + s;\ *(aDestPixels++) = dest | (dest >> 16);\ } #define WRITE_PIXEL_OPTIMIZED #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE #undef WRITE_PIXEL_OPTIMIZED #undef WRITE_PIXEL_OPTIMIZED_555 #undef WRITE_PIXEL_OPTIMIZED_565 } else { // Colorized version int ca = theColor.mAlpha; int cr = theColor.mRed + 1; int cg = theColor.mGreen + 1; int cb = theColor.mBlue + 1; #define DEST_PIXEL_TYPE ushort #define WRITE_PIXEL\ {\ ushort dest = *aDestPixels;\ a1 = (a1*ca)>>8; a2 = (a2*ca)>>8; a3 = (a3*ca)>>8; a4 = (a4*ca)>>8; \ int oma = 256 - (a1 + a2 + a3 + a4); \ *(aDestPixels++) = \ ( ((((dest & aBMask) * oma) >> 8) & aBMask) + \ (((( (((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) >> 8) * cb) >> aBlueRightShift) << aBlueShift) ) | \ ( ((((dest & aGMask) * oma) >> 8) & aGMask) + \ (((( (((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) >> 8) * cg) >> aGreenRightShift) << aGreenShift) ) | \ ( ((((dest & aRMask) * oma) >> 8) & aRMask) + \ (((( (((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> 8) * cr) >> aRedRightShift) << aRedShift) ); \ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } } else if (aNumBits == 32) { uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + ((int)aDestRect.mY * mSurface->pitch/4) + (int)aDestRect.mX; int aDestPixelsPitch = mSurface->pitch/4; if (theColor == Color::White) { #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ uint32_t dest = *aDestPixels;\ int oma = 256 - (a1 + a2 + a3 + a4);\ *(aDestPixels++) = \ (((((dest & aBMask) * oma) >> 8) & aBMask) + \ (((((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) >> aBlueRightShift) << aBlueShift)) | \ (((((dest & aGMask) * oma) >> 8) & aGMask) + \ (((((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) >> aGreenRightShift) << aGreenShift)) | \ (((((dest & aRMask) * oma) >> 8) & aRMask) + \ (((((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> aRedRightShift) << aRedShift));\ } #define WRITE_PIXEL_OPTIMIZED\ {\ uint32_t dest = *aDestPixels;\ int oma = 256 - (a1 + a2 + a3 + a4);\ uint32_t src_b = ((src1 & 0xFF00FF) * a1 + (src2 & 0xFF00FF) * a2 + (src3 & 0xFF00FF) * a3 + (src4 & 0xFF00FF) * a4) & 0xFF00FF00;\ uint32_t src_b2 = ((src1 & 0xFF00) * a1 + (src2 & 0xFF00) * a2 + (src3 & 0xFF00) * a3 + (src4 & 0xFF00) * a4) & 0xFF0000;\ *(aDestPixels++) =\ ((((dest & 0xFF00FF) * oma + src_b) >> 8) & 0xFF00FF) |\ ((((dest & 0x00FF00) * oma + src_b2) >> 8) & 0x00FF00);\ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef WRITE_PIXEL_OPTIMIZED #undef DEST_PIXEL_TYPE } else { // Colorized version int ca = theColor.mAlpha; int cr = theColor.mRed + 1; int cg = theColor.mGreen + 1; int cb = theColor.mBlue + 1; #define DEST_PIXEL_TYPE uint32_t #define WRITE_PIXEL\ {\ uint32_t dest = *aDestPixels;\ a1 = (a1*ca)>>8; a2 = (a2*ca)>>8; a3 = (a3*ca)>>8; a4 = (a4*ca)>>8; \ int oma = 256 - (a1 + a2 + a3 + a4);\ *(aDestPixels++) = \ ( ((((dest & aBMask) * oma) >> 8) & aBMask) + \ (((( (((src1 & 0x0000FF) * a1) + \ ((src2 & 0x0000FF) * a2) + \ ((src3 & 0x0000FF) * a3) + \ ((src4 & 0x0000FF) * a4)) >> 8) * cb) >> aBlueRightShift) << aBlueShift) ) | \ ( ((((dest & aGMask) * oma) >> 8) & aGMask) + \ (((( (((src1 & 0x00FF00) * a1) + \ ((src2 & 0x00FF00) * a2) + \ ((src3 & 0x00FF00) * a3) + \ ((src4 & 0x00FF00) * a4)) >> 8) * cg) >> aGreenRightShift) << aGreenShift) ) | \ ( ((((dest & aRMask) * oma) >> 8) & aRMask) + \ (((( (((src1 & 0xFF0000) * a1) + \ ((src2 & 0xFF0000) * a2) + \ ((src3 & 0xFF0000) * a3) + \ ((src4 & 0xFF0000) * a4)) >> 8) * cr) >> aRedRightShift) << aRedShift) );\ } #include "BltRotatedHelper.inc" #undef WRITE_PIXEL #undef DEST_PIXEL_TYPE } } UnlockSurface(); } libtuxcap-1.4.0/tuxcap/include/MemoryImage.h0000644000175000017500000001260311202747625020712 0ustar inniyahinniyah#ifndef __MEMORYIMAGE_H__ #define __MEMORYIMAGE_H__ #include "Image.h" #define OPTIMIZE_SOFTWARE_DRAWING #ifdef OPTIMIZE_SOFTWARE_DRAWING extern bool gOptimizeSoftwareDrawing; #endif namespace Sexy { const uint32_t MEMORYCHECK_ID = 0x4BEEFADE; class NativeDisplay; class SexyAppBase; class MemoryImage : public Image { public: uint32_t* mBits; int mBitsChangedCount; void* mD3DData; uint32_t mD3DFlags; // see D3DInterface.h for possible values uint32_t* mColorTable; uchar* mColorIndices; bool mForcedMode; bool mHasTrans; bool mHasAlpha; bool mIsVolatile; bool mPurgeBits; bool mWantPal; uint32_t* mNativeAlphaData; uchar* mRLAlphaData; uchar* mRLAdditiveData; bool mBitsChanged; SexyAppBase* mApp; private: void Init(); public: virtual void* GetNativeAlphaData(NativeDisplay *theNative); virtual uchar* GetRLAlphaData(); virtual uchar* GetRLAdditiveData(NativeDisplay *theNative); virtual void PurgeBits(); virtual void DeleteSWBuffers(); virtual void Delete3DBuffers(); virtual void DeleteExtraBuffers(); virtual void ReInit(); virtual void BitsChanged(); virtual void CommitBits(); virtual void DeleteNativeData(); void NormalBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); void AdditiveBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor); void NormalDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); void AdditiveDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); void NormalDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); void AdditiveDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor); void SlowStretchBlt(Image* theImage, const Rect& theDestRect, const FRect& theSrcRect, const Color& theColor, int theDrawMode); void FastStretchBlt(Image* theImage, const Rect& theDestRect, const FRect& theSrcRect, const Color& theColor, int theDrawMode); bool BltRotatedClipHelper(float &theX, float &theY, const Rect &theSrcRect, const Rect &theClipRect, double theRot, FRect &theDestRect, float theRotCenterX, float theRotCenterY); bool StretchBltClipHelper(const Rect &theSrcRect, const Rect &theClipRect, const Rect &theDestRect, FRect &theSrcRectOut, Rect &theDestRectOut); bool StretchBltMirrorClipHelper(const Rect &theSrcRect, const Rect &theClipRect, const Rect &theDestRect, FRect &theSrcRectOut, Rect &theDestRectOut); void BltMatrixHelper(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, void *theSurface, int theBytePitch, int thePixelFormat, bool blend); void BltTrianglesTexHelper(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect &theClipRect, const Color &theColor, int theDrawMode, void *theSurface, int theBytePitch, int thePixelFormat, float tx, float ty, bool blend); void FillScanLinesWithCoverage(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode, const unsigned char* theCoverage, int theCoverX, int theCoverY, int theCoverWidth, int theCoverHeight); public: MemoryImage(); MemoryImage(SexyAppBase* theApp); MemoryImage(const MemoryImage& theMemoryImage); virtual ~MemoryImage(); virtual void Clear(); virtual void SetBits(uint32_t* theBits, int theWidth, int theHeight, bool commitBits = true); virtual void Create(int theWidth, int theHeight); virtual uint32_t* GetBits(); virtual void FillRect(const Rect& theRect, const Color& theColor, int theDrawMode); virtual void ClearRect(const Rect& theRect); virtual void DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode); virtual void Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode); virtual void BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode); virtual void BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY); virtual void StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch); virtual void BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend); virtual void BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend); virtual void SetImageMode(bool hasTrans, bool hasAlpha); virtual void SetVolatile(bool isVolatile); virtual bool Palletize(); }; } #endif //__MEMORYIMAGE_H__ libtuxcap-1.4.0/tuxcap/demo2/0000755000175000017500000000000011212652053015676 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/demo2/GameApp.cpp0000644000175000017500000003205611062533665017734 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // Why are we including ImageFont.h and not Font.h? Font.h is just a generic // base class. ImageFont creates fonts from an image that contains all the // text characters as well as a text file that indicates character widths // and kerning information, as well as some more advanced features not used // in this tutorial such as font layers, etc. #include "ImageFont.h" // The Image.h file just declares basic functions. All images are either of // the DDImage or MemoryImage type. For this demo, we will use DDImage // types, as they are the type returned by the image loading code. // A DDImage is actually derived from MemoryImage, so where an Image or // MemoryImage is required, a DDImage will suffice as well. A DDImage // contains optimized code for use with DirectX 7+. #include "DDImage.h" // This will let us load sounds #include "SoundManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Demo 2"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Demo2"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; mBoard = NULL; mTextFont = NULL; mNumberFont = NULL; mTurbotImg = NULL; mMoonImg = NULL; mOpaqueBeamImg = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; // We need to clean up after ourselves and delete the image and // font information. delete mTextFont; delete mNumberFont; delete mTurbotImg; delete mMoonImg; delete mOpaqueBeamImg; // We need to release the memory allocated to our sounds too. // This call frees up the memory for ALL sound effects. mSoundManager->ReleaseSounds(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // In later demos, you will see more done with this function. // For now, we have nothing else to initialize, so we are done. // Once complete, the LoadingThreadProc function will automatically // start and we will begin loading all our needed resources. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // This time, we have things to load. Let's load in our two fonts // and our three images. // Besides loading data, // this thread can also update the progress indicator for the loading // screen, which you will see in later demos. // Once complete, the LoadingThreadCompleted function will be called. // Loading images is easy: you don't have to specify the image type. // Depending on the file extension, the appropriate image decoder // will be used. The following image types are supported: // Targa (.tga), JPEG (.jpg), PNG (.png), GIF (.gif). You do NOT have // to specify the extension when loading the file if you don't want to. // In this case, all of the above extensions will be looked for. // A discussion of image formats is beyond the scope of this tutorial. // There is some important information to know about images. // You will notice in the "images" directory that for each image, // there is a black and white image with the same name but with // an underscore ("_") at the end of it. By default, when you load // and image, the code automatically looks for the presence of // that file to use for the alpha information. Some file formats // have the alpha channel built into them, like PNG files. But // others, like JPEG or GIF files, do not. The purpose of the alpha // file is of course to generate an image that doesn't have jagged // lines, or to control the opacity of various parts of the image. // As a side not, the alpha image file may also begin with the // underscore instead of ending with it, it matters not, and again, // is automatically loaded in by the image loading code. // You need to clean up the memory allocated by these functions yourself. mOpaqueBeamImg = (Image*) GetImage("images/beam_opaque.jpg"); // If the file was not found or couldn't be loaded (i.e. due to an // incompatible file format) the returned value will be NULL. // You should always check this, and if it occurs, display an error // message, then set mLoadingFailed to true, and then immediately return. if (mOpaqueBeamImg == NULL) { // The PopUp method displays a standard Windows message box. // If in full screen mode, this will appropriately handle things such // that the GDI surface is properly rendered and the dialog box appears // as expected. #if 0 Popup("There was an error loading the file: images/beam_opaque"); #endif mLoadingFailed = true; return; } // Now load the other two images mMoonImg = (Image*) GetImage("images/moon.gif"); if (mMoonImg == NULL) { #if 0 Popup("There was an error loading the file: images/moon"); #endif mLoadingFailed = true; return; } mTurbotImg = (Image*) GetImage("images/turbot_worry.gif"); if (mTurbotImg == NULL) { #if 0 Popup("There was an error loading the file: images/turbot_worry"); #endif mLoadingFailed = true; return; } // So we've loaded the images, that's all there is right? Wrong. // If possible, we should try to palletize the images. An image that // contains 255 or fewer colors can be palletized. This results in // a memory savings of about 4x and doesn't affect the image quality // at all. It's the same principals that the GIF format uses: instead // of representing each red, green, blue, alpha value as a separate // quantity (1 byte each, 4 bytes in total per pixel), we represent // the actual combined RGBA value as a single number, from 0-255. // This number is an index into a lookup table. Thus, every time // the value (200,43,11,128), for example, is used, instead of // representing that value as a 4 byte value every time it // appears, we'd represent it with a 1 byte index into a lookup // table that contained the above RGBA value. Don't worry, you // don't have to really know or care about any of that if you // didn't understand it. What you need to know is that by calling the // Palletize() method on an image, you potentially can reduce the // amount of RAM it consumes by 4 times. The Palletize method // returns a boolean indicating if it could or couldn't be palletized. ((DDImage*)mOpaqueBeamImg)->Palletize(); ((DDImage*)mMoonImg)->Palletize(); ((DDImage*)mTurbotImg)->Palletize(); // Now let's load and create some fonts. A font consists of an // image and a text file. The image works on the same principles // as a normal image file (like the ones above) works on. Except // that with fonts, there is only 1 image, the alpha image. // Thus, you will see in the "fonts" directory two images that // begin with the underscore prefix. If there isn't a file // of the same name without an underscore, then it is assumed that // the file is of the same dimensions as the underscore file and that // it is to be all white and fully opaque. This is done with fonts because // it's common to want to change the color of the font, and to change // the color, the base, original image color, should be white and // fully opaque. More information on colorizing fonts and images can // be found in Board.cpp, but for now know that the image in the fonts // directory contains the alpha information for your font, and that it // is assumed that the "main" image is pure white. // The other file in the directory is a text file, commonly with the // same name as the image, but without the underscore character, but // not always. The file will define the name of the image to load. // This file defines the characters, their widths, their offsets // within the image, the point size, and any layers (which are not // used or discussed in this demo). This is the data file and is // how the font knows how to take a string and convert it into // the proper images representing each character. A font is really // just an image but with an extra data file that tells the program // how to map strings to their image representation. // You load a font by specifying the text data file. mTextFont = new ImageFont(this, "fonts/Kiloton9.txt"); // We need to check to see if the font was properly initialized. // If it wasn't, then an error occurred and we need to abort. if (!mTextFont->mFontData->mInitialized) { delete mTextFont; #if 0 Popup("There was an error loading fonts/Kiloton9.txt"); #endif mLoadingFailed = true; return; } mNumberFont = new ImageFont(this, "fonts/supernova20.txt"); if (!mNumberFont->mFontData->mInitialized) { delete mNumberFont; #if 0 Popup("There was an error loading fonts/supernova20.txt"); #endif mLoadingFailed = true; return; } // Let's load some sounds. You assign a unique unsigned integer ID to each // sound. It is with this ID that you indicate which sound you // want to play. Valid types of sounds to load are: // WAV, OGG, AU, and if you have FMod and enable FMod: MP3. Although // you should probably not use MP3 due to patent/copyright issues // unless of course that either doesn't bother you or you happen // to have the legal right to do so. Like images, you don't have // to specify the file extension. LoadSound returns a boolean // indicating success or failure. if (!mSoundManager->LoadSound(1, "sounds/timer")) { #if 0 Popup("There was an error loading sounds/timer"); #endif mLoadingFailed = true; return; } if (!mSoundManager->LoadSound(2, "sounds/mutator")) { #if 0 Popup("There was an error loading sounds/mutator"); #endif mLoadingFailed = true; return; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); // And just to test out our sound playing abilities, let's play the // mutator sound to indicate that we're done loading. // We do that by calling GameApp's PlaySample() // method and specifying the integral ID of the sound to play. This // ID is the same as we used when loading the sound in GameApp::LoadingThreadProc() PlaySample(2); } libtuxcap-1.4.0/tuxcap/demo2/CMakeLists.txt0000644000175000017500000000370610762446645020465 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../demo_2") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/demo2/Board.h0000644000175000017500000000777710641010432017112 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget { private: GameApp* mApp; int mPulseAmt; // See Draw(): used to make an image pulse over time bool mIncPulse; // If true, then we're increasing the pulse value, otherwise, decreasing public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/demo2/GameApp.h0000644000175000017500000000717310641010432017363 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; // Alright, fonts and images! You'll learn more about these in GameApp.cpp // so check there for more info. class ImageFont; class Image; class GameApp : public SexyAppBase { private: Board* mBoard; public: // These are the fonts and images we'll be using for this demo. See // GameApp.cpp for full information on fonts and images. We're going to // make them public for easy accessing, since the point of this tutorial // is to quickly get you up to speed on using the framework. ImageFont* mTextFont; ImageFont* mNumberFont; Image* mOpaqueBeamImg; Image* mMoonImg; Image* mTurbotImg; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/demo2/main.cpp0000644000175000017500000000022710641010432017321 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/demo2/Board.cpp0000644000175000017500000003625410641010432017435 0ustar inniyahinniyah#include "Board.h" #include "GameApp.h" #include "Graphics.h" // See the Draw method for more information on using the Color class. #include "Color.h" // Why are we including ImageFont.h and not Font.h? Font.h is just a generic // base class. ImageFont creates fonts from an image that contains all the // text characters as well as a text file that indicates character widths // and kerning information, as well as some more advanced features not used // in this tutorial such as font layers, etc. #include "ImageFont.h" // The Image.h file just declares basic functions. All images are either of // the DDImage or MemoryImage type. For this demo, we will use DDImage // types, as they are the type returned by the image loading code. // A DDImage is actually derived from MemoryImage, so where an Image or // MemoryImage is required, a DDImage will suffice as well. A DDImage // contains optimized code for use with Directdraw #include "DDImage.h" // The Rectangle template, used to specify X, Y, Width, Height #include "Rect.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; // Start by fully glowing and making the pulse decrease mPulseAmt = 255; mIncPulse = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); // Every frame (100 times per second) let's change the pulse amount by // 1. When we reach either 0 or 255 (the lower/upper bounds of // a color value) we'll reverse the pulsing direction. See the Draw() // method for its usage: we're going to draw an image with varying intenstiy // over time. if (mIncPulse) { if (++mPulseAmt >= 255) { mIncPulse = false; mPulseAmt = 255; } } else { if (--mPulseAmt <= 0) { mIncPulse = true; mPulseAmt = 0; } } // Let's play the timer sound effect once every 2 second. // Since this method is called 100 times per second, just mod // mUpdateCnt by 200. We do that by calling GameApp's PlaySample() // method and specifying the integral ID of the sound to play. This // ID is the same as we used when loading the sound in GameApp::LoadingThreadProc() if (mUpdateCnt % 200 == 0) mApp->PlaySample(1); // What about playing a sound but making it play on either the left or // right speaker? And what about pitch shifting? These are all possible, // but we won't learn about them until a later demo. // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // And now for the good stuff! The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(0, 0, 0)); g->FillRect(0, 0, mWidth, mHeight); // Now let's print some text. In order to do so, we need to instruct the // graphics object as to which font we want to use. We do that with // the SetFont method. Then we call the DrawString method and pass in // a normal string and give it an X, Y to draw at. But wait! If we just // draw a string right now, we won't see it. Can you guess why? // The graphics object is still using the color, white, which we // set a few lines above. Thus, when it goes to draw the string, // it will draw it in white. How do you change the text color? // Easy: it's just like you learned for drawing those primitives: // just use SetColor and you're done! It doesn't matter whether you // set the color before or after you set the font, fyi. g->SetColor(Color(255, 0, 0)); g->SetFont(mApp->mTextFont); g->DrawString(_S("Woo! Text! Ya!"), 10, 10); // Wait a minute, didn't we say to draw at a Y value of 10? Then why does it // appear to be drawing at about 0? That's because the text is offset // by the ascent of the font. A discussion of font terms is beyond the // scope of this demo, but basically just remember that if you want to // display the text at the exact Y coordinate, that you should add // the value of the font's ascent. You can get the ascent by calling // GetAscent() on the font in question. I'm going to use the same // Y value of 10 just to show you the slight difference using GetAscent makes. g->SetColor(Color(55, 90, 255)); // We already set the font, no need to set it again unless we want a new one g->DrawString(_S("I like Techno and Drum n' Bass"), 170, 10 + mApp->mTextFont->GetAscent()); // And to help you out visually, let's draw a line at Y coordinate 10: g->SetColor(Color(255, 255, 255,255)); g->DrawLine(0, 10, mWidth, 10); // Just for fun, let's change the font. This font, as you can see from its image, // only contains digits and a few symbols. As an example, I will draw a string // containing only those characters as well as a string containing characters that // the font can't represent to show you what would happen. g->SetFont(mApp->mNumberFont); g->SetColor(Color(255, 255, 0)); g->DrawString(_S("+200"), 10, 40); g->DrawString(_S("+200 pts"), 10, 60); // You can also get the width of a string in pixels for any given font. In addition, you // can use a printf style function, StrFormat, which is defined in Common.h, to // format strings. You might want to look at Common.h for some...common...and handy functions. g->SetColor(Color(0, 255, 255)); SexyString myString = StrFormat(_S("You got %d points!"), 147); g->SetFont(mApp->mTextFont); g->DrawString(myString, 10, 80); g->SetColor(Color(0, 255, 0)); g->DrawString(_S(" I am to the right of that previous string."), 10 + mApp->mTextFont->StringWidth(myString), 80); // What about some other common text functions, like justifying and word wrapping? // Not a problem. The Widget class contains some useful features. // For justification, the easiest is to use the WriteString method. // The valid justification values are: // -1: Left justified (same as DrawString) // 0: Centered // 1: Right justified // // For centered/right justified, you can also specify a width indicating the size of the region you // are printing in. The sole purpose of that is to control the centering/right aligning. g->SetColor(Color(255, 255, 255)); WriteString(g, _S("Left justified at X of 200"), 200, 95, -1, -1); WriteString(g, _S("Centered using app width"), 0, 110, mWidth, 0); WriteString(g, _S("Centered using width of 200, X of 200"), 200, 125, 200, 0); // And now for a word wrapping example. With this function, you specify a rectangular region // that represents the "box" in which you want the text to be displayed. You can also // set the line spacing, or use -1 for the default font height, and you can also set // the justification using the same values as for WriteString. We'll also draw the "box" using // the DrawRect function, for illustrative purposes. You may notice that I didn't offset the // Y coordinate of the text by the font's ascent: that's because WriteWordWrapped automatically // does that for you. g->SetColor(Color(255, 255, 255)); g->DrawRect(30, 140, 200, 400); g->SetColor(Color(0, 255, 0)); WriteWordWrapped(g, Rect(30, 140, 200, 400), _S("This is some text that is wrapped inside of the rectangle \ at X of 30, Y of 140, width of 200, height of 400. It has \ been wrapped using the default left justification and the \ default line spacing."), -1, -1); //////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Enough talk, let's draw images! // The simplest way to draw an image is with, coincidentally, the DrawImage method. // Just specify the image and the X, Y to draw at and boom! It's done. g->DrawImage(mApp->mTurbotImg, 230, 140); // What about changing the color of an image? This is called colorization, and it works just like // all the previous examples: You call SetColor with the color you want. But wait! There's // an extra step: Because colorizing an image on the fly is slower than normal drawing, you have // to explicity tell the graphics object that you want to enable it. This is done by calling the // SetColorizeImages method of the Graphics class with a parameter value of "true". // IMPORTANT: You should call SetColorizeImages again but with a parameter of "false" when you // are done drawing your colorized image! Otherwise all subsequent image drawing calls will // be colorized using the most recent value from SetColor. You may call SetColor either before // or after SetColorizeImages, it doesn't matter. For this example, we'll draw an image normally // and then colorized. We'll also use the GetHeight() method to draw this image just below the // previous one. g->DrawImage(mApp->mOpaqueBeamImg, 230, 140 + mApp->mTurbotImg->GetHeight()); g->SetColor(Color(255, 0, 0)); g->SetColorizeImages(true); g->DrawImage(mApp->mOpaqueBeamImg, 230 + mApp->mOpaqueBeamImg->GetWidth(), 140 + mApp->mTurbotImg->GetHeight()); g->SetColorizeImages(false); // You may have noticed that part of the previous two images was drawn offscreen. The graphics object by // default sets a clipping region to the size of the widget, and anything drawn outside of it // is clipped, or not drawn. You'll see some more advanced uses of clipping and widgets in a later demo. // There's another cool effect you can do to images: Drawing additively instead of normally. // Additive drawing is just what the name implies: when you draw the image, instead of // drawing using the exact RGBA values of the image, it actually combines them with whatever // pixel values there are in the location in which it is placed. One common use of this is // to draw the same image, but brighter: To do so, you'd just draw the image normally first, // then draw the same image on top of it but additively. Let's try an example and draw // our first image, mApp->mTurbotImg, additively to get a bright effect. g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth(), 140); // Enable additive drawing with the call below. IMPORTANT: You should set the // drawmode back to Graphics::DRAWMODE_NORMAL when done, so that other images // don't get drawn additively. Additive drawing is slower than colorization, // so keep that in mind if you are concerned about your game's performance. g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth(), 140); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); // You can even draw an image colorized and additively. This is comonly used to // implement a pulsing sort of effect. Let's do just that: the variable, // mPulseAmt, is updated in our Update method and controls the RGB value // that we'll use to make our image pulse. Again, be sure to set things back // to normal when you are done. Also, it matters not in which order the // SetDrawMode, SetColor, and SetColorizeImages calls are made. g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth() * 2, 140); g->SetDrawMode(Graphics::DRAWMODE_ADDITIVE); g->SetColor(Color(mPulseAmt, mPulseAmt, mPulseAmt)); g->SetColorizeImages(true); g->DrawImage(mApp->mTurbotImg, 230 + mApp->mTurbotImg->GetWidth() * 2, 140); g->SetDrawMode(Graphics::DRAWMODE_NORMAL); g->SetColorizeImages(false); // And finally, let's just have a simple example of alpha blending. We'll // Draw our first image, a picture of a moon, normally, and draw // our friend Turbot at reduced opacity on top of it. The result is you can // see through turbot to the moon below. Notice that we set the color // for turbot to r=255, g=255, b=255, alpha=128: This results in the // RGB values not being changed, only the alpha. Using a value of 255 for // a colorization amount basically means that the color component will not // be altered. g->DrawImage(mApp->mMoonImg, 400, 300); g->SetColor(Color(255, 255, 255, 60)); g->SetColorizeImages(true); g->DrawImage(mApp->mTurbotImg, 400, 300); g->SetColorizeImages(false); } libtuxcap-1.4.0/tuxcap/demo1/0000755000175000017500000000000011212652053015675 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/demo1/GameApp.cpp0000644000175000017500000001103511062533665017725 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" #include "Common.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Demo 1"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Demo1"; // Set the application width/height in terms of pixels here. mWidth = 640; mHeight = 480; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // In later demos, you will see more done with this function. // For now, we have nothing else to initialize, so we are done. // Once complete, the LoadingThreadProc function will automatically // start and we will begin loading all our needed resources. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // In this particular demo, there are no resources that we // need to load. In every game and in all subsequent demos, however, // there will be things we need to load. Besides loading data, // this thread can also update the progress indicator for the loading // screen, which you will see in later demos. // Once complete, the LoadingThreadCompleted function will be called. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 640x480. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); } libtuxcap-1.4.0/tuxcap/demo1/CMakeLists.txt0000644000175000017500000000370611062704301020440 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../demo_1") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/demo1/Board.h0000644000175000017500000000753110641010426017100 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget { private: GameApp* mApp; public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/demo1/GameApp.h0000644000175000017500000000612010641010426017354 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/demo1/main.cpp0000644000175000017500000000022710641010426017323 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/demo1/Board.cpp0000644000175000017500000001601510641010426017430 0ustar inniyahinniyah#include "Board.h" #include "Graphics.h" // See the Draw method for more information on using the Color class. #include "Color.h" // A generic X, Y point template. See Draw() below for usage info. #include "Point.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // And now for the good stuff! The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by drawing some geometric primitives. By // default, the drawing color is black. We will change it later // on. The first command clears the screen by drawing a // black rectangle (black due to the default color) that is // located at coordinate 0, 0 and is the same size as our // Board widget, which is the same size as the application and // thus is the same size of the game window. g->FillRect(0, 0, mWidth, mHeight); // You may notice that there's another form of FillRect, one that // takes a Rect object as its sole parameter. That does the // same thing as the above function, but sometimes its more useful // to draw using a Rect object. // Now let's learn how to change the color of the shapes we're drawing. // Call the "SetColor" method to change the current drawing color. // The parameter is a Color object which can take 3 or 4 parameters. // If you call it with only 3 parameters, the 4th one, which is the // alpha value, is set to 255 for fully opaque. The first three are // in order, red, green, and blue. They range from 0 to 255. g->SetColor(Color(255, 128, 64)); // some ugly orangish color // Let's draw a smaller rectangle with its upper left corner // in the center of the screen. g->FillRect(mWidth / 2, mHeight / 2, 50, 50); // Now let's continue with some other primitives. How about // drawing a few lines? We'll use a few other colors too. g->SetColor(Color(255, 0, 0)); // red // Parameter order is X1, Y1, X2, Y2 g->DrawLine(0, 0, 200, 150); g->SetColor(Color(0, 255, 0)); // green g->DrawLine(mWidth, 0, mWidth - 200, 150); g->SetColor(Color(0, 0, 255)); // blue g->DrawLine(0, mHeight, 200, mHeight - 150); g->SetColor(Color(255, 255, 255)); // white g->DrawLine(mWidth, mHeight, mWidth - 200, mHeight - 150); // Let's draw another rectangle, with vertices where each of // the previous 4 lines were. This time, however, let's not // fill it in and just draw its outline instead. We // accomplish that with the DrawRect function, which doesn't // fill in the center. g->SetColor(Color(255, 0, 255)); // purple g->DrawRect(200, 150, (mWidth - 200) - 200, (mHeight - 150) - 150); // Tired of drawing lines and quads? How about drawing a triangle // instad? To do that, we use the generic PolyFill function which // draws a closed polygon with any number of points, >= 2. // We pass this function an array containing these points. We'll // create such an array right now, although in reality you'd // probably make this a constant instead of creating it every time. // We'll make use of the Point template which will use the int type // to specify the X, Y coordinates of each point in our triangle. // It is assumed that the last point connects to the first point. Point trianglePoints[3]; trianglePoints[0] = Point(30, 30); trianglePoints[1] = Point(30, 60); trianglePoints[2] = Point(60, 45); g->SetColor(Color(255, 255, 0)); // yellow g->PolyFill(trianglePoints, 3); // And how about a pentagram as well? g->SetColor(Color(0, 255, 255)); // cyan Point pentaPoints[5]; pentaPoints[0] = Point(200, 0); pentaPoints[1] = Point(150, 40); pentaPoints[2] = Point(150, 80); pentaPoints[3] = Point(250, 80); pentaPoints[4] = Point(250, 40); g->PolyFill(pentaPoints, 5); } libtuxcap-1.4.0/tuxcap/demo3/0000755000175000017500000000000011212652053015677 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/demo3/GameApp.cpp0000644000175000017500000003265311202747624017736 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The Image.h file just declares basic functions. All images are either of // the DDImage or MemoryImage type. For this demo, we will use DDImage // types, as they are the type returned by the image loading code. // A DDImage is actually derived from MemoryImage, so where an Image or // MemoryImage is required, a DDImage will suffice as well. A DDImage // contains optimized code for use with DirectX 7+. #include "DDImage.h" // We're going to create a font for Board's button widget's label #include "ImageFont.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Demo 3"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Demo3"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 800; mHeight = 600; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. // mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; // We need to clean up after ourselves and delete the image and // font information. delete mTurbotImg; delete mLightningImg; delete mAlteredImg; delete mFont; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // In later demos, you will see more done with this function. // For now, we have nothing else to initialize, so we are done. // Once complete, the LoadingThreadProc function will automatically // start and we will begin loading all our needed resources. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // This time, we have things to load. Let's load in our two fonts // and our three images. // Besides loading data, // this thread can also update the progress indicator for the loading // screen, which you will see in later demos. // Once complete, the LoadingThreadCompleted function will be called. // Loading images is easy: you don't have to specify the image type. // Depending on the file extension, the appropriate image decoder // will be used. The following image types are supported: // Targa (.tga), JPEG (.jpg), PNG (.png), GIF (.gif). You do NOT have // to specify the extension when loading the file if you don't want to. // In this case, all of the above extensions will be looked for. // A discussion of image formats is beyond the scope of this tutorial. // There is some important information to know about images. // You will notice in the "images" directory that for each image, // there is a black and white image with the same name but with // an underscore ("_") at the end of it. By default, when you load // and image, the code automatically looks for the presence of // that file to use for the alpha information. Some file formats // have the alpha channel built into them, like PNG files. But // others, like JPEG or GIF files, do not. The purpose of the alpha // file is of course to generate an image that doesn't have jagged // lines, or to control the opacity of various parts of the image. // As a side not, the alpha image file may also begin with the // underscore instead of ending with it, it matters not, and again, // is automatically loaded in by the image loading code. // You need to clean up the memory allocated by these functions yourself. mTurbotImg = (DDImage*) GetImage("images/turbot_worry.gif"); // If the file was not found or couldn't be loaded (i.e. due to an // incompatible file format) the returned value will be NULL. // You should always check this, and if it occurs, display an error // message, then set mLoadingFailred to true, and then immediately return. if (mTurbotImg == NULL) { mLoadingFailed = true; // The PopUp method displays a standard Windows message box. // If in full screen mode, this will appropriately handle things such // that the GDI surface is properly rendered and the dialog box appears // as expected. #if 0 Popup("There was an error loading the file: images/turbot_worry"); #endif return; } mLightningImg = (DDImage*) GetImage("images/lightning.gif"); if (mLightningImg == NULL) { mLoadingFailed = true; #if 0 Popup("There was an error loading the file: images/lightning"); #endif return; } // There's something different about mLightningImg. If you look at the // image in the iamges directory, you'll notice that it has multiple frames // arranged in rows. This is an animation strip and is the main way that we // accomplish animation. Rather than putting each frame in a separate file, // we place it in one file and make each frame have the same width/height. // When loading, the image loader has no idea that we even want to consider // the image as being made of multiple frames. So we have to manually tell // it how many rows and/or columns it has. In this case, there is only 1 // column, but there are 8 rows. We set this via mNumRows and mNumCols. // You'll see why this is important in the Board class. mLightningImg->mNumRows = 8; mLightningImg->mNumCols = 1; // So we've loaded the images, that's all there is right? Wrong. // If possible, we should try to palletize the images. An image that // contains 255 or fewer colors can be palletized. This results in // a memory savings of about 4x and doesn't affect the image quality // at all. It's the same principals that the GIF format uses: instead // of representing each red, green, blue, alpha value as a separate // quantity (1 byte each, 4 bytes in total per pixel), we represent // the actual combined RGBA value as a single number, from 0-255. // This number is an index into a lookup table. Thus, every time // the value (200,43,11,128), for example, is used, instead of // representing that value as a 4 byte value every time it // appears, we'd represent it with a 1 byte index into a lookup // table that contained the above RGBA value. Don't worry, you // don't have to really know or care about any of that if you // didn't understand it. What you need to know is that by calling the // Palletize() method on an image, you potentially can reduce the // amount of RAM it consumes by 4 times. The Palletize method // returns a boolean indicating if it could or couldn't be palletized. mLightningImg->Palletize(); mTurbotImg->Palletize(); // This is the same as in Demo2. Check the comments there // if you've forgotten how to load and initialize a font. mFont = new ImageFont(this, "fonts/Kiloton9.txt"); // We need to check to see if the font was properly initialized. // If it wasn't, then an error occurred and we need to abort. if (!mFont->mFontData->mInitialized) { delete mFont; mLoadingFailed = true; #if 0 Popup("There was an error loading fonts/Kiloton9.txt"); #endif return; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); // As part of a new topic in this demo, we're also going to modify the image // data for mTurbotImg and make a grayscale version of it. I'll explain // each step of the way: // 1. Let's make a copy of the image so we don't ruin the original. // We should make sure to delete this when we're done. mAlteredImg = (DDImage*) CopyImage(mTurbotImg); // 2. Now we need to get the pixel data. The pixel data is stored as // an uint32_t array, where each entry represents the RGBA value. // The data is actually stored in ARGB format, where alpha is // the leftmost byte and blue is the rightmost byte. uint32_t* bits = ((DDImage*)mAlteredImg)->GetBits(); // 3. Now we will loop over each pixel in the image. The size of the bits array // is simply the width times the height. for (int i = 0; i < mAlteredImg->GetWidth() * mAlteredImg->GetHeight(); i++) { // 4. Get the ARGB color value for this pixel uint32_t c = bits[i]; // 5. To illustrate the ARGB storage format, we will assign each // component to a variable, although we're actually only going to care // about the RGB values, for this particular example. The 4 lines below // extract out the individual ARGB values. unsigned char alpha = (unsigned char) (c >> 24); unsigned char red = (unsigned char) ((c >> 16) & 0xFF); unsigned char green = (unsigned char) ((c >> 8) & 0xFF); unsigned char blue = (unsigned char) (c & 0xFF); // 6. Just like the Color class, the ARGB values are from 0-255. // Let's alter these to produce a grayscale image using one of many // conversion methods. This method uses 30% of the red value, // 59% of the green value, and 11% of the blue value: uint32_t gray = (uint32_t) ((float)red * 0.30f + (float)green * 0.59f + (float)blue * 0.11f); // 7. Now we need to put the pixel data back into the image's data. // We do the opposite of how we extracted the ARGB values above and // use a left shift instead of a right shift: // alpha red green blue bits[i] = (alpha << 24) | (gray << 16) | (gray << 8) | gray; } // The image won't use this modified data until we inform it that we've // done some messing around with it. We do that with the BitsChanged() // function call. After that, we're all done! Pretty simple. It just // depends on what you want to actually do with the RGBA data. Extracting // the information and putting it back is as simple as a few shifts. ((DDImage*)mAlteredImg)->BitsChanged(); } libtuxcap-1.4.0/tuxcap/demo3/CMakeLists.txt0000644000175000017500000000371010762446645020461 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists #SET(Required_Packages #list packages here #SDL OpenGL GLU #) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../demo_3") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/demo3/Board.h0000644000175000017500000002567510641010425017112 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" // You'll learn about responding to button events in this demo. // Any class that wants to respond to them must derive from ButtonListener. #include "ButtonListener.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // We're going to make a modified copy of GameApp::mTurbotImg, so we'll // need to forward declare the DDImage class. See Board::CreateMirroredStretchedImg. class DDImage; // We're going to create a button in this demo and respond to its // click event. class ButtonWidget; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public ButtonListener { private: GameApp* mApp; ButtonWidget* mButton; // The button that we're going to create in this demo int mAnimFrame; // The current frame of animation we're on for the mLightningImg image. int mMouseX, mMouseY; // As an example, we'll keep track of the mouse cursor position and display it on screen // We'll also keep track of which button is down bool mLeftDown; bool mRightDown; bool mMiddleDown; public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: MouseMove // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime the // mouse moves. The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored (you'll learn about how // to bypass that in a later demo). ////////////////////////////////////////////////////////////////////////// virtual void MouseMove(int x, int y); ////////////////////////////////////////////////////////////////////////// // Function: MouseDrag // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime the // mouse moves AND a button is held down. This is the same thing as // MouseMove except that it represents a drag operation. When dragging, // MouseDrag will be called INSTEAD OF MouseMove. // The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored (you'll learn about how // to bypass that in a later demo). ////////////////////////////////////////////////////////////////////////// virtual void MouseDrag(int x, int y); ////////////////////////////////////////////////////////////////////////// // Function: MouseDown // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // theClickCount - An integer indicating which mouse button // was pressed. One of the following: // 1: Left button // 2: Double-left-click // 3: Middle button // -1: Right button // -2: Double-right-click // // IMPORTANT: Because you can't have a double click with a // single click, you will receive BOTH a left (or right) button as well // as a double left (or right) button message whenever you double-click. // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime // a mouse button is in the down state. // The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored (you'll learn about how // to bypass that in a later demo). ////////////////////////////////////////////////////////////////////////// virtual void MouseDown(int x, int y, int theClickCount); ////////////////////////////////////////////////////////////////////////// // Function: MouseUp // Parameters: // x - X coordinate relative to the application of the mouse // y - Y coordinate relative to the application of the mouse // theClickCount - An integer indicating which mouse button // was pressed. One of the following: // 1: Left button // 2: Double-left-click // 3: Middle button // -1: Right button // -2: Double-right-click // // IMPORTANT: Because you can't have a double click with a // single click, you will receive BOTH a left (or right) button as well // as a double left (or right) button message whenever you double-click. // // Returns: none // // Purpose: Called by the WidgetManager automatically anytime // a mouse button is in the up state after previously being in the down state. // The topmost widget (i.e. the widget most immediately // under the cursor) is the one who gets the function call, and any // widgets underneath by default are ignored (you'll learn about how // to bypass that in a later demo). ////////////////////////////////////////////////////////////////////////// virtual void MouseUp(int x, int y, int theClickCount); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/demo3/GameApp.h0000644000175000017500000000777210641010425017373 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; // You'll learn more about images in GameApp.cpp and Demo2, // so check there for more info. You'll notice we're using DDImage instead // of Image, like we did in Demo 2. That's for convenience only, so that // we don't have to type cast the image every time we want to work with it. class DDImage; // We'll need a font for the label on our button (see Board for more info on buttons) class ImageFont; class GameApp : public SexyAppBase { private: Board* mBoard; public: // These are the images we'll be using for this demo. See // GameApp.cpp for full information. We're going to // make them public for easy accessing, since the point of this tutorial // is to quickly get you up to speed on using the framework. DDImage* mTurbotImg; DDImage* mLightningImg; DDImage* mAlteredImg; // Used in our example of modifying the image bits to make an altered version of an image. ImageFont* mFont; // The font we'll use for the label on our button in Board public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/demo3/main.cpp0000644000175000017500000000022710641010425017324 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/demo3/Board.cpp0000644000175000017500000004310310641010425017427 0ustar inniyahinniyah#include "Board.h" #include "GameApp.h" #include "Graphics.h" // See the Draw method for more information on using the Color class. #include "Color.h" // The Image.h file just declares basic functions. All images are either of // the DDImage or MemoryImage type. For this demo, we will use DDImage // types, as they are the type returned by the image loading code. // A DDImage is actually derived from MemoryImage, so where an Image or // MemoryImage is required, a DDImage will suffice as well. A DDImage // contains optimized code for use with DirectX 7+. #include "DDImage.h" // The Rectangle template, used to specify X, Y, Width, Height #include "Rect.h" // We're going to be making a button in this demo so we need to // include this file. #include "ButtonWidget.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" #include "ImageFont.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; // Start off drawing the first frame of mLightningImg mAnimFrame = 0; mButton = NULL; mMouseX = mMouseY = 0; mLeftDown = mRightDown = mMiddleDown = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete mButton; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); // Let's update our animation frame every 5 update ticks. This // is equivalent to 20 times per second. if (mUpdateCnt % 5 == 0) { // In GameApp we specified how many rows and columns this image // had. Thus, if our current frame of animation exceeds the number // of frames that we have, we should reset the animation frame back // to 0. if (++mAnimFrame >= mApp->mLightningImg->mNumRows) mAnimFrame = 0; } // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(0, 0, 0)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) g->DrawImage(mApp->mTurbotImg, 0, 0, mApp->mTurbotImg->GetWidth() * 2, mApp->mTurbotImg->GetHeight() * 2); g->DrawImage(mApp->mTurbotImg, 0, 275, mApp->mTurbotImg->GetWidth() / 2, mApp->mTurbotImg->GetHeight() / 2); // The default stretching algorithm (the one used in the two examples above) uses // the slow stretching method. The slow stretching method anti-aliases the resulting // image to give a smoother, less pixelated look. While this tends to look a lot // nicer, it also requires more processing power. Thus, if you either don't need // or don't care about the anti-aliasing, you can instruct the graphics object // to use fast stretching. Just remember: unless you turn fast stretching off when // done, it will remain on. Let's give it a try by drawing the same image // stretched twice as large using fast stretching. g->SetFastStretch(true); g->DrawImage(mApp->mTurbotImg, 275, 0, mApp->mTurbotImg->GetWidth() * 2, mApp->mTurbotImg->GetHeight() * 2); g->SetFastStretch(false); // A good use of fast/non fast stretching is to enable the slower stretching method // for users with a supported 3D card and to disable it for users that have // to run in software mode. You'll learn more about determining if a user is in // 3D mode or not in a later demo, but keep this simple optimization in mind // when creating drawing code for your games. // Another cool thing we can do is to draw an image mirrored. This is exactly // like using the DrawImage command except that you use DrawImageMirror // instead. The optional fourth argument is just a convenience switch: if it's false, // it will draw the image normally. In 3D mode, this is just as fast as a normal draw. g->DrawImageMirror(mApp->mTurbotImg, 75, 275); // But what if you want to draw the image mirrored AND stretched? It's a little different, // but still easy. The first parameter, like usual, is the image you want to draw. // The second parameter is a Rect which indicates the destination region you want to draw // the image to: The XY of the Rect is just what you think it is, it's the pixel coordinate // the image should be drawn at. The Width, Height of the Rect however is how you accomplish // the stretching/shrinking. Specify a different width/height from the original image size // and you've just accomplished resizing the original image! Note that we have a third // parameter, also a Rect. This is the source rectangle, and indicates the region of // image you wish to draw. As you'll see in our animation example, you don't have to // always draw the entire image. You can specify a rectangular region of the source image // that you wish to draw, which is useful for large strips of animation (more below). // For our current case, however, we want to draw the entire image. So we specify that // we should draw from the top left (0,0) coordinate of the source image and we should // use it's full width/height. Again, just like with DrawImage, you can use the // SetFastStretch call to set whether you want the nice, slow, smooth scaling, or the quick // and efficient exact scaling. In 3D mode, this is just as fast as a normal stretched draw. g->DrawImageMirror(mApp->mTurbotImg, Rect(200, 275, mApp->mTurbotImg->GetWidth() * 2, mApp->mTurbotImg->GetHeight() * 2), Rect(0, 0, mApp->mTurbotImg->GetWidth(), mApp->mTurbotImg->GetHeight())); // Remember that black and white image we made in GameApp::LoadingThreadCompleted? // How about we draw it now so you can see what the result looks like: g->DrawImage(mApp->mAlteredImg, 500, 0); // And now for the exciting part: animation! As you can see in ::Update, we // increment the animation frame every 5 update ticks. We don't want to use // DrawImage because that will render the entire image. Instead, we only // want to draw a particular cel. We do that with the DrawImageCel function, // specifying the row or column to draw like so: g->DrawImageCel(mApp->mLightningImg, 0, 540, mAnimFrame); // If your animation strips contain both multiple rows AND columns, // you will need to use one of the alternate forms of DrawImageCel. // DrawImageCel is really just a convenience wrapper around DrawImage. // As you may have seen, you can tell DrawImage to draw just a particular // rectangular region of the image. Here is the equivalent function // call that we could have used in place of DrawImageCel above: //g->DrawImage(mApp->mLightningImg, //Rect(0, 540, mApp->mLightningImg->GetWidth(), mApp->mLightningImg->GetCelHeight()), //Rect(0, mApp->mLightningImg->GetCelHeight() * mAnimFrame, mApp->mLightningImg->GetWidth(), mApp->mLightningImg->GetCelHeight())); // // As you can see, DrawImageCel is a lot quicker to type. // Let's also display the current mouse XY and which button(s) are held down. // You should recall how to set fonts and change their colors from Demo2. // You will notice that the X, Y is not updated when the cursor moves over // the button that we added. This can be explained by reading the comments // for the MouseMove/MouseDrag/MouseDown/MouseUp methods. g->SetFont(mApp->mFont); g->SetColor(Color(255, 255, 255)); g->DrawString(StrFormat(_S("X, Y is %d, %d"), mMouseX, mMouseY), 630, 20); SexyString buttonStr; if (mLeftDown) buttonStr += _S("Left button is down. "); if (mRightDown) buttonStr += _S("Right button is down. "); if (mMiddleDown) buttonStr += _S("Middle button is down. "); WriteWordWrapped(g, Rect(630, 40, mWidth - 630, 300), buttonStr, -1, -1); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); // Now let's create our first widget: a button. We do that by // telling the button what integer ID it should be identified with, // and by passing it a pointer to a button listener. Widgets have // "listeners" which respond to their particular events. Any class // can be a listener. For this particular demo, it is convenient for the // Board class to be the listener, but it is also common to use GameApp // as the main listener for all application buttons. The choice is up // to you and your needs. mButton = new ButtonWidget(1, this); // Remember how we had to position and size the Board class when we first // created it? A button is no different, it too is a widget. Let's // place this button on screen and set it's size now: mButton->Resize(675, 500, 100, 50); // Because a button can have a label on it, we should set the font to use: mButton->SetFont(mApp->mFont); // And just what should that label be? How about the word "Off". // We'll make it so that when it's clicked, it changes to "On" and // back to "Off" again. mButton->mLabel = _S("Off"); // We can also change some colors, like the label color and the color // the label gets when moused over using the constants below: mButton->SetColor(ButtonWidget::COLOR_LABEL, Color(0, 255, 0)); mButton->SetColor(ButtonWidget::COLOR_LABEL_HILITE, Color(0, 255, 0)); // And finally, just like with the Board class, we have to add it // if we want to do anything with it. theWidgetManager->AddWidget(mButton); // If you want, you can also control the placement of the button. // You can put it in front of another widget, behind another widget, // at the top of the drawing order, or at the bottom of the // drawing order. You accomplish that with the WidgetManager's // PutInFront, PutBehind, BringToFront, BringToBack methods, respectively. // But wait, what does this button look like? If you don't specify an // image to use, the default Windows widget look will be used. We'll cover // images and widgets in a later demo. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); // We should now also remove any widgets we are responsible for. In // our current case, we made a button in AddedToManager. Let's remove // it now: theWidgetManager->RemoveWidget(mButton); // We'll delete it in our destructor. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::ButtonDepress(int theId) { // Because we told our button that we, the Board class, are // going to listen for its particular events, this method will // thus be called when our button has any events it wants us // to know about. In our current case, we only want to know when // the button is clicked, but you could also respond to a few others. // Let's change the label on our button whenever it is clicked, from // "Off" to "On" and back again. if (theId == 1) { // We assigned ID of 1 to our button. You'd ideally want to use // a constant, but since this is a demo and there's only 1 button, // we're going to just use a literal instead. When a button // causes an action, it calls the appropriate listener function and // let's the listener know who it is via the ID parameter. if (mButton->mLabel == _S("Off")) mButton->mLabel = _S("On"); else mButton->mLabel = _S("Off"); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseMove(int x, int y) { // This is called because the mouse cursor changed position and // the Board class was the widget closest to the cursor. // We're going to keep track of the XY coordinate whenever we // get this message for the sake of this demo. mMouseX = x; mMouseY = y; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseDrag(int x, int y) { // This is called because the mouse cursor changed position while // a button was down (a drag) and // the Board class was the widget closest to the cursor. // We're going to keep track of the XY coordinate whenever we // get this message for the sake of this demo. // Note that MouseDrag is called instead of MouseMove under // this condition. mMouseX = x; mMouseY = y; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseDown(int x, int y, int theClickCount) { // Let the parent class know about this and perform any actions // it needs to. Widget::MouseDown(x, y, theClickCount); // Let's just keep track of which button is currently held down. if (theClickCount == 3) mMiddleDown = true; else if (theClickCount > 0) mLeftDown = true; else if (theClickCount < 0) mRightDown = true; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::MouseUp(int x, int y, int theClickCount) { // Let the parent class know about this and perform any actions // it needs to. Widget::MouseUp(x, y, theClickCount); //You can actually tell if the left, right, // or middle buttons are currently held down by calling one of these // WidgetManager methods: IsLeftButtonDown, IsRightButtonDown, // IsMiddleButtonDown. However, we're going to keep track of this // manually just to illustrate a point. if (theClickCount == 3) mMiddleDown = false; else if (theClickCount > 0) mLeftDown = false; else if (theClickCount < 0) mRightDown = false; } libtuxcap-1.4.0/tuxcap/lib/0000755000175000017500000000000011212654601015437 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/lib/NaturalCubicSpline.cpp0000644000175000017500000004077510662644475021727 0ustar inniyahinniyah#include "NaturalCubicSpline.h" #include "Graphics.h" #include "SexyVector.h" #include "XMLParser.h" #include "XMLWriter.h" #include #include using namespace Sexy; NaturalCubicSpline::NaturalCubicSpline(void) { mArcLength = 0.0f; mGranularity = 24; mClosed = false; } NaturalCubicSpline::~NaturalCubicSpline(void) { } void NaturalCubicSpline::Draw(Graphics *g) { g->SetColor(Color(0xaa,0xff, 0xaa)); for(int i = 0; i < GetNumControlPoints(); i++) { DrawControlPoint(g, i, 4); } if(mSpline.size() > 2) { g->SetColor(Color(0xaa,0xaa, 0xff)); for(int i = 0; i < GetNumSplineSegments(); i++) { DrawSplineSegment(g, i); } } else { g->SetColor(Color(0xaa,0xaa, 0xff)); for(unsigned int i = 1; i < mPoints.size(); i++) { g->DrawLineAA(mPoints[i].mX, mPoints[i].mY, mPoints[i-1].mX, mPoints[i-1].mY); } } } void NaturalCubicSpline::DrawControlPoint(Sexy::Graphics *g, int theControlPointId, int theWidth) { if(theControlPointId >= 0 && theControlPointId < (int)mPoints.size()) g->FillRect(mPoints[theControlPointId].mX - theWidth/2, mPoints[theControlPointId].mY - theWidth/2, theWidth, theWidth); } void NaturalCubicSpline::DrawSplineSegment(Sexy::Graphics *g, int theSplineSegmentId) { if(theSplineSegmentId >= 0 && theSplineSegmentId < (int)mXCubics.size()) { for(unsigned int i = 0; i < mGranularity; i++) { int index = i + theSplineSegmentId*mGranularity + 1; g->DrawLineAA((int)mSpline[index].mX, (int)mSpline[index].mY, (int)mSpline[index-1].mX, (int)mSpline[index-1].mY); } } } void NaturalCubicSpline::AddPoint(Sexy::Point thePoint) { mXCoords.push_back((float)thePoint.mX); mYCoords.push_back((float)thePoint.mY); mPoints.push_back(thePoint); RegenerateSplines(); } // Returns the Tangent of a point on the line specified in Ribbon Coordinates. // Tangents Tell the direction of travel and can be used to rotate the object to // face the correct direction. Sexy::FPoint NaturalCubicSpline::GetTangentAt(float theLength) { if(mXCubics.size() == 0) return Sexy::FPoint(0,0); if(mSpline.size() == 0) return Sexy::FPoint(0,0); if(theLength < 0.0f) return Sexy::FPoint(0,0); if(theLength > mArcLength) return Sexy::FPoint(0,0); float aDistance = theLength; unsigned int anIndex = 0; for(unsigned int i = 0; i < mSplineSegmentLengths.size(); i++, anIndex++) { aDistance -= mSplineSegmentLengths[i]; if(aDistance < 0.0f) { aDistance += mSplineSegmentLengths[i]; break; } } if(anIndex < mSplineSegmentLengths.size()) { float u = aDistance/mSplineSegmentLengths[anIndex]; Sexy::SexyVector2 aVector(mXCubics[anIndex].tangent(u), mYCubics[anIndex].tangent(u)); aVector = aVector.Normalize(); return Sexy::FPoint(aVector.x, aVector.y); } return Sexy::FPoint(0,0); } // Resolves a Distance on the spline to a Cartesian 2d Point on the Screen. // Exact position evaluated on the spline. Sexy::Point NaturalCubicSpline::GetPointAt(float theDistanceOnTheSpline) { if(mPoints.size() == 0) return Sexy::Point(0,0); if(mSpline.size() == 0) return mPoints.back(); if(theDistanceOnTheSpline < 0.0f) return mPoints.front(); if(theDistanceOnTheSpline > mArcLength) return mPoints.back(); float aDistance = theDistanceOnTheSpline; unsigned int anIndex = 0; for(unsigned int i = 0; i < mSplineSegmentLengths.size(); i++, anIndex++) { aDistance -= mSplineSegmentLengths[i]; if(aDistance < 0.0f) { aDistance += mSplineSegmentLengths[i]; break; } } if(anIndex < mSplineSegmentLengths.size()) { float u = aDistance/mSplineSegmentLengths[anIndex]; return Sexy::Point((int)mXCubics[anIndex].eval(u), (int)mYCubics[anIndex].eval(u)); } return mPoints.back(); } // Creates and stores the Cubic Spline Data needed for all functions releated to Class. // Requires 3 or more points caches the Splines as series of straight lines for faster operations // such as picking and drawing. void NaturalCubicSpline::RegenerateSplines() { if(mClosed) //Full Circle { RegenerateClosedSpline(mXCoords, mXCubics); RegenerateClosedSpline(mYCoords, mYCubics); } else { RegenerateSpline(mXCoords, mXCubics); RegenerateSpline(mYCoords, mYCubics); } mSpline.clear(); mSplineSegmentLengths.clear(); if(mXCubics.size()) { mSpline.push_back(Sexy::FPoint((float)mXCubics[0].eval(0), (float)mYCubics[0].eval(0))); for(unsigned int x = 0; x < mXCubics.size(); x++) { mSplineSegmentLengths.push_back(0.0f); for(unsigned int steps = 1; steps <= mGranularity; steps++) { float u = (float) steps / (float)mGranularity; mSpline.push_back(Sexy::FPoint((float)mXCubics[x].eval(u), (float)mYCubics[x].eval(u))); // Cache Segment Lengths unsigned int index = x*mGranularity + steps-1; mSplineSegmentLengths[x] += (float)sqrt( (((float)mSpline[index].mX - mSpline[index+1].mX)*((float)mSpline[index].mX - mSpline[index+1].mX)) + (((float)mSpline[index].mY - mSpline[index+1].mY)*((float)mSpline[index].mY - mSpline[index+1].mY))); } } mArcLength = 0.0f; for(unsigned int i = 1; i < mSpline.size(); i++) mArcLength += (float)sqrt( ((float)mSpline[i].mX - mSpline[i-1].mX)*((float)mSpline[i].mX - mSpline[i-1].mX) + ((float)mSpline[i].mY - mSpline[i-1].mY)*((float)mSpline[i].mY - mSpline[i-1].mY)); } } // Generates the Spline with the assumption that the end is connected to the beginning void NaturalCubicSpline::RegenerateClosedSpline(std::vector& theInput, std::vector& theOutput) { theOutput.clear(); if(theInput.size() < 3) return; int n = (int)theInput.size() - 1; std::vector w(n+1); std::vector v(n+1); std::vector y(n+1); std::vector D(n+1); float z, F, G, H; int k; /* We solve the equation [4 1 1] [D[0]] [3(theInput[1] - theInput[n]) ] |1 4 1 | |D[1]| |3(theInput[2] - theInput[0]) | | 1 4 1 | | . | = | . | | ..... | | . | | . | | 1 4 1| | . | |3(theInput[n] - theInput[n-2])| [1 1 4] [D[n]] [3(theInput[0] - theInput[n-1])] by decomposing the matrix into upper triangular and lower matrices and then back sustitution. See Spath "Spline Algorithms for Curves and Surfaces" pp 19--21. The D[i] are the derivatives at the knots. */ w[1] = v[1] = z = 1.0f/4.0f; y[0] = z * 3 * (theInput[1] - theInput[n]); H = 4; F = 3 * (theInput[0] - theInput[n-1]); G = 1; for ( k = 1; k < n; k++) { v[k+1] = z = 1/(4 - v[k]); w[k+1] = -z * w[k]; y[k] = z * (3*(theInput[k+1]-theInput[k-1]) - y[k-1]); H = H - G * w[k]; F = F - G * y[k-1]; G = -v[k] * G; } H = H - (G+1)*(v[n]+w[n]); y[n] = F - (G+1)*y[n-1]; D[n] = y[n]/H; D[n-1] = y[n-1] - (v[n]+w[n])*D[n]; /* This equation is WRONG! in my copy of Spath */ for ( k = n-2; k >= 0; k--) { D[k] = y[k] - v[k+1]*D[k+1] - w[k+1]*D[n]; } /* now compute the coefficients of the cubics */ for ( k = 0; k < n; k++) { theOutput.push_back(Cubic((float)theInput[k], D[k], 3*(theInput[k+1] - theInput[k]) - 2*D[k] - D[k+1], 2*(theInput[k] - theInput[k+1]) + D[k] + D[k+1])); } theOutput.push_back(Cubic((float)theInput[n], D[n], 3*(theInput[0] - theInput[n]) - 2*D[n] - D[0], 2*(theInput[n] - theInput[0]) + D[n] + D[0])); } // Generates the Spline void NaturalCubicSpline::RegenerateSpline(std::vector& theInput, std::vector& theOutput) { theOutput.clear(); if(theInput.size() < 3) return; int n = (int)theInput.size() - 1; std::vector gamma(n+1); std::vector delta(n+1); std::vector D(n+1); int i; /* We solve the equation [2 1 ] [D[0]] [3(theInput[1] - theInput[0]) ] |1 4 1 | |D[1]| |3(theInput[2] - theInput[0]) | | 1 4 1 | | . | = | . | | ..... | | . | | . | | 1 4 1| | . | |3(theInput[n] - theInput[n-2])| [ 1 2] [D[n]] [3(theInput[n] - theInput[n-1])] by using row operations to convert the matrix to upper triangular and then back sustitution. The D[i] are the derivatives at the knots. */ gamma[0] = 1.0f/2.0f; for ( i = 1; i < n; i++) { gamma[i] = 1/(4-gamma[i-1]); } gamma[n] = 1/(2-gamma[n-1]); delta[0] = 3*(theInput[1]-theInput[0])*gamma[0]; for ( i = 1; i < n; i++) { delta[i] = (3*(theInput[i+1]-theInput[i-1])-delta[i-1])*gamma[i]; } delta[n] = (3*(theInput[n]-theInput[n-1])-delta[n-1])*gamma[n]; D[n] = delta[n]; for ( i = n-1; i >= 0; i--) { D[i] = delta[i] - gamma[i]*D[i+1]; } /* now compute the coefficients of the cubics */ for ( i = 0; i < n; i++) theOutput.push_back(Cubic((float)theInput[i], D[i], 3*(theInput[i+1] - theInput[i]) - 2*D[i] - D[i+1], 2*(theInput[i] - theInput[i+1]) + D[i] + D[i+1])); } // Returns the linear distance on the Spline Closest to the input Point // This is computed by using the cached line segments (not exact solution) float NaturalCubicSpline::GetClosestPointOnSegmentToPoint(Sexy::Point thePoint) { if(mSpline.size()) { float min_distance = FLT_MAX;// Something Large int min_index = -1; for(unsigned int i = 1; i < mSpline.size(); i++) { float temp_min_dist = (float)sqrt((thePoint.mX - mSpline[i].mX)*(thePoint.mX - mSpline[i].mX) + (thePoint.mY - mSpline[i].mY)*(thePoint.mY - mSpline[i].mY)); if(temp_min_dist < min_distance) { min_distance = temp_min_dist; min_index = i; } } if(min_index > 0 && min_distance < 20.00f) { unsigned int min_cubic_index = (min_index - 1)/mGranularity; float min_u = GetMinUFromLineAB(mSpline[min_index-1], mSpline[min_index], thePoint); int step_mod = (min_index)%mGranularity; float ret_dist = 0.0f; for(unsigned int i = 0; i < min_cubic_index; i++) { ret_dist += mSplineSegmentLengths[i]; } unsigned int start_segments = min_cubic_index*mGranularity; for(unsigned int i = start_segments + 1; i < start_segments+step_mod; i++) { ret_dist += (float)sqrt((mSpline[i].mX-mSpline[i-1].mX)*(mSpline[i].mX-mSpline[i-1].mX) + (mSpline[i].mY-mSpline[i-1].mY)*(mSpline[i].mY-mSpline[i-1].mY)); } ret_dist += (float)min_u * (float)sqrt((mSpline[min_index].mX-mSpline[min_index-1].mX)*(mSpline[min_index].mX-mSpline[min_index-1].mX) + (mSpline[min_index].mY-mSpline[min_index-1].mY)*(mSpline[min_index].mY-mSpline[min_index-1].mY)); return ret_dist; } } return 0.0f; } float NaturalCubicSpline::GetMinDistanceFromLineAB(Sexy::FPoint A, Sexy::FPoint B, Sexy::Point C) { float Bx_Ax = (float)(B.mX - A.mX); float By_Ay = (float)(B.mY - A.mY); float u = GetMinUFromLineAB(A,B,C); float x = (float)(A.mX + u*Bx_Ax); float y = (float)(A.mY + u*By_Ay); return sqrt((C.mX - x)*(C.mX - x) + (C.mY - y)*(C.mY - y)); } float NaturalCubicSpline::GetMinUFromLineAB(Sexy::FPoint A, Sexy::FPoint B, Sexy::Point C) { float Bx_Ax = (float)(B.mX - A.mX); float Cx_Ax = (float)(C.mX - A.mX); float By_Ay = (float)(B.mY - A.mY); float Cy_Ay = (float)(C.mY - A.mY); float Bx_Ax_2 = (float)((Bx_Ax) * (Bx_Ax)); float By_Ay_2 = (float)((By_Ay) * (By_Ay)); return (Cx_Ax*Bx_Ax + Cy_Ay*By_Ay)/(Bx_Ax_2 + By_Ay_2); } // Returns -1 if no point founds int NaturalCubicSpline::GetControlPointIdNear(Sexy::Point thePoint) { float min_distance = FLT_MAX; int ret_index = -1; for(unsigned int i = 0; i < mPoints.size(); i++) { float dist = (float)sqrt((float)(thePoint.mX - mPoints[i].mX)*(thePoint.mX - mPoints[i].mX) + (thePoint.mY - mPoints[i].mY)*(thePoint.mY - mPoints[i].mY)); if( dist < 20.0f && dist < min_distance) { min_distance = dist; ret_index = i; } } return ret_index; } // Returns -1 if No Segments Found int NaturalCubicSpline::GetSegmentIdNear(Sexy::Point thePoint) { float min_distance = FLT_MAX;// Something Large int min_index = -1; for(unsigned int i = 0; i < mSpline.size(); i++) { float temp_min_dist = (float)sqrt((thePoint.mX - mSpline[i].mX)*(thePoint.mX - mSpline[i].mX) + (thePoint.mY - mSpline[i].mY)*(thePoint.mY - mSpline[i].mY)); if(temp_min_dist < min_distance) { min_distance = temp_min_dist; min_index = i; } } if(min_index >= 0 && min_distance < 20.00f) { return min_index/mGranularity; } return -1; } // Returns the Coordinates of the Control Point Specified by the id Sexy::Point NaturalCubicSpline::GetControlPoint(int theControlPointId) { if(theControlPointId < (int)mPoints.size()) return mPoints[theControlPointId]; return Sexy::Point(0,0); } // Used to Move Control Points and Adjust the Spline. Use 'GetControlPointIdNear' to get a valid ID void NaturalCubicSpline::SetControlPoint(int theControlPointId, Sexy::Point thePoint) { if(theControlPointId >= 0 && theControlPointId < (int)mPoints.size()) { mPoints[theControlPointId] = thePoint; mXCoords[theControlPointId] = (float)thePoint.mX; mYCoords[theControlPointId] = (float)thePoint.mY; RegenerateSplines(); } } // Call this To Add a Control Point at the Mid-way point of the cubic // addressed by theSplineSegmentId void NaturalCubicSpline::BisectSegment(int theSplineSegmentId) { if(theSplineSegmentId >= 0 && theSplineSegmentId < (int)mXCubics.size()) { Sexy::Point aBisectingPoint((int)mXCubics[theSplineSegmentId].eval(0.5f), (int)mYCubics[theSplineSegmentId].eval(0.5f)); std::stack aStack; for(int i = (int)mPoints.size()-1; i > theSplineSegmentId; i--) { aStack.push(mPoints.back()); mPoints.pop_back(); mXCoords.pop_back(); mYCoords.pop_back(); } AddPoint(aBisectingPoint); while(!aStack.empty()) { AddPoint(aStack.top()); aStack.pop(); } RegenerateSplines(); } } void NaturalCubicSpline::DeleteControlPoint(int theControlPointId) { if(theControlPointId >= 0 && theControlPointId < (int)mPoints.size()) { std::stack aStack; for(int i = (int)mPoints.size() - 1; i >= 0; i--) { if((int) i != theControlPointId) aStack.push(mPoints[i]); } ClearAllPoints(); while(!aStack.empty()) { AddPoint(aStack.top()); aStack.pop(); } RegenerateSplines(); } } void NaturalCubicSpline::ClearAllPoints() { mPoints.clear(); mXCoords.clear(); mYCoords.clear(); mArcLength = 0.0f; RegenerateSplines(); } // Parse an XML snippet named NaturalCubicSpline void NaturalCubicSpline::Serialize(Sexy::XMLParser *theParser, Sexy::XMLElement *theNode) { ClearAllPoints(); if(theParser && theNode && !theParser->HasFailed()) { if(theNode->mValue == "NaturalCubicSpline") { if(theNode->mAttributes.find("granularity") != theNode->mAttributes.end()) mGranularity = sexyatoi(theNode->mAttributes["granularity"].c_str()); if(theNode->mAttributes.find("isClosed") != theNode->mAttributes.end()) mClosed = (theNode->mAttributes["isClosed"] == "true"); } while(theParser->NextElement(theNode)) { switch(theNode->mType) { case XMLElement::TYPE_START: { if(theNode->mValue == "Point") { if(theNode->mAttributes.find("x") != theNode->mAttributes.end() && theNode->mAttributes.find("y") != theNode->mAttributes.end()) { int x = 0,y = 0; x = sexyatoi(theNode->mAttributes["x"].c_str()); y = sexyatoi(theNode->mAttributes["y"].c_str()); AddPoint(Sexy::Point(x,y)); } } else if(theNode->mValue == "NaturalCubicSpline") { if(theNode->mAttributes.find("granularity") != theNode->mAttributes.end()) mGranularity = sexyatoi(theNode->mAttributes["granularity"].c_str()); if(theNode->mAttributes.find("isClosed") != theNode->mAttributes.end()) mClosed = (theNode->mAttributes["isClosed"] == "true"); } break; } case XMLElement::TYPE_END: { if(theNode->mValue == "NaturalCubicSpline") { RegenerateSplines(); return; } break; } } } } RegenerateSplines(); } // XMLWriter class is included with this solution void NaturalCubicSpline::Serialize(Sexy::XMLWriter *theWriter) { if(theWriter) { theWriter->StartElement("NaturalCubicSpline"); theWriter->WriteAttribute("isClosed", (mClosed)? "true" : "false"); theWriter->WriteAttribute("granularity", (int)mGranularity); for(unsigned int i = 0; i < mPoints.size(); i++) { theWriter->StartElement("Point"); theWriter->WriteAttribute("x", mPoints[i].mX); theWriter->WriteAttribute("y", mPoints[i].mY); theWriter->StopElement(); } theWriter->StopElement(); } } void NaturalCubicSpline::OpenFile(std::string theFileName) { XMLParser aParser; if(aParser.OpenFile(theFileName) && !aParser.HasFailed()) { XMLElement aNode; Serialize(&aParser, &aNode); } } void NaturalCubicSpline::SaveToFile(std::string theFileName) { XMLWriter aWriter; if(aWriter.OpenFile(theFileName) && !aWriter.HasFailed()) Serialize(&aWriter); aWriter.CloseFile(); } libtuxcap-1.4.0/tuxcap/lib/Quantize.cpp0000644000175000017500000000346611202747627017766 0ustar inniyahinniyah#include "Quantize.h" #include #include using namespace Sexy; bool Sexy::Quantize8Bit(const uint32_t* theSrcBits, int theWidth, int theHeight, uchar* theDestColorIndices, uint32_t* theDestColorTable) { int aSize = theWidth*theHeight; int aColorTableSize = 0; uint32_t aSearchTable[256]; uchar aTranslationTable[256]; // From search table to color table if (aSize > 0) { aSearchTable[0] = theSrcBits[0]; theDestColorTable[0] = theSrcBits[0]; aTranslationTable[0] = 0; theDestColorIndices[0] = 0; aColorTableSize++; } for (int anIdx = 1; anIdx < aSize; anIdx++) { uint32_t aColor = theSrcBits[anIdx]; int aLeftPos = 0; int aRightPos = aColorTableSize-1; int aMiddlePos = (aLeftPos+aRightPos)/2; for (;;) { uint32_t aCheckColor = aSearchTable[aMiddlePos]; if (aColor < aCheckColor) aRightPos = aMiddlePos - 1; else if (aColor > aCheckColor) aLeftPos = aMiddlePos + 1; else { theDestColorIndices[anIdx] = aTranslationTable[aMiddlePos]; break; } if (aLeftPos > aRightPos) { if (aColorTableSize >= 256) return false; int anInsertPos = aLeftPos; if ((anInsertPos < aColorTableSize) && (aColor > aSearchTable[anInsertPos])) anInsertPos++; // Insert color into the table memmove(aSearchTable+anInsertPos+1, aSearchTable+anInsertPos, (aColorTableSize-anInsertPos) * sizeof(uint32_t)); aSearchTable[anInsertPos] = aColor; memmove(aTranslationTable+anInsertPos+1, aTranslationTable+anInsertPos, (aColorTableSize-anInsertPos) * sizeof(uchar)); aTranslationTable[anInsertPos] = aColorTableSize; theDestColorTable[aColorTableSize] = aColor; theDestColorIndices[anIdx] = aColorTableSize; aColorTableSize++; break; } aMiddlePos = (aLeftPos+aRightPos)/2; } } return true; } libtuxcap-1.4.0/tuxcap/lib/Ratio.cpp0000644000175000017500000000112710736754547017246 0ustar inniyahinniyah#include "Ratio.h" namespace Sexy { Ratio::Ratio() : mNumerator(1) , mDenominator(1) { } Ratio::Ratio(int theNumerator, int theDenominator) { Set(theNumerator, theDenominator); } void Ratio::Set(int theNumerator, int theDenominator) { // find the greatest-common-denominator of theNumerator and theDenominator. int t; int a = theNumerator; int b = theDenominator; while (b != 0) { t = b; b = a % b; a = t; } // divide by the g-c-d to reduce mNumerator/mDenominator to lowest terms. mNumerator = theNumerator/a; mDenominator = theDenominator/a; } } libtuxcap-1.4.0/tuxcap/lib/SDLMain.m0000644000175000017500000002572010742156504017060 0ustar inniyahinniyah/* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import "SDL.h" #import "SDLMain.h" #import /* for MAXPATHLEN */ #import /* For some reaon, Apple removed setAppleMenu from the headers in 10.4, but the method still is there and works. To avoid warnings, we declare it ourselves here. */ @interface NSApplication(SDL_Missing_Methods) - (void)setAppleMenu:(NSMenu *)menu; @end /* Use this flag to determine whether we use SDLMain.nib or not */ #define SDL_USE_NIB_FILE 0 /* Use this flag to determine whether we use CPS (docking) or not */ #define SDL_USE_CPS 1 #ifdef SDL_USE_CPS /* Portions of CPS.h */ typedef struct CPSProcessSerNum { UInt32 lo; UInt32 hi; } CPSProcessSerNum; extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); #endif /* SDL_USE_CPS */ static int gArgc; static char **gArgv; static BOOL gFinderLaunch; static BOOL gCalledAppMainline = FALSE; static NSString *getApplicationName(void) { NSDictionary *dict; NSString *appName = 0; /* Determine the application name */ dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); if (dict) appName = [dict objectForKey: @"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; return appName; } #if SDL_USE_NIB_FILE /* A helper category for NSString */ @interface NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #endif @interface SDLApplication : NSApplication @end @implementation SDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { if (shouldChdir) { char parentdir[MAXPATHLEN]; CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) { assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ } CFRelease(url); CFRelease(url2); } } #if SDL_USE_NIB_FILE /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { NSRange aRange; NSEnumerator *enumerator; NSMenuItem *menuItem; aRange = [[aMenu title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; enumerator = [[aMenu itemArray] objectEnumerator]; while ((menuItem = [enumerator nextObject])) { aRange = [[menuItem title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; if ([menuItem hasSubmenu]) [self fixMenu:[menuItem submenu] withAppName:appName]; } [ aMenu sizeToFit ]; } #else static void setApplicationMenu(void) { /* warning: this code is very odd */ NSMenu *appleMenu; NSMenuItem *menuItem; NSString *title; NSString *appName; appName = getApplicationName(); appleMenu = [[NSMenu alloc] initWithTitle:@""]; /* Add menu items */ title = [@"About " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Hide " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appleMenu addItem:[NSMenuItem separatorItem]]; title = [@"Quit " stringByAppendingString:appName]; [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; /* Put menu into the menubar */ menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [menuItem setSubmenu:appleMenu]; [[NSApp mainMenu] addItem:menuItem]; /* Tell the application object that this is now the application menu */ [NSApp setAppleMenu:appleMenu]; /* Finally give up our references to the objects */ [appleMenu release]; [menuItem release]; } /* Create a window menu */ static void setupWindowMenu(void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } /* Replacement for NSApplicationMain */ static void CustomApplicationMain (int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; #ifdef SDL_USE_CPS { CPSProcessSerNum PSN; /* Tell the dock about us */ if (!CPSGetCurrentProcess(&PSN)) if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) if (!CPSSetFrontProcess(&PSN)) [SDLApplication sharedApplication]; } #endif /* SDL_USE_CPS */ /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setApplicationMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Start the main event loop */ [NSApp run]; [sdlMain release]; [pool release]; } #endif /* * Catch document open requests...this lets us notice files when the app * was launched by double-clicking a document, or when a document was * dragged/dropped on the app's icon. You need to have a * CFBundleDocumentsType section in your Info.plist to get this message, * apparently. * * Files are added to gArgv, so to the app, they'll look like command line * arguments. Previously, apps launched from the finder had nothing but * an argv[0]. * * This message may be received multiple times to open several docs on launch. * * This message is ignored once the app's mainline has been called. */ - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename { const char *temparg; size_t arglen; char *arg; char **newargv; if (!gFinderLaunch) /* MacOS is passing command line args. */ return FALSE; if (gCalledAppMainline) /* app has started, ignore this document. */ return FALSE; temparg = [filename UTF8String]; arglen = SDL_strlen(temparg) + 1; arg = (char *) SDL_malloc(arglen); if (arg == NULL) return FALSE; newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)); if (newargv == NULL) { SDL_free(arg); return FALSE; } gArgv = newargv; SDL_strlcpy(arg, temparg, arglen); gArgv[gArgc++] = arg; gArgv[gArgc] = NULL; return TRUE; } /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE /* Set the main menu to contain the real app name instead of "SDL App" */ [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; #endif /* Hand off to main application code */ gCalledAppMainline = TRUE; status = SDL_main (gArgc, gArgv); /* We're done, thank you for playing */ exit(status); } @end @implementation NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages(buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char **argv) { /* Copy the arguments into a global variable */ /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgv = (char **) SDL_malloc(sizeof (char *) * 2); gArgv[0] = argv[0]; gArgv[1] = NULL; gArgc = 1; gFinderLaunch = YES; } else { int i; gArgc = argc; gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); for (i = 0; i <= argc; i++) gArgv[i] = argv[i]; gFinderLaunch = NO; } #if SDL_USE_NIB_FILE [SDLApplication poseAsClass:[NSApplication class]]; NSApplicationMain (argc, argv); #else CustomApplicationMain (argc, argv); #endif return 0; } libtuxcap-1.4.0/tuxcap/lib/AudiereLoader.cpp0000644000175000017500000000075410766713353020673 0ustar inniyahinniyah/* Original AudiereLoader by Rheenen 2005 */ #include "AudiereLoader.h" #include "audiere.h" audiere::AudioDevicePtr gAudiereDevice; audiere::MIDIDevicePtr gAudiereMIDIDevice; audiere::AudioDevicePtr getAudiereDevice(void) { if (!gAudiereDevice) gAudiereDevice = audiere::OpenDevice(NULL); return gAudiereDevice; } audiere::MIDIDevicePtr getAudiereMIDIDevice(void) { if (!gAudiereMIDIDevice) gAudiereMIDIDevice = audiere::OpenMIDIDevice(NULL); return gAudiereMIDIDevice; } libtuxcap-1.4.0/tuxcap/lib/MusicInterface.cpp0000644000175000017500000000247010641010435021043 0ustar inniyahinniyah#include "MusicInterface.h" #include "SexyAppBase.h" using namespace Sexy; MusicInterface::MusicInterface() { } MusicInterface::~MusicInterface() { } bool MusicInterface::LoadMusic(int theSongId, const std::string& theFileName) { return false; } void MusicInterface::PlayMusic(int theSongId, int theOffset, bool noLoop) { } void MusicInterface::StopMusic(int theSongId) { } void MusicInterface::PauseMusic(int theSongId) { } void MusicInterface::ResumeMusic(int theSongId) { } void MusicInterface::StopAllMusic() { } void MusicInterface::UnloadMusic(int theSongId) { } void MusicInterface::UnloadAllMusic() { } void MusicInterface::PauseAllMusic() { } void MusicInterface::ResumeAllMusic() { } void MusicInterface::FadeIn(int theSongId, int theOffset, double theSpeed, bool noLoop) { } void MusicInterface::FadeOut(int theSongId, bool stopSong, double theSpeed) { } void MusicInterface::FadeOutAll(bool stopSong, double theSpeed) { } void MusicInterface::SetSongVolume(int theSongId, double theVolume) { } void MusicInterface::SetSongMaxVolume(int theSongId, double theMaxVolume) { } bool MusicInterface::IsPlaying(int theSongId) { return false; } void MusicInterface::SetVolume(double theVolume) { } void MusicInterface::SetMusicAmplify(int theSongId, double theAmp) { } void MusicInterface::Update() { } libtuxcap-1.4.0/tuxcap/lib/Dialog.cpp0000644000175000017500000002415610641010435017346 0ustar inniyahinniyah#include "Common.h" #include "Dialog.h" #include "DialogButton.h" #include "SexyAppBase.h" #include "WidgetManager.h" #if 0 #include "SysFont.h" #endif #include "ImageFont.h" using namespace Sexy; SexyString Sexy::DIALOG_YES_STRING = _S("YES"); SexyString Sexy::DIALOG_NO_STRING = _S("NO"); SexyString Sexy::DIALOG_OK_STRING = _S("OK"); SexyString Sexy::DIALOG_CANCEL_STRING = _S("CANCEL"); static int gDialogColors[][3] = {{255, 255, 255}, {255, 255, 0}, {255, 255, 255}, {255, 255, 255}, {255, 255, 255}, {80, 80, 80}, {255, 255, 255}}; Dialog::Dialog(Image* theComponentImage, Image* theButtonComponentImage, int theId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode) { mId = theId; mResult = 0x7FFFFFFF; mComponentImage = theComponentImage; mIsModal = isModal; mContentInsets = Insets(24, 24, 24, 24); mTextAlign = 0; mLineSpacingOffset = 0; mSpaceAfterHeader = 10; mButtonSidePadding = 0; mButtonHorzSpacing = 8; mDialogListener = gSexyAppBase; mDialogHeader = theDialogHeader; mDialogFooter = theDialogFooter; mButtonMode = theButtonMode; if ((mButtonMode == BUTTONS_YES_NO) || (mButtonMode == BUTTONS_OK_CANCEL)) { mYesButton = new DialogButton(theButtonComponentImage, ID_YES, this); mNoButton = new DialogButton(theButtonComponentImage, ID_NO, this); if (mButtonMode == BUTTONS_YES_NO) { mYesButton->mLabel = DIALOG_YES_STRING; mNoButton->mLabel = DIALOG_NO_STRING; } else { mYesButton->mLabel = DIALOG_OK_STRING; mNoButton->mLabel = DIALOG_CANCEL_STRING; } } else if (mButtonMode == BUTTONS_FOOTER) { mYesButton = new DialogButton(theButtonComponentImage, ID_FOOTER, this); mYesButton->mLabel = mDialogFooter; mNoButton = NULL; } else { mYesButton = NULL; mNoButton = NULL; mNumButtons = 0; } mDialogLines = theDialogLines; mButtonHeight = (theButtonComponentImage == NULL) ? 24 : theButtonComponentImage->mHeight; mHasTransparencies = true; mHasAlpha = true; mHeaderFont = NULL; mLinesFont = NULL; mDragging = false; mPriority = 1; if (theButtonComponentImage == NULL) { gDialogColors[COLOR_BUTTON_TEXT][0] = 0; gDialogColors[COLOR_BUTTON_TEXT][1] = 0; gDialogColors[COLOR_BUTTON_TEXT][2] = 0; gDialogColors[COLOR_BUTTON_TEXT_HILITE][0] = 0; gDialogColors[COLOR_BUTTON_TEXT_HILITE][1] = 0; gDialogColors[COLOR_BUTTON_TEXT_HILITE][2] = 0; } SetColors(gDialogColors, NUM_COLORS); } Dialog::~Dialog() { delete mYesButton; delete mNoButton; delete mHeaderFont; delete mLinesFont; } void Dialog::SetColor(int theIdx, const Color& theColor) { Widget::SetColor(theIdx, theColor); if (theIdx == COLOR_BUTTON_TEXT) { if (mYesButton != NULL) mYesButton->SetColor(DialogButton::COLOR_LABEL, theColor); if (mNoButton != NULL) mNoButton->SetColor(DialogButton::COLOR_LABEL, theColor); } else if (theIdx == COLOR_BUTTON_TEXT_HILITE) { if (mYesButton != NULL) mYesButton->SetColor(DialogButton::COLOR_LABEL_HILITE, theColor); if (mNoButton != NULL) mNoButton->SetColor(DialogButton::COLOR_LABEL_HILITE, theColor); } } void Dialog::SetButtonFont(Font* theFont) { if (mYesButton != NULL) mYesButton->SetFont(theFont); if (mNoButton != NULL) mNoButton->SetFont(theFont); } void Dialog::SetHeaderFont(Font* theFont) { delete mHeaderFont; mHeaderFont = theFont->Duplicate(); } void Dialog::SetLinesFont(Font* theFont) { delete mLinesFont; mLinesFont = theFont->Duplicate(); } void Dialog::EnsureFonts() { #if 0 if (mHeaderFont == NULL) mHeaderFont = new SysFont(gSexyAppBase, "Arial Unicode MS", 14); if (mLinesFont == NULL) mLinesFont = new SysFont(gSexyAppBase, "Arial Unicode MS", 12); #endif } int Dialog::GetPreferredHeight(int theWidth) { EnsureFonts(); int aHeight = mContentInsets.mTop + mContentInsets.mBottom + mBackgroundInsets.mTop + mBackgroundInsets.mBottom; bool needSpace = false; if (mDialogHeader.length() > 0) { aHeight += mHeaderFont->GetHeight() - mHeaderFont->GetAscentPadding(); needSpace = true; } if (mDialogLines.length() > 0) { if (needSpace) aHeight += mSpaceAfterHeader; Graphics g; g.SetFont(mLinesFont); aHeight += GetWordWrappedHeight(&g, theWidth-mContentInsets.mLeft-mContentInsets.mRight-mBackgroundInsets.mLeft-mBackgroundInsets.mRight-4, mDialogLines, mLinesFont->GetLineSpacing() + mLineSpacingOffset); needSpace = true; } if ((mDialogFooter.length() != 0) && (mButtonMode != BUTTONS_FOOTER)) { if (needSpace) aHeight += 8; aHeight += mHeaderFont->GetLineSpacing(); needSpace = true; } if (mYesButton != NULL) { if (needSpace) aHeight += 8; aHeight += mButtonHeight + 8; } return aHeight; } void Dialog::Draw(Graphics* g) { EnsureFonts(); Rect aBoxRect(mBackgroundInsets.mLeft,mBackgroundInsets.mTop,mWidth-mBackgroundInsets.mLeft-mBackgroundInsets.mRight,mHeight-mBackgroundInsets.mTop-mBackgroundInsets.mBottom); if (mComponentImage != NULL) { g->DrawImageBox(aBoxRect,mComponentImage); } else { g->SetColor(GetColor(COLOR_OUTLINE, Color(gDialogColors[COLOR_OUTLINE]))); g->DrawRect(12, 12, mWidth - 12*2 - 1, mHeight - 12*2 - 1); g->SetColor(GetColor(COLOR_BKG, Color(gDialogColors[COLOR_BKG]))); g->FillRect(12+1, 12+1, mWidth - 12*2 - 2, mHeight - 12*2 - 2); g->SetColor(Color(0, 0, 0, 128)); g->FillRect(mWidth - 12, 12*2, 12, mHeight - 12*3); g->FillRect(12*2, mHeight-12, mWidth - 12*2, 12); } int aCurY = mContentInsets.mTop + mBackgroundInsets.mTop; if (mDialogHeader.length() > 0) { aCurY += mHeaderFont->GetAscent() - mHeaderFont->GetAscentPadding(); g->SetFont(mHeaderFont); g->SetColor(mColors[COLOR_HEADER]); WriteCenteredLine(g, aCurY, mDialogHeader); aCurY += mHeaderFont->GetHeight() - mHeaderFont->GetAscent(); aCurY += mSpaceAfterHeader; } //g->SetFont(mLinesFont); g->SetFont(mLinesFont); g->SetColor(mColors[COLOR_LINES]); /*for (int i = 0; i < mDialogLines.size(); i++) { WriteCenteredLine(g, aCurY, mDialogLines[i]); aCurY += mLinesFont->GetHeight(); }*/ Rect aRect(mBackgroundInsets.mLeft+mContentInsets.mLeft+2, aCurY, mWidth-mContentInsets.mLeft-mContentInsets.mRight-mBackgroundInsets.mLeft-mBackgroundInsets.mRight-4, 0); aCurY += WriteWordWrapped(g, aRect, mDialogLines, mLinesFont->GetLineSpacing() + mLineSpacingOffset, mTextAlign); if ((mDialogFooter.length() != 0) && (mButtonMode != BUTTONS_FOOTER)) { aCurY += 8; aCurY += mHeaderFont->GetLineSpacing(); g->SetFont(mHeaderFont); g->SetColor(mColors[COLOR_FOOTER]); WriteCenteredLine(g, aCurY, mDialogFooter); } } void Dialog::AddedToManager(WidgetManager* theWidgetManager) { Widget::AddedToManager(theWidgetManager); if (mYesButton != NULL) theWidgetManager->AddWidget(mYesButton); if (mNoButton != NULL) theWidgetManager->AddWidget(mNoButton); } void Dialog::RemovedFromManager(WidgetManager* theWidgetManager) { Widget::RemovedFromManager(theWidgetManager); if (mYesButton != NULL) theWidgetManager->RemoveWidget(mYesButton); if (mNoButton != NULL) theWidgetManager->RemoveWidget(mNoButton); } void Dialog::OrderInManagerChanged() { Widget::OrderInManagerChanged(); if (mYesButton != NULL) mWidgetManager->PutInfront(mYesButton,this); if (mNoButton != NULL) mWidgetManager->PutInfront(mNoButton,this); } void Dialog::Resize(int theX, int theY, int theWidth, int theHeight) { Widget::Resize(theX, theY, theWidth, theHeight); if ((mYesButton != NULL) && (mNoButton != NULL)) { int aBtnWidth = (mWidth - mContentInsets.mLeft - mContentInsets.mRight - mBackgroundInsets.mLeft - mBackgroundInsets.mRight - mButtonSidePadding*2 - mButtonHorzSpacing) / 2; int aBtnHeight = mButtonHeight; mYesButton->Resize(mX + mBackgroundInsets.mLeft + mContentInsets.mLeft + mButtonSidePadding, mY + mHeight - mContentInsets.mBottom - mBackgroundInsets.mBottom - aBtnHeight, aBtnWidth, aBtnHeight); mNoButton->Resize(mYesButton->mX + aBtnWidth + mButtonHorzSpacing, mYesButton->mY, aBtnWidth, aBtnHeight); } else if (mYesButton != NULL) { int aBtnHeight = mButtonHeight; mYesButton->Resize(mX + mContentInsets.mLeft + mBackgroundInsets.mLeft, mY + mHeight - mContentInsets.mBottom - mBackgroundInsets.mBottom - aBtnHeight, mWidth - mContentInsets.mLeft - mContentInsets.mRight - mBackgroundInsets.mLeft - mBackgroundInsets.mRight, aBtnHeight); } } void Dialog::MouseDown(int x, int y, int theBtnNum, int theClickCount) { if (theClickCount == 1) { mWidgetManager->mApp->SetCursor(CURSOR_DRAGGING); mDragging = true; mDragMouseX = x; mDragMouseY = y; } Widget::MouseDown(x,y,theBtnNum, theClickCount); } void Dialog::MouseDrag(int x, int y) { if (mDragging) { int aNewX = mX + x - mDragMouseX; int aNewY = mY + y - mDragMouseY; if (aNewX < -8) aNewX = -8; else if (aNewX + mWidth > mWidgetManager->mWidth + 8) aNewX = mWidgetManager->mWidth - mWidth + 8; if (aNewY < -8) aNewY = -8; else if (aNewY + mHeight > mWidgetManager->mHeight + 8) aNewY = mWidgetManager->mHeight- mHeight + 8; mDragMouseX = mX + x - aNewX; mDragMouseY = mY + y - aNewY; if (mDragMouseX < 8) mDragMouseX = 8; else if (mDragMouseX > mWidth-9) mDragMouseX = mWidth-9; if (mDragMouseY < 8) mDragMouseY = 8; else if (mDragMouseY > mHeight-9) mDragMouseY = mHeight-9; Move(aNewX, aNewY); } } void Dialog::MouseUp(int x, int y, int theBtnNum, int theClickCount) { if (mDragging) { mWidgetManager->mApp->SetCursor(CURSOR_POINTER); mDragging = false; } Widget::MouseUp(x,y, theBtnNum, theClickCount); } void Dialog::Update() { Widget::Update(); //Move(mX, mY+1); } bool Dialog::IsModal() { return mIsModal; } int Dialog::WaitForResult(bool autoKill) { //gSexyAppBase->DoMainLoop(mId); while ((gSexyAppBase->UpdateAppStep(NULL)) && (mWidgetManager != NULL) && (mResult == 0x7FFFFFFF)); if (autoKill) gSexyAppBase->KillDialog(mId); return mResult; } void Dialog::ButtonPress(int theId) { if ((theId == ID_YES) || (theId == ID_NO)) mDialogListener->DialogButtonPress(mId, theId); } void Dialog::ButtonDepress(int theId) { if ((theId == ID_YES) || (theId == ID_NO)) { mResult = theId; mDialogListener->DialogButtonDepress(mId, theId); } } void Dialog::ButtonDownTick(int theId) { } libtuxcap-1.4.0/tuxcap/lib/PropertiesParser.cpp0000644000175000017500000001313610645717035021472 0ustar inniyahinniyah#include "PropertiesParser.h" #include "XMLParser.h" #include using namespace Sexy; PropertiesParser::PropertiesParser(SexyAppBase* theApp) { mApp = theApp; mHasFailed = false; mXMLParser = NULL; } void PropertiesParser::Fail(const SexyString& theErrorText) { if (!mHasFailed) { mHasFailed = true; int aLineNum = mXMLParser->GetCurrentLineNum(); mError = theErrorText; if (aLineNum > 0) mError += StrFormat(_S(" on Line %d"), aLineNum); if (!mXMLParser->GetFileName().empty()) mError += StrFormat(_S(" in File '%s'"), mXMLParser->GetFileName().c_str()); } } PropertiesParser::~PropertiesParser() { } bool PropertiesParser::ParseSingleElement(SexyString* aString) { *aString = _S(""); for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType == XMLElement::TYPE_START) { Fail(_S("Unexpected Section: '") + aXMLElement.mValue + _S("'")); return false; } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { *aString = aXMLElement.mValue; } else if (aXMLElement.mType == XMLElement::TYPE_END) { return true; } } } bool PropertiesParser::ParseStringArray(StringVector* theStringVector) { theStringVector->clear(); for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue == _S("String")) { SexyString aString; if (!ParseSingleElement(&aString)) return false; theStringVector->push_back(SexyStringToStringFast(aString)); } else { Fail(_S("Invalid Section '") + aXMLElement.mValue + _S("'")); return false; } } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { Fail(_S("Element Not Expected '") + aXMLElement.mValue + _S("'")); return false; } else if (aXMLElement.mType == XMLElement::TYPE_END) { return true; } } } bool PropertiesParser::ParseProperties() { for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue == _S("String")) { SexyString aDef; if (!ParseSingleElement(&aDef)) return false; std::string anId = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mApp->SetString(anId, SexyStringToWStringFast(aDef)); } else if (aXMLElement.mValue == _S("StringArray")) { StringVector aDef; if (!ParseStringArray(&aDef)) return false; std::string anId = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mApp->mStringVectorProperties.insert(StringStringVectorMap::value_type(anId, aDef)); } else if (aXMLElement.mValue == _S("Boolean")) { SexyString aVal; if (!ParseSingleElement(&aVal)) return false; aVal = Upper(aVal); bool boolVal; if ((aVal == _S("1")) || (aVal == _S("YES")) || (aVal == _S("ON")) || (aVal == _S("TRUE"))) boolVal = true; else if ((aVal == _S("0")) || (aVal == _S("NO")) || (aVal == _S("OFF")) || (aVal == _S("FALSE"))) boolVal = false; else { Fail(_S("Invalid Boolean Value: '") + aVal + _S("'")); return false; } std::string anId = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mApp->SetBoolean(anId, boolVal); } else if (aXMLElement.mValue == _S("Integer")) { SexyString aVal; if (!ParseSingleElement(&aVal)) return false; int anInt; if (!StringToInt(aVal, &anInt)) { Fail(_S("Invalid Integer Value: '") + aVal + _S("'")); return false; } std::string anId = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mApp->SetInteger(anId, anInt); } else if (aXMLElement.mValue == _S("Double")) { SexyString aVal; if (!ParseSingleElement(&aVal)) return false; double aDouble; if (!StringToDouble(aVal, &aDouble)) { Fail(_S("Invalid Double Value: '") + aVal + _S("'")); return false; } std::string anId = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mApp->SetDouble(anId, aDouble); } else { Fail(_S("Invalid Section '") + aXMLElement.mValue + _S("'")); return false; } } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { Fail(_S("Element Not Expected '") + aXMLElement.mValue + _S("'")); return false; } else if (aXMLElement.mType == XMLElement::TYPE_END) { return true; } } } bool PropertiesParser::DoParseProperties() { if (!mXMLParser->HasFailed()) { for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) break; if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue == _S("Properties")) { if (!ParseProperties()) break; } else { Fail(_S("Invalid Section '") + aXMLElement.mValue + _S("'")); break; } } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { Fail(_S("Element Not Expected '") + aXMLElement.mValue + _S("'")); break; } } } if (mXMLParser->HasFailed()) Fail(mXMLParser->GetErrorText()); delete mXMLParser; mXMLParser = NULL; return !mHasFailed; } bool PropertiesParser::ParsePropertiesBuffer(const Buffer& theBuffer) { mXMLParser = new XMLParser(); mXMLParser->SetStringSource(theBuffer.UTF8ToWideString()); return DoParseProperties(); } bool PropertiesParser::ParsePropertiesFile(const std::string& theFilename) { mXMLParser = new XMLParser(); mXMLParser->OpenFile(theFilename); return DoParseProperties(); } SexyString PropertiesParser::GetErrorText() { return mError; } libtuxcap-1.4.0/tuxcap/lib/Physics.cpp0000644000175000017500000006114111202747627017602 0ustar inniyahinniyah/* Sexy Chipmunk, a physics engine for the PopCap Games Framework using Scott Lembcke's excellent chipmunk physics library */ /* Copyright (c) 2007-2008 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "Physics.h" #include #include #include "Graphics.h" /* TODO * inline * copy constructor, assignment operator */ using namespace Sexy; Physics::Physics():space(NULL),steps(1) , listener(NULL){ cpInitChipmunk(); } Physics::~Physics() { Clear(); } void Physics::Init() { if (space == NULL) { cpResetShapeIdCounter(); space = cpSpaceNew(); assert(space != NULL); cpSpaceSetDefaultCollisionPairFunc(space, NULL, NULL); space->gravity = cpv(0,100); delta = 1.0f/60.0f/(cpFloat)steps; } } void Physics::SetSteps(int steps) { this->steps = steps; delta = 1.0f/60.0f/(cpFloat)steps; } int Physics::CollFunc(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data) { assert(data != NULL); TypedData* t_data = reinterpret_cast(data); PhysicsObject* obj1 = FindObject(t_data->objects, a->body, a); PhysicsObject* obj2 = FindObject(t_data->objects, b->body, b); assert(obj1 != NULL); assert(obj2 != NULL); assert(sizeof(CollisionPoint) == sizeof(cpContact)); CollisionObject col(obj1, obj2, reinterpret_cast(contacts), numContacts, normal_coef); return t_data->listener->HandleTypedCollision(&col); } SexyVector2 Physics::SumCollisionImpulses(int numContacts, CollisionPoint* contacts) { assert(sizeof(CollisionPoint) == sizeof(cpContact)); cpVect sum_impulse = cpContactsSumImpulses((cpContact*)contacts, numContacts); return SexyVector2(sum_impulse.x, sum_impulse.y); } SexyVector2 Physics::SumCollisionImpulsesWithFriction(int numContacts, CollisionPoint* contacts) { assert(sizeof(CollisionPoint) == sizeof(cpContact)); cpVect sum_impulse = cpContactsSumImpulsesWithFriction(reinterpret_cast(contacts), numContacts); return SexyVector2(sum_impulse.x, sum_impulse.y); } void Physics::AllCollisions(void* ptr, void* data) { assert(data != NULL && ptr != NULL); cpArbiter *arb = reinterpret_cast(ptr); std::pair* >* p = reinterpret_cast* >* >(data); PhysicsObject* obj1 = FindObject(p->second, arb->a->body, arb->a); PhysicsObject* obj2 = FindObject(p->second, arb->b->body, arb->b); assert(obj1 != NULL); assert(obj2 != NULL); assert(sizeof(CollisionPoint) == sizeof(cpContact)); CollisionObject col(obj1, obj2, reinterpret_cast(arb->contacts), arb->numContacts); p->first->HandleCollision(&col); } void Physics::HashQuery(void* ptr, void* data) { assert(ptr != NULL && data != NULL); TypedData* t_data = reinterpret_cast(data); cpShape* shape = reinterpret_cast(ptr); PhysicsObject* obj = FindObject(t_data->objects, shape); assert(obj != NULL); t_data->listener->DrawPhysicsObject(obj, t_data->graphics); } void Physics::Update() { { assert(listener != NULL); for(int i=0; iBeforePhysicsStep(); cpSpaceStep(space, delta); listener->AfterPhysicsStep(); std::pair* > p = std::make_pair* >(listener, &objects); cpArrayEach(space->arbiters, &AllCollisions, &p); } } } void Physics::Draw(Graphics* g) { TypedData data; data.graphics = g; data.objects = &objects; data.listener = listener; cpSpaceHashEach(space->activeShapes, &HashQuery, reinterpret_cast(&data)); cpSpaceHashEach(space->staticShapes, &HashQuery, reinterpret_cast(&data)); } void Physics::SetGravity(const SexyVector2& gravity) { assert(space != NULL); space->gravity = cpv(gravity.x, gravity.y); } void Physics::SetDamping(cpFloat damping) { assert(space != NULL); space->damping = damping; } void Physics::SetIterations(int iter) { assert(space != NULL); space->iterations = iter; } void Physics::ResizeStaticHash(float dimension, int count) { assert(space != NULL); cpSpaceResizeStaticHash(space, dimension, count); } void Physics::ResizeActiveHash(float dimension, int count) { assert(space != NULL); cpSpaceResizeStaticHash(space, dimension, count); } void Physics::Clear() { std::vector::iterator it = objects.begin(); while (it != objects.end()) { delete (*it); ++it; } objects.clear(); joints.clear(); cpSpaceFreeChildren(space); cpSpaceFree(space); space = NULL; } PhysicsObject* Physics::CreateObject(cpFloat mass, cpFloat inertia) { assert(IsInitialized()); PhysicsObject* obj = new PhysicsObject(mass, inertia, this); objects.push_back(obj); return obj; } PhysicsObject* Physics::CreateStaticObject() { PhysicsObject* obj = new PhysicsObject(INFINITY, INFINITY, this, true); objects.push_back(obj); return obj; } void Physics::DestroyObject(PhysicsObject* object) { assert(IsValidObject(object)); if (!object->shapes.empty()) { if (object->is_static) { std::vector::iterator it = object->shapes.begin(); while (it != object->shapes.end()) { cpSpaceRemoveStaticShape(space, *it); ++it; } } else { std::vector::iterator it = object->shapes.begin(); while (it != object->shapes.end()) { cpSpaceRemoveShape(space, *it); ++it; } } } if (!object->is_static) { cpSpaceRemoveBody(space, object->body); } else { cpSpaceRehashStatic(space); } std::vector j = GetJointsOfObject(object); std::vector::iterator it = j.begin(); while (it != j.end()) { RemoveJoint(*it); ++it; } cpBodyFree(object->body); std::vector::iterator sit = object->shapes.begin(); while (sit != object->shapes.end()) { cpShapeFree(*sit); ++sit; } std::vector::iterator pit = std::find(objects.begin(), objects.end(), object); if (pit != objects.end()) { delete (*pit); objects.erase(pit); } } bool Physics::IsValidObject(PhysicsObject* object) const { std::vector::const_iterator it = std::find(objects.begin(), objects.end(), object); return (it != objects.end()); } void Physics::RegisterCollisionType(uint32_t type_a, uint32_t type_b) { TypedData* data = new TypedData; data->objects = &objects; data->listener = listener; cpSpaceAddCollisionPairFunc(space, type_a, type_b, (cpCollFunc)&CollFunc, reinterpret_cast(data)); } void Physics::UnregisterCollisionType(uint32_t type_a, uint32_t type_b) { unsigned int ids[] = {type_a, type_b}; unsigned int hash = CP_HASH_PAIR(type_a, type_b); cpCollPairFunc *old_pair = static_cast(cpHashSetFind(space->collFuncSet, hash, ids)); delete reinterpret_cast(old_pair->data); cpSpaceRemoveCollisionPairFunc(space, type_a, type_b); } void Physics::ApplySpringForce(PhysicsObject* obj1, PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2, float rest_length, float spring, float damping) { cpDampedSpring(obj1->body, obj2->body, cpv(anchor1.x, anchor1.y), cpv(anchor2.x, anchor2.y), rest_length, spring, damping, delta); } Joint Physics::CreatePinJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2) { cpJoint* joint = cpPinJointNew(obj1->body, obj2->body, cpv(anchor1.x, anchor1.y), cpv(anchor2.x, anchor2.y)); joints.push_back(joint); cpSpaceAddJoint(space,joint); return Joint(joint, const_cast(obj1), const_cast(obj2), anchor1, anchor2); } Joint Physics::CreateSlideJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& anchor1, const SexyVector2& anchor2, float min, float max) { cpJoint* joint = cpSlideJointNew(obj1->body, obj2->body, cpv(anchor1.x, anchor1.y), cpv(anchor2.x, anchor2.y), min, max); joints.push_back(joint); cpSpaceAddJoint(space,joint); return Joint(joint, const_cast(obj1), const_cast(obj2), anchor1, anchor2); } Joint Physics::CreatePivotJoint(const PhysicsObject* obj1, const PhysicsObject* obj2, const SexyVector2& pivot) { cpJoint* joint = cpPivotJointNew(obj1->body, obj2->body ,cpv(pivot.x, pivot.y)); joints.push_back(joint); cpSpaceAddJoint(space,joint); return Joint(joint, const_cast(obj1), const_cast(obj2), pivot); } std::vector > Physics::GetJoints() const { std::vector::const_iterator it = joints.begin(); std::vector > v; while (it != joints.end()) { cpVect pos1 = (*it)->a->p; cpVect pos2 = (*it)->b->p; cpVect s, e, v1,v2; switch((*it)->type) { case CP_PIN_JOINT: v1= ((cpPinJoint*)(*it))->anchr1; s = cpvadd(pos1, cpvrotate((*it)->a->rot, v1)); v2= ((cpPinJoint*)(*it))->anchr2; e = cpvadd(pos2, cpvrotate((*it)->b->rot, v2)); break; case CP_SLIDE_JOINT: v1= ((cpSlideJoint*)(*it))->anchr1; s = cpvadd(pos1, cpvrotate((*it)->a->rot, v1)); v2= ((cpSlideJoint*)(*it))->anchr2; e = cpvadd(pos2, cpvrotate((*it)->b->rot, v2)); break; case CP_PIVOT_JOINT: v1= ((cpPivotJoint*)(*it))->anchr1; s = pos1;//cpvadd(pos1, cpvrotate(v1, (*it)->a->rot)); v2= ((cpPivotJoint*)(*it))->anchr2; e = pos2;//cpvadd(pos2, cpvrotate(v2, (*it)->b->rot)); break; } AddUniqueJoint(&v, SexyVector2(s.x,s.y),SexyVector2(e.x,e.y)); ++it; } return v; } std::vector > Physics::GetJoints(const PhysicsObject* obj1, const PhysicsObject* obj2) const { const std::vector j = GetJointsOfObject(obj1); std::vector > v; std::vector::const_iterator it = j.begin(); while (it != j.end()) { if (((*it)->a == obj1->body || (*it)->b == obj1->body) && ((*it)->a == obj2->body || (*it)->b == obj2->body)) { SexyVector2 start = obj1->GetPosition(); SexyVector2 end = obj2->GetPosition(); cpVect v1,v2; switch((*it)->type) { case CP_PIN_JOINT: v1= ((cpPinJoint*)(*it))->anchr1; v2= ((cpPinJoint*)(*it))->anchr2; if ((*it)->a == obj1->body) { cpVect rot = cpvrotate((*it)->a->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->b->rot,v2); end += SexyVector2(rot.x,rot.y); } else { cpVect rot = cpvrotate((*it)->b->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->a->rot,v2); end += SexyVector2(rot.x,rot.y); } break; case CP_SLIDE_JOINT: v1= ((cpSlideJoint*)(*it))->anchr1; v2= ((cpSlideJoint*)(*it))->anchr2; if ((*it)->a == obj1->body) { cpVect rot = cpvrotate((*it)->a->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->b->rot,v2); end += SexyVector2(rot.x,rot.y); } else { cpVect rot = cpvrotate((*it)->b->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->a->rot,v2); end += SexyVector2(rot.x,rot.y); } break; case CP_PIVOT_JOINT: break; } AddUniqueJoint(&v, start, end); } ++it; } return v; } std::vector > Physics::GetJoints(const PhysicsObject* obj1) const { const std::vector j = GetJointsOfObject(obj1); std::vector > v; std::vector::const_iterator it = j.begin(); while (it != j.end()) { SexyVector2 start = obj1->GetPosition(); SexyVector2 end; if ((*it)->a == obj1->body) { cpVect v = (*it)->b->p; end = SexyVector2(v.x,v.y); } else { cpVect v = (*it)->a->p; end = SexyVector2(v.x,v.y); } cpVect v1,v2; switch((*it)->type) { case CP_PIN_JOINT: v1= ((cpPinJoint*)(*it))->anchr1; v2= ((cpPinJoint*)(*it))->anchr2; if ((*it)->a == obj1->body) { cpVect rot = cpvrotate((*it)->a->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->b->rot,v2); end += SexyVector2(rot.x,rot.y); } else { cpVect rot = cpvrotate((*it)->b->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->a->rot,v2); end += SexyVector2(rot.x,rot.y); } break; case CP_SLIDE_JOINT: v1= ((cpSlideJoint*)(*it))->anchr1; v2= ((cpSlideJoint*)(*it))->anchr2; if ((*it)->a == obj1->body) { cpVect rot = cpvrotate((*it)->a->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->b->rot,v2); end += SexyVector2(rot.x,rot.y); } else { cpVect rot = cpvrotate((*it)->b->rot,v1); start += SexyVector2(rot.x, rot.y); rot = cpvrotate((*it)->a->rot,v2); end += SexyVector2(rot.x,rot.y); } break; case CP_PIVOT_JOINT: break; } AddUniqueJoint(&v, start, end); ++it; } return v; } void Physics::AddUniqueJoint(std::vector >* v, const SexyVector2& start, const SexyVector2& end) const { std::vector >::iterator vit = v->begin(); while (vit != v->end()) { if (((*vit).first == start && (*vit).second == end) || ((*vit).first == end && (*vit).second == start)) { return; } ++vit; } v->push_back(std::make_pair(start,end)); } bool Physics::IsJoined(const PhysicsObject* obj1, const PhysicsObject* obj2) const { std::vector::const_iterator it = joints.begin(); while (it != joints.end()) { if (((*it)->a == obj1->body || (*it)->b == obj1->body) && ((*it)->a == obj2->body || (*it)->b == obj2->body)) { return true; } ++it; } return false; } void Physics::RemoveJoint(const PhysicsObject* obj1, const PhysicsObject* obj2) { assert(obj1->body != NULL && obj2->body != NULL); std::vector::iterator it = joints.begin(); while (it != joints.end()) { if (((*it)->a == obj1->body || (*it)->b == obj1->body) && ((*it)->a == obj2->body || (*it)->b == obj2->body)) { cpSpaceRemoveJoint(space, *it); joints.erase(it); } else ++it; } } void Physics::RemoveJoints(const PhysicsObject* obj) { std::vector joints = GetJointsOfObject(obj); std::vector::const_iterator it = joints.begin(); while(it != joints.end()) { RemoveJoint(*it); ++it; } } void Physics::RemoveJoint(const Joint& joint) { RemoveJoint(joint.joint); } void Physics::RemoveJoint(const cpJoint* joint) { std::vector::iterator it = std::find(joints.begin(), joints.end(), joint); if (it != joints.end()) { cpSpaceRemoveJoint(space, *it); joints.erase(it); } } const std::vector Physics::GetJointsOfObject(const PhysicsObject* obj) const { assert(obj->body != NULL); std::vector j; std::vector::const_iterator it = joints.begin(); while (it != joints.end()) { if ((*it)->a == obj->body || (*it)->b == obj->body) { j.push_back(*it); } ++it; } return j; } PhysicsObject* Physics::FindObject(std::vector* objects, cpBody* body, cpShape* shape){ std::vector::const_iterator it = objects->begin(); while (it != objects->end()) { if ((*it)->body == body) { std::vector::const_iterator sit = (*it)->shapes.begin(); int count = 0; while (sit != (*it)->shapes.end()) { if (*sit == shape) { (*it)->colliding_shape_index = count; return *it; } ++count; ++sit; } } ++it; } return NULL; } PhysicsObject* Physics::FindObject(std::vector* objects, cpShape* shape){ std::vector::const_iterator it = objects->begin(); while (it != objects->end()) { std::vector::const_iterator sit = (*it)->shapes.begin(); int count = 0; while (sit != (*it)->shapes.end()) { if (*sit == shape) { (*it)->colliding_shape_index = count; return *it; } ++count; ++sit; } ++it; } return NULL; } std::set Physics::GetJoinedPhysicsObjects(const PhysicsObject* obj1) const { const std::vector j = GetJointsOfObject(obj1); std::set v; std::vector::const_iterator it = j.begin(); while (it != j.end()) { cpBody* body; if ((*it)->a == obj1->body) { body = (*it)->b; } else { body =(*it)->a; } std::vector::const_iterator sit = objects.begin(); while (sit != objects.end()) { if ((*sit)->body == body) { v.insert(*sit); break; } ++sit; } ++it; } return v; } /***********************************************PhysicsObject**************************/ PhysicsObject::PhysicsObject(cpFloat mass, cpFloat inertia, Physics* physics, bool is_static):physics(physics), is_static(is_static), colliding_shape_index(0) { assert(physics != NULL); body = cpBodyNew(mass, inertia); if (!is_static) { assert (physics->space != NULL); cpSpaceAddBody(physics->space, body); } shapes.clear(); } PhysicsObject::~PhysicsObject() {} float PhysicsObject::GetAngle() const { assert(body != NULL); return (float)body->a; } SexyVector2 PhysicsObject::GetRotation() const { assert(body != NULL); return SexyVector2(body->rot.x, body->rot.y); } SexyVector2 PhysicsObject::GetPosition() const { assert(body != NULL); return SexyVector2(body->p.x, body->p.y); } SexyVector2 PhysicsObject::GetVelocity() const { assert(body != NULL); return SexyVector2(body->v.x, body->v.y); } void PhysicsObject::AddCircleShape(cpFloat radius, const SexyVector2& offset, cpFloat elasticity, cpFloat friction) { assert(body != NULL); cpShape* shape = cpCircleShapeNew(body, radius, cpv(offset.x, offset.y)); assert(shape != NULL); shape->e = elasticity; shape->u = friction; if (physics->space != NULL) { if (is_static) cpSpaceAddStaticShape(physics->space, shape); else cpSpaceAddShape(physics->space, shape); } shapes.push_back(shape); } void PhysicsObject::AddSegmentShape(const SexyVector2& begin, const SexyVector2& end, cpFloat radius, cpFloat elasticity, cpFloat friction) { assert(body != NULL); cpShape* shape = cpSegmentShapeNew(body, cpv(begin.x, begin.y), cpv(end.x,end.y), radius); assert(shape != NULL); shape->e = elasticity; shape->u = friction; if (physics->space != NULL) { if (is_static) cpSpaceAddStaticShape(physics->space, shape); else cpSpaceAddShape(physics->space, shape); } shapes.push_back(shape); } void PhysicsObject::AddPolyShape(int numVerts, SexyVector2* vectors, const SexyVector2& offset, cpFloat elasticity, cpFloat friction) { assert(body != NULL); assert(sizeof(SexyVector2) == sizeof(cpVect)); cpShape* shape = cpPolyShapeNew(body, numVerts, (cpVect*)vectors, cpv(offset.x, offset.y)); assert(shape != NULL); shape->e = elasticity; shape->u = friction; if (physics->space != NULL) { if (is_static) cpSpaceAddStaticShape(physics->space, shape); else cpSpaceAddShape(physics->space, shape); } shapes.push_back(shape); } void PhysicsObject::SetAngularVelocity(cpFloat w) { assert(body != NULL); body->w = w; } void PhysicsObject::SetVelocity(const SexyVector2& v) { assert(body != NULL); body->v = cpv(v.x, v.y); } void PhysicsObject::SetCollisionType(unsigned int type, int shape_index) { assert(shapes.size() > shape_index); shapes[shape_index]->collision_type = type; } void PhysicsObject::SetGroup(unsigned int group, int shape_index) { assert(shapes.size() > shape_index); shapes[shape_index]->group = group; } void PhysicsObject::SetLayers(unsigned int layers, int shape_index) { assert(shapes.size() > shape_index); shapes[shape_index]->layers = layers; } void PhysicsObject::SetData(void* data, int shape_index) { assert(shapes.size() > shape_index); shapes[shape_index]->data = data; } unsigned int PhysicsObject::GetCollisionType(int shape_index) const { assert(shapes.size() > shape_index); return shapes[shape_index]->collision_type; } unsigned int PhysicsObject::GetGroup(int shape_index) const { assert(shapes.size() > shape_index); return shapes[shape_index]->group; } unsigned int PhysicsObject::GetLayers(int shape_index) const { assert(shapes.size() > shape_index); return shapes[shape_index]->layers; } void* PhysicsObject::GetData(int shape_index) const { assert(shapes.size() > shape_index); return shapes[shape_index]->data; } int PhysicsObject::GetShapeType(int shape_index) const { assert(shapes.size() > shape_index); return shapes[shape_index]->type; } int PhysicsObject::GetNumberVertices(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)POLY_SHAPE); return ((cpPolyShape*)shapes[shape_index])->numVerts; } SexyVector2 PhysicsObject::GetVertex(int vertex_index, int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)POLY_SHAPE); cpVect position = cpvadd(body->p, cpvrotate(((cpPolyShape*)shapes[shape_index])->verts[vertex_index], body->rot)); return SexyVector2(position.x, position.y); } SexyVector2 PhysicsObject::GetSegmentShapeBegin(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)SEGMENT_SHAPE); cpVect position = cpvadd(body->p, cpvrotate(((cpSegmentShape*)shapes[shape_index])->a, body->rot)); return SexyVector2(position.x, position.y); } SexyVector2 PhysicsObject::GetSegmentShapeEnd(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)SEGMENT_SHAPE); cpVect position = cpvadd(body->p, cpvrotate(((cpSegmentShape*)shapes[shape_index])->b, body->rot)); return SexyVector2(position.x, position.y); } float PhysicsObject::GetSegmentShapeRadius(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)SEGMENT_SHAPE); return (float)((cpSegmentShape*)shapes[shape_index])->r; } float PhysicsObject::GetCircleShapeRadius(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)CIRCLE_SHAPE); return (float)((cpCircleShape*)shapes[shape_index])->r; } SexyVector2 PhysicsObject::GetCircleShapeCenter(int shape_index) const { assert(shapes.size() > shape_index && shapes[shape_index]->type ==(cpShapeType)CIRCLE_SHAPE); cpVect position = cpvadd(body->p, cpvrotate(((cpCircleShape*)shapes[shape_index])->c, body->rot)); //FIXME does c stand for center of gravity?? return SexyVector2(position.x, position.y); } void PhysicsObject::UpdateVelocity() { assert(is_static && physics->space != NULL); cpBodyUpdateVelocity(body, physics->space->gravity, physics->space->damping, physics->delta); } void PhysicsObject::UpdatePosition() { assert(is_static && physics->space != NULL); cpBodyUpdatePosition(body, physics->delta); cpSpaceRehashStatic(physics->space); } int PhysicsObject::GetNumberOfShapes() const { return shapes.size(); } int PhysicsObject::GetCollidingShapeIndex() const { return colliding_shape_index; } libtuxcap-1.4.0/tuxcap/lib/Common.cpp0000644000175000017500000006502211202747625017410 0ustar inniyahinniyah#include "Common.h" #include "MTRand.h" #if 0 #include "Debug.h" #include #include #include "PerfTimer.h" #endif #include #include #include #include #include #include #include #include #include bool Sexy::gDebug = false; static Sexy::MTRand gMTRand; namespace Sexy { std::string gAppDataFolder = ""; std::string gAppResourceFolder = ""; } std::string Sexy::GetAppDataFolder() { return Sexy::gAppDataFolder; } std::string Sexy::GetAppResourceFolder() { return Sexy::gAppResourceFolder; } int Sexy::Rand() { return gMTRand.Next(); } int Sexy::Rand(int range) { return gMTRand.Next((uint32_t)range); } float Sexy::Rand(float range) { return gMTRand.Next(range); } void Sexy::SRand(uint32_t theSeed) { gMTRand.SRand(theSeed); } std::string Sexy::GetFileName(const std::string& thePath, bool noExtension) { int aLastSlash = std::max((int) thePath.rfind('\\'), (int) thePath.rfind('/')); if (noExtension) { int aLastDot = (int)thePath.rfind('.'); if (aLastDot > aLastSlash) return thePath.substr(aLastSlash + 1, aLastDot - aLastSlash - 1); } if (aLastSlash == -1) return thePath; else return thePath.substr(aLastSlash + 1); } #if 0 bool Sexy::CheckFor98Mill() { static bool needOsCheck = true; static bool is98Mill = false; if (needOsCheck) { bool invalid = false; OSVERSIONINFOEXA osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); if( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0) { osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA); if ( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0) return false; } needOsCheck = false; is98Mill = osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS; // let's check Win95, 98, *AND* ME. } return is98Mill; } bool Sexy::CheckForVista() { static bool needOsCheck = true; static bool isVista = false; if (needOsCheck) { bool invalid = false; OSVERSIONINFOEXA osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFOEXA)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); if( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0) { osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFOA); if ( GetVersionExA((LPOSVERSIONINFOA)&osvi) == 0) return false; } needOsCheck = false; isVista = osvi.dwMajorVersion >= 6; } return isVista; } std::string Sexy::URLEncode(const std::string& theString) { char* aHexChars = "0123456789ABCDEF"; std::string aString; for (unsigned i = 0; i < theString.length(); i++) { switch (theString[i]) { case ' ': aString.insert(aString.end(), '+'); break; case '?': case '&': case '%': case '+': case '\r': case '\n': case '\t': aString.insert(aString.end(), '%'); aString.insert(aString.end(), aHexChars[(theString[i] >> 4) & 0xF]); aString.insert(aString.end(), aHexChars[(theString[i] ) & 0xF]); break; default: aString.insert(aString.end(), theString[i]); } } return aString; } #endif void Sexy::SetAppDataFolder(const std::string& thePath) { #if 0 if (CheckForVista()) #endif { std::string aPath = thePath; if (!aPath.empty()) { if (aPath[aPath.length()-1] != '\\' && aPath[aPath.length()-1] != '/') aPath += '\\'; } Sexy::gAppDataFolder = ReplaceBackSlashes(aPath); } } void Sexy::SetAppResourceFolder(const std::string& thePath) { #if 0 if (CheckForVista()) #endif { std::string aPath = thePath; if (!aPath.empty()) { if (aPath[aPath.length()-1] != '\\' && aPath[aPath.length()-1] != '/') aPath += '\\'; } Sexy::gAppResourceFolder = ReplaceBackSlashes(aPath); } } std::string Sexy::StringToUpper(const std::string& theString) { std::string aString; for (unsigned i = 0; i < theString.length(); i++) aString += toupper(theString[i]); return aString; } std::wstring Sexy::StringToUpper(const std::wstring& theString) { std::wstring aString; for (unsigned i = 0; i < theString.length(); i++) aString += towupper(theString[i]); return aString; } std::string Sexy::StringToLower(const std::string& theString) { std::string aString; for (unsigned i = 0; i < theString.length(); i++) aString += tolower(theString[i]); return aString; } std::wstring Sexy::StringToLower(const std::wstring& theString) { std::wstring aString; for (unsigned i = 0; i < theString.length(); ++i) aString += tolower(theString[i]); return aString; } std::wstring Sexy::StringToWString(const std::string &theString) { std::wstring aString; aString.reserve(theString.length()); for(size_t i = 0; i < theString.length(); ++i) aString += (unsigned char)theString[i]; return aString; } std::string Sexy::WStringToString(const std::wstring &theString) { size_t aRequiredLength = wcstombs( NULL, theString.c_str(), 0 ); if (aRequiredLength < 16384) { char aBuffer[16384]; wcstombs( aBuffer, theString.c_str(), 16384 ); return std::string(aBuffer); } else { assert(aRequiredLength != (size_t)-1); if (aRequiredLength == (size_t)-1) return ""; char* aBuffer = new char[aRequiredLength+1]; wcstombs( aBuffer, theString.c_str(), aRequiredLength+1 ); std::string aStr = aBuffer; delete[] aBuffer; return aStr; } } SexyString Sexy::StringToSexyString(const std::string& theString) { #ifdef _USE_WIDE_STRING return StringToWString(theString); #else return SexyString(theString); #endif } SexyString Sexy::WStringToSexyString(const std::wstring &theString) { #ifdef _USE_WIDE_STRING return SexyString(theString); #else return WStringToString(theString); #endif } std::string Sexy::SexyStringToString(const SexyString& theString) { #ifdef _USE_WIDE_STRING return WStringToString(theString); #else return std::string(theString); #endif } std::wstring Sexy::SexyStringToWString(const SexyString& theString) { #ifdef _USE_WIDE_STRING return std::wstring(theString); #else return StringToWString(theString); #endif } #if 0 std::string Sexy::Trim(const std::string& theString) { int aStartPos = 0; while ( aStartPos < (int) theString.length() && isspace(theString[aStartPos]) ) aStartPos++; int anEndPos = theString.length() - 1; while ( anEndPos >= 0 && isspace(theString[anEndPos]) ) anEndPos--; return theString.substr(aStartPos, anEndPos - aStartPos + 1); } std::wstring Sexy::Trim(const std::wstring& theString) { int aStartPos = 0; while ( aStartPos < (int) theString.length() && iswspace(theString[aStartPos]) ) aStartPos++; int anEndPos = theString.length() - 1; while ( anEndPos >= 0 && iswspace(theString[anEndPos]) ) anEndPos--; return theString.substr(aStartPos, anEndPos - aStartPos + 1); } #endif bool Sexy::StringToInt(const std::string theString, int* theIntVal) { *theIntVal = 0; if (theString.length() == 0) return false; int theRadix = 10; bool isNeg = false; unsigned i = 0; if (theString[i] == '-') { isNeg = true; i++; } for (; i < theString.length(); i++) { char aChar = theString[i]; if ((theRadix == 10) && (aChar >= '0') && (aChar <= '9')) *theIntVal = (*theIntVal * 10) + (aChar - '0'); else if ((theRadix == 0x10) && (((aChar >= '0') && (aChar <= '9')) || ((aChar >= 'A') && (aChar <= 'F')) || ((aChar >= 'a') && (aChar <= 'f')))) { if (aChar <= '9') *theIntVal = (*theIntVal * 0x10) + (aChar - '0'); else if (aChar <= 'F') *theIntVal = (*theIntVal * 0x10) + (aChar - 'A') + 0x0A; else *theIntVal = (*theIntVal * 0x10) + (aChar - 'a') + 0x0A; } else if (((aChar == 'x') || (aChar == 'X')) && (i == 1) && (*theIntVal == 0)) { theRadix = 0x10; } else { *theIntVal = 0; return false; } } if (isNeg) *theIntVal = -*theIntVal; return true; } bool Sexy::StringToInt(const std::wstring theString, int* theIntVal) { *theIntVal = 0; if (theString.length() == 0) return false; int theRadix = 10; bool isNeg = false; unsigned i = 0; if (theString[i] == '-') { isNeg = true; i++; } for (; i < theString.length(); i++) { wchar_t aChar = theString[i]; if ((theRadix == 10) && (aChar >= L'0') && (aChar <= L'9')) *theIntVal = (*theIntVal * 10) + (aChar - L'0'); else if ((theRadix == 0x10) && (((aChar >= L'0') && (aChar <= L'9')) || ((aChar >= L'A') && (aChar <= L'F')) || ((aChar >= L'a') && (aChar <= L'f')))) { if (aChar <= L'9') *theIntVal = (*theIntVal * 0x10) + (aChar - L'0'); else if (aChar <= L'F') *theIntVal = (*theIntVal * 0x10) + (aChar - L'A') + 0x0A; else *theIntVal = (*theIntVal * 0x10) + (aChar - L'a') + 0x0A; } else if (((aChar == L'x') || (aChar == L'X')) && (i == 1) && (*theIntVal == 0)) { theRadix = 0x10; } else { *theIntVal = 0; return false; } } if (isNeg) *theIntVal = -*theIntVal; return true; } bool Sexy::StringToDouble(const std::string theString, double* theDoubleVal) { *theDoubleVal = 0.0; if (theString.length() == 0) return false; bool isNeg = false; unsigned i = 0; if (theString[i] == '-') { isNeg = true; i++; } for (; i < theString.length(); i++) { char aChar = theString[i]; if ((aChar >= '0') && (aChar <= '9')) *theDoubleVal = (*theDoubleVal * 10) + (aChar - '0'); else if (aChar == '.') { i++; break; } else { *theDoubleVal = 0.0; return false; } } double aMult = 0.1; for (; i < theString.length(); i++) { char aChar = theString[i]; if ((aChar >= '0') && (aChar <= '9')) { *theDoubleVal += (aChar - '0') * aMult; aMult /= 10.0; } else { *theDoubleVal = 0.0; return false; } } if (isNeg) *theDoubleVal = -*theDoubleVal; return true; } bool Sexy::StringToDouble(const std::wstring theString, double* theDoubleVal) { *theDoubleVal = 0.0; if (theString.length() == 0) return false; bool isNeg = false; unsigned i = 0; if (theString[i] == '-') { isNeg = true; i++; } for (; i < theString.length(); i++) { wchar_t aChar = theString[i]; if ((aChar >= L'0') && (aChar <= L'9')) *theDoubleVal = (*theDoubleVal * 10) + (aChar - L'0'); else if (aChar == L'.') { i++; break; } else { *theDoubleVal = 0.0; return false; } } double aMult = 0.1; for (; i < theString.length(); i++) { wchar_t aChar = theString[i]; if ((aChar >= L'0') && (aChar <= L'9')) { *theDoubleVal += (aChar - L'0') * aMult; aMult /= 10.0; } else { *theDoubleVal = 0.0; return false; } } if (isNeg) *theDoubleVal = -*theDoubleVal; return true; } // TODO: Use for localization of number output? SexyString Sexy::CommaSeperate(int theValue) { if (theValue == 0) return _S("0"); SexyString aCurString; int aPlace = 0; int aCurValue = theValue; while (aCurValue > 0) { if ((aPlace != 0) && (aPlace % 3 == 0)) aCurString = _S(',') + aCurString; aCurString = (SexyChar) (_S('0') + (aCurValue % 10)) + aCurString; aCurValue /= 10; aPlace++; } return aCurString; } std::string Sexy::GetPathFrom(const std::string& theRelPath, const std::string& theDir) { std::string aDriveString; std::string aNewPath = theDir; if ((theRelPath.length() >= 2) && (theRelPath[1] == ':')) return theRelPath; char aSlashChar = '/'; if ((theRelPath.find('\\') != -1) || (theDir.find('\\') != -1)) aSlashChar = '\\'; if ((aNewPath.length() >= 2) && (aNewPath[1] == ':')) { aDriveString = aNewPath.substr(0, 2); aNewPath.erase(aNewPath.begin(), aNewPath.begin()+2); } // Append a trailing slash if necessary if ((aNewPath.length() > 0) && (aNewPath[aNewPath.length()-1] != '\\') && (aNewPath[aNewPath.length()-1] != '/')) aNewPath += aSlashChar; std::string aTempRelPath = theRelPath; for (;;) { if (aNewPath.length() == 0) break; int aFirstSlash = aTempRelPath.find('\\'); int aFirstForwardSlash = aTempRelPath.find('/'); if ((aFirstSlash == -1) || ((aFirstForwardSlash != -1) && (aFirstForwardSlash < aFirstSlash))) aFirstSlash = aFirstForwardSlash; if (aFirstSlash == -1) break; std::string aChDir = aTempRelPath.substr(0, aFirstSlash); aTempRelPath.erase(aTempRelPath.begin(), aTempRelPath.begin() + aFirstSlash + 1); if (aChDir.compare("..") == 0) { int aLastDirStart = aNewPath.length() - 1; while ((aLastDirStart > 0) && (aNewPath[aLastDirStart-1] != '\\') && (aNewPath[aLastDirStart-1] != '/')) aLastDirStart--; std::string aLastDir = aNewPath.substr(aLastDirStart, aNewPath.length() - aLastDirStart - 1); if (aLastDir.compare("..") == 0) { aNewPath += ".."; aNewPath += aSlashChar; } else { aNewPath.erase(aNewPath.begin() + aLastDirStart, aNewPath.end()); } } else if (aChDir.compare("") == 0) { aNewPath = aSlashChar; break; } else if (aChDir.compare(".") != 0) { aNewPath += aChDir + aSlashChar; break; } } aNewPath = aDriveString + aNewPath + aTempRelPath; if (aSlashChar == '/') { for (;;) { int aSlashPos = aNewPath.find('\\'); if (aSlashPos == -1) break; aNewPath[aSlashPos] = '/'; } } else { for (;;) { int aSlashPos = aNewPath.find('/'); if (aSlashPos == -1) break; aNewPath[aSlashPos] = '\\'; } } return aNewPath; } std::vector Sexy::GetFilesInDir(const std::string& theDir) { std::vector names; DIR* dir = opendir(theDir.c_str()); if (dir == NULL) return names; struct dirent* sdir; while ((sdir = readdir(dir)) != NULL) { std::string s = sdir->d_name; names.push_back(s); } closedir(dir); return names; } std::string Sexy::GetFileDir(const std::string& thePath, bool withSlash) { int aLastSlash = std::max((int) thePath.rfind('\\'), (int) thePath.rfind('/')); if (aLastSlash == -1) return "./"; else { if (withSlash) return thePath.substr(0, aLastSlash+1); else return thePath.substr(0, aLastSlash); } } bool Sexy::AllowAllAccess(const std::string& theFileName) { chmod (theFileName.c_str(), 0666); return true; } bool Sexy::FileExists(const std::string& theFileName) { struct stat s; int res = stat(theFileName.c_str(), &s); if (res == -1) return false; return S_ISREG(s.st_mode); } bool Sexy::CreateFile(const std::string& theFileName) { FILE* f = fopen(theFileName.c_str(), "w"); if (f != NULL) fclose(f); else return false; return true; } std::string Sexy::GetFullPath(const std::string& theRelPath) { return GetPathFrom(theRelPath, GetCurDir()); } std::string Sexy::GetCurDir() { char aDir[512]; return getcwd(aDir, sizeof(aDir)); } #if 0 bool Sexy::Deltree(const std::string& thePath) { bool success = true; std::string aSourceDir = thePath; if (aSourceDir.length() < 2) return false; if ((aSourceDir[aSourceDir.length() - 1] != '\\') || (aSourceDir[aSourceDir.length() - 1] != '/')) aSourceDir += "\\"; WIN32_FIND_DATAA aFindData; HANDLE aFindHandle = FindFirstFileA((aSourceDir + "*.*").c_str(), &aFindData); if (aFindHandle == INVALID_HANDLE_VALUE) return false; do { if ((aFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { if ((strcmp(aFindData.cFileName, ".") != 0) && (strcmp(aFindData.cFileName, "..") != 0)) { // Follow the directory if (!Deltree(aSourceDir + aFindData.cFileName)) success = false; } } else { std::string aFullName = aSourceDir + aFindData.cFileName; if (!DeleteFileA(aFullName.c_str())) success = false; } } while (FindNextFileA(aFindHandle, &aFindData)); FindClose(aFindHandle); if (rmdir(thePath.c_str()) == 0) success = false; return success; } std::string Sexy::AddTrailingSlash(const std::string& theDirectory, bool backSlash) { if (!theDirectory.empty()) { char aChar = theDirectory[theDirectory.length()-1]; if (aChar!='\\' && aChar!='/') return theDirectory + (backSlash?'\\':'/'); else return theDirectory; } else return ""; } time_t Sexy::GetFileDate(const std::string& theFileName) { time_t aFileDate = 0; WIN32_FIND_DATAA aFindData; HANDLE aFindHandle = ::FindFirstFileA(theFileName.c_str(), &aFindData); if (aFindHandle != INVALID_HANDLE_VALUE) { FILETIME aFileTime = aFindData.ftLastWriteTime; //FileTimeToUnixTime(&aFileTime, &aFileDate, FALSE); LONGLONG ll = (__int64) aFileTime.dwHighDateTime << 32; ll = ll + aFileTime.dwLowDateTime - 116444736000000000; aFileDate = (time_t) (ll/10000000); FindClose(aFindHandle); } return aFileDate; } #endif std::string Sexy::vformat(const char* fmt, va_list argPtr) { // We draw the line at a 1MB string. const int maxSize = 1000000; // If the string is less than 161 characters, // allocate it on the stack because this saves // the malloc/free time. const int bufSize = 161; char stackBuffer[bufSize]; int attemptedSize = bufSize - 1; int numChars = 0; #ifdef _WIN32 numChars = _vsnprintf(stackBuffer, attemptedSize, fmt, argPtr); #else numChars = vsnprintf(stackBuffer, attemptedSize, fmt, argPtr); #endif //cout << "NumChars: " << numChars << endl; if ((numChars >= 0) && (numChars <= attemptedSize)) { // Needed for case of 160-character printf thing stackBuffer[numChars] = '\0'; // Got it on the first try. return std::string(stackBuffer); } // Now use the heap. char* heapBuffer = NULL; while (((numChars == -1) || (numChars > attemptedSize)) && (attemptedSize < maxSize)) { // Try a bigger size attemptedSize *= 2; heapBuffer = (char*)realloc(heapBuffer, (attemptedSize + 1)); #ifdef _WIN32 numChars = _vsnprintf(heapBuffer, attemptedSize, fmt, argPtr); #else numChars = vsnprintf(heapBuffer, attemptedSize, fmt, argPtr); #endif } heapBuffer[numChars] = 0; std::string result = std::string(heapBuffer); free(heapBuffer); return result; } //overloaded StrFormat: should only be used by the xml strings std::string Sexy::StrFormat(const char* fmt ...) { va_list argList; va_start(argList, fmt); std::string result = vformat(fmt, argList); va_end(argList); return result; } #if 0 std::wstring Sexy::vformat(const wchar_t* fmt, va_list argPtr) { // We draw the line at a 1MB string. const int maxSize = 1000000; // If the string is less than 161 characters, // allocate it on the stack because this saves // the malloc/free time. const int bufSize = 161; wchar_t stackBuffer[bufSize]; int attemptedSize = bufSize - 1; int numChars = 0; #ifdef _WIN32 numChars = _vsnwprintf(stackBuffer, attemptedSize, fmt, argPtr); #else numChars = vsnwprintf(stackBuffer, attemptedSize, fmt, argPtr); #endif //cout << "NumChars: " << numChars << endl; if ((numChars >= 0) && (numChars <= attemptedSize)) { // Needed for case of 160-character printf thing stackBuffer[numChars] = '\0'; // Got it on the first try. return std::wstring(stackBuffer); } // Now use the heap. wchar_t* heapBuffer = NULL; while (((numChars == -1) || (numChars > attemptedSize)) && (attemptedSize < maxSize)) { // Try a bigger size attemptedSize *= 2; //heapBuffer = (wchar_t*)realloc(heapBuffer, (attemptedSize + 1)); heapBuffer = (wchar_t*)realloc(heapBuffer, (attemptedSize + 1)*sizeof(wchar_t)); #ifdef _WIN32 numChars = _vsnwprintf(heapBuffer, attemptedSize, fmt, argPtr); #else numChars = vsnwprintf(heapBuffer, attemptedSize, fmt, argPtr); #endif } heapBuffer[numChars] = 0; std::wstring result = std::wstring(heapBuffer); free(heapBuffer); return result; } //overloaded StrFormat: should only be used by the xml strings std::wstring Sexy::StrFormat(const wchar_t* fmt ...) { va_list argList; va_start(argList, fmt); std::wstring result = vformat(fmt, argList); va_end(argList); return result; } std::string Sexy::Evaluate(const std::string& theString, const DefinesMap& theDefinesMap) { std::string anEvaluatedString = theString; for (;;) { int aPercentPos = anEvaluatedString.find('%'); if (aPercentPos == std::string::npos) break; int aSecondPercentPos = anEvaluatedString.find('%', aPercentPos + 1); if (aSecondPercentPos == std::string::npos) break; std::string aName = anEvaluatedString.substr(aPercentPos + 1, aSecondPercentPos - aPercentPos - 1); std::string aValue; DefinesMap::const_iterator anItr = theDefinesMap.find(aName); if (anItr != theDefinesMap.end()) aValue = anItr->second; else aValue = ""; anEvaluatedString.erase(anEvaluatedString.begin() + aPercentPos, anEvaluatedString.begin() + aSecondPercentPos + 1); anEvaluatedString.insert(anEvaluatedString.begin() + aPercentPos, aValue.begin(), aValue.begin() + aValue.length()); } return anEvaluatedString; } #endif std::string Sexy::XMLDecodeString(const std::string& theString) { std::string aNewString; int aUTF8Len = 0; int aUTF8CurVal = 0; for (uint32_t i = 0; i < theString.length(); i++) { char c = theString[i]; if (c == '&') { int aSemiPos = theString.find(';', i); if (aSemiPos != -1) { std::string anEntName = theString.substr(i+1, aSemiPos-i-1); i = aSemiPos; if (anEntName == "lt") c = '<'; else if (anEntName == "amp") c = '&'; else if (anEntName == "gt") c = '>'; else if (anEntName == "quot") c = '"'; else if (anEntName == "apos") c = '\''; else if (anEntName == "nbsp") c = ' '; else if (anEntName == "cr") c = '\n'; } } aNewString += c; } return aNewString; } std::wstring Sexy::XMLDecodeString(const std::wstring& theString) { std::wstring aNewString; int aUTF8Len = 0; int aUTF8CurVal = 0; for (uint32_t i = 0; i < theString.length(); i++) { wchar_t c = theString[i]; if (c == L'&') { int aSemiPos = theString.find(L';', i); if (aSemiPos != -1) { std::wstring anEntName = theString.substr(i+1, aSemiPos-i-1); i = aSemiPos; if (anEntName == L"lt") c = L'<'; else if (anEntName == L"amp") c = L'&'; else if (anEntName == L"gt") c = L'>'; else if (anEntName == L"quot") c = L'"'; else if (anEntName == L"apos") c = L'\''; else if (anEntName == L"nbsp") c = L' '; else if (anEntName == L"cr") c = L'\n'; } } aNewString += c; } return aNewString; } std::string Sexy::XMLEncodeString(const std::string& theString) { std::string aNewString; bool hasSpace = false; for (uint32_t i = 0; i < theString.length(); i++) { char c = theString[i]; if (c == ' ') { if (hasSpace) { aNewString += " "; continue; } hasSpace = true; } else hasSpace = false; /*if ((uchar) c >= 0x80) { // Convert to UTF aNewString += (char) (0xC0 | ((c >> 6) & 0xFF)); aNewString += (char) (0x80 | (c & 0x3F)); } else*/ { switch (c) { case '<': aNewString += "<"; break; case '&': aNewString += "&"; break; case '>': aNewString += ">"; break; case '"': aNewString += """; break; case '\'': aNewString += "'"; break; case '\n': aNewString += "&cr;"; break; default: aNewString += c; break; } } } return aNewString; } std::wstring Sexy::XMLEncodeString(const std::wstring& theString) { std::wstring aNewString; bool hasSpace = false; for (uint32_t i = 0; i < theString.length(); i++) { wchar_t c = theString[i]; if (c == ' ') { if (hasSpace) { aNewString += L" "; continue; } hasSpace = true; } else hasSpace = false; /*if ((uchar) c >= 0x80) { // Convert to UTF aNewString += (char) (0xC0 | ((c >> 6) & 0xFF)); aNewString += (char) (0x80 | (c & 0x3F)); } else*/ { switch (c) { case L'<': aNewString += L"<"; break; case L'&': aNewString += L"&"; break; case L'>': aNewString += L">"; break; case L'"': aNewString += L"""; break; case L'\'': aNewString += L"'"; break; case L'\n': aNewString += L"&cr;"; break; default: aNewString += c; break; } } } return aNewString; } std::string Sexy::Upper(const std::string& _data) { std::string s = _data; std::transform(s.begin(), s.end(), s.begin(), toupper); return s; } std::wstring Sexy::Upper(const std::wstring& _data) { std::wstring s = _data; std::transform(s.begin(), s.end(), s.begin(), towupper); return s; } std::string Sexy::Lower(const std::string& _data) { std::string s = _data; std::transform(s.begin(), s.end(), s.begin(), tolower); return s; } std::wstring Sexy::Lower(const std::wstring& _data) { std::wstring s = _data; std::transform(s.begin(), s.end(), s.begin(), towlower); return s; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int Sexy::StrFindNoCase(const char *theStr, const char *theFind) { int p1,p2; int cp = 0; const int len1 = (int)strlen(theStr); const int len2 = (int)strlen(theFind); while(cp < len1) { p1 = cp; p2 = 0; while(p1 0) && ((theDirectory[aLen-1] == '\\') || (theDirectory[aLen-1] == '/'))) return theDirectory.substr(0, aLen - 1); else return theDirectory; } std::string Sexy::BuildIniName(std::string copy, const std::string& theSubstitute) { int pos = copy.find_first_of("\\/"); while (pos != std::string::npos) { copy.replace(pos, 1,theSubstitute); pos = copy.find_first_of("\\/"); } return copy; } std::string Sexy::ReplaceBackSlashes(std::string copy) { int pos = copy.find_first_of('\\'); while (pos != std::string::npos) { if (pos + 1 < copy.size() && copy.at(pos+1) == '\\') { copy.replace(pos+1, 1, "/"); copy.erase(pos, 1); } else { copy.replace(pos, 1, "/"); } pos = copy.find_first_of('\\'); } return copy; } void Sexy::MkDir(const std::string& theDir) { std::string aPath = theDir; int aCurPos = 0; for (;;) { int aSlashPos = aPath.find_first_of("\\/", aCurPos); if (aSlashPos == -1) { mkdir(aPath.c_str(),0777); break; } aCurPos = aSlashPos+1; std::string aCurPath = aPath.substr(0, aSlashPos); mkdir(aCurPath.c_str(),0777); } } libtuxcap-1.4.0/tuxcap/lib/Buffer.cpp0000644000175000017500000003202311202747625017364 0ustar inniyahinniyah#include #include "Buffer.h" #if 0 #include "Debug.h" #endif #define POLYNOMIAL 0x04c11db7L static bool bCrcTableGenerated = false; static uint32_t crc_table[256]; using namespace Sexy; using namespace std; static const char* gWebEncodeMap = ".-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; static int gWebDecodeMap[256] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, 0, -1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, -1, -1, -1, -1, -1 , -1, -1, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 , 30, 31, 32, 33, 34, 35, 36, 37, -1, -1, -1, -1, -1, -1, 38, 39, 40, 41, 42, 43 , 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 , -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; //---------------------------------------------------------------------------- // Generate the table of CRC remainders for all possible bytes. //---------------------------------------------------------------------------- static void GenerateCRCTable(void) { bCrcTableGenerated = true; register int i, j; register uint32_t crc_accum; for (i = 0; i < 256; i++) { crc_accum = ((uint32_t) i << 24); for ( j = 0; j < 8; j++ ) { if (crc_accum & 0x80000000L) crc_accum = (crc_accum << 1) ^ POLYNOMIAL; else crc_accum = (crc_accum << 1); } crc_table[i] = crc_accum; } } //---------------------------------------------------------------------------- // Update the CRC on the data block one byte at a time. //---------------------------------------------------------------------------- static uint32_t UpdateCRC(uint32_t crc_accum, const char *data_blk_ptr, int data_blk_size) { if (!bCrcTableGenerated) GenerateCRCTable(); register int i, j; for (j = 0; j < data_blk_size; j++) { i = ((int) (crc_accum >> 24) ^ *data_blk_ptr++) & 0xff; crc_accum = (crc_accum << 8) ^ crc_table[i]; } return crc_accum; } //---------------------------------------------------------------------------- // Stream UTF8 data in a const char* to keep receiving wchar_ts //---------------------------------------------------------------------------- static int GetUTF8Char(const char** theBuffer, int theLen, wchar_t* theChar) { static const unsigned short aMaskData[] = { 0xC0, // 1 extra byte 0xE0, // 2 extra bytes 0xF0, // 3 extra bytes 0xF8, // 4 extra bytes 0xFC // 5 extra bytes }; if (theLen == 0) return 0; const char* aBuffer = *theBuffer; int aTempChar = int((unsigned char)*aBuffer++); if ((aTempChar & 0x80) != 0) { if ((aTempChar & 0xC0) != 0xC0) return 0; // sanity check: high bit should not be set without the next highest bit being set, too. int aBytesRead[6]; int* aBytesReadPtr = &aBytesRead[0]; *aBytesReadPtr++ = aTempChar; int aLen; for (aLen = 0; aLen < (int)(sizeof(aMaskData)/sizeof(*aMaskData)); ++aLen) { if ( (aTempChar & aMaskData[aLen]) == ((aMaskData[aLen] << 1) & aMaskData[aLen]) ) break; } if (aLen >= (int)(sizeof(aMaskData)/sizeof(*aMaskData))) return 0; aTempChar &= ~aMaskData[aLen]; int aTotalLen = aLen+1; if (aTotalLen < 2 || aTotalLen > 6) return 0; int anExtraChar = 0; while (aLen > 0 && (aBuffer - *theBuffer) < theLen) { anExtraChar = int((unsigned char)*aBuffer++); if ((anExtraChar & 0xC0) != 0x80) return 0; // sanity check: high bit set, and next highest bit NOT set. *aBytesReadPtr++ = anExtraChar; aTempChar = (aTempChar << 6) | (anExtraChar & 0x3F); --aLen; } if (aLen > 0) return 0; // ran out of data before ending sequence // validate substrings bool valid = true; switch (aTotalLen) { case 2: valid = !((aBytesRead[0] & 0x3E) == 0); break; case 3: valid = !((aBytesRead[0] & 0x1F) == 0 && (aBytesRead[1] & 0x20) == 0); break; case 4: valid = !((aBytesRead[0] & 0x0F) == 0 && (aBytesRead[1] & 0x30) == 0); break; case 5: valid = !((aBytesRead[0] & 0x07) == 0 && (aBytesRead[1] & 0x38) == 0); break; case 6: valid = !((aBytesRead[0] & 0x03) == 0 && (aBytesRead[1] & 0x3C) == 0); break; } if (!valid) return 0; } int aConsumedCount = aBuffer - *theBuffer; if ( (aTempChar >= 0xD800 && aTempChar <= 0xDFFF) || (aTempChar >= 0xFFFE && aTempChar <= 0xFFFF) ) return 0; *theChar = (wchar_t)aTempChar; *theBuffer = aBuffer; return aConsumedCount; } Buffer::Buffer() { mDataBitSize = 0; mReadBitPos = 0; mWriteBitPos = 0; } Buffer::~Buffer() { } std::string Buffer::ToWebString() const { std::string aString; int aSizeBits = mWriteBitPos; int anOldReadBitPos = mReadBitPos; mReadBitPos = 0; char aStr[256]; sprintf(aStr, "%08X", aSizeBits); aString += aStr; int aNumChars = (aSizeBits + 5) / 6; for (int aCharNum = 0; aCharNum < aNumChars; aCharNum++) aString += gWebEncodeMap[ReadNumBits(6, false)]; mReadBitPos = anOldReadBitPos; return aString; } std::wstring Buffer::UTF8ToWideString() const { const char* aData = (const char*)GetDataPtr(); int aLen = GetDataLen(); bool firstChar = true; std::wstring aString; aString.reserve(aLen); // worst case while (aLen > 0) { wchar_t aChar; int aConsumed = GetUTF8Char(&aData, aLen, &aChar); if (aConsumed == 0) break; aLen -= aConsumed; if (firstChar) { firstChar = false; if (aChar == 0xFEFF) continue; } aString += aChar; } return aString; } void Buffer::FromWebString(const std::string& theString) { Clear(); if (theString.size() < 4) return; int aSizeBits = 0; for (int aDigitNum = 0; aDigitNum < 8; aDigitNum++) { char aChar = theString[aDigitNum]; int aVal = 0; if ((aChar >= '0') && (aChar <= '9')) aVal = aChar - '0'; else if ((aChar >= 'A') && (aChar <= 'F')) aVal = (aChar - 'A') + 10; else if ((aChar >= 'a') && (aChar <= 'f')) aVal = (aChar - 'f') + 10; aSizeBits += (aVal << ((7 - aDigitNum) * 4)); } int aCharIdx = 8; int aNumBitsLeft = aSizeBits; while (aNumBitsLeft > 0) { uchar aChar = theString[aCharIdx++]; int aVal = gWebDecodeMap[aChar]; int aNumBits = min(aNumBitsLeft, 6); WriteNumBits(aVal, aNumBits); aNumBitsLeft -= aNumBits; } SeekFront(); } void Buffer::SeekFront() const { mReadBitPos = 0; } void Buffer::Clear() { mReadBitPos = 0; mWriteBitPos = 0; mDataBitSize = 0; mData.clear(); } void Buffer::WriteByte(uchar theByte) { if (mWriteBitPos % 8 == 0) mData.push_back((char) theByte); else { int anOfs = mWriteBitPos % 8; mData[mWriteBitPos /8] |= theByte << anOfs; mData.push_back((char) (theByte >> (8-anOfs))); } mWriteBitPos += 8; if (mWriteBitPos > mDataBitSize) mDataBitSize = mWriteBitPos; } void Buffer::WriteNumBits(int theNum, int theBits) { for (int aBitNum = 0; aBitNum < theBits; aBitNum++) { if (mWriteBitPos % 8 == 0) mData.push_back(0); if ((theNum & (1< mDataBitSize) mDataBitSize = mWriteBitPos; } int Buffer::GetBitsRequired(int theNum, bool isSigned) { if (theNum < 0) // two's compliment stuff theNum = -theNum - 1; int aNumBits = 0; while (theNum >= 1<> 8)); } void Buffer::WriteLong(int32_t theLong) { WriteByte((uchar)theLong); WriteByte((uchar)(theLong >> 8)); WriteByte((uchar)(theLong >> 16)); WriteByte((uchar)(theLong >> 24)); } void Buffer::WriteString(const std::string& theString) { WriteShort((short) theString.length()); for (int i = 0; i < (int)theString.length(); i++) WriteByte(theString[i]); } void Buffer::WriteUTF8String(const std::wstring& theString) { if ((mWriteBitPos & 7) != 0) // boo! let's get byte aligned. mWriteBitPos = (mWriteBitPos + 8) & ~7; WriteShort((short) theString.length()); for (int i = 0; i < (int)theString.length(); ++i) { const unsigned int c = (unsigned int)theString[i]; // just in case wchar_t is only 16 bits, and it generally is in visual studio if (c < 0x80) { WriteByte((uchar)c); } else if (c < 0x800) { WriteByte((uchar)(0xC0 | (c>>6))); WriteByte((uchar)(0x80 | (c & 0x3F))); } else if (c < 0x10000) { WriteByte((uchar)(0xE0 | c>>12)); WriteByte((uchar)(0x80 | ((c>>6) & 0x3F))); WriteByte((uchar)(0x80 | (c & 0x3F))); } else if (c < 0x110000) { WriteByte((uchar)(0xF0 | (c>>18))); WriteByte((uchar)(0x80 | ((c>>12) & 0x3F))); WriteByte((uchar)(0x80 | ((c>>6) & 0x3F))); WriteByte((uchar)(0x80 | (c & 0x3F))); } // are the remaining ranges really necessary? add if so! } } void Buffer::WriteLine(const std::string& theString) { WriteBytes((const uchar*) (theString + "\r\n").c_str(), (int) theString.length() + 2); } void Buffer::WriteBuffer(const ByteVector& theBuffer) { WriteLong((short) theBuffer.size()); for (int i = 0; i < (int)theBuffer.size(); i++) WriteByte(theBuffer[i]); } void Buffer::WriteBytes(const uchar* theByte, int theCount) { for (int i = 0; i < theCount; i++) WriteByte(theByte[i]); } void Buffer::SetData(const ByteVector& theBuffer) { mData = theBuffer; mDataBitSize = mData.size() * 8; } void Buffer::SetData(uchar* thePtr, int theCount) { mData.clear(); mData.insert(mData.begin(), thePtr, thePtr + theCount); mDataBitSize = mData.size() * 8; } uchar Buffer::ReadByte() const { if ((mReadBitPos + 7)/8 >= (int)mData.size()) { return 0; // Underflow } if (mReadBitPos % 8 == 0) { uchar b = mData[mReadBitPos/8]; mReadBitPos += 8; return b; } else { int anOfs = mReadBitPos % 8; uchar b = 0; b = mData[mReadBitPos/8] >> anOfs; b |= mData[(mReadBitPos/8)+1] << (8 - anOfs); mReadBitPos += 8; return b; } } int Buffer::ReadNumBits(int theBits, bool isSigned) const { int aByteLength = (int) mData.size(); int theNum = 0; bool bset = false; for (int aBitNum = 0; aBitNum < theBits; aBitNum++) { int aBytePos = mReadBitPos/8; if (aBytePos >= aByteLength) break; bset = (mData[aBytePos] & (1<<(mReadBitPos%8))); if (bset) theNum |= 1< 0 && i < aLen; ++i) { wchar_t aChar; int aConsumed = GetUTF8Char(&aData, aDataSizeBytes, &aChar); if (aConsumed == 0) break; aDataSizeBytes -= aConsumed; aString += aChar; } assert(i == aLen); // if this fires, the UTF-8 data was malformed. return aString; } std::string Buffer::ReadLine() const { std::string aString; for (;;) { char c = ReadByte(); if ((c == 0) || (c == '\n')) break; if (c != '\r') aString += c; } return aString; } void Buffer::ReadBytes(uchar* theData, int theLen) const { for (int i = 0; i < theLen; i++) theData[i] = ReadByte(); } void Buffer::ReadBuffer(ByteVector* theByteVector) const { theByteVector->clear(); uint32_t aLength = ReadLong(); theByteVector->resize(aLength); ReadBytes(&(*theByteVector)[0], aLength); } const uchar* Buffer::GetDataPtr() const { if (mData.size() == 0) return NULL; return &mData[0]; } int Buffer::GetDataLen() const { return (mDataBitSize + 7) / 8; // Round up } int Buffer::GetDataLenBits() const { return mDataBitSize; } uint32_t Buffer::GetCRC32(uint32_t theSeed) const { uint32_t aCRC = theSeed; aCRC = UpdateCRC(aCRC, (const char*) &mData[0], (int) mData.size()); return aCRC; } bool Buffer::AtEnd() const { //return mReadBitPos >= (int)mData.size()*8; return mReadBitPos >= mDataBitSize; } bool Buffer::PastEnd() const { return mReadBitPos > mDataBitSize; } libtuxcap-1.4.0/tuxcap/lib/SWTri_Pixel565.cpp0000644000175000017500000000324710641010433020554 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. #if defined(TEXTURED) { #include "SWTri_GetTexel.cpp" if (alpha > 0x08) { #include "SWTri_TexelARGB.cpp" #if defined(GLOBAL_ARGB) || defined (TEX_ALPHA) || defined(MOD_ARGB) { if (alpha < 0xf0) { unsigned int trb, tg; #if !defined(LINEAR_BLEND) { trb = (((tex&0xff00ff) * alpha) >> 8) & 0xff00ff; tg = (((tex&0x00ff00) * alpha) >> 8) & 0x00ff00; } #else { trb = tex&0xff00ff; tg = tex&0x00ff00; } #endif trb = ((trb>>8)&0xf800)|((trb>>3)&0x001f); tg = ((tg>>5)&0x07e0); tex = *pix; alpha = (0xff - alpha)>>3; unsigned int prb = (((tex&0xf81f) * alpha) >> 5) & 0xf81f; unsigned int pg = (((tex&0x07e0) * alpha) >> 5) & 0x07e0; *pix = (trb|tg) + (prb|pg); } else { *pix = ((tex>>8)&0xf800)|((tex>>5)&0x07e0)|((tex>>3)&0x001f); } } #else { *pix = ((tex>>8)&0xf800)|((tex>>5)&0x07e0)|((tex>>3)&0x001f); } #endif } } #elif defined(MOD_ARGB) { if (a > 0xf00000) { *pix = ((r>>8)&0xf800)|((g>>13)&0x07e0)|((b>>19)&0x001f); } else if (a > 0x080000) { unsigned int alpha = a >> 16; unsigned int _rb = ((((r&0xff0000) | (b>>16)) * alpha)>> 8)&0xff00ff; unsigned int _g = (((g&0xff0000) * alpha)>>16)&0x00ff00; _rb = ((_rb>>8)&0xf800)|((_rb>>3)&0x001f); _g = ((_g>>5)&0x07e0); unsigned int p = *pix; alpha = (0xff - alpha)>>3; unsigned int prb = (((p&0xf81f) * alpha) >> 5) & 0xf81f; unsigned int pg = (((p&0x07e0) * alpha) >> 5) & 0x07e0; *pix = (_rb|_g)+(prb|pg); } } #endif libtuxcap-1.4.0/tuxcap/lib/ScrollbuttonWidget.cpp0000644000175000017500000000327710641010442022004 0ustar inniyahinniyah#include "ScrollbuttonWidget.h" #include "ButtonListener.h" #include "Graphics.h" using namespace Sexy; ScrollbuttonWidget::ScrollbuttonWidget(int theId, ButtonListener *theButtonListener, int theType) : ButtonWidget(theId, theButtonListener) { mHorizontal = false; mType = theType; } ScrollbuttonWidget::~ScrollbuttonWidget() { } void ScrollbuttonWidget::Draw(Graphics *g) { int anArrowOffset = 0; g->SetColor(Color(212, 212, 212)); g->FillRect(0, 0, mWidth, mHeight); if (mIsDown && mIsOver && !mDisabled) { anArrowOffset = 1; g->SetColor(Color(132, 132, 132)); g->DrawRect(0, 0, mWidth-1, mHeight-1); } else { g->SetColor(Color(255, 255, 255)); g->FillRect(1, 1, mWidth-2, 1); g->FillRect(1, 1, 1, mHeight-2); g->SetColor(Color::Black); g->FillRect(0, mHeight - 1, mWidth, 1); g->FillRect(mWidth - 1, 0, 1, mHeight); g->SetColor(Color(132, 132, 132)); g->FillRect(1, mHeight - 2, mWidth - 2, 1); g->FillRect(mWidth - 2, 1, 1, mHeight - 2); } if (!mDisabled) g->SetColor(Color::Black); else g->SetColor(Color(132, 132, 132)); if (mHorizontal || (mType==3 || mType==4)) { for (int i = 0; i < 4; i++) { if (mId == 0 || mType==3) g->FillRect(i + (mWidth-4)/2 + anArrowOffset, mHeight/2 - i - 1 + anArrowOffset, 1, 1 + i*2); else g->FillRect((3 - i) + (mWidth-4)/2 + anArrowOffset, mHeight/2 - i - 1 + anArrowOffset, 1, 1 + i*2); } } else { for (int i = 0; i < 4; i++) { if (mId == 0 || mType==1) g->FillRect(mWidth/2 - i - 1 + anArrowOffset, i + (mHeight-4)/2 + anArrowOffset, 1 + i*2, 1); else g->FillRect(mWidth/2 - i - 1 + anArrowOffset, (3 - i) + (mHeight-4)/2 + anArrowOffset, 1 + i*2, 1); } } } libtuxcap-1.4.0/tuxcap/lib/XMLParser.cpp0000644000175000017500000004203610654427350017775 0ustar inniyahinniyah#include "XMLParser.h" #if 0 #include "Debug.h" #include "..\PakLib\PakInterface.h" #endif #include #include #include using namespace Sexy; XMLParser::XMLParser() { mFile = NULL; mLineNum = 0; mAllowComments = false; mGetCharFunc = &XMLParser::GetUTF8Char; mForcedEncodingType = false; } XMLParser::~XMLParser() { if (mFile != NULL) fclose(mFile); } void XMLParser::SetEncodingType(XMLEncodingType theEncoding) { switch (theEncoding) { case ASCII: mGetCharFunc = &XMLParser::GetAsciiChar; mForcedEncodingType = true; break; case UTF_8: mGetCharFunc = &XMLParser::GetUTF8Char; mForcedEncodingType = true; break; case UTF_16: mGetCharFunc = &XMLParser::GetUTF16Char; mForcedEncodingType = true; break; case UTF_16_LE: mGetCharFunc = &XMLParser::GetUTF16LEChar; mForcedEncodingType = true; break; case UTF_16_BE: mGetCharFunc = &XMLParser::GetUTF16BEChar; mForcedEncodingType = true; break; } } void XMLParser::Fail(const SexyString& theErrorText) { mHasFailed = true; mErrorText = theErrorText; } void XMLParser::Init() { mSection = _S(""); mLineNum = 1; mHasFailed = false; mErrorText = _S(""); mFirstChar = true; mByteSwap = false; } bool XMLParser::AddAttribute(XMLElement* theElement, const SexyString& theAttributeKey, const SexyString& theAttributeValue) { std::pair aRet; aRet = theElement->mAttributes.insert(XMLParamMap::value_type(theAttributeKey, theAttributeValue)); if (!aRet.second) aRet.first->second = theAttributeValue; if (theAttributeKey != _S("/")) theElement->mAttributeIteratorList.push_back(aRet.first); return aRet.second; } bool XMLParser::GetAsciiChar(wchar_t* theChar, bool* error) { wchar_t aChar = 0; if (fread(&aChar, 1, 1, mFile) != 1) return false; *theChar = aChar; return true; } bool XMLParser::GetUTF8Char(wchar_t* theChar, bool* error) { static const unsigned short aMaskData[] = { 0xC0, // 1 extra byte 0xE0, // 2 extra bytes 0xF0, // 3 extra bytes 0xF8, // 4 extra bytes 0xFC // 5 extra bytes }; *error = true; int aTempChar = 0; if (fread(&aTempChar, 1, 1, mFile) == 1) { if ((aTempChar & 0x80) != 0) { if ((aTempChar & 0xC0) != 0xC0) return false; // sanity check: high bit should not be set without the next highest bit being set too. int aBytesRead[6]; int* aBytesReadPtr = &aBytesRead[0]; *aBytesReadPtr++ = aTempChar; int aLen; for (aLen = 0; aLen < (int)(sizeof(aMaskData)/sizeof(*aMaskData)); ++aLen) { if ( (aTempChar & aMaskData[aLen]) == ((aMaskData[aLen] << 1) & aMaskData[aLen]) ) break; } if (aLen >= (int)(sizeof(aMaskData)/sizeof(*aMaskData))) return false; aTempChar &= ~aMaskData[aLen]; int aTotalLen = aLen+1; assert(aTotalLen >= 2 && aTotalLen <= 6); int anExtraChar = 0; while (aLen > 0) { if (fread(&anExtraChar, 1, 1, mFile) != 1) return false; if ((anExtraChar & 0xC0) != 0x80) return false; // sanity check: high bit set, and next highest bit NOT set. *aBytesReadPtr++ = anExtraChar; aTempChar = (aTempChar << 6) | (anExtraChar & 0x3F); --aLen; } // validate substrings bool valid = true; switch (aTotalLen) { case 2: valid = !((aBytesRead[0] & 0x3E) == 0); break; case 3: valid = !((aBytesRead[0] & 0x1F) == 0 && (aBytesRead[1] & 0x20) == 0); break; case 4: valid = !((aBytesRead[0] & 0x0F) == 0 && (aBytesRead[1] & 0x30) == 0); break; case 5: valid = !((aBytesRead[0] & 0x07) == 0 && (aBytesRead[1] & 0x38) == 0); break; case 6: valid = !((aBytesRead[0] & 0x03) == 0 && (aBytesRead[1] & 0x3C) == 0); break; } if (!valid) return false; } if ( (aTempChar >= 0xD800 && aTempChar <= 0xDFFF) || (aTempChar >= 0xFFFE && aTempChar <= 0xFFFF) ) return false; if (aTempChar == 0xFEFF && mFirstChar) // zero-width non breaking space as the first char is a byte order marker. { mFirstChar = false; return GetUTF8Char(theChar, error); } *theChar = (wchar_t)aTempChar; *error = false; return true; } *error = false; return false; } bool XMLParser::GetUTF16Char(wchar_t* theChar, bool* error) { wchar_t aTempChar = 0; if (fread(&aTempChar, 2, 1, mFile) != 1) return false; if (mFirstChar) { mFirstChar = false; if (aTempChar == 0xFEFF) { mByteSwap = false; return GetUTF16Char(theChar, error); } else if (aTempChar == 0xFFFE) { mByteSwap = true; return GetUTF16Char(theChar, error); } } if (mByteSwap) aTempChar = (wchar_t)((aTempChar << 8) | (aTempChar >> 8)); if ((aTempChar & 0xD800) == 0xD800) { wchar_t aNextChar = 0; if (fread(&aNextChar, 2, 1, mFile) != 1) return false; if (mByteSwap) aNextChar = (wchar_t)((aNextChar << 8) | (aNextChar >> 8)); if ((aNextChar & 0xDC00) == 0xDC00) { *theChar = (wchar_t)((((aTempChar & ~0xD800) << 10) | (aNextChar & ~0xDC00)) + 0x10000); } else return false; } else *theChar = aTempChar; return true; } bool XMLParser::GetUTF16LEChar(wchar_t* theChar, bool* error) { wchar_t aTempChar = 0; if (fread(&aTempChar, 2, 1, mFile) != 1) return false; aTempChar = WORD_LITTLEE_TO_NATIVE(aTempChar); if ((aTempChar & 0xD800) == 0xD800) { wchar_t aNextChar = 0; if (fread(&aNextChar, 2, 1, mFile) != 1) return false; aNextChar = WORD_LITTLEE_TO_NATIVE(aTempChar); if ((aNextChar & 0xDC00) == 0xDC00) { *theChar = (wchar_t)((((aTempChar & ~0xD800) << 10) | (aNextChar & ~0xDC00)) + 0x10000); } else return false; } return true; } bool XMLParser::GetUTF16BEChar(wchar_t* theChar, bool* error) { wchar_t aTempChar = 0; if (fread(&aTempChar, 2, 1, mFile) != 1) return false; aTempChar = WORD_BIGE_TO_NATIVE(aTempChar); if ((aTempChar & 0xD800) == 0xD800) { wchar_t aNextChar = 0; if (fread(&aNextChar, 2, 1, mFile) != 1) return false; aNextChar = WORD_BIGE_TO_NATIVE(aTempChar); if ((aNextChar & 0xDC00) == 0xDC00) { *theChar = (wchar_t)((((aTempChar & ~0xD800) << 10) | (aNextChar & ~0xDC00)) + 0x10000); } else return false; } return true; } bool XMLParser::OpenFile(const std::string& theFileName) { mFile = fopen(theFileName.c_str(), "r"); if (mFile == NULL) { mLineNum = 0; Fail(StringToSexyString("Unable to open file " + theFileName)); return false; } else if (!mForcedEncodingType) { fseek(mFile, 0, SEEK_END); long aFileLen = ftell(mFile); fseek(mFile, 0, SEEK_SET); mGetCharFunc = &XMLParser::GetAsciiChar; if (aFileLen >= 2) // UTF-16? { int aChar1 = fgetc(mFile); int aChar2 = fgetc(mFile); if ( (aChar1 == 0xFF && aChar2 == 0xFE) || (aChar1 == 0xFE && aChar2 == 0xFF) ) mGetCharFunc = &XMLParser::GetUTF16Char; ungetc(aChar2, mFile); ungetc(aChar1, mFile); } if (mGetCharFunc == &XMLParser::GetAsciiChar) { if (aFileLen >= 3) // UTF-8? { int aChar1 = fgetc(mFile); int aChar2 = fgetc(mFile); int aChar3 = fgetc(mFile); if (aChar1 == 0xEF && aChar2 == 0xBB && aChar3 == 0xBF) mGetCharFunc = &XMLParser::GetUTF8Char; ungetc(aChar3, mFile); ungetc(aChar2, mFile); ungetc(aChar1, mFile); } } } mFileName = theFileName.c_str(); Init(); return true; } void XMLParser::SetStringSource(const std::wstring& theString) { Init(); int aSize = theString.size(); mBufferedText.resize(aSize); for (int i = 0; i < aSize; i++) mBufferedText[i] = theString[aSize - i - 1]; } void XMLParser::SetStringSource(const std::string& theString) { SetStringSource(StringToWString(theString)); } bool XMLParser::NextElement(XMLElement* theElement) { for (;;) { theElement->mType = XMLElement::TYPE_NONE; theElement->mSection = mSection; theElement->mValue = _S(""); theElement->mAttributes.clear(); theElement->mInstruction.erase(); bool hasSpace = false; bool inQuote = false; bool gotEndQuote = false; bool doingAttribute = false; bool AttributeVal = false; std::wstring aAttributeKey; std::wstring aAttributeValue; std::wstring aLastAttributeKey; for (;;) { // Process character by character wchar_t c; int aVal; if (mBufferedText.size() > 0) { c = mBufferedText[mBufferedText.size()-1]; mBufferedText.pop_back(); aVal = 1; } else { if (mFile != NULL) { bool error = false; if ((this->*mGetCharFunc)(&c, &error)) { aVal = 1; } else { if (error) Fail(_S("Illegal Character")); aVal = 0; } } else { aVal = 0; } } if (aVal == 1) { bool processChar = false; if (c == L'\n') { mLineNum++; } if (theElement->mType == XMLElement::TYPE_COMMENT) { // Just add text to theElement->mInstruction until we find --> SexyString* aStrPtr = &theElement->mInstruction; *aStrPtr += (SexyChar)c; int aLen = aStrPtr->length(); if ((c == L'>') && (aLen >= 3) && ((*aStrPtr)[aLen - 2] == L'-') && ((*aStrPtr)[aLen - 3] == L'-')) { *aStrPtr = aStrPtr->substr(0, aLen - 3); break; } } else if (theElement->mType == XMLElement::TYPE_INSTRUCTION) { // Just add text to theElement->mInstruction until we find ?> SexyString* aStrPtr = &theElement->mValue; if ((theElement->mInstruction.length() != 0) || (::iswspace(c))) aStrPtr = &theElement->mInstruction; *aStrPtr += (SexyChar)c; int aLen = aStrPtr->length(); if ((c == L'>') && (aLen >= 2) && ((*aStrPtr)[aLen - 2] == L'?')) { *aStrPtr = aStrPtr->substr(0, aLen - 2); break; } } else { if (c == L'"') { inQuote = !inQuote; if (theElement->mType==XMLElement::TYPE_NONE || theElement->mType==XMLElement::TYPE_ELEMENT) processChar = true; if (!inQuote) gotEndQuote = true; } else if (!inQuote) { if (c == L'<') { if (theElement->mType == XMLElement::TYPE_ELEMENT) { //TODO: Fix buffered text. Not sure what I meant by that. //OLD: mBufferedText = c + mBufferedText; mBufferedText.push_back(c); break; } if (theElement->mType == XMLElement::TYPE_NONE) { theElement->mType = XMLElement::TYPE_START; } else { Fail(_S("Unexpected '<'")); return false; } } else if (c == L'>') { if (theElement->mType == XMLElement::TYPE_START) { bool insertEnd = false; if (aAttributeKey == L"/") { // We will get this if we have a space before the />, so we can ignore it // and go about our business now insertEnd = true; } else { // Probably isn't committed yet if (aAttributeKey.length() > 0) { // theElement->mAttributes[aLastAttributeKey] = aAttributeValue; aAttributeKey = XMLDecodeString(aAttributeKey); aAttributeValue = XMLDecodeString(aAttributeValue); aLastAttributeKey = aAttributeKey; AddAttribute(theElement, WStringToSexyString(aLastAttributeKey), WStringToSexyString(aAttributeValue)); aAttributeKey = L""; aAttributeValue = L""; } if (aLastAttributeKey.length() > 0) { SexyString aVal = theElement->mAttributes[WStringToSexyString(aLastAttributeKey)]; int aLen = aVal.length(); if ((aLen > 0) && (aVal[aLen-1] == '/')) { // Its an empty element, fake start and end segments // theElement->mAttributes[aLastAttributeKey] = aVal.substr(0, aLen - 1); AddAttribute(theElement, WStringToSexyString(aLastAttributeKey), XMLDecodeString(aVal.substr(0, aLen - 1))); insertEnd = true; } } else { int aLen = theElement->mValue.length(); if ((aLen > 0) && (theElement->mValue[aLen-1] == '/')) { // Its an empty element, fake start and end segments theElement->mValue = theElement->mValue.substr(0, aLen - 1); insertEnd = true; } } } // Do we want to fake an ending section? if (insertEnd) { SexyString anAddString = _S("mValue + _S(">"); int anOldSize = mBufferedText.size(); int anAddLength = anAddString.length(); mBufferedText.resize(anOldSize + anAddLength); for (int i = 0; i < anAddLength; i++) mBufferedText[anOldSize + i] = (wchar_t)(anAddString[anAddLength - i - 1]); // clear out aAttributeKey, since it contains "/" as its value and will insert // it into the element's attribute map. aAttributeKey = L""; //OLD: mBufferedText = "mValue + ">" + mBufferedText; } if (mSection.length() != 0) mSection += _S("/"); mSection += theElement->mValue; break; } else if (theElement->mType == XMLElement::TYPE_END) { int aLastSlash = mSection.rfind(_S('/')); if ((aLastSlash == -1) && (mSection.length() == 0)) { Fail(_S("Unexpected End")); return false; } SexyString aLastSectionName = mSection.substr(aLastSlash + 1); if (aLastSectionName != theElement->mValue) { Fail(_S("End '") + theElement->mValue + _S("' Doesn't Match Start '") + aLastSectionName + _S("'")); return false; } if (aLastSlash == -1) mSection.erase(mSection.begin(), mSection.end()); else mSection.erase(mSection.begin() + aLastSlash, mSection.end()); break; } else { Fail(_S("Unexpected '>'")); return false; } } else if ((c == L'/') && (theElement->mType == XMLElement::TYPE_START) && (theElement->mValue == _S(""))) { theElement->mType = XMLElement::TYPE_END; } else if ((c == L'?') && (theElement->mType == XMLElement::TYPE_START) && (theElement->mValue == _S(""))) { theElement->mType = XMLElement::TYPE_INSTRUCTION; } else if (::isspace((uchar) c)) { if (theElement->mValue != _S("")) hasSpace = true; // It's a comment! if ((theElement->mType == XMLElement::TYPE_START) && (theElement->mValue == _S("!--"))) theElement->mType = XMLElement::TYPE_COMMENT; } else if (c > 32) { processChar = true; } else { Fail(_S("Illegal Character")); return false; } } else { processChar = true; } if (processChar) { if (theElement->mType == XMLElement::TYPE_NONE) theElement->mType = XMLElement::TYPE_ELEMENT; if (theElement->mType == XMLElement::TYPE_START) { if (hasSpace) { if ((!doingAttribute) || ((!AttributeVal) && (c != _S('='))) || ((AttributeVal) && ((aAttributeValue.length() > 0) || gotEndQuote))) { if (doingAttribute) { aAttributeKey = XMLDecodeString(aAttributeKey); aAttributeValue = XMLDecodeString(aAttributeValue); // theElement->mAttributes[aAttributeKey] = aAttributeValue; AddAttribute(theElement, WStringToSexyString(aAttributeKey), WStringToSexyString(aAttributeValue)); aAttributeKey = L""; aAttributeValue = L""; aLastAttributeKey = aAttributeKey; } else { doingAttribute = true; } AttributeVal = false; } hasSpace = false; } std::wstring* aStrPtr = NULL; if (!doingAttribute) { theElement->mValue += (SexyChar)c; } else { if (c == L'=') { AttributeVal = true; gotEndQuote = false; } else { if (!AttributeVal) aStrPtr = &aAttributeKey; else aStrPtr = &aAttributeValue; } } if (aStrPtr != NULL) { *aStrPtr += c; } } else { if (hasSpace) { theElement->mValue += _S(" "); hasSpace = false; } theElement->mValue += (SexyChar)c; } } } } else { if (theElement->mType != XMLElement::TYPE_NONE) Fail(_S("Unexpected End of File")); return false; } } if (aAttributeKey.length() > 0) { aAttributeKey = XMLDecodeString(aAttributeKey); aAttributeValue = XMLDecodeString(aAttributeValue); // theElement->mAttributes[aAttributeKey] = aAttributeValue; AddAttribute(theElement, WStringToSexyString(aAttributeKey), WStringToSexyString(aAttributeValue)); } theElement->mValue = XMLDecodeString(theElement->mValue); // Ignore comments if ((theElement->mType != XMLElement::TYPE_COMMENT) || mAllowComments) return true; } } bool XMLParser::HasFailed() { return mHasFailed; } SexyString XMLParser::GetErrorText() { return mErrorText; } int XMLParser::GetCurrentLineNum() { return mLineNum; } std::string XMLParser::GetFileName() { return mFileName; } libtuxcap-1.4.0/tuxcap/lib/ImageLib.cpp0000644000175000017500000003432511202747626017634 0ustar inniyahinniyah#define XMD_H #include #include "ImageLib.h" #include #include "Common.h" #include "SexyAppBase.h" #if 0 #include #include "..\PakLib\PakInterface.h" #endif using namespace ImageLib; using namespace Magick; ImageLib::Image::Image() { mWidth = 0; mHeight = 0; mBits = NULL; } ImageLib::Image::Image(int width, int height) { mWidth = width; mHeight = height; mBits = new uint32_t[mWidth * mHeight]; } ImageLib::Image::~Image() { delete[] mBits; } int ImageLib::Image::GetWidth() { return mWidth; } int ImageLib::Image::GetHeight() { return mHeight; } uint32_t* ImageLib::Image::GetBits() { return mBits; } #if 0 ////////////////////////////////////////////////////////////////////////// // PNG Pak Support static void png_pak_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { png_size_t check; /* fread() returns 0 on error, so it is OK to store this in a png_size_t * instead of an int, which is what fread() actually returns. */ check = (png_size_t)p_fread(data, (png_size_t)1, length, (PFILE*)png_ptr->io_ptr); if (check != length) { png_error(png_ptr, "Read Error"); } } bool ImageLib::WriteJPEGImage(const std::string& theFileName,ImageLib::Image* theImage) { FILE *fp; if ((fp = fopen(theFileName.c_str(), "wb")) == NULL) return false; struct jpeg_compress_struct cinfo; struct my_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { /* If we get here, the JPEG code has signaled an error. * We need to clean up the JPEG object, close the input file, and return. */ jpeg_destroy_compress(&cinfo); fclose(fp); return false; } jpeg_create_compress(&cinfo); cinfo.image_width = theImage->mWidth; cinfo.image_height = theImage->mHeight; cinfo.input_components = 3; cinfo.in_color_space = JCS_RGB; cinfo.optimize_coding = 1; jpeg_set_defaults(&cinfo); jpeg_set_quality(&cinfo, 80, TRUE); jpeg_stdio_dest(&cinfo, fp); jpeg_start_compress(&cinfo, true); int row_stride = theImage->GetWidth() * 3; unsigned char* aTempBuffer = new unsigned char[row_stride]; uint32_t* aSrcPtr = theImage->mBits; for (int aRow = 0; aRow < theImage->mHeight; aRow++) { unsigned char* aDest = aTempBuffer; for (int aCol = 0; aCol < theImage->mWidth; aCol++) { uint32_t src = *(aSrcPtr++); *aDest++ = (src >> 16) & 0xFF; *aDest++ = (src >> 8) & 0xFF; *aDest++ = (src ) & 0xFF; } jpeg_write_scanlines(&cinfo, &aTempBuffer, 1); } delete [] aTempBuffer; jpeg_finish_compress(&cinfo); jpeg_destroy_compress(&cinfo); fclose(fp); return true; } boo ImageLib::WritePNGImage(const std::string& theFileName,ImageLib::Image* theImage) { png_structp png_ptr; png_infop info_ptr; FILE *fp; if ((fp = fopen(theFileName.c_str(), "wb")) == NULL) return false; png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { fclose(fp); return false; } // Allocate/initialize the memory for image information. REQUIRED. info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { fclose(fp); png_destroy_write_struct(&png_ptr, (png_infopp)NULL); return false; } // Set error handling if you are using the setjmp/longjmp method (this is // the normal method of doing things with libpng). REQUIRED unless you // set up your own error handlers in the png_create_write_struct() earlier. if (setjmp(png_ptr->jmpbuf)) { // Free all of the memory associated with the png_ptr and info_ptr png_destroy_write_struct(&png_ptr, &info_ptr); fclose(fp); // If we get here, we had a problem writeing the file return NULL; } png_init_io(png_ptr, fp); png_color_8 sig_bit; sig_bit.red = 8; sig_bit.green = 8; sig_bit.blue = 8; /* if the image has an alpha channel then */ sig_bit.alpha = 8; png_set_sBIT(png_ptr, info_ptr, &sig_bit); png_set_bgr(png_ptr); png_set_IHDR(png_ptr, info_ptr, theImage->mWidth, theImage->mHeight, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); // Add filler (or alpha) byte (before/after each RGB triplet) //png_set_expand(png_ptr); //png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); //png_set_gray_1_2_4_to_8(png_ptr); //png_set_palette_to_rgb(png_ptr); //png_set_gray_to_rgb(png_ptr); png_write_info(png_ptr, info_ptr); for (int i = 0; i < theImage->mHeight; i++) { png_bytep aRowPtr = (png_bytep) (theImage->mBits + i*theImage->mWidth); png_write_rows(png_ptr, &aRowPtr, 1); } // write rest of file, and get additional chunks in info_ptr - REQUIRED png_write_end(png_ptr, info_ptr); // clean up after the write, and free any memory allocated - REQUIRED png_destroy_write_struct(&png_ptr, &info_ptr); // close the file fclose(fp); return true; } bool ImageLib::WriteTGAImage(const std::string& theFileName,ImageLib::Image* theImage) { FILE* aTGAFile = fopen(theFileName.c_str(), "wb"); if (aTGAFile == NULL) return false; BYTE aHeaderIDLen = 0; fwrite(&aHeaderIDLen, sizeof(BYTE), 1, aTGAFile); BYTE aColorMapType = 0; fwrite(&aColorMapType, sizeof(BYTE), 1, aTGAFile); BYTE anImageType = 2; fwrite(&anImageType, sizeof(BYTE), 1, aTGAFile); WORD aFirstEntryIdx = 0; fwrite(&aFirstEntryIdx, sizeof(WORD), 1, aTGAFile); WORD aColorMapLen = 0; fwrite(&aColorMapLen, sizeof(WORD), 1, aTGAFile); BYTE aColorMapEntrySize = 0; fwrite(&aColorMapEntrySize, sizeof(BYTE), 1, aTGAFile); WORD anXOrigin = 0; fwrite(&anXOrigin, sizeof(WORD), 1, aTGAFile); WORD aYOrigin = 0; fwrite(&aYOrigin, sizeof(WORD), 1, aTGAFile); WORD anImageWidth = theImage->mWidth; fwrite(&anImageWidth, sizeof(WORD), 1, aTGAFile); WORD anImageHeight = theImage->mHeight; fwrite(&anImageHeight, sizeof(WORD), 1, aTGAFile); BYTE aBitCount = 32; fwrite(&aBitCount, sizeof(BYTE), 1, aTGAFile); BYTE anImageDescriptor = 8 | (1<<5); fwrite(&anImageDescriptor, sizeof(BYTE), 1, aTGAFile); fwrite(theImage->mBits, 4, theImage->mWidth*theImage->mHeight, aTGAFile); fclose(aTGAFile); return true; } bool ImageLib::WriteBMPImage(const std::string& theFileName,ImageLib::Image* theImage) { FILE* aFile = fopen(theFileName.c_str(), "wb"); if (aFile == NULL) return false; BITMAPFILEHEADER aFileHeader; BITMAPINFOHEADER aHeader; memset(&aFileHeader,0,sizeof(aFileHeader)); memset(&aHeader,0,sizeof(aHeader)); int aNumBytes = theImage->mWidth*theImage->mHeight*4; aFileHeader.bfType = ('M'<<8) | 'B'; aFileHeader.bfSize = sizeof(aFileHeader) + sizeof(aHeader) + aNumBytes; aFileHeader.bfOffBits = sizeof(aHeader); aHeader.biSize = sizeof(aHeader); aHeader.biWidth = theImage->mWidth; aHeader.biHeight = theImage->mHeight; aHeader.biPlanes = 1; aHeader.biBitCount = 32; aHeader.biCompression = BI_RGB; fwrite(&aFileHeader,sizeof(aFileHeader),1,aFile); fwrite(&aHeader,sizeof(aHeader),1,aFile); DWORD *aRow = theImage->mBits + (theImage->mHeight-1)*theImage->mWidth; int aRowSize = theImage->mWidth*4; for (int i=0; imHeight; i++, aRow-=theImage->mWidth) fwrite(aRow,4,theImage->mWidth,aFile); fclose(aFile); return true; } #endif int ImageLib::gAlphaComposeColor = 0xFFFFFF; bool ImageLib::gAutoLoadAlpha = true; bool ImageLib::gIgnoreJPEG2000Alpha = true; ImageLib::Image* ImageLib::GetImage(std::string theFilename, bool lookForAlphaImage) { if (!gAutoLoadAlpha) lookForAlphaImage = false; theFilename = Sexy::ReplaceBackSlashes(theFilename); int aLastDotPos = theFilename.rfind('.'); int aLastSlashPos = (int)theFilename.rfind('/'); std::string anExt; std::string aFilename; if (aLastDotPos > aLastSlashPos) { anExt = theFilename.substr(aLastDotPos, theFilename.length() - aLastDotPos); aFilename = theFilename.substr(0, aLastDotPos); } else { aFilename = theFilename; } ImageLib::Image* anImage = NULL; Magick::Image mImage; bool ok = false; if (anExt.length() == 0) { std::list coderList; coderList.push_back("jpg"); coderList.push_back("png"); coderList.push_back("gif"); coderList.push_back("jp2"); coderList.push_back("tga"); coderList.push_back("tif"); coderList.push_back("bmp"); std::list::const_iterator entry = coderList.begin(); while( entry != coderList.end() ) { try { if (Sexy::gSexyAppBase->FileExists(theFilename + "." + *entry)) { // Read a file into image object mImage.read( theFilename + "." + *entry); ok = true; break; } else if (Sexy::gSexyAppBase->FileExists(theFilename + "." + Sexy::Upper(*entry))) { // Read a file into image object mImage.read( theFilename + "." + Sexy::Upper(*entry)); ok = true; break; } } catch( Magick::Exception &error_ ) { return NULL; } catch (std::exception &error) { return NULL; } catch ( ...) { return NULL; } ++entry; } } else { try { // Read a file into image object if (Sexy::gSexyAppBase->FileExists(theFilename)) { mImage.read( theFilename ); ok = true; } else if (Sexy::gSexyAppBase->FileExists(aFilename + Sexy::Lower(anExt))) { mImage.read( aFilename + Sexy::Lower(anExt)); ok = true; } else if (Sexy::gSexyAppBase->FileExists(aFilename + Sexy::Upper(anExt))) { mImage.read( aFilename + Sexy::Upper(anExt) ); ok = true; } } catch( Magick::Exception &error_ ) { return NULL; } catch (std::exception &error) { return NULL; } catch ( ...) { return NULL; } } // Check for alpha images Image* anAlphaImage = NULL; if(lookForAlphaImage) { // Check _ImageName anAlphaImage = GetImage(aFilename + "_", false); if(anAlphaImage==NULL) { anAlphaImage = GetImage(aFilename.substr(0, aLastSlashPos+1) + "_" + aFilename.substr(aLastSlashPos+1, aFilename.length() - aLastSlashPos - 1), false); } } // Compose alpha channel with image if (anAlphaImage != NULL) { if (ok && anImage == NULL) { //TODO put this in a function anImage = new ImageLib::Image(mImage.baseColumns(), mImage.baseRows()); const Magick::PixelPacket* pixels = mImage.getConstPixels(0,0,mImage.baseColumns(), mImage.baseRows()); for(int i = 0; i < mImage.baseColumns() * mImage.baseRows(); ++i) { const Magick::PixelPacket* p = pixels + i; Magick::Color c(*p); Magick::ColorRGB rgb = c; *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 2) = (unsigned char)(rgb.red() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 1) = (unsigned char)(rgb.green() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 0) = (unsigned char)(rgb.blue() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 3) = 255 - (unsigned char)(c.alpha() * 255.0f); } } if (anImage != NULL) { if ((anImage->mWidth == anAlphaImage->mWidth) && (anImage->mHeight == anAlphaImage->mHeight)) { uint32_t* aBits1 = anImage->mBits; uint32_t* aBits2 = anAlphaImage->mBits; int aSize = anImage->mWidth*anImage->mHeight; for (int i = 0; i < aSize; i++) { *aBits1 = (*aBits1 & 0x00FFFFFF) | ((*aBits2 & 0xFF) << 24); ++aBits1; ++aBits2; } } delete anAlphaImage; } else if (gAlphaComposeColor==0xFFFFFF) { anImage = anAlphaImage; uint32_t* aBits1 = anImage->mBits; int aSize = anImage->mWidth*anImage->mHeight; for (int i = 0; i < aSize; i++) { *aBits1 = (0x00FFFFFF) | ((*aBits1 & 0xFF) << 24); ++aBits1; } } else { const int aColor = gAlphaComposeColor; anImage = anAlphaImage; uint32_t* aBits1 = anImage->mBits; int aSize = anImage->mWidth*anImage->mHeight; for (int i = 0; i < aSize; i++) { *aBits1 = aColor | ((*aBits1 & 0xFF) << 24); ++aBits1; } } } if (anImage == NULL && ok) { anImage = new ImageLib::Image(mImage.baseColumns(), mImage.baseRows()); const Magick::PixelPacket* pixels = mImage.getConstPixels(0,0,mImage.baseColumns(), mImage.baseRows()); for(int i = 0; i < mImage.baseColumns() * mImage.baseRows(); ++i) { const Magick::PixelPacket* p = pixels + i; Magick::Color c(*p); Magick::ColorRGB rgb = c; *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 2) = (unsigned char)(rgb.red() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 1) = (unsigned char)(rgb.green() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 0)= (unsigned char)(rgb.blue() * 255.0f); *((unsigned char*)anImage->mBits + i * sizeof(uint32_t) + 3) = 255 - (unsigned char)(c.alpha() * 255.0f); } } return anImage; } libtuxcap-1.4.0/tuxcap/lib/CursorWidget.cpp0000644000175000017500000000101410654431553020570 0ustar inniyahinniyah#include "CursorWidget.h" #include "Image.h" using namespace Sexy; CursorWidget::CursorWidget() { mImage = NULL; mMouseVisible = false; } void CursorWidget::Draw(Graphics* g) { if (mImage != NULL) g->DrawImage(mImage, 0, 0); } void CursorWidget::SetImage(Image* theImage) { mImage = theImage; if (mImage != NULL) Resize(mX, mY, theImage->mWidth, theImage->mHeight); } Point CursorWidget::GetHotspot() { if (mImage == NULL) return Point(0, 0); return Point(mImage->GetWidth()/2, mImage->GetHeight()/2); } libtuxcap-1.4.0/tuxcap/lib/MemoryImage.cpp0000644000175000017500000013500111202747626020367 0ustar inniyahinniyah#include "MemoryImage.h" #include "SexyAppBase.h" #include "Graphics.h" #include "DDInterface.h" #include "D3DInterface.h" #include "NativeDisplay.h" #if 0 #include "PerfTimer.h" #include "Debug.h" #endif #include "Quantize.h" #include "SWTri.h" #include #include #include #include "SDL.h" using namespace Sexy; #ifdef OPTIMIZE_SOFTWARE_DRAWING bool gOptimizeSoftwareDrawing = false; #endif MemoryImage::MemoryImage() { mApp = gSexyAppBase; Init(); } MemoryImage::MemoryImage(SexyAppBase* theApp) { mApp = theApp; Init(); } MemoryImage::MemoryImage(const MemoryImage& theMemoryImage) : Image(theMemoryImage), mApp(theMemoryImage.mApp), mHasAlpha(theMemoryImage.mHasAlpha), mHasTrans(theMemoryImage.mHasTrans), mBitsChanged(theMemoryImage.mBitsChanged), mIsVolatile(theMemoryImage.mIsVolatile), mPurgeBits(theMemoryImage.mPurgeBits), mWantPal(theMemoryImage.mWantPal), mD3DFlags(theMemoryImage.mD3DFlags), mBitsChangedCount(theMemoryImage.mBitsChangedCount), mD3DData(NULL) { bool deleteBits = false; MemoryImage* aNonConstMemoryImage = (MemoryImage*) &theMemoryImage; if ((theMemoryImage.mBits == NULL) && (theMemoryImage.mColorTable == NULL)) { // Must be a DDImage with only a DDSurface aNonConstMemoryImage->GetBits(); deleteBits = true; } if (theMemoryImage.mBits != NULL) { mBits = new uint32_t[mWidth*mHeight + 1]; mBits[mWidth*mHeight] = MEMORYCHECK_ID; memcpy(mBits, theMemoryImage.mBits, (mWidth*mHeight + 1)*sizeof(uint32_t)); } else mBits = NULL; if (deleteBits) { // Remove the temporary source bits delete [] aNonConstMemoryImage->mBits; aNonConstMemoryImage->mBits = NULL; } if (theMemoryImage.mColorTable != NULL) { mColorTable = new uint32_t[256]; memcpy(mColorTable, theMemoryImage.mColorTable, 256*sizeof(uint32_t)); } else mColorTable = NULL; if (theMemoryImage.mColorIndices != NULL) { mColorIndices = new uchar[mWidth*mHeight]; memcpy(mColorIndices, theMemoryImage.mColorIndices, mWidth*mHeight*sizeof(uchar)); } else mColorIndices = NULL; if (theMemoryImage.mNativeAlphaData != NULL) { if (theMemoryImage.mColorTable == NULL) { mNativeAlphaData = new uint32_t[mWidth*mHeight]; memcpy(mNativeAlphaData, theMemoryImage.mNativeAlphaData, mWidth*mHeight*sizeof(uint32_t)); } else { mNativeAlphaData = new uint32_t[256]; memcpy(mNativeAlphaData, theMemoryImage.mNativeAlphaData, 256*sizeof(uint32_t)); } } else mNativeAlphaData = NULL; if (theMemoryImage.mRLAlphaData != NULL) { mRLAlphaData = new uchar[mWidth*mHeight]; memcpy(mRLAlphaData, theMemoryImage.mRLAlphaData, mWidth*mHeight); } else mRLAlphaData = NULL; if (theMemoryImage.mRLAdditiveData != NULL) { mRLAdditiveData = new uchar[mWidth*mHeight]; memcpy(mRLAdditiveData, theMemoryImage.mRLAdditiveData, mWidth*mHeight); } else mRLAdditiveData = NULL; mApp->AddMemoryImage(this); } MemoryImage::~MemoryImage() { mApp->RemoveMemoryImage(this); delete [] mBits; delete [] mNativeAlphaData; delete [] mRLAlphaData; delete [] mRLAdditiveData; delete [] mColorIndices; delete [] mColorTable; } void MemoryImage::Init() { mBits = NULL; mColorTable = NULL; mColorIndices = NULL; mNativeAlphaData = NULL; mRLAlphaData = NULL; mRLAdditiveData = NULL; mHasTrans = false; mHasAlpha = false; mBitsChanged = false; mForcedMode = false; mIsVolatile = false; mD3DData = NULL; mD3DFlags = 0; mBitsChangedCount = 0; mPurgeBits = false; mWantPal = false; mApp->AddMemoryImage(this); } void MemoryImage::BitsChanged() { mBitsChanged = true; mBitsChangedCount++; delete [] mNativeAlphaData; mNativeAlphaData = NULL; delete [] mRLAlphaData; mRLAlphaData = NULL; delete [] mRLAdditiveData; mRLAdditiveData = NULL; // Verify secret value at end to protect against overwrite if (mBits != NULL) { assert(mBits[mWidth*mHeight] == MEMORYCHECK_ID); } } void MemoryImage::NormalDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { double aMinX = std::min(theStartX, theEndX); double aMinY = std::min(theStartY, theEndY); double aMaxX = std::max(theStartX, theEndX); double aMaxY =std::max(theStartY, theEndY); uint32_t aRMask = 0xFF0000; uint32_t aGMask = 0x00FF00; uint32_t aBMask = 0x0000FF; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; uint32_t *aSurface = GetBits(); //FIXME if (true)//(mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 32) { if (theColor.mAlpha == 255) { uint32_t aColor = 0xFF000000 | ((((theColor.mRed * aRMask) + aRRoundAdd) >> 8) & aRMask) | ((((theColor.mGreen * aGMask) + aGRoundAdd) >> 8) & aGMask) | ((((theColor.mBlue * aBMask) + aBRoundAdd) >> 8) & aBMask); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mWidth; int aRowAdd = aRowWidth;; if (abs((int)dv) < abs((int)dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; *aDestPixels = aColor; aDestPixels++; aCurY = (int)theStartY; aCurX = (int)theStartX + 1; G = 2 * (int)(dv - dh); DeltaG1 = 2 * (int)(dv - dh); DeltaG2 = 2 * (int)dv; G += DeltaG2 * (int)(((int)theStartY - (int) theStartY)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurX++; aDestPixels++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; *aDestPixels = aColor; aDestPixels += aRowAdd; aCurX = (int)theStartX; aCurY = (int)theStartY + 1; G = 2 * (int)(dh - dv); minG = maxG = G; DeltaG1 = 2 * (int)( dh - dv ); DeltaG2 = 2 * (int)dh; G += DeltaG2 * (int)(((int)theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurY++; aDestPixels += aRowAdd; } } } else { uint32_t src = 0xFF000000 | ((((((theColor.mRed * theColor.mAlpha + 0x80) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask) | ((((((theColor.mGreen * theColor.mAlpha + 0x80) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) | ((((((theColor.mBlue * theColor.mAlpha + 0x80) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask); int oma = 256 - theColor.mAlpha; double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mWidth; int aRowAdd = aRowWidth; if (abs((int)dv) < abs((int)dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY = (int)theStartY; aCurX = (int)theStartX + 1; G = 2 * (int)(dv - dh); DeltaG1 = 2 * (int)(dv - dh); DeltaG2 = 2 * (int)dv; G += DeltaG2 * (int)(((int)theStartX - (int) theStartX)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aDestPixels += aRowAdd; aCurX = (int)theStartX; aCurY = (int)theStartY + 1; G = 2 * (int)(dh - dv); minG = maxG = G; DeltaG1 = 2 * (int)( dh - dv ); DeltaG2 = 2 * (int)dh; G += DeltaG2 * (int)(((int)theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY++; aDestPixels += aRowAdd; } } } } } void MemoryImage::AdditiveDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { double aMinX = std::min(theStartX, theEndX); double aMinY = std::min(theStartY, theEndY); double aMaxX =std::max(theStartX, theEndX); double aMaxY = std::max(theStartY, theEndY); uint32_t aRMask = 0xFF0000; uint32_t aGMask = 0x00FF00; uint32_t aBMask = 0x0000FF; int aRedShift = 16; int aGreenShift = 8; int aBlueShift = 0; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; uchar* aMaxTable = mApp->mAdd8BitMaxTable; uint32_t *aSurface = GetBits(); if (true)//(mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 32) { uint32_t rc = ((theColor.mRed * theColor.mAlpha) / 255); uint32_t gc = ((theColor.mGreen * theColor.mAlpha) / 255); uint32_t bc = ((theColor.mBlue * theColor.mAlpha) / 255); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mWidth; int aRowAdd = aRowWidth; if (abs((int)dv) < abs((int)dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; int r = aMaxTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = 0xFF000000 | (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY = (int)theStartY; aCurX = (int)theStartX + 1; G = 2 * (int)(dv - dh); DeltaG1 = 2 * (int)(dv - dh); DeltaG2 = 2 * (int)dv; while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = 0xFF000000 | (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) aSurface) + ((int) theStartY * mWidth) + (int) theStartX; uint32_t dest = *aDestPixels; int r = aMaxTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = 0xFF000000 | (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aDestPixels += aRowAdd; aCurX = (int)theStartX; aCurY = (int)theStartY + 1; G = 2 * (int)(dh - dv); minG = maxG = G; DeltaG1 = 2 * (int)( dh - dv ); DeltaG2 = 2 * (int)dh; while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = 0xFF000000 | (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY++; aDestPixels += aRowAdd; } } } } void MemoryImage::DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { if (theStartY == theEndY) { //FIXME is this correct or should it be the min on ints? int aStartX = (int)std::min(theStartX, theEndX); int aEndX = (int)std::max(theStartX, theEndX); FillRect(Rect(aStartX, (int)theStartY, aEndX-aStartX+1, (int)theEndY-(int)theStartY+1), theColor, theDrawMode); return; } else if (theStartX == theEndX) { //FIXME is this correct or should it be the min on ints? int aStartY = (int)std::min(theStartY, theEndY); int aEndY = (int)std::max(theStartY, theEndY); FillRect(Rect((int)theStartX, aStartY, (int)theEndX-(int)theStartX+1, aEndY-aStartY+1), theColor, theDrawMode); return; } switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalDrawLine(theStartX, theStartY, theEndX, theEndY, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveDrawLine(theStartX, theStartY, theEndX, theEndY, theColor); break; } BitsChanged(); } void MemoryImage::NormalDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { uint32_t* aBits = GetBits(); uint32_t color = theColor.ToInt(); int aX0 = (int)theStartX, aX1 = (int)theEndX; int aY0 = (int)theStartY, aY1 = (int)theEndY; int aXinc = 1; if (aY0 > aY1) { int aTempX = aX0, aTempY = aY0; aX0 = aX1; aY0 = aY1; aX1 = aTempX; aY1 = aTempY; double aTempXd = theStartX, aTempYd = theStartY; theStartX = theEndX; theStartY = theEndY; theEndX = aTempXd; theEndY = aTempYd; } int dx = aX1 - aX0; int dy = aY1 - aY0; double dxd = theEndX - theStartX; double dyd = theEndY - theStartY; if (dx < 0) { dx = -dx; aXinc = -1; dxd = -dxd; } if (theColor.mAlpha != 255) { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #define BLEND_PIXEL(p) \ {\ int aDestAlpha = dest >> 24;\ int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255;\ a = 255 * a / aNewDestAlpha;\ oma = 256 - a;\ *(p) = (aNewDestAlpha << 24) |\ ((((color & 0xFF0000) * a + (dest & 0xFF0000) * oma) >> 8) & 0xFF0000) |\ ((((color & 0x00FF00) * a + (dest & 0x00FF00) * oma) >> 8) & 0x00FF00) |\ ((((color & 0x0000FF) * a + (dest & 0x0000FF) * oma) >> 8) & 0x0000FF);\ } const int STRIDE = mWidth; #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } else { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (w) #define BLEND_PIXEL(p) \ {\ int aDestAlpha = dest >> 24;\ int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255;\ a = 255 * a / aNewDestAlpha;\ oma = 256 - a;\ *(p) = (aNewDestAlpha << 24) |\ ((((color & 0xFF0000) * a + (dest & 0xFF0000) * oma) >> 8) & 0xFF0000) |\ ((((color & 0x00FF00) * a + (dest & 0x00FF00) * oma) >> 8) & 0x00FF00) |\ ((((color & 0x0000FF) * a + (dest & 0x0000FF) * oma) >> 8) & 0x0000FF);\ } const int STRIDE = mWidth; #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } BitsChanged(); } void MemoryImage::AdditiveDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { } void MemoryImage::DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { if (theStartY == theEndY) { //FIXME is this correct or should it be the min on ints? int aStartX = (int)std::min(theStartX, theEndX); int aEndX =(int)std:: max(theStartX, theEndX); FillRect(Rect(aStartX, (int)theStartY, aEndX-aStartX+1, (int)theEndY-(int)theStartY+1), theColor, theDrawMode); return; } else if (theStartX == theEndX) { //FIXME is this correct or should it be the min on ints? int aStartY = (int)std::min(theStartY, theEndY); int aEndY = (int)std::max(theStartY, theEndY); FillRect(Rect((int)theStartX, aStartY, (int)theEndX-(int)theStartX+1, aEndY-aStartY+1), theColor, theDrawMode); return; } switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalDrawLineAA(theStartX, theStartY, theEndX, theEndY, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveDrawLineAA(theStartX, theStartY, theEndX, theEndY, theColor); break; } BitsChanged(); } void MemoryImage::CommitBits() { //if (gDebug) // mApp->CopyToClipboard("+MemoryImage::CommitBits"); if ((mBitsChanged) && (!mForcedMode)) { // Analyze if (mBits != NULL) { mHasTrans = false; mHasAlpha = false; int aSize = mWidth*mHeight; uint32_t* ptr = mBits; for (int i = 0; i < aSize; i++) { uchar anAlpha = (uchar) (*ptr++ >> 24); if (anAlpha == 0) mHasTrans = true; else if (anAlpha != 255) mHasAlpha = true; } } else if (mColorTable != NULL) { mHasTrans = false; mHasAlpha = false; int aSize = 256; uint32_t* ptr = mColorTable; for (int i = 0; i < aSize; i++) { uchar anAlpha = (uchar) (*ptr++ >> 24); if (anAlpha == 0) mHasTrans = true; else if (anAlpha != 255) mHasAlpha = true; } } else { mHasTrans = true; mHasAlpha = false; } mBitsChanged = false; } //if (gDebug) // mApp->CopyToClipboard("-MemoryImage::CommitBits"); } void MemoryImage::SetImageMode(bool hasTrans, bool hasAlpha) { mForcedMode = true; mHasTrans = hasTrans; mHasAlpha = hasAlpha; } void MemoryImage::SetVolatile(bool isVolatile) { mIsVolatile = isVolatile; } void* MemoryImage::GetNativeAlphaData(NativeDisplay *theDisplay) { if (mNativeAlphaData != NULL) return mNativeAlphaData; CommitBits(); const int rRightShift = 16 + (8-theDisplay->mRedBits); const int gRightShift = 8 + (8-theDisplay->mGreenBits); const int bRightShift = 0 + (8-theDisplay->mBlueBits); const int rLeftShift = theDisplay->mRedShift; const int gLeftShift = theDisplay->mGreenShift; const int bLeftShift = theDisplay->mBlueShift; const int rMask = theDisplay->mRedMask; const int gMask = theDisplay->mGreenMask; const int bMask = theDisplay->mBlueMask; if (mColorTable == NULL) { uint32_t* aSrcPtr = GetBits(); uint32_t* anAlphaData = new uint32_t[mWidth*mHeight]; uint32_t* aDestPtr = anAlphaData; int aSize = mWidth*mHeight; for (int i = 0; i < aSize; i++) { uint32_t val = *(aSrcPtr++); int anAlpha = val >> 24; uint32_t r = ((val & 0xFF0000) * (anAlpha+1)) >> 8; uint32_t g = ((val & 0x00FF00) * (anAlpha+1)) >> 8; uint32_t b = ((val & 0x0000FF) * (anAlpha+1)) >> 8; *(aDestPtr++) = (((r >> rRightShift) << rLeftShift) & rMask) | (((g >> gRightShift) << gLeftShift) & gMask) | (((b >> bRightShift) << bLeftShift) & bMask) | (anAlpha << 24); } mNativeAlphaData = anAlphaData; } else { uint32_t* aSrcPtr = mColorTable; uint32_t* anAlphaData = new uint32_t[256]; for (int i = 0; i < 256; i++) { uint32_t val = *(aSrcPtr++); int anAlpha = val >> 24; uint32_t r = ((val & 0xFF0000) * (anAlpha+1)) >> 8; uint32_t g = ((val & 0x00FF00) * (anAlpha+1)) >> 8; uint32_t b = ((val & 0x0000FF) * (anAlpha+1)) >> 8; anAlphaData[i] = (((r >> rRightShift) << rLeftShift) & rMask) | (((g >> gRightShift) << gLeftShift) & gMask) | (((b >> bRightShift) << bLeftShift) & bMask) | (anAlpha << 24); } mNativeAlphaData = anAlphaData; } return mNativeAlphaData; } uchar* MemoryImage::GetRLAlphaData() { CommitBits(); if (mRLAlphaData == NULL) { mRLAlphaData = new uchar[mWidth*mHeight]; if (mColorTable == NULL) { uint32_t* aSrcPtr; if (mNativeAlphaData != NULL) aSrcPtr = (uint32_t*) mNativeAlphaData; else aSrcPtr = GetBits(); #define NEXT_SRC_COLOR (*(aSrcPtr++)) #include "MI_GetRLAlphaData.inc" #undef NEXT_SRC_COLOR } else { uchar* aSrcPtr = mColorIndices; uint32_t* aColorTable = mColorTable; #define NEXT_SRC_COLOR (aColorTable[*(aSrcPtr++)]) #include "MI_GetRLAlphaData.inc" #undef NEXT_SRC_COLOR } } return mRLAlphaData; } uchar* MemoryImage::GetRLAdditiveData(NativeDisplay *theNative) { if (mRLAdditiveData == NULL) { if (mColorTable == NULL) { uint32_t* aBits = (uint32_t*) GetNativeAlphaData(theNative); mRLAdditiveData = new uchar[mWidth*mHeight]; uchar* aWPtr = mRLAdditiveData; uint32_t* aRPtr = aBits; if (mWidth==1) { memset(aWPtr,1,mHeight); } else { for (int aRow = 0; aRow < mHeight; aRow++) { int aRCount = 1; int aRLCount = 1; int aLastAClass = (((*aRPtr++) & 0xFFFFFF) != 0) ? 1 : 0; while (aRCount < mWidth) { aRCount++; int aThisAClass = (((*aRPtr++) & 0xFFFFFF) != 0) ? 1 : 0; if ((aThisAClass != aLastAClass) || (aRCount == mWidth)) { if (aThisAClass == aLastAClass) aRLCount++; for (int i = aRLCount; i > 0; i--) { if (i >= 255) *aWPtr++ = 255; else *aWPtr++ = i; } if ((aRCount == mWidth) && (aThisAClass != aLastAClass)) *aWPtr++ = 1; aLastAClass = aThisAClass; aRLCount = 1; } else { aRLCount++; } } } } } else { uint32_t* aNativeColorTable = (uint32_t*) GetNativeAlphaData(theNative); mRLAdditiveData = new uchar[mWidth*mHeight]; uchar* aWPtr = mRLAdditiveData; uchar* aRPtr = mColorIndices; if (mWidth==1) { memset(aWPtr,1,mHeight); } else { for (int aRow = 0; aRow < mHeight; aRow++) { int aRCount = 1; int aRLCount = 1; int aLastAClass = (((aNativeColorTable[*aRPtr++]) & 0xFFFFFF) != 0) ? 1 : 0; while (aRCount < mWidth) { aRCount++; int aThisAClass = (((aNativeColorTable[*aRPtr++]) & 0xFFFFFF) != 0) ? 1 : 0; if ((aThisAClass != aLastAClass) || (aRCount == mWidth)) { if (aThisAClass == aLastAClass) aRLCount++; for (int i = aRLCount; i > 0; i--) { if (i >= 255) *aWPtr++ = 255; else *aWPtr++ = i; } if ((aRCount == mWidth) && (aThisAClass != aLastAClass)) *aWPtr++ = 1; aLastAClass = aThisAClass; aRLCount = 1; } else { aRLCount++; } } } } } } return mRLAdditiveData; } void MemoryImage::PurgeBits() { mPurgeBits = true; if (mApp->Is3DAccelerated()) { // Due to potential D3D threading issues we have to defer the texture creation // and therefore the actual purging if (mD3DData == NULL) return; } else { if ((mBits == NULL) && (mColorIndices == NULL)) return; GetNativeAlphaData(gSexyAppBase->mDDInterface); } delete [] mBits; mBits = NULL; if (mD3DData != NULL) { delete [] mColorIndices; mColorIndices = NULL; delete [] mColorTable; mColorTable = NULL; } } void MemoryImage::DeleteSWBuffers() { if ((mBits == NULL) && (mColorIndices == NULL)) GetBits(); delete [] mNativeAlphaData; mNativeAlphaData = NULL; delete [] mRLAdditiveData; mRLAdditiveData = NULL; delete [] mRLAlphaData; mRLAlphaData = NULL; } void MemoryImage::Delete3DBuffers() { #if 0 mApp->Remove3DData(this); #endif } void MemoryImage::DeleteExtraBuffers() { DeleteSWBuffers(); Delete3DBuffers(); } void MemoryImage::ReInit() { // Fix any un-palletizing if (mWantPal) Palletize(); if (mPurgeBits) PurgeBits(); } void MemoryImage::DeleteNativeData() { if ((mBits == NULL) && (mColorIndices == NULL)) GetBits(); // We need to keep the bits around delete [] mNativeAlphaData; mNativeAlphaData = NULL; delete [] mRLAdditiveData; mRLAdditiveData = NULL; } void MemoryImage::SetBits(uint32_t* theBits, int theWidth, int theHeight, bool commitBits) { if (theBits != mBits) { delete [] mColorIndices; mColorIndices = NULL; delete [] mColorTable; mColorTable = NULL; if (theWidth != mWidth || theHeight != mHeight) { delete [] mBits; mBits = new uint32_t[theWidth*theHeight + 1]; mWidth = theWidth; mHeight = theHeight; } memcpy(mBits, theBits, mWidth*mHeight*sizeof(uint32_t)); mBits[mWidth*mHeight] = MEMORYCHECK_ID; BitsChanged(); if (commitBits) CommitBits(); } } void MemoryImage::Create(int theWidth, int theHeight) { delete [] mBits; mBits = NULL; mWidth = theWidth; mHeight = theHeight; // All zeros --> trans + alpha mHasTrans = true; mHasAlpha = true; BitsChanged(); } uint32_t* MemoryImage::GetBits() { if (mBits == NULL) { int aSize = mWidth*mHeight; mBits = new uint32_t[aSize+1]; mBits[aSize] = MEMORYCHECK_ID; if (mColorTable != NULL) { for (int i = 0; i < aSize; i++) mBits[i] = mColorTable[mColorIndices[i]]; delete [] mColorIndices; mColorIndices = NULL; delete [] mColorTable; mColorTable = NULL; delete [] mNativeAlphaData; mNativeAlphaData = NULL; } else if (mNativeAlphaData != NULL) { NativeDisplay* aDisplay = gSexyAppBase->mDDInterface; const int rMask = aDisplay->mRedMask; const int gMask = aDisplay->mGreenMask; const int bMask = aDisplay->mBlueMask; const int rLeftShift = aDisplay->mRedShift + (aDisplay->mRedBits); const int gLeftShift = aDisplay->mGreenShift + (aDisplay->mGreenBits); const int bLeftShift = aDisplay->mBlueShift + (aDisplay->mBlueBits); uint32_t* aDestPtr = mBits; uint32_t* aSrcPtr = mNativeAlphaData; int aSize = mWidth*mHeight; for (int i = 0; i < aSize; i++) { uint32_t val = *(aSrcPtr++); int anAlpha = val >> 24; uint32_t r = (((((val & rMask) << 8) / (anAlpha+1)) & rMask) << 8) >> rLeftShift; uint32_t g = (((((val & gMask) << 8) / (anAlpha+1)) & gMask) << 8) >> gLeftShift; uint32_t b = (((((val & bMask) << 8) / (anAlpha+1)) & bMask) << 8) >> bLeftShift; *(aDestPtr++) = (r << 16) | (g << 8) | (b) | (anAlpha << 24); } } else if ((mD3DData == NULL) || (!mApp->mDDInterface->mD3DInterface->RecoverBits(this))) { memset(mBits, 0, aSize*sizeof(uint32_t)); } } return mBits; } void MemoryImage::FillRect(const Rect& theRect, const Color& theColor, int theDrawMode) { uint32_t src = theColor.ToInt(); uint32_t* aBits = GetBits(); int oldAlpha = src >> 24; if (oldAlpha == 0xFF) { for (int aRow = theRect.mY; aRow < theRect.mY+theRect.mHeight; aRow++) { uint32_t* aDestPixels = &aBits[aRow*mWidth+theRect.mX]; for (int i = 0; i < theRect.mWidth; i++) *aDestPixels++ = src; } } else { for (int aRow = theRect.mY; aRow < theRect.mY+theRect.mHeight; aRow++) { uint32_t* aDestPixels = &aBits[aRow*mWidth+theRect.mX]; for (int i = 0; i < theRect.mWidth; i++) { uint32_t dest = *aDestPixels; int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * oldAlpha) / 255; int newAlpha = 255 * oldAlpha / aNewDestAlpha; int oma = 256 - newAlpha; #ifdef OPTIMIZE_SOFTWARE_DRAWING *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0xFF00FF) * oma + (src & 0xFF00FF) * newAlpha) >> 8) & 0xFF00FF) | ((((dest & 0x00FF00) * oma + (src & 0x00FF00) * newAlpha) >> 8) & 0x00FF00); #else *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * newAlpha) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * newAlpha) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((src & 0xFF0000) * newAlpha) >> 8) & 0xFF0000); #endif } } } BitsChanged(); } void MemoryImage::ClearRect(const Rect& theRect) { uint32_t* aBits = GetBits(); for (int aRow = theRect.mY; aRow < theRect.mY+theRect.mHeight; aRow++) { uint32_t* aDestPixels = &aBits[aRow*mWidth+theRect.mX]; for (int i = 0; i < theRect.mWidth; i++) *aDestPixels++ = 0; } BitsChanged(); } void MemoryImage::Clear() { uint32_t* ptr = GetBits(); if (ptr != NULL) { for (int i = 0; i < mWidth*mHeight; i++) *ptr++ = 0; BitsChanged(); } } void MemoryImage::AdditiveBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor) { theImage->mDrawn = true; MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); uchar* aMaxTable = mApp->mAdd8BitMaxTable; if (aSrcMemoryImage != NULL) { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aSrcMemoryImage->GetBits(); #define NEXT_SRC_COLOR (*(aSrcPtr++)) #define SRC_TYPE uint32_t #include "MI_AdditiveBlt.inc" #undef NEXT_SRC_COLOR #undef SRC_TYPE } else { uint32_t* aColorTable = aSrcMemoryImage->mColorTable; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define NEXT_SRC_COLOR (aColorTable[*(aSrcPtr++)]) #define SRC_TYPE uchar #include "MI_AdditiveBlt.inc" #undef NEXT_SRC_COLOR #undef SRC_TYPE } BitsChanged(); } } void MemoryImage::NormalBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor) { theImage->mDrawn = true; MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); if (aSrcMemoryImage != NULL) { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aSrcMemoryImage->GetBits()) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; #define NEXT_SRC_COLOR (*(aSrcPtr++)) #define READ_SRC_COLOR (*(aSrcPtr)) #define EACH_ROW uint32_t* aSrcPtr = aSrcPixelsRow #include "MI_NormalBlt.inc" #undef NEXT_SRC_COLOR #undef READ_SRC_COLOR #undef EACH_ROW } else { uint32_t* aColorTable = aSrcMemoryImage->mColorTable; uchar* aSrcPixelsRow = aSrcMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; #define NEXT_SRC_COLOR (aColorTable[*(aSrcPtr++)]) #define READ_SRC_COLOR (aColorTable[*(aSrcPtr)]) #define EACH_ROW uchar* aSrcPtr = aSrcPixelsRow #include "MI_NormalBlt.inc" #undef NEXT_SRC_COLOR #undef READ_SRC_COLOR #undef EACH_ROW } BitsChanged(); } } void MemoryImage::Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; assert((theColor.mRed >= 0) && (theColor.mRed <= 255)); assert((theColor.mGreen >= 0) && (theColor.mGreen <= 255)); assert((theColor.mBlue >= 0) && (theColor.mBlue <= 255)); assert((theColor.mAlpha >= 0) && (theColor.mAlpha <= 255)); switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalBlt(theImage, theX, theY, theSrcRect, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveBlt(theImage, theX, theY, theSrcRect, theColor); break; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void MemoryImage::BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; BltRotated(theImage,theX,theY,theSrcRect,theClipRect,theColor,theDrawMode,0,0,0); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool MemoryImage::BltRotatedClipHelper(float &theX, float &theY, const Rect &theSrcRect, const Rect &theClipRect, double theRot, FRect &theDestRect, float theRotCenterX, float theRotCenterY) { // Clipping Code (this used to be in Graphics::DrawImageRotated) float aCos = cosf(theRot); float aSin = sinf(theRot); // Map the four corners and find the bounding rectangle float px[4] = { 0, theSrcRect.mWidth, theSrcRect.mWidth, 0 }; float py[4] = { 0, 0, theSrcRect.mHeight, theSrcRect.mHeight }; float aMinX = 10000000; float aMaxX = -10000000; float aMinY = 10000000; float aMaxY = -10000000; for (int i=0; i<4; i++) { float ox = px[i] - theRotCenterX; float oy = py[i] - theRotCenterY; px[i] = (theRotCenterX + ox*aCos + oy*aSin) + theX; py[i] = (theRotCenterY + oy*aCos - ox*aSin) + theY; if (px[i] < aMinX) aMinX = px[i]; if (px[i] > aMaxX) aMaxX = px[i]; if (py[i] < aMinY) aMinY = py[i]; if (py[i] > aMaxY) aMaxY = py[i]; } FRect aClipRect(theClipRect.mX,theClipRect.mY,theClipRect.mWidth,theClipRect.mHeight); FRect aDestRect = FRect(aMinX, aMinY, aMaxX-aMinX, aMaxY-aMinY).Intersection(aClipRect); if ((aDestRect.mWidth <= 0) || (aDestRect.mHeight <= 0)) // nothing to draw return false; theDestRect = aDestRect; return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool MemoryImage::StretchBltClipHelper(const Rect &theSrcRect, const Rect &theClipRect, const Rect &theDestRect, FRect &theSrcRectOut, Rect &theDestRectOut) { theDestRectOut = Rect(theDestRect.mX , theDestRect.mY, theDestRect.mWidth, theDestRect.mHeight).Intersection(theClipRect); double aXFactor = theSrcRect.mWidth / (double) theDestRect.mWidth; double aYFactor = theSrcRect.mHeight / (double) theDestRect.mHeight; theSrcRectOut = FRect(theSrcRect.mX + (theDestRectOut.mX - theDestRect.mX)*aXFactor, theSrcRect.mY + (theDestRectOut.mY - theDestRect.mY)*aYFactor, theSrcRect.mWidth + (theDestRectOut.mWidth - theDestRect.mWidth)*aXFactor, theSrcRect.mHeight + (theDestRectOut.mHeight - theDestRect.mHeight)*aYFactor); return theSrcRectOut.mWidth>0 && theSrcRectOut.mHeight>0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool MemoryImage::StretchBltMirrorClipHelper(const Rect &theSrcRect, const Rect &theClipRect, const Rect &theDestRect, FRect &theSrcRectOut, Rect &theDestRectOut) { theDestRectOut = Rect(theDestRect.mX, theDestRect.mY, theDestRect.mWidth, theDestRect.mHeight).Intersection(theClipRect); double aXFactor = theSrcRect.mWidth / (double) theDestRect.mWidth; double aYFactor = theSrcRect.mHeight / (double) theDestRect.mHeight; int aTotalClip = theDestRect.mWidth - theDestRectOut.mWidth; int aLeftClip = theDestRectOut.mX - theDestRect.mX; int aRightClip = aTotalClip-aLeftClip; theSrcRectOut = FRect(theSrcRect.mX + (aRightClip)*aXFactor, theSrcRect.mY + (theDestRectOut.mY - theDestRect.mY)*aYFactor, theSrcRect.mWidth + (theDestRectOut.mWidth - theDestRect.mWidth)*aXFactor, theSrcRect.mHeight + (theDestRectOut.mHeight - theDestRect.mHeight)*aYFactor); return theSrcRectOut.mWidth>0 && theSrcRectOut.mHeight>0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void MemoryImage::BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY) { theImage->mDrawn = true; // This BltRotatedClipHelper clipping used to happen in Graphics::DrawImageRotated FRect aDestRect; if (!BltRotatedClipHelper(theX, theY, theSrcRect, theClipRect, theRot, aDestRect,theRotCenterX,theRotCenterY)) return; MemoryImage* aMemoryImage = dynamic_cast(theImage); uchar* aMaxTable = mApp->mAdd8BitMaxTable; if (aMemoryImage != NULL) { if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aMemoryImage->GetBits() + theSrcRect.mX + theSrcRect.mY*theSrcRect.mWidth; #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) if (theDrawMode == Graphics::DRAWMODE_NORMAL) { #include "MI_BltRotated.inc" } else { #include "MI_BltRotated_Additive.inc" } #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = aMemoryImage->mColorTable; uchar* aSrcBits = aMemoryImage->mColorIndices + theSrcRect.mX + theSrcRect.mY*theSrcRect.mWidth; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) if (theDrawMode == Graphics::DRAWMODE_NORMAL) { #include "MI_BltRotated.inc" } else { #include "MI_BltRotated_Additive.inc" } #undef SRC_TYPE #undef READ_COLOR } BitsChanged(); } } void MemoryImage::SlowStretchBlt(Image* theImage, const Rect& theDestRect, const FRect& theSrcRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; // This thing was a pain to write. I bet i could have gotten something just as good // from some Graphics Gems book. uint32_t* aDestEnd = GetBits() + (mWidth * mHeight); MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); if (aSrcMemoryImage != NULL) { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aSrcMemoryImage->GetBits(); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "MI_SlowStretchBlt.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = aSrcMemoryImage->mColorTable; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "MI_SlowStretchBlt.inc" #undef SRC_TYPE #undef READ_COLOR } BitsChanged(); } } //TODO: Make the special version void MemoryImage::FastStretchBlt(Image* theImage, const Rect& theDestRect, const FRect& theSrcRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); if (aSrcMemoryImage != NULL) { uint32_t* aDestPixelsRow = ((uint32_t*) GetBits()) + (theDestRect.mY * mWidth) + theDestRect.mX; uint32_t* aSrcPixelsRow = (uint32_t*) aSrcMemoryImage->GetBits();; double aSrcY = theSrcRect.mY; double anAddX = theSrcRect.mWidth / theDestRect.mWidth; double anAddY = theSrcRect.mHeight / theDestRect.mHeight; if (theColor == Color::White) { for (int y = 0; y < theDestRect.mHeight; y++) { double aSrcX = theSrcRect.mX; uint32_t* aDestPixels = aDestPixelsRow; for (int x = 0; x < theDestRect.mWidth; x++) { aSrcX += anAddX; uint32_t* aSrcPixels = aSrcPixelsRow + ((int) aSrcX) + (aSrcMemoryImage->mWidth * ((int) aSrcY)); uint32_t src = *aSrcPixels; uint32_t dest = *aDestPixels; int a = src >> 24; if (a != 0) { int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; int oma = 256 - a; *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0x0000FF) * oma) >> 8) + (((src & 0x0000FF) * a) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma) >> 8) + (((src & 0x00FF00) * a) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma) >> 8) + (((src & 0xFF0000) * a) >> 8) & 0xFF0000); } else aDestPixels++; } aDestPixelsRow += mWidth; aSrcY += anAddY; } } else { } } BitsChanged(); } void MemoryImage::StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch) { theImage->mDrawn = true; Rect aDestRect; FRect aSrcRect; if (!StretchBltClipHelper(theSrcRect, theClipRect, theDestRect, aSrcRect, aDestRect)) return; if (fastStretch) FastStretchBlt(theImage, aDestRect, aSrcRect, theColor, theDrawMode); else SlowStretchBlt(theImage, aDestRect, aSrcRect, theColor, theDrawMode); } void MemoryImage::BltMatrixHelper(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, void *theSurface, int theBytePitch, int thePixelFormat, bool blend) { MemoryImage *anImage = dynamic_cast(theImage); if (anImage==NULL) return; float w2 = theSrcRect.mWidth/2.0f; float h2 = theSrcRect.mHeight/2.0f; float u0 = (float)theSrcRect.mX/theImage->mWidth; float u1 = (float)(theSrcRect.mX + theSrcRect.mWidth)/theImage->mWidth; float v0 = (float)theSrcRect.mY/theImage->mHeight; float v1 = (float)(theSrcRect.mY + theSrcRect.mHeight)/theImage->mHeight; SWHelper::XYZStruct aVerts[4] = { { -w2, -h2, u0, v0, 0xFFFFFFFF }, { w2, -h2, u1, v0, 0xFFFFFFFF }, { -w2, h2, u0, v1, 0xFFFFFFFF }, { w2, h2, u1, v1, 0xFFFFFFFF } }; for (int i=0; i<4; i++) { SexyVector3 v(aVerts[i].mX, aVerts[i].mY, 1); v = theMatrix*v; aVerts[i].mX = v.x + x - 0.5f; aVerts[i].mY = v.y + y - 0.5f; } SWHelper::SWDrawShape(aVerts, 4, anImage, theColor, theDrawMode, theClipRect, theSurface, theBytePitch, thePixelFormat, blend,false); } void MemoryImage::BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend) { theImage->mDrawn = true; uint32_t *aSurface = GetBits(); int aPitch = mWidth*4; int aFormat = 0x8888; if (mForcedMode && !mHasAlpha && !mHasTrans) aFormat = 0x888; BltMatrixHelper(theImage,x,y,theMatrix,theClipRect,theColor,theDrawMode,theSrcRect,aSurface,aPitch,aFormat,blend); BitsChanged(); } void MemoryImage::BltTrianglesTexHelper(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect &theClipRect, const Color &theColor, int theDrawMode, void *theSurface, int theBytePitch, int thePixelFormat, float tx, float ty, bool blend) { MemoryImage *anImage = dynamic_cast(theTexture); // if (anImage==NULL) // return; int aColor = theColor.ToInt(); for (int i=0; imX - theCoverX; int y = aSpan->mY - theCoverY; uint32_t* aDestPixels = &theBits[aSpan->mY*mWidth + aSpan->mX]; const unsigned char* aCoverBits = &theCoverage[y*theCoverWidth+x]; for (int w = 0; w < aSpan->mWidth; ++w) { int cover = *aCoverBits++ + 1; int a = (cover * theColor.mAlpha) >> 8; int oma; uint32_t dest = *aDestPixels; if (a > 0) { int aDestAlpha = dest >> 24; int aNewDestAlpha = aDestAlpha + ((255 - aDestAlpha) * a) / 255; a = 255 * a / aNewDestAlpha; oma = 256 - a; *(aDestPixels++) = (aNewDestAlpha << 24) | ((((dest & 0x0000FF) * oma + (src & 0x0000FF) * a) >> 8) & 0x0000FF) | ((((dest & 0x00FF00) * oma + (src & 0x00FF00) * a) >> 8) & 0x00FF00) | ((((dest & 0xFF0000) * oma + (src & 0xFF0000) * a) >> 8) & 0xFF0000); } } } BitsChanged(); } void MemoryImage::BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend) { theTexture->mDrawn = true; uint32_t *aSurface = GetBits(); int aPitch = mWidth*4; int aFormat = 0x8888; if (mForcedMode && !mHasAlpha && !mHasTrans) aFormat = 0x888; BltTrianglesTexHelper(theTexture,theVertices,theNumTriangles,theClipRect,theColor,theDrawMode,aSurface,aPitch,aFormat,tx,ty,blend); BitsChanged(); } bool MemoryImage::Palletize() { CommitBits(); if (mColorTable != NULL) return true; GetBits(); if (mBits == NULL) return false; mColorIndices = new uchar[mWidth*mHeight]; mColorTable = new uint32_t[256]; if (!Quantize8Bit(mBits, mWidth, mHeight, mColorIndices, mColorTable)) { delete [] mColorIndices; mColorIndices = NULL; delete [] mColorTable; mColorTable = NULL; mWantPal = false; return false; } delete [] mBits; mBits = NULL; delete [] mNativeAlphaData; mNativeAlphaData = NULL; mWantPal = true; return true; } libtuxcap-1.4.0/tuxcap/lib/DialogButton.cpp0000644000175000017500000000450010641010435020531 0ustar inniyahinniyah#include "DialogButton.h" #if 0 #include "SysFont.h" #endif #include "Font.h" #include "WidgetManager.h" using namespace Sexy; static int gDialogButtonColors[][3] = { {255, 255, 255}, {255, 255, 255}, {0, 0, 0}, {255, 255, 255}, {132, 132, 132}, {212, 212, 212}}; DialogButton::DialogButton(Image* theComponentImage, int theId, ButtonListener* theListener) : ButtonWidget(theId, theListener) { mComponentImage = theComponentImage; mTextOffsetX = mTextOffsetY = 0; mTranslateX = mTranslateY = 1; mDoFinger = true; SetColors(gDialogButtonColors, NUM_COLORS); } void DialogButton::Draw(Graphics* g) { if (mBtnNoDraw) return; if (mComponentImage==NULL) { ButtonWidget::Draw(g); return; } #if 0 if ((mFont == NULL) && (mLabel.length() > 0)) mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 12, true); #endif bool doTranslate = IsButtonDown(); if (mNormalRect.mWidth==0) { if (doTranslate) g->Translate(mTranslateX, mTranslateY); g->DrawImageBox(Rect(0, 0, mWidth, mHeight), mComponentImage); } else { if (mDisabled && (mDisabledRect.mWidth > 0) && (mDisabledRect.mHeight > 0)) g->DrawImageBox(mDisabledRect, Rect(0, 0, mWidth, mHeight), mComponentImage); else if (IsButtonDown()) g->DrawImageBox(mDownRect, Rect(0, 0, mWidth, mHeight), mComponentImage); else if ((mOverAlpha > 0)) { if (mOverAlpha<1) g->DrawImageBox(mNormalRect, Rect(0, 0, mWidth, mHeight), mComponentImage); g->SetColorizeImages(true); g->SetColor(Color(255,255,255,(int)(mOverAlpha * 255))); g->DrawImageBox(mOverRect, Rect(0, 0, mWidth, mHeight), mComponentImage); g->SetColorizeImages(false); } else if(mIsOver) g->DrawImageBox(mOverRect, Rect(0, 0, mWidth, mHeight), mComponentImage); else g->DrawImageBox(mNormalRect, Rect(0, 0, mWidth, mHeight), mComponentImage); if (doTranslate) g->Translate(mTranslateX, mTranslateY); } if (mFont != NULL) { g->SetFont(mFont); if (mIsOver) g->SetColor(mColors[COLOR_LABEL_HILITE]); else g->SetColor(mColors[COLOR_LABEL]); int aFontX = (mWidth - mFont->StringWidth(mLabel))/2; int aFontY = (mHeight + mFont->GetAscent() - mFont->GetAscentPadding() - mFont->GetAscent()/6 - 1)/2; g->DrawString(mLabel, aFontX + mTextOffsetX, aFontY + mTextOffsetY); } if (doTranslate) g->Translate(-mTranslateX, -mTranslateY); } libtuxcap-1.4.0/tuxcap/lib/ParticlePhysicsSystem.cpp0000644000175000017500000001214610737720610022467 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeParticleSystem helper class header ** ** Hacked on by ** ** Kevin Lynx ** James Poag ** W.P. van Paassen */ #include "ParticlePhysicsSystem.h" #include "hgeRandom.h" void ParticlePhysicsSystem::_update(float fDeltaTime) { int i; float ang; hgeParticle *par; hgeVector vecAccel, vecAccel2; if(fAge >= 0) { fAge += fDeltaTime; if(fAge >= info.fLifetime) fAge = -2.0f; } // Play Animation if(mAnimPlaying) _updatePlay(fDeltaTime); // update all alive particles if(bUpdateBoundingBox) rectBoundingBox.Clear(); par=particles; for(i=0; ifAge += fDeltaTime; if(par->fAge >= par->fTerminalAge) { physics->DestroyObject(par->ph_object); nParticlesAlive--; memcpy(par, &particles[nParticlesAlive], sizeof(hgeParticle)); i--; continue; } SexyVector2 pos = par->ph_object->GetPosition(); par->vecLocation.x = pos.x; par->vecLocation.y = pos.y; vecAccel = par->vecLocation-vecLocation; vecAccel.Normalize(); vecAccel2 = vecAccel; vecAccel *= par->fRadialAccel; // vecAccel2.Rotate(M_PI_2); // the following is faster ang = vecAccel2.x; vecAccel2.x = -vecAccel2.y; vecAccel2.y = ang; vecAccel2 *= par->fTangentialAccel; par->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime; par->vecVelocity.y += par->fGravity*fDeltaTime; if (bOldFormat) par->vecLocation += par->vecVelocity; else par->vecLocation += par->vecVelocity * fDeltaTime; par->fSpin += par->fSpinDelta*fDeltaTime; par->fSize += par->fSizeDelta*fDeltaTime; par->colColor += par->colColorDelta*fDeltaTime; //-----use hgeColor if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y); par++; } // generate new particles if(fAge != -2.0f) { float fParticlesNeeded = info.nEmission*fDeltaTime + fEmissionResidue; int nParticlesCreated = (unsigned int)fParticlesNeeded; fEmissionResidue=fParticlesNeeded-nParticlesCreated; par=&particles[nParticlesAlive]; for(i=0; i=MAX_PARTICLES) break; par->fAge = 0.0f; //random par->fTerminalAge = Random_Float(info.fParticleLifeMin, info.fParticleLifeMax); par->vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*Random_Float(0.0f, 1.0f); par->vecLocation.x += Random_Float(-2.0f, 2.0f); par->vecLocation.y += Random_Float(-2.0f, 2.0f); ang=info.fDirection-M_PI_2+Random_Float(0,info.fSpread)-info.fSpread/2.0f; if(info.bRelative) ang += (vecPrevLocation-vecLocation).Angle()+M_PI_2; par->vecVelocity.x = cosf(ang); par->vecVelocity.y = sinf(ang); par->vecVelocity *= Random_Float(info.fSpeedMin, info.fSpeedMax); par->fGravity = Random_Float(info.fGravityMin, info.fGravityMax); par->fRadialAccel = Random_Float(info.fRadialAccelMin, info.fRadialAccelMax); par->fTangentialAccel = Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax); par->fSize = Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar); par->fSizeDelta = (info.fSizeEnd-par->fSize) / par->fTerminalAge; par->fSpin = Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar); par->fSpinDelta = (info.fSpinEnd-par->fSpin) / par->fTerminalAge; ////-----use hgeColor par->colColor.r = Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar); par->colColor.g = Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar); par->colColor.b = Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar); par->colColor.a = Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar); par->colColorDelta.r = (info.colColorEnd.r-par->colColor.r) / par->fTerminalAge; par->colColorDelta.g = (info.colColorEnd.g-par->colColor.g) / par->fTerminalAge; par->colColorDelta.b = (info.colColorEnd.b-par->colColor.b) / par->fTerminalAge; par->colColorDelta.a = (info.colColorEnd.a-par->colColor.a) / par->fTerminalAge; //create physic object par->ph_object = physics->CreateObject(10.0f, physics->ComputeMomentForCircle(1.0f, 0.0f, 2.0f, SexyVector2(0.0f,0.0f))); par->ph_object->SetPosition(SexyVector2(par->vecLocation.x, par->vecLocation.y)); par->ph_object->AddCircleShape(2.0f, SexyVector2(0,0),0.9f,2.5f); par->ph_object->SetVelocity(SexyVector2(par->vecVelocity.x, par->vecVelocity.y)); par->ph_object->SetCollisionType(collision_type); par->ph_object->SetGroup(collision_group); if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y); nParticlesAlive++; par++; } } vecPrevLocation=vecLocation; } libtuxcap-1.4.0/tuxcap/lib/Widget.cpp0000644000175000017500000002605410654427350017405 0ustar inniyahinniyah#include "Widget.h" #include "WidgetManager.h" #include "Graphics.h" #include "Font.h" #include "Image.h" #include "SexyAppBase.h" #if 0 #include "debug.h" #endif using namespace Sexy; bool Widget::mWriteColoredString = true; Widget::Widget() { mWidgetManager = NULL; mVisible = true; mDisabled = false; mIsDown = false; mIsOver = false; mDoFinger = false; mMouseVisible = true; mHasFocus = false; mHasTransparencies = false; mWantsFocus = false; mTabPrev = NULL; mTabNext = NULL; } Widget::~Widget() { mColors.clear(); } void Widget::WidgetRemovedHelper() { if (mWidgetManager==NULL) return; // Call RemovedFromManager on all child widgets and disable them and stuff like that for (WidgetList::iterator aWidgetItr = mWidgets.begin(); aWidgetItr != mWidgets.end(); ++aWidgetItr) { Widget *aWidget = *aWidgetItr; aWidget->WidgetRemovedHelper(); } mWidgetManager->DisableWidget(this); PreModalInfoList::iterator anItr = mWidgetManager->mPreModalInfoList.begin(); while (anItr != mWidgetManager->mPreModalInfoList.end()) { PreModalInfo* aPreModalInfo = &(*anItr); if (aPreModalInfo->mPrevBaseModalWidget == this) aPreModalInfo->mPrevBaseModalWidget = NULL; if (aPreModalInfo->mPrevFocusWidget == this) aPreModalInfo->mPrevFocusWidget = NULL; ++anItr; } RemovedFromManager(mWidgetManager); MarkDirtyFull(this); mWidgetManager = NULL; } void Widget::OrderInManagerChanged() { } bool Widget::IsPointVisible(int x, int y) { return true; } void Widget::SetVisible(bool isVisible) { if (mVisible == isVisible) return; mVisible = isVisible; if (mVisible) MarkDirty(); else MarkDirtyFull(); if (mWidgetManager != NULL) mWidgetManager->RehupMouse(); } void Widget::Draw(Graphics* g) // Already translated { } void Widget::DrawOverlay(Graphics* g) { } void Widget::DrawOverlay(Graphics* g, int thePriority) { DrawOverlay(g); } void Widget::SetColors(int theColors[][3], int theNumColors) { mColors.clear(); for (int i = 0; i < theNumColors; i++) SetColor(i, Color(theColors[i][0], theColors[i][1], theColors[i][2])); MarkDirty(); } void Widget::SetColors(int theColors[][4], int theNumColors) { mColors.clear(); for (int i = 0; i < theNumColors; i++) SetColor(i, Color(theColors[i][0], theColors[i][1], theColors[i][2], theColors[i][3])); MarkDirty(); } void Widget::SetColor(int theIdx, const Color& theColor) { if (theIdx >= (int)mColors.size()) mColors.resize(theIdx + 1); mColors[theIdx] = theColor; MarkDirty(); } const Color& Widget::GetColor(int theIdx) { static Color aColor; if (theIdx < (int) mColors.size()) return mColors[theIdx]; return aColor; } Color Widget::GetColor(int theIdx, const Color& theDefaultColor) { if (theIdx < (int) mColors.size()) return mColors[theIdx]; return theDefaultColor; } void Widget::Resize(int theX, int theY, int theWidth, int theHeight) { if ((mX == theX) && (mY == theY) && (mWidth == theWidth) && (mHeight == theHeight)) return; // Mark everything dirty that is over or under the old position MarkDirtyFull(); mX = theX; mY = theY; mWidth = theWidth; mHeight = theHeight; // Mark things dirty that are over the new position MarkDirty(); if (mWidgetManager != NULL) mWidgetManager->RehupMouse(); } void Widget::Resize(const Rect& theRect) { Resize(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } void Widget::Move(int theNewX, int theNewY) { Resize(theNewX, theNewY, mWidth, mHeight); } bool Widget::WantsFocus() { return mWantsFocus; } void Widget::SetDisabled(bool isDisabled) { if (mDisabled == isDisabled) return; mDisabled = isDisabled; if ((isDisabled) && (mWidgetManager != NULL)) mWidgetManager->DisableWidget(this); MarkDirty(); // Incase a widget is enabled right under our cursor if ((!isDisabled) && (mWidgetManager != NULL) && (Contains(mWidgetManager->mLastMouseX, mWidgetManager->mLastMouseY))) mWidgetManager->MousePosition(mWidgetManager->mLastMouseX, mWidgetManager->mLastMouseY); } void Widget::GotFocus() { mHasFocus = true; } void Widget::LostFocus() { mHasFocus = false; } void Widget::Update() { WidgetContainer::Update(); } void Widget::UpdateF(float theFrac) { } void Widget::KeyChar(SexyChar theChar) { } void Widget::KeyDown(KeyCode theKey) { if (theKey == SDLK_TAB) { if (mWidgetManager->mKeyDown[SDLK_RSHIFT] || mWidgetManager->mKeyDown[SDLK_LSHIFT]) { if (mTabPrev != NULL) mWidgetManager->SetFocus(mTabPrev); } else { if (mTabNext != NULL) mWidgetManager->SetFocus(mTabNext); } } } void Widget::KeyUp(KeyCode theKey) { } void Widget::ShowFinger(bool on) { if (mWidgetManager == NULL) return; if (on) mWidgetManager->mApp->SetCursor(CURSOR_HAND); else mWidgetManager->mApp->SetCursor(CURSOR_POINTER); /*if (on) mWidgetManager->mApplet.setCursor(new Cursor(Cursor.HAND_CURSOR)); else mWidgetManager->mApplet.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));*/ } void Widget::MouseEnter() { } void Widget::MouseLeave() { } void Widget::MouseMove(int x, int y) { } void Widget::MouseDown(int x, int y, int theClickCount) { if (theClickCount == 3) MouseDown(x, y, 2, 1); else if (theClickCount >= 0) MouseDown(x, y, 0, theClickCount); else MouseDown(x, y, 1, -theClickCount); } void Widget::MouseDown(int x, int y, int theBtnNum, int theClickCount) { } void Widget::MouseUp(int x, int y) { } void Widget::MouseUp(int x, int y, int theLastDownButtonId) { MouseUp(x, y); if (theLastDownButtonId == 3) MouseUp(x, y, 2, 1); else if (theLastDownButtonId >= 0) MouseUp(x, y, 0, theLastDownButtonId); else MouseUp(x, y, 1, -theLastDownButtonId); } void Widget::MouseUp(int x, int y, int theBtnNum, int theClickCount) { } void Widget::MouseDrag(int x, int y) { } void Widget::MouseWheel(int theDelta) { } //////// Helper functions Rect Widget::WriteCenteredLine(Graphics* g, int anOffset, const SexyString& theLine) { Font* aFont = g->GetFont(); int aWidth = aFont->StringWidth(theLine); int aX = (mWidth - aWidth) / 2; g->DrawString(theLine, aX, anOffset); return Rect(aX, anOffset - aFont->GetAscent(), aWidth, aFont->GetHeight()); } Rect Widget::WriteCenteredLine(Graphics* g, int anOffset, const SexyString& theLine, Color theColor1, Color theColor2, const Point& theShadowOffset) { Font* aFont = g->GetFont(); int aWidth = aFont->StringWidth(theLine); int aX = (mWidth - aWidth) / 2; g->SetColor(theColor2); g->DrawString(theLine, (mWidth - aWidth)/2 + theShadowOffset.mX, anOffset + theShadowOffset.mY); g->SetColor(theColor1); g->DrawString(theLine, (mWidth - aWidth)/2, anOffset); // account for shadow in position and size // TODO: this may not be necessary. return Rect( aX + std::min(0,theShadowOffset.mX), anOffset - aFont->GetAscent() + std::min(0,theShadowOffset.mY), aWidth + abs(theShadowOffset.mX), aFont->GetHeight() + abs(theShadowOffset.mY)); } int Widget::WriteString(Graphics* g, const SexyString& theString, int theX, int theY, int theWidth, int theJustification, bool drawString, int theOffset, int theLength) { bool oldColored = g->mWriteColoredString; g->mWriteColoredString = mWriteColoredString; int aXOffset = g->WriteString(theString,theX,theY,theWidth,theJustification,drawString,theOffset,theLength); g->mWriteColoredString = oldColored; return aXOffset; } int Widget::WriteWordWrapped(Graphics* g, const Rect& theRect, const SexyString& theLine, int theLineSpacing, int theJustification) { bool oldColored = g->mWriteColoredString; g->mWriteColoredString = mWriteColoredString; int aReturn = g->WriteWordWrapped(theRect,theLine,theLineSpacing,theJustification); g->mWriteColoredString = oldColored; return aReturn; } int Widget::GetWordWrappedHeight(Graphics* g, int theWidth, const SexyString& theLine, int aLineSpacing) { return g->GetWordWrappedHeight(theWidth,theLine,aLineSpacing); } int Widget::GetNumDigits(int theNumber) { int aDivisor = 10; int aNumDigits = 1; while (theNumber >= aDivisor) { aNumDigits++; aDivisor *= 10; } return aNumDigits; } void Widget::WriteNumberFromStrip(Graphics* g, int theNumber, int theX, int theY, Image* theNumberStrip, int aSpacing) { int aDivisor = 10; int aNumDigits = 1; while (theNumber >= aDivisor) { aNumDigits++; aDivisor *= 10; } if (theNumber == 0) aDivisor = 10; int aDigitLen = theNumberStrip->GetWidth() / 10; for (int aDigitIdx = 0; aDigitIdx < aNumDigits; aDigitIdx++) { aDivisor /= 10; int aDigit = (theNumber / aDivisor) % 10; Graphics* aClipG = g->Create(); aClipG->ClipRect(theX + aDigitIdx*(aDigitLen + aSpacing), theY, aDigitLen, theNumberStrip->GetHeight()); aClipG->DrawImage(theNumberStrip, theX + aDigitIdx*(aDigitLen + aSpacing) - aDigit*aDigitLen, theY); delete aClipG; } } bool Widget::Contains(int theX, int theY) { return ((theX >= mX) && (theX < mX + mWidth) && (theY >= mY) && (theY < mY + mHeight)); } Rect Widget::GetInsetRect() { return Rect(mX + mMouseInsets.mLeft, mY + mMouseInsets.mTop, mWidth - mMouseInsets.mLeft - mMouseInsets.mRight, mHeight - mMouseInsets.mTop - mMouseInsets.mBottom); } void Widget::DeferOverlay(int thePriority) { mWidgetManager->DeferOverlay(this, thePriority); } void Widget::Layout(int theLayoutFlags, Widget *theRelativeWidget, int theLeftPad, int theTopPad, int theWidthPad, int theHeightPad) { int aRelLeft = theRelativeWidget->Left(); int aRelTop = theRelativeWidget->Top(); if (theRelativeWidget==mParent) { aRelLeft = 0; aRelTop = 0; } int aRelWidth = theRelativeWidget->Width(); int aRelHeight = theRelativeWidget->Height(); int aRelRight = aRelLeft + aRelWidth; int aRelBottom = aRelTop + aRelHeight; int aLeft = Left(); int aTop = Top(); int aWidth = Width(); int aHeight = Height(); int aType = 1; while(aType 0x08) { #include "SWTri_TexelARGB.cpp" #if defined(GLOBAL_ARGB) || defined (TEX_ALPHA) || defined(MOD_ARGB) { if (alpha < 0xf0) { unsigned int p = *pix; unsigned int da = p >> 24; unsigned int tr,tg,tb; #if !defined(LINEAR_BLEND) { tr = ((tex&0xFF0000)*alpha)&0xFF000000; tg = ((tex&0x00FF00)*alpha)&0x00FF0000; tb = ((tex&0x0000FF)*alpha)&0x0000FF00; } #else { tr = (tex&0xFF0000)<<8; tg = (tex&0x00FF00)<<8; tb = (tex&0x0000FF)<<8; } #endif unsigned int dr = (((p&0xFF0000)*da)>>8) & 0xFF0000; unsigned int dg = (((p&0x00FF00)*da)>>8) & 0x00FF00; unsigned int db = (((p&0x0000FF)*da)>>8) & 0x0000FF; int finalAlpha = 256 - (((256 - alpha)*(256 - da))>>8); tr = ((tr + (256-alpha)*dr)/finalAlpha) & 0xFF0000; tg = ((tg + (256-alpha)*dg)/finalAlpha) & 0x00FF00; tb = ((tb + (256-alpha)*db)/finalAlpha) & 0x0000FF; *pix = ((finalAlpha-1)<<24) | tr | tg | tb; } else { *pix = tex | 0xFF000000; } } #else { *pix = tex | 0xFF000000; } #endif } } #elif defined(MOD_ARGB) { if (a > 0xf00000) { *pix = 0xFF000000 | ((r)&0xff0000)|((g>>8)&0xff00)|((b>>16)&0xff); } else if (a > 0x080000) { unsigned int p = *pix; unsigned int da = p >> 24; int alpha = a>>16; unsigned int tr = ((r)*(alpha))&0xFF000000; unsigned int tg = ((g>>8)*(alpha))&0x00FF0000; unsigned int tb = ((b>>16)*(alpha))&0x0000FF00; unsigned int dr = (((p&0xFF0000)*da)>>8) & 0xFF0000; unsigned int dg = (((p&0x00FF00)*da)>>8) & 0x00FF00; unsigned int db = (((p&0x0000FF)*da)>>8) & 0x0000FF; int finalAlpha = 256 - (((256 - alpha)*(256 - da))>>8); tr = ((tr + (256-alpha)*dr)/finalAlpha) & 0xFF0000; tg = ((tg + (256-alpha)*dg)/finalAlpha) & 0x00FF00; tb = ((tb + (256-alpha)*db)/finalAlpha) & 0x0000FF; *pix = ((finalAlpha-1)<<24) | tr | tg | tb; } else asm("nop"); } #endif libtuxcap-1.4.0/tuxcap/lib/CMakeLists.txt0000644000175000017500000001776011212654545020221 0ustar inniyahinniyah INCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle ${libtuxcap_SOURCE_DIR}/tuxcap/pycap ) SET (MY_SOURCES Ratio.cpp Buffer.cpp SexyAppBase.cpp MTRand.cpp Common.cpp Color.cpp Insets.cpp SexyMatrix.cpp Font.cpp Image.cpp ImageLib.cpp Graphics.cpp Flags.cpp Quantize.cpp NativeDisplay.cpp MemoryImage.cpp SWTri.cpp D3DInterface.cpp WidgetContainer.cpp WidgetManager.cpp Widget.cpp DescParser.cpp SharedImage.cpp ImageFont.cpp MusicInterface.cpp ButtonWidget.cpp DDImage.cpp DDInterface.cpp ResourceManager.cpp KeyCodes.cpp XMLParser.cpp ListWidget.cpp EditWidget.cpp HyperlinkWidget.cpp ScrollbarWidget.cpp ScrollbuttonWidget.cpp Checkbox.cpp Slider.cpp Dialog.cpp CursorWidget.cpp TextWidget.cpp DialogButton.cpp XMLWriter.cpp PropertiesParser.cpp NaturalCubicSpline.cpp Physics.cpp SDLMixerMusicInterface.cpp SDLMixerSoundManager.cpp SDLMixerSoundInstance.cpp ParticlePhysicsSystem.cpp #FlashWidget.cpp ) SET (CHIPMUNK_SOURCES ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/chipmunk.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpArbiter.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpArray.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpBB.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpBody.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpCollision.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpHashSet.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpJoint.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpPolyShape.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpShape.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpSpace.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpSpaceHash.c ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpVect.c ) SET_SOURCE_FILES_PROPERTIES(${CHIPMUNK_SOURCES} PROPERTIES COMPILE_FLAGS "-ffast-math -std=gnu99" ) SET (HGE_SOURCES ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgeparticle.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgepmanager.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgeRandom.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgerect.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgevector.cpp ) SET_SOURCE_FILES_PROPERTIES(${HGE_SOURCES} PROPERTIES COMPILE_FLAGS "-ffast-math" ) SET (PYCAP_SOURCES ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapApp.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapBoard.cpp ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapResources.cpp ) SET (MY_HEADERS ${libtuxcap_SOURCE_DIR}/tuxcap/include/Buffer.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ButtonListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ButtonWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Checkbox.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/CheckboxListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Color.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Common.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/CursorWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/D3DInterface.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/DDImage.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/DDInterface.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/DescParser.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/DialogButton.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Dialog.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/DialogListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/EditListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/EditWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Flags.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Font.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Graphics.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/HyperlinkWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ImageFont.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Image.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ImageLib.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Insets.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/KeyCodes.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ListListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ListWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/MemoryImage.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/MTRand.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/MusicInterface.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/NativeDisplay.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/NaturalCubicSpline.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Point.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/PropertiesParser.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Quantize.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Ratio.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Rect.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ResourceManager.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ScrollbarWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ScrollbuttonWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ScrollListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SDLMixerMusicInterface.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SDLMixerSoundInstance.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SDLMixerSoundManager.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SexyAppBase.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SexyMatrix.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Physics.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/PhysicsListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SexyVector.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SharedImage.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Slider.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SliderListener.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SoundInstance.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SoundManager.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/SWTri.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/TextWidget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/TriVertex.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/WidgetContainer.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/Widget.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/WidgetManager.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/XMLParser.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/XMLWriter.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/ParticlePhysicsSystem.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/chipmunk.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpArbiter.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpArray.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpBB.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpBody.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpCollision.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpHashSet.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpJoint.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpPolyShape.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpShape.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpSpace.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpSpaceHash.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/cpVect.h ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk/prime.h ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgecolor.h ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgeparticle.h ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgeRandom.h ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgerect.h ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle/hgevector.h ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapApp.h ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapBoard.h ${libtuxcap_SOURCE_DIR}/tuxcap/pycap/PycapResources.h ) IF(AUDIERELIB_FOUND) SET(MY_SOURCES ${MY_SOURCES} AudiereSoundManager.cpp AudiereSoundInstance.cpp AudiereLoader.cpp AudiereMusicInterface.cpp) SET(MY_HEADERS ${MY_HEADERS} ${libtuxcap_SOURCE_DIR}/tuxcap/include/AudiereLoader.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/AudiereMusicInterface.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/AudiereSoundInstance.h ${libtuxcap_SOURCE_DIR}/tuxcap/include/AudiereSoundManager.h ) ENDIF(AUDIERELIB_FOUND) ADD_LIBRARY(tuxcap_static STATIC ${MY_SOURCES} ${CHIPMUNK_SOURCES} ${HGE_SOURCES} ${PYCAP_SOURCES}) ADD_LIBRARY(tuxcap SHARED ${MY_SOURCES} ${CHIPMUNK_SOURCES} ${HGE_SOURCES} ${PYCAP_SOURCES}) SET_TARGET_PROPERTIES(tuxcap PROPERTIES VERSION 4.0 ) SET_TARGET_PROPERTIES(tuxcap_static PROPERTIES PREFIX "lib" SUFFIX ".a" OUTPUT_NAME "tuxcap" ) INSTALL(TARGETS tuxcap tuxcap_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib ) INSTALL(FILES ${MY_HEADERS} DESTINATION include/tuxcap ) libtuxcap-1.4.0/tuxcap/lib/SWTri_Loop.cpp0000644000175000017500000000213311202747627020155 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. int64_t subTex = x0 - lx; unsigned int u, v, r, g, b, a; #if defined(MOD_ARGB) a = la + static_cast((da * subTex)>>16); r = lr + static_cast((dr * subTex)>>16); g = lg + static_cast((dg * subTex)>>16); b = lb + static_cast((db * subTex)>>16); #endif #if defined(TEXTURED) u = lu + static_cast((du * subTex)>>16); v = lv + static_cast((dv * subTex)>>16); #endif PTYPE * pix = fb + (x0>>16); int width = ((x1-x0)>>16); while(width-- > 0) { #include PIXEL_INCLUDE // if (bit_format == 0x888) PIXEL888() // if (bit_format == 0x565) PIXEL565() // if (bit_format == 0x555) PIXEL555() // if (bit_format == 0x8888) PIXEL8888() ++pix; #if defined(MOD_ARGB) a += da; r += dr; g += dg; b += db; #endif #if defined(TEXTURED) u += du; v += dv; #endif } lx += ldx; sx += sdx; fb += pitch; #if defined (MOD_ARGB) la += lda; lr += ldr; lg += ldg; lb += ldb; #endif #if defined (TEXTURED) lu += ldu; lv += ldv; #endif libtuxcap-1.4.0/tuxcap/lib/SharedImage.cpp0000644000175000017500000000367010641010442020314 0ustar inniyahinniyah#include "SharedImage.h" #include "MemoryImage.h" #include "DDImage.h" #include "SexyAppBase.h" using namespace Sexy; SharedImage::SharedImage() { mImage = NULL; mRefCount = 0; } SharedImageRef::SharedImageRef(const SharedImageRef& theSharedImageRef) { mSharedImage = theSharedImageRef.mSharedImage; if (mSharedImage != NULL) mSharedImage->mRefCount++; mUnsharedImage = theSharedImageRef.mUnsharedImage; mOwnsUnshared = false; } SharedImageRef::SharedImageRef() { mSharedImage = NULL; mUnsharedImage = NULL; mOwnsUnshared = false; } SharedImageRef::SharedImageRef(SharedImage* theSharedImage) { mSharedImage = theSharedImage; if (theSharedImage != NULL) mSharedImage->mRefCount++; mUnsharedImage = NULL; mOwnsUnshared = false; } SharedImageRef::~SharedImageRef() { Release(); } void SharedImageRef::Release() { if (mOwnsUnshared) delete mUnsharedImage; mUnsharedImage = NULL; if (mSharedImage != NULL) { if (--mSharedImage->mRefCount == 0) gSexyAppBase->mCleanupSharedImages = true; } mSharedImage = NULL; } SharedImageRef& SharedImageRef::operator=(const SharedImageRef& theSharedImageRef) { Release(); mSharedImage = theSharedImageRef.mSharedImage; if (mSharedImage != NULL) mSharedImage->mRefCount++; return *this; } SharedImageRef& SharedImageRef::operator=(SharedImage* theSharedImage) { Release(); mSharedImage = theSharedImage; mSharedImage->mRefCount++; return *this; } SharedImageRef& SharedImageRef::operator=(MemoryImage* theUnsharedImage) { Release(); mUnsharedImage = theUnsharedImage; return *this; } MemoryImage* SharedImageRef::operator->() { return (MemoryImage*) *this; } SharedImageRef::operator Image*() { return (MemoryImage*) *this; } SharedImageRef::operator MemoryImage*() { if (mUnsharedImage != NULL) return mUnsharedImage; else return (DDImage*) *this; } SharedImageRef::operator DDImage*() { if (mSharedImage != NULL) return mSharedImage->mImage; else return NULL; } libtuxcap-1.4.0/tuxcap/lib/Graphics.cpp0000644000175000017500000012052011202747625017713 0ustar inniyahinniyah#include "Graphics.h" #include "Image.h" #include "Font.h" #include "MemoryImage.h" #include "DDImage.h" #if 0 #include "Debug.h" #endif #include "SWTri.h" #include "Rect.h" #include "SexyMatrix.h" #include #include #include "SDL.h" using namespace Sexy; Image GraphicsState::mStaticImage; const Point* Graphics::mPFPoints; ////////////////////////////////////////////////////////////////////////// void GraphicsState::CopyStateFrom(const GraphicsState* theState) { mDestImage = theState->mDestImage; mTransX = theState->mTransX; mTransY = theState->mTransY; mClipRect = theState->mClipRect; mFont = theState->mFont; mColor = theState->mColor; mDrawMode = theState->mDrawMode; mColorizeImages = theState->mColorizeImages; mFastStretch = theState->mFastStretch; mWriteColoredString = theState->mWriteColoredString; mLinearBlend = theState->mLinearBlend; mScaleX = theState->mScaleX; mScaleY = theState->mScaleY; mScaleOrigX = theState->mScaleOrigX; mScaleOrigY = theState->mScaleOrigY; mIs3D = theState->mIs3D; } ////////////////////////////////////////////////////////////////////////// Graphics::Graphics(const Graphics& theGraphics) { CopyStateFrom(&theGraphics); } Graphics::Graphics(Image* theDestImage) { mTransX = 0; mTransY = 0; mScaleX = 1; mScaleY = 1; mScaleOrigX = 0; mScaleOrigY = 0; mFont = NULL; mDestImage = theDestImage; mDrawMode = DRAWMODE_NORMAL; mColorizeImages = false; mFastStretch = false; mWriteColoredString = true; mLinearBlend = false; if (mDestImage == NULL) { mDestImage = &mStaticImage; mIs3D = false; } else { mIs3D = DDImage::Check3D(theDestImage); } mClipRect = Rect(0, 0, mDestImage->GetWidth(), mDestImage->GetHeight()); } Graphics::~Graphics() { } void Graphics::PushState() { mStateStack.push_back(GraphicsState()); mStateStack.back().CopyStateFrom(this); } void Graphics::PopState() { assert(mStateStack.size() > 0); if (mStateStack.size() > 0) { CopyStateFrom(&mStateStack.back()); mStateStack.pop_back(); } } Graphics* Graphics::Create() { return new Graphics(*this); } Sexy::Font* Graphics::GetFont() { return mFont; } void Graphics::SetFont(Sexy::Font* theFont) { mFont = theFont; } void Graphics::SetColor(const Color& theColor) { mColor = theColor; } const Color& Graphics::GetColor() { return mColor; } void Graphics::SetDrawMode(int theDrawMode) { mDrawMode = theDrawMode; } int Graphics::GetDrawMode() { return mDrawMode; } void Graphics::SetColorizeImages(bool colorizeImages) { mColorizeImages = colorizeImages; } bool Graphics::GetColorizeImages() { return mColorizeImages; } void Graphics::SetFastStretch(bool fastStretch) { mFastStretch = fastStretch; } bool Graphics::GetFastStretch() { return mFastStretch; } void Graphics::SetLinearBlend(bool linear) { mLinearBlend = linear; } bool Graphics::GetLinearBlend() { return mLinearBlend; } void Graphics::ClearRect(int theX, int theY, int theWidth, int theHeight) { Rect aDestRect = Rect((int)(theX + mTransX),(int)( theY + mTransY), theWidth, theHeight).Intersection(mClipRect); mDestImage->ClearRect(aDestRect); } void Graphics::ClearRect(const Rect& theRect) { ClearRect(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } void Graphics::FillRect(int theX, int theY, int theWidth, int theHeight) { if (mColor.mAlpha == 0) return; Rect aDestRect = Rect((int)(theX + mTransX), (int)(theY + mTransY), theWidth, theHeight).Intersection(mClipRect); mDestImage->FillRect(aDestRect, mColor, mDrawMode); } void Graphics::FillRect(const Rect& theRect) { FillRect(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } void Graphics::DrawRect(int theX, int theY, int theWidth, int theHeight) { if (mColor.mAlpha == 0) return; Rect aDestRect = Rect((int)(theX + mTransX), (int)(theY + mTransY), theWidth, theHeight); Rect aFullDestRect = Rect((int)(theX + mTransX), (int)(theY + mTransY), theWidth + 1, theHeight + 1); Rect aFullClippedRect = aFullDestRect.Intersection(mClipRect); if (aFullDestRect == aFullClippedRect) { mDestImage->DrawRect(aDestRect, mColor, mDrawMode); } else { FillRect(theX, theY, theWidth + 1, 1); FillRect(theX, theY + theHeight, theWidth + 1, 1); FillRect(theX, theY + 1, 1, theHeight - 1); FillRect(theX + theWidth, theY + 1, 1, theHeight - 1); } } void Graphics::DrawRect(const Rect& theRect) { DrawRect(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } int Graphics::PFCompareInd(const void* u, const void* v) { return mPFPoints[*((int*) u)].mY <= mPFPoints[*((int*) v)].mY ? -1 : 1; } int Graphics::PFCompareActive(const void* u, const void* v) { return ((Edge*) u)->mX <= ((Edge*) v)->mX ? -1 : 1; } void Graphics::PFDelete(int i) // remove edge i from active list { int j; for (j=0; j=mPFNumActiveEdges) return; /* edge not in active list; happens at aMinY*/ mPFNumActiveEdges--; memcpy(&mPFActiveEdgeList[j], &mPFActiveEdgeList[j+1], (mPFNumActiveEdges-j)*sizeof mPFActiveEdgeList[0]); } void Graphics::PFInsert(int i, int y) // append edge i to end of active list { int j; double dx; const Point *p, *q; j = imX - p->mX)/(double) (q->mY - p->mY); mPFActiveEdgeList[mPFNumActiveEdges].mX = dx*(y+0.5 - p->mY - mTransY) + p->mX + mTransX; mPFActiveEdgeList[mPFNumActiveEdges].i = i; mPFActiveEdgeList[mPFNumActiveEdges].b = p->mY - 1.0/dx * p->mX; mPFNumActiveEdges++; } void Graphics::PolyFill(const Point *theVertexList, int theNumVertices, bool convex) { if (convex && mDestImage->PolyFill3D(theVertexList,theNumVertices,&mClipRect,mColor,mDrawMode,(int)mTransX,(int)mTransY,convex)) return; Span aSpans[MAX_TEMP_SPANS]; int aSpanPos = 0; int k, y0, y1, y, i, j, xl, xr; int *ind; /* list of vertex indices, sorted by mPFPoints[ind[j]].y */ int aMinX = mClipRect.mX; int aMaxX = mClipRect.mX + mClipRect.mWidth - 1; int aMinY = mClipRect.mY; int aMaxY = mClipRect.mY + mClipRect.mHeight - 1; mPFNumVertices = theNumVertices; mPFPoints = theVertexList; if (mPFNumVertices<=0) return; ind = new int[mPFNumVertices]; mPFActiveEdgeList = new Edge[mPFNumVertices]; /* create y-sorted array of indices ind[k] into vertex list */ for (k=0; k0 ? i-1 : mPFNumVertices-1; // vertex previous to i if (mPFPoints[j].mY + mTransY <= y-0.5) // old edge, remove from active list PFDelete(j); else if (mPFPoints[j].mY + mTransY > y+0.5) // new edge, add to active list PFInsert(j, y); j = i y+0.5) // new edge, add to active list PFInsert(i, y); } // sort active edge list by active[j].mX qsort(mPFActiveEdgeList, mPFNumActiveEdges, sizeof mPFActiveEdgeList[0], PFCompareActive); // draw horizontal segments for scanline y for (j = 0; j < mPFNumActiveEdges; j += 2) { // draw horizontal segments // span 'tween j & j+1 is inside, span tween j+1 & j+2 is outside xl = (int) ceil(mPFActiveEdgeList[j].mX-0.5); // left end of span if (xlaMaxX) xr = aMaxX; if ((xl <= xr) && (aSpanPos < MAX_TEMP_SPANS)) { Span* aSpan = &aSpans[aSpanPos++]; aSpan->mY = y; aSpan->mX = xl; aSpan->mWidth = xr - xl + 1; } mPFActiveEdgeList[j].mX += mPFActiveEdgeList[j].mDX; // increment edge coords mPFActiveEdgeList[j+1].mX += mPFActiveEdgeList[j+1].mDX; } } mDestImage->FillScanLines(aSpans, aSpanPos, mColor, mDrawMode); delete ind; delete mPFActiveEdgeList; } void Graphics::PolyFillAA(const Point *theVertexList, int theNumVertices, bool convex) { if (convex && mDestImage->PolyFill3D(theVertexList,theNumVertices,&mClipRect,mColor,mDrawMode,(int)mTransX,(int)mTransY,convex)) return; int i; Span aSpans[MAX_TEMP_SPANS]; int aSpanPos = 0; static unsigned char aCoverageBuffer[256*256]; int aCoverWidth = 256, aCoverHeight = 256; int aCoverLeft, aCoverRight, aCoverTop, aCoverBottom; for (i = 0; i < theNumVertices; ++i) { const Point* aPt = &theVertexList[i]; if (i == 0) { aCoverLeft = aCoverRight = aPt->mX; aCoverTop = aCoverBottom = aPt->mY; } else { aCoverLeft = std::min(aCoverLeft, aPt->mX); aCoverRight = std::max(aCoverRight, aPt->mX); aCoverTop = std::min(aCoverTop, aPt->mY); aCoverBottom = std::max(aCoverBottom, aPt->mY); } } unsigned char* coverPtr = aCoverageBuffer; if ((aCoverRight-aCoverLeft+1) > aCoverWidth || (aCoverBottom-aCoverTop+1) > aCoverHeight) { aCoverWidth = aCoverRight-aCoverLeft+1; aCoverHeight = aCoverBottom-aCoverTop+1; coverPtr = new unsigned char[aCoverWidth*aCoverHeight]; } memset(coverPtr, 0, aCoverWidth*aCoverHeight); int k, y0, y1, y, j, xl, xr; int *ind; /* list of vertex indices, sorted by mPFPoints[ind[j]].y */ int aMinX = mClipRect.mX; int aMaxX = mClipRect.mX + mClipRect.mWidth - 1; int aMinY = mClipRect.mY; int aMaxY = mClipRect.mY + mClipRect.mHeight - 1; mPFNumVertices = theNumVertices; mPFPoints = theVertexList; if (mPFNumVertices<=0) return; ind = new int[mPFNumVertices]; mPFActiveEdgeList = new Edge[mPFNumVertices]; /* create y-sorted array of indices ind[k] into vertex list */ for (k=0; k0 ? i-1 : mPFNumVertices-1; // vertex previous to i if (mPFPoints[j].mY + mTransY <= y-0.5) // old edge, remove from active list PFDelete(j); else if (mPFPoints[j].mY + mTransY > y+0.5) // new edge, add to active list PFInsert(j, y); j = i y+0.5) // new edge, add to active list PFInsert(i, y); } // sort active edge list by active[j].mX qsort(mPFActiveEdgeList, mPFNumActiveEdges, sizeof mPFActiveEdgeList[0], PFCompareActive); // draw horizontal segments for scanline y for (j = 0; j < mPFNumActiveEdges; j += 2) { // draw horizontal segments // span 'tween j & j+1 is inside, span tween j+1 & j+2 is outside xl = (int) ceil(mPFActiveEdgeList[j].mX-0.5); // left end of span int lErr = int((fabs((mPFActiveEdgeList[j].mX-0.5) - xl)) * 255); if (xlaMaxX) { xr = aMaxX; rErr = 255; } if ((xl <= xr) && (aSpanPos < MAX_TEMP_SPANS)) { Span* aSpan = &aSpans[aSpanPos++]; aSpan->mY = y; aSpan->mX = xl; aSpan->mWidth = xr - xl + 1; unsigned char* coverRow = coverPtr + (y - aCoverTop) * aCoverWidth; if (xr == xl) { coverRow[xl-aCoverLeft] = std::min(255, coverRow[xl-aCoverLeft] + ((lErr*rErr)>>8)); } else { if (fabs(mPFActiveEdgeList[j].mDX) > 1.0f) // mostly horizontal on the left edge { double m = 1.0 / mPFActiveEdgeList[j].mDX, b = mPFActiveEdgeList[j].b, c = fabs(mPFActiveEdgeList[j].mDX); do { double _y = m * xl + b; lErr = std::min(255, int(fabs((_y) - y - .5) * 255)); coverRow[xl-aCoverLeft] = std::min(255, coverRow[xl-aCoverLeft] + lErr); xl++; c -= 1.0; } while (xl <= xr && c > 0); } else { coverRow[xl-aCoverLeft] = std::min(255, coverRow[xl-aCoverLeft] + lErr); xl++; } if (fabs(mPFActiveEdgeList[j+1].mDX) > 1.0f) // mostly horizontal on the right edge { double m = 1.0 / mPFActiveEdgeList[j+1].mDX, b = mPFActiveEdgeList[j+1].b, c = fabs(mPFActiveEdgeList[j+1].mDX); do { double _y = m * xr + b; rErr = std::min(255, int(fabs((_y) - y - .5) * 255)); coverRow[xr-aCoverLeft] = std::min(255, coverRow[xr-aCoverLeft] + rErr); xr--; c -= 1.0; } while (xr >= xl && c > 0); } else { coverRow[xr-aCoverLeft] = std::min(255, coverRow[xr-aCoverLeft] + rErr); xr--; } if (xl <= xr) memset(&coverRow[xl-aCoverLeft], 255, xr-xl+1); } } mPFActiveEdgeList[j].mX += mPFActiveEdgeList[j].mDX; // increment edge coords mPFActiveEdgeList[j+1].mX += mPFActiveEdgeList[j+1].mDX; } } mDestImage->FillScanLinesWithCoverage(aSpans, aSpanPos, mColor, mDrawMode, coverPtr, aCoverLeft, aCoverTop, aCoverWidth, aCoverHeight); if (coverPtr != aCoverageBuffer) delete[] coverPtr; delete[] ind; delete[] mPFActiveEdgeList; } bool Graphics::DrawLineClipHelper(double* theStartX, double* theStartY, double* theEndX, double* theEndY) { double aStartX = *theStartX; double aStartY = *theStartY; double aEndX = *theEndX; double aEndY = *theEndY; // Clip X if (aStartX > aEndX) { std::swap(aStartX,aEndX); std::swap(aStartY,aEndY); } if (aStartX < mClipRect.mX) { if (aEndX < mClipRect.mX) return false; double aSlope = (aEndY - aStartY) / (aEndX - aStartX); aStartY += (mClipRect.mX - aStartX ) * aSlope; aStartX = mClipRect.mX; } if (aEndX >= mClipRect.mX + mClipRect.mWidth) { if (aStartX >= mClipRect.mX + mClipRect.mWidth) return false; double aSlope = (aEndY - aStartY) / (aEndX - aStartX); aEndY += (mClipRect.mX + mClipRect.mWidth - 1 - aEndX) * aSlope; aEndX = mClipRect.mX + mClipRect.mWidth - 1; } // Clip Y if (aStartY > aEndY) { std::swap(aStartX,aEndX); std::swap(aStartY,aEndY); } if (aStartY < mClipRect.mY) { if (aEndY < mClipRect.mY) return false; double aSlope = (aEndX - aStartX) / (aEndY - aStartY); aStartX += (mClipRect.mY - aStartY ) * aSlope; aStartY = mClipRect.mY; } if (aEndY >= mClipRect.mY + mClipRect.mHeight) { if (aStartY >= mClipRect.mY + mClipRect.mHeight) return false; double aSlope = (aEndX - aStartX) / (aEndY - aStartY); aEndX += (mClipRect.mY + mClipRect.mHeight - 1 - aEndY) * aSlope; aEndY = mClipRect.mY + mClipRect.mHeight - 1; } *theStartX = aStartX; *theStartY = aStartY; *theEndX = aEndX; *theEndY = aEndY; return true; } void Graphics::DrawLine(int theStartX, int theStartY, int theEndX, int theEndY) { double aStartX = theStartX + mTransX; double aStartY = theStartY + mTransY; double aEndX = theEndX + mTransX; double aEndY = theEndY + mTransY; if (!DrawLineClipHelper(&aStartX, &aStartY, &aEndX, &aEndY)) return; mDestImage->DrawLine(aStartX, aStartY, aEndX, aEndY, mColor, mDrawMode); } void Graphics::DrawLineAA(int theStartX, int theStartY, int theEndX, int theEndY) { double aStartX = theStartX + mTransX; double aStartY = theStartY + mTransY; double aEndX = theEndX + mTransX; double aEndY = theEndY + mTransY; if (!DrawLineClipHelper(&aStartX, &aStartY, &aEndX, &aEndY)) return; mDestImage->DrawLineAA(aStartX, aStartY, aEndX, aEndY, mColor, mDrawMode); } void Graphics::DrawString(const SexyString& theString, int theX, int theY) { if (mFont != NULL) mFont->DrawString(this, theX, theY, theString, mColor, mClipRect); } void Graphics::DrawImage(Sexy::Image* theImage, int theX, int theY) { if (mScaleX!=1 || mScaleY!=1) { DrawImage(theImage,theX,theY,Rect(0,0,theImage->mWidth,theImage->mHeight)); return; } theX +=(int) mTransX; theY += (int)mTransY; Rect aDestRect = Rect(theX, theY, theImage->GetWidth(), theImage->GetHeight()).Intersection(mClipRect); Rect aSrcRect(aDestRect.mX - theX, aDestRect.mY - theY, aDestRect.mWidth, aDestRect.mHeight); if ((aSrcRect.mWidth > 0) && (aSrcRect.mHeight > 0)) mDestImage->Blt(theImage, aDestRect.mX, aDestRect.mY, aSrcRect, mColorizeImages ? mColor : Color::White, mDrawMode); } void Graphics::DrawImage(Image* theImage, int theX, int theY, const Rect& theSrcRect) { assert(theSrcRect.mX + theSrcRect.mWidth <= theImage->GetWidth()); assert(theSrcRect.mY + theSrcRect.mHeight <= theImage->GetHeight()); if ((theSrcRect.mX + theSrcRect.mWidth > theImage->GetWidth()) || (theSrcRect.mY + theSrcRect.mHeight > theImage->GetHeight())) return; theX += (int)mTransX; theY += (int)mTransY; if (mScaleX!=1 || mScaleY!=1) { Rect aDestRect((int)(mScaleOrigX+floor((theX-mScaleOrigX)*mScaleX)),(int)(mScaleOrigY+floor((theY-mScaleOrigY)*mScaleY)), (int)(ceil(theSrcRect.mWidth*mScaleX)),(int)(ceil(theSrcRect.mHeight*mScaleY))); mDestImage->StretchBlt(theImage, aDestRect, theSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, mFastStretch); return; } Rect aDestRect = Rect(theX, theY, theSrcRect.mWidth, theSrcRect.mHeight).Intersection(mClipRect); Rect aSrcRect(theSrcRect.mX + aDestRect.mX - theX, theSrcRect.mY + aDestRect.mY - theY, aDestRect.mWidth, aDestRect.mHeight); if ((aSrcRect.mWidth > 0) && (aSrcRect.mHeight > 0)) mDestImage->Blt(theImage, aDestRect.mX, aDestRect.mY, aSrcRect, mColorizeImages ? mColor : Color::White, mDrawMode); } void Graphics::DrawImageMirror(Image* theImage, int theX, int theY, bool mirror) { DrawImageMirror(theImage,theX,theY,Rect(0,0,theImage->mWidth,theImage->mHeight),mirror); } void Graphics::DrawImageMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, bool mirror) { if (!mirror) { DrawImage(theImage, theX, theY, theSrcRect); return; } theX += (int)mTransX; theY += (int)mTransY; assert(theSrcRect.mX + theSrcRect.mWidth <= theImage->GetWidth()); assert(theSrcRect.mY + theSrcRect.mHeight <= theImage->GetHeight()); if ((theSrcRect.mX + theSrcRect.mWidth > theImage->GetWidth()) || (theSrcRect.mY + theSrcRect.mHeight > theImage->GetHeight())) return; Rect aDestRect = Rect(theX, theY, theSrcRect.mWidth, theSrcRect.mHeight).Intersection(mClipRect); int aTotalClip = theSrcRect.mWidth - aDestRect.mWidth; int aLeftClip = aDestRect.mX - theX; int aRightClip = aTotalClip-aLeftClip; Rect aSrcRect(theSrcRect.mX + aRightClip, theSrcRect.mY + aDestRect.mY - theY, aDestRect.mWidth, aDestRect.mHeight); if ((aSrcRect.mWidth > 0) && (aSrcRect.mHeight > 0)) mDestImage->BltMirror(theImage, aDestRect.mX, aDestRect.mY, aSrcRect, mColorizeImages ? mColor : Color::White, mDrawMode); } void Graphics::DrawImageMirror(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, bool mirror) { if (!mirror) { DrawImage(theImage,theDestRect,theSrcRect); return; } Rect aDestRect = Rect((int)(theDestRect.mX + mTransX), (int)(theDestRect.mY + mTransY), theDestRect.mWidth, theDestRect.mHeight); mDestImage->StretchBltMirror(theImage, aDestRect, theSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, mFastStretch); } void Graphics::DrawImage(Image* theImage, int theX, int theY, int theStretchedWidth, int theStretchedHeight) { Rect aDestRect = Rect((int)(theX + mTransX), (int)(theY + mTransY), theStretchedWidth, theStretchedHeight); Rect aSrcRect = Rect(0, 0, theImage->mWidth, theImage->mHeight); mDestImage->StretchBlt(theImage, aDestRect, aSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, mFastStretch); } void Graphics::DrawImage(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect) { Rect aDestRect = Rect((int)(theDestRect.mX + mTransX), (int)(theDestRect.mY + mTransY), theDestRect.mWidth, theDestRect.mHeight); mDestImage->StretchBlt(theImage, aDestRect, theSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, mFastStretch); } void Graphics::DrawImageF(Image* theImage, float theX, float theY) { theX += mTransX; theY += mTransY; Rect aSrcRect(0, 0, theImage->mWidth, theImage->mHeight); mDestImage->BltF(theImage, theX, theY, aSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode); } void Graphics::DrawImageF(Image* theImage, float theX, float theY, const Rect& theSrcRect) { assert(theSrcRect.mX + theSrcRect.mWidth <= theImage->GetWidth()); assert(theSrcRect.mY + theSrcRect.mHeight <= theImage->GetHeight()); theX += mTransX; theY += mTransY; mDestImage->BltF(theImage, theX, theY, theSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode); } void Graphics::DrawImageRotated(Image* theImage, int theX, int theY, double theRot, const Rect *theSrcRect) { if (theSrcRect == NULL) { int aRotCenterX = theImage->GetWidth() / 2; int aRotCenterY = theImage->GetHeight() / 2; DrawImageRotatedF(theImage, theX, theY, theRot, aRotCenterX, aRotCenterY, theSrcRect); } else { int aRotCenterX = theSrcRect->mWidth / 2; int aRotCenterY = theSrcRect->mHeight / 2; DrawImageRotatedF(theImage, theX, theY, theRot, aRotCenterX, aRotCenterY, theSrcRect); } } void Graphics::DrawImageRotatedF(Image* theImage, float theX, float theY, double theRot, const Rect *theSrcRect) { if (theSrcRect == NULL) { float aRotCenterX = theImage->GetWidth() / 2.0f; float aRotCenterY = theImage->GetHeight() / 2.0f; DrawImageRotatedF(theImage, theX, theY, theRot, aRotCenterX, aRotCenterY, theSrcRect); } else { float aRotCenterX = theSrcRect->mWidth / 2.0f; float aRotCenterY = theSrcRect->mHeight / 2.0f; DrawImageRotatedF(theImage, theX, theY, theRot, aRotCenterX, aRotCenterY, theSrcRect); } } void Graphics::DrawImageRotated(Image* theImage, int theX, int theY, double theRot, int theRotCenterX, int theRotCenterY, const Rect *theSrcRect) { DrawImageRotatedF(theImage,theX,theY,theRot,theRotCenterX,theRotCenterY,theSrcRect); } void Graphics::DrawImageRotatedF(Image* theImage, float theX, float theY, double theRot, float theRotCenterX, float theRotCenterY, const Rect *theSrcRect) { theX += mTransX; theY += mTransY; if (theSrcRect==NULL) { Rect aSrcRect(0,0,theImage->mWidth,theImage->mHeight); mDestImage->BltRotated(theImage, theX, theY, aSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, theRot, theRotCenterX, theRotCenterY); } else mDestImage->BltRotated(theImage, theX, theY, *theSrcRect, mClipRect, mColorizeImages ? mColor : Color::White, mDrawMode, theRot, theRotCenterX, theRotCenterY); } void Graphics::DrawImageMatrix(Image* theImage, const SexyMatrix3 &theMatrix, float x, float y) { Rect aSrcRect(0,0,theImage->mWidth,theImage->mHeight); mDestImage->BltMatrix(theImage,x+mTransX,y+mTransY,theMatrix,mClipRect,mColorizeImages?mColor:Color::White,mDrawMode,aSrcRect,mLinearBlend); } void Graphics::DrawImageMatrix(Image* theImage, const SexyMatrix3 &theMatrix, const Rect &theSrcRect, float x, float y) { mDestImage->BltMatrix(theImage,x+mTransX,y+mTransY,theMatrix,mClipRect,mColorizeImages?mColor:Color::White,mDrawMode,theSrcRect,mLinearBlend); } void Graphics::DrawImageTransformHelper(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x, float y, bool useFloat) { if (theTransform.mComplex || (DDImage::Check3D(mDestImage) && useFloat)) { DrawImageMatrix(theImage,theTransform.GetMatrix(),theSrcRect,x,y); return; } // Translate into appropriate graphics call float w2 = theSrcRect.mWidth/2.0f; float h2 = theSrcRect.mHeight/2.0f; if (theTransform.mHaveRot) { float rx = w2-theTransform.mTransX1; float ry = h2-theTransform.mTransY1; x = x + theTransform.mTransX2 - rx + 0.5f; y = y + theTransform.mTransY2 - ry + 0.5f; if (useFloat) DrawImageRotatedF(theImage,x,y,theTransform.mRot,rx,ry,&theSrcRect); else DrawImageRotated(theImage,(int)x,(int)y,theTransform.mRot,(int)rx,(int)ry,&theSrcRect); } else if (theTransform.mHaveScale) { bool mirror = false; if (theTransform.mScaleX==-1) { if (theTransform.mScaleY==1) { x = x + theTransform.mTransX1 + theTransform.mTransX2 - w2 + 0.5f; y = y + theTransform.mTransY1 + theTransform.mTransY2 - h2 + 0.5f; DrawImageMirror(theImage,(int)x,(int)y,theSrcRect); return; } mirror = true; } float sw = w2*theTransform.mScaleX; float sh = h2*theTransform.mScaleY; x = x + theTransform.mTransX2 - sw; y = y + theTransform.mTransY2 - sh; Rect aDestRect((int)x,(int)y,(int)(sw*2),(int)(sh*2)); DrawImageMirror(theImage,aDestRect,theSrcRect,mirror); } else { x = x + theTransform.mTransX1 + theTransform.mTransX2 - w2 + 0.5f; y = y + theTransform.mTransY1 + theTransform.mTransY2 - h2 + 0.5f; if (useFloat) DrawImageF(theImage,x,y,theSrcRect); else DrawImage(theImage,(int)x,(int)y,theSrcRect); } } void Graphics::DrawImageTransform(Image* theImage, const Transform &theTransform, float x, float y) { DrawImageTransformHelper(theImage,theTransform,Rect(0,0,theImage->mWidth,theImage->mHeight),x,y,false); } void Graphics::DrawImageTransformF(Image* theImage, const Transform &theTransform, float x, float y) { DrawImageTransformHelper(theImage,theTransform,Rect(0,0,theImage->mWidth,theImage->mHeight),x,y,true); } void Graphics::DrawImageTransform(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x, float y) { DrawImageTransformHelper(theImage,theTransform,theSrcRect,x,y,false); } void Graphics::DrawImageTransformF(Image* theImage, const Transform &theTransform, const Rect &theSrcRect, float x, float y) { DrawImageTransformHelper(theImage,theTransform,theSrcRect,x,y,true); } void Graphics::DrawTriangleTex(Image *theTexture, const TriVertex &v1, const TriVertex &v2, const TriVertex &v3) { TriVertex v[1][3] = {{v1,v2,v3}}; mDestImage->BltTrianglesTex(theTexture,v,1,mClipRect,mColorizeImages?mColor:Color::White,mDrawMode,mTransX,mTransY,mLinearBlend); } void Graphics::DrawTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles) { mDestImage->BltTrianglesTex(theTexture,theVertices,theNumTriangles,mClipRect,mColorizeImages?mColor:Color::White,mDrawMode,mTransX,mTransY,mLinearBlend); } void Graphics::ClearClipRect() { mClipRect = Rect(0, 0, mDestImage->GetWidth(), mDestImage->GetHeight()); } void Graphics::SetClipRect(int theX, int theY, int theWidth, int theHeight) { mClipRect = Rect(0, 0, mDestImage->GetWidth(), mDestImage->GetHeight()).Intersection( Rect((int)(theX + mTransX), (int)(theY + mTransY), theWidth, theHeight)); } void Graphics::SetClipRect(const Rect& theRect) { SetClipRect(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } void Graphics::ClipRect(int theX, int theY, int theWidth, int theHeight) { mClipRect = mClipRect.Intersection(Rect((int)(theX + mTransX), (int)(theY + mTransY), theWidth, theHeight)); } void Graphics::ClipRect(const Rect& theRect) { ClipRect(theRect.mX, theRect.mY, theRect.mWidth, theRect.mHeight); } void Graphics::Translate(int theTransX, int theTransY) { mTransX += theTransX; mTransY += theTransY; } void Graphics::TranslateF(float theTransX, float theTransY) { mTransX += theTransX; mTransY += theTransY; } void Graphics::SetScale(float theScaleX, float theScaleY, float theOrigX, float theOrigY) { mScaleX = theScaleX; mScaleY = theScaleY; mScaleOrigX = theOrigX + mTransX; mScaleOrigY = theOrigY + mTransY; } int Graphics::StringWidth(const SexyString& theString) { return mFont->StringWidth(theString); } void Graphics::DrawImageBox(const Rect& theDest, Image* theComponentImage) { DrawImageBox(Rect(0,0,theComponentImage->mWidth,theComponentImage->mHeight),theDest,theComponentImage); } void Graphics::DrawImageBox(const Rect& theSrc, const Rect &theDest, Image* theComponentImage) { if (theSrc.mWidth<=0 || theSrc.mHeight<=0) return; int cw = theSrc.mWidth/3; int ch = theSrc.mHeight/3; int cx = theSrc.mX; int cy = theSrc.mY; int cmw = theSrc.mWidth - cw*2; int cmh = theSrc.mHeight - ch*2; // Draw 4 corners DrawImage(theComponentImage, theDest.mX, theDest.mY, Rect(cx,cy, cw, ch)); DrawImage(theComponentImage, theDest.mX + theDest.mWidth-cw, theDest.mY, Rect(cx + cw + cmw, cy, cw, ch)); DrawImage(theComponentImage, theDest.mX, theDest.mY + theDest.mHeight-ch, Rect(cx, cy + ch + cmh, cw, ch)); DrawImage(theComponentImage, theDest.mX + theDest.mWidth-cw, theDest.mY + theDest.mHeight-ch, Rect(cx + cw + cmw, cy + ch + cmh, cw, ch)); // Draw top and bottom Graphics aVertClip(*this); aVertClip.ClipRect(theDest.mX + cw, theDest.mY, theDest.mWidth-cw*2, theDest.mHeight); int aCol, aRow; for (aCol = 0; aCol < (theDest.mWidth-cw*2+cmw-1)/cmw; aCol++) { aVertClip.DrawImage(theComponentImage, theDest.mX + cw + aCol*cmw, theDest.mY, Rect(cx + cw, cy, cmw, ch)); aVertClip.DrawImage(theComponentImage, theDest.mX + cw + aCol*cmw, theDest.mY + theDest.mHeight-ch, Rect(cx + cw, cy + ch + cmh, cmw, ch)); } // Draw sides Graphics aHorzClip(*this); aHorzClip.ClipRect(theDest.mX, theDest.mY + ch, theDest.mWidth, theDest.mHeight-ch*2); for (aRow = 0; aRow < (theDest.mHeight-ch*2+cmh-1)/cmh; aRow++) { aHorzClip.DrawImage(theComponentImage, theDest.mX, theDest.mY + ch + aRow*cmh, Rect(cx, cy + ch, cw, cmh)); aHorzClip.DrawImage(theComponentImage, theDest.mX + theDest.mWidth-cw, theDest.mY + ch + aRow*cmh, Rect(cx + cw + cmw, cy + ch, cw, cmh)); } // Draw middle Graphics aMidClip(*this); aMidClip.ClipRect(theDest.mX + cw, theDest.mY + ch, theDest.mWidth-cw*2, theDest.mHeight-ch*2); for (aCol = 0; aCol < (theDest.mWidth-cw*2+cmw-1)/cmw; aCol++) for (aRow = 0; aRow < (theDest.mHeight-ch*2+cmh-1)/cmh; aRow++) aMidClip.DrawImage(theComponentImage, theDest.mX + cw + aCol*cmw, theDest.mY + ch + aRow*cmh, Rect(cx + cw, cy + ch, cmw, cmh)); } void Graphics::DrawImageCel(Image* theImageStrip, int theX, int theY, int theCel) { DrawImageCel(theImageStrip, theX, theY, theCel % theImageStrip->mNumCols, theCel / theImageStrip->mNumCols); } void Graphics::DrawImageCel(Image* theImageStrip, const Rect& theDestRect, int theCel) { DrawImageCel(theImageStrip, theDestRect, theCel % theImageStrip->mNumCols, theCel / theImageStrip->mNumCols); } void Graphics::DrawImageCel(Image* theImageStrip, int theX, int theY, int theCelCol, int theCelRow) { if (theCelRow<0 || theCelCol<0 || theCelRow >= theImageStrip->mNumRows || theCelCol >= theImageStrip->mNumCols) return; int aCelWidth = theImageStrip->mWidth / theImageStrip->mNumCols; int aCelHeight = theImageStrip->mHeight / theImageStrip->mNumRows; Rect aSrcRect(aCelWidth*theCelCol, aCelHeight*theCelRow, aCelWidth, aCelHeight); DrawImage(theImageStrip,theX,theY,aSrcRect); } void Graphics::DrawImageAnim(Image* theImageAnim, int theX, int theY, int theTime) { DrawImageCel(theImageAnim, theX, theY, theImageAnim->GetAnimCel(theTime)); } void Graphics::DrawImageCel(Image* theImageStrip, const Rect& theDestRect, int theCelCol, int theCelRow) { if (theCelRow<0 || theCelCol<0 || theCelRow >= theImageStrip->mNumRows || theCelCol >= theImageStrip->mNumCols) return; int aCelWidth = theImageStrip->mWidth / theImageStrip->mNumCols; int aCelHeight = theImageStrip->mHeight / theImageStrip->mNumRows; Rect aSrcRect(aCelWidth*theCelCol, aCelHeight*theCelRow, aCelWidth, aCelHeight); DrawImage(theImageStrip,theDestRect,aSrcRect); } int Graphics::WriteString(const SexyString& theString, int theX, int theY, int theWidth, int theJustification, bool drawString, int theOffset, int theLength, int theOldColor) { Font* aFont = GetFont(); if (theOldColor==-1) theOldColor = mColor.ToInt(); if (drawString) { switch (theJustification) { case 0: theX += (theWidth - WriteString(theString, theX, theY, theWidth, -1, false, theOffset, theLength, theOldColor))/2; break; case 1: theX += theWidth - WriteString(theString, theX, theY, theWidth, -1, false, theOffset, theLength, theOldColor); break; } } if(theLength<0 || theOffset+theLength>(int)theString.length()) theLength = (int)theString.length(); else theLength = theOffset + theLength; SexyString aString; int aXOffset = 0; for (int i = theOffset; i < theLength; i++) { if ((theString[i] == '^') && mWriteColoredString) { if (i+1theLength-8) // badly formatted color specification break; else // change color instruction { Uint32 aColor = 0; if (theString[i+1]==_S('o')) { if (sexystrncmp(theString.c_str()+i+1, _S("oldclr"), 6) == 0) aColor = theOldColor; } else { for (int aDigitNum = 0; aDigitNum < 6; aDigitNum++) { SexyChar aChar = theString[i+aDigitNum+1]; int aVal = 0; if ((aChar >= _S('0')) && (aChar <= _S('9'))) aVal = aChar - _S('0'); else if ((aChar >= _S('A')) && (aChar <= _S('F'))) aVal = (aChar - _S('A')) + 10; else if ((aChar >= _S('a')) && (aChar <= _S('f'))) aVal = (aChar - _S('a')) + 10; aColor += (aVal << ((5 - aDigitNum) * 4)); } } if (drawString) { DrawString(aString, theX + aXOffset, theY); SetColor(Color((aColor >> 16) & 0xFF, (aColor >> 8) & 0xFF, (aColor) & 0xFF, GetColor().mAlpha)); } i += 7; aXOffset += GetFont()->StringWidth(aString); aString = _S(""); } } else aString += theString[i]; } if (drawString) { DrawString(aString, theX + aXOffset, theY); } aXOffset += GetFont()->StringWidth(aString); return aXOffset; } static int WriteWordWrappedHelper(Graphics *g, const SexyString& theString, int theX, int theY, int theWidth, int theJustification, bool drawString, int theOffset, int theLength, int theOldColor, int theMaxChars) { if (theOffset+theLength>theMaxChars) { theLength = theMaxChars-theOffset; if (theLength<=0) return -1; } return g->WriteString(theString,theX,theY,theWidth,theJustification,drawString,theOffset,theLength,theOldColor); } int Graphics::WriteWordWrapped(const Rect& theRect, const SexyString& theLine, int theLineSpacing, int theJustification, int *theMaxWidth, int theMaxChars, int *theLastWidth) { Color anOrigColor = GetColor(); int anOrigColorInt = anOrigColor.ToInt(); if ((anOrigColorInt&0xFF000000)==0xFF000000) anOrigColorInt &= ~0xFF000000; if (theMaxChars<0) theMaxChars = (int)theLine.length(); Font* aFont = GetFont(); int aYOffset = aFont->GetAscent() - aFont->GetAscentPadding(); if (theLineSpacing == -1) theLineSpacing = aFont->GetLineSpacing(); SexyString aCurString; uint32_t aCurPos = 0; int aLineStartPos = 0; int aCurWidth = 0; SexyChar aCurChar = 0; SexyChar aPrevChar = 0; int aSpacePos = -1; int aMaxWidth = 0; int anIndentX = 0; if (theLastWidth != NULL) { anIndentX = *theLastWidth; aCurWidth = anIndentX; } while (aCurPos < theLine.length()) { aCurChar = theLine[aCurPos]; if(aCurChar==_S('^') && mWriteColoredString) // Handle special color modifier { if(aCurPos+1 just skip the extra '^' else { aCurPos+=8; continue; // skip the color specifier when calculating the width } } } else if(aCurChar==_S(' ')) aSpacePos = aCurPos; else if(aCurChar==_S('\n')) { aCurWidth = theRect.mWidth+1; // force word wrap aSpacePos = aCurPos; aCurPos++; // skip enter on next go round } aCurWidth += aFont->CharWidthKern(aCurChar, aPrevChar); aPrevChar = aCurChar; if(aCurWidth > theRect.mWidth) // need to wrap { int aWrittenWidth; if(aSpacePos!=-1) { //aWrittenWidth = WriteWordWrappedHelper(this, theLine, theRect.mX, theRect.mY + aYOffset, theRect.mWidth, // theJustification, true, aLineStartPos, aSpacePos-aLineStartPos, anOrigColorInt, theMaxChars); int aPhysPos = (int)(theRect.mY + aYOffset + mTransY); if ((aPhysPos >= mClipRect.mY) && (aPhysPos < mClipRect.mY + mClipRect.mHeight + theLineSpacing)) { WriteWordWrappedHelper(this, theLine, theRect.mX + anIndentX, theRect.mY + aYOffset, theRect.mWidth, theJustification, true, aLineStartPos, aSpacePos-aLineStartPos, anOrigColorInt, theMaxChars); /*WriteString(theLine, theRect.mX + anIndentX, theRect.mY + aYOffset, theRect.mWidth, theJustification, true, aLineStartPos, aSpacePos-aLineStartPos);*/ } aWrittenWidth = aCurWidth + anIndentX; if (aWrittenWidth<0) break; aCurPos = aSpacePos+1; if (aCurChar != _S('\n')) { while (aCurPos*theMaxWidth) *theMaxWidth = aWrittenWidth; if (theLastWidth!=NULL) *theLastWidth = aWrittenWidth; } if (aWrittenWidth > aMaxWidth) aMaxWidth = aWrittenWidth; aLineStartPos = aCurPos; aSpacePos = -1; aCurWidth = 0; aPrevChar = 0; anIndentX = 0; aYOffset += theLineSpacing; } else aCurPos++; } if(aLineStartPos<(int)theLine.length()) // write the last piece { int aWrittenWidth = WriteWordWrappedHelper(this, theLine, theRect.mX + anIndentX, theRect.mY + aYOffset, theRect.mWidth, theJustification, true, aLineStartPos, theLine.length()-aLineStartPos, anOrigColorInt, theMaxChars); if (aWrittenWidth>=0) { if (aWrittenWidth > aMaxWidth) aMaxWidth = aWrittenWidth; if (theMaxWidth!=NULL && aWrittenWidth>*theMaxWidth) *theMaxWidth = aWrittenWidth; if (theLastWidth!=NULL) *theLastWidth = aWrittenWidth; aYOffset += theLineSpacing; } } else if (aCurChar == '\n') { aYOffset += theLineSpacing; if (theLastWidth != NULL) *theLastWidth = 0; } SetColor(anOrigColor); if (theMaxWidth!=NULL) *theMaxWidth = aMaxWidth; return aYOffset + aFont->GetDescent() - theLineSpacing; } int Graphics::DrawStringColor(const SexyString& theLine, int theX, int theY, int theOldColor) { return WriteString(theLine, theX, theY, -1, -1,true,0,-1,theOldColor); } int Graphics::DrawStringWordWrapped(const SexyString& theLine, int theX, int theY, int theWrapWidth, int theLineSpacing, int theJustification, int *theMaxWidth) { int aYOffset = mFont->GetAscent() - mFont->GetAscentPadding(); Rect aRect(theX,theY-aYOffset,theWrapWidth,0); return WriteWordWrapped(aRect, theLine, theLineSpacing, theJustification, theMaxWidth); } int Graphics::GetWordWrappedHeight(int theWidth, const SexyString& theLine, int theLineSpacing, int *theMaxWidth) { Graphics aTestG; aTestG.SetFont(mFont); int aHeight = aTestG.WriteWordWrapped(Rect(0, 0, theWidth, 0), theLine, theLineSpacing, -1, theMaxWidth); return aHeight; } libtuxcap-1.4.0/tuxcap/lib/EditWidget.cpp0000644000175000017500000003760711202747625020221 0ustar inniyahinniyah#include "EditWidget.h" #if 0 #include "SysFont.h" #endif #include "Font.h" #include "WidgetManager.h" #include "SexyAppBase.h" #include "EditListener.h" #include "SDL_keysym.h" using namespace Sexy; static int gEditWidgetColors[][3] = {{255, 255, 255}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {255, 255, 255}}; EditWidget::EditWidget(int theId, EditListener* theEditListener) { mId = theId; mEditListener = theEditListener; mFont = NULL; mHadDoubleClick = false; mHilitePos = -1; mLastModifyIdx = -1; mLeftPos = 0; mUndoCursor = 0; mUndoHilitePos = 0; mLastModifyIdx = 0; mBlinkAcc = 0; mCursorPos = 0; mShowingCursor = false; mDrawSelOverride = false; mMaxChars = -1; mMaxPixels = -1; mPasswordChar = 0; mBlinkDelay = 40; SetColors(gEditWidgetColors, NUM_COLORS); } EditWidget::~EditWidget() { delete mFont; ClearWidthCheckFonts(); } void EditWidget::ClearWidthCheckFonts() { for (WidthCheckList::iterator anItr = mWidthCheckList.begin(); anItr != mWidthCheckList.end(); ++anItr) delete anItr->mFont; mWidthCheckList.clear(); } void EditWidget::AddWidthCheckFont(Font *theFont, int theMaxPixels) { mWidthCheckList.push_back(WidthCheck()); WidthCheck &aCheck = mWidthCheckList.back(); aCheck.mWidth = theMaxPixels; aCheck.mFont = theFont->Duplicate(); } void EditWidget::SetText(const SexyString& theText, bool leftPosToZero) { mString = theText; mCursorPos = mString.length(); mHilitePos = 0; if (leftPosToZero) mLeftPos = 0; else FocusCursor(true); MarkDirty(); } SexyString& EditWidget::GetDisplayString() { if (mPasswordChar==0) return mString; if (mPasswordDisplayString.size()!=mString.size()) { mPasswordDisplayString = SexyString(mString.size(), mPasswordChar); //mPasswordDisplayString.resize(mString.size()); //for (int i=0; i<(int)mPasswordDisplayString.length(); i++) // mPasswordDisplayString[i] = mPasswordChar; } return mPasswordDisplayString; } bool EditWidget::WantsFocus() { return true; } void EditWidget::Resize(int theX, int theY, int theWidth, int theHeight) { Widget::Resize(theX, theY, theWidth, theHeight); FocusCursor(false); } void EditWidget::SetFont(Font* theFont, Font* theWidthCheckFont) { delete mFont; mFont = theFont->Duplicate(); ClearWidthCheckFonts(); if (theWidthCheckFont != NULL) AddWidthCheckFont(theWidthCheckFont); } void EditWidget::Draw(Graphics* g) // Already translated { #if 0 if (mFont == NULL) mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 10, false); #endif SexyString &aString = GetDisplayString(); g->SetColor(mColors[COLOR_BKG]); g->FillRect(0, 0, mWidth, mHeight); for (int i = 0; i < 2; i++) { Graphics* aClipG = g->Create(); aClipG->SetFont(mFont); if (i == 1) { int aCursorX = mFont->StringWidth(aString.substr(0, mCursorPos)) - mFont->StringWidth(aString.substr(0, mLeftPos)); int aHiliteX = aCursorX+2; if ((mHilitePos != -1) && (mCursorPos != mHilitePos)) aHiliteX = mFont->StringWidth(aString.substr(0, mHilitePos)) - mFont->StringWidth(aString.substr(0, mLeftPos)); if (!mShowingCursor) aCursorX += 2; aCursorX = std::min(std::max(0, aCursorX), mWidth-8); aHiliteX = std::min(std::max(0, aHiliteX), mWidth-8); aClipG->ClipRect(4 + std::min(aCursorX, aHiliteX), (mHeight - mFont->GetHeight())/2, abs(aHiliteX - aCursorX), mFont->GetHeight()); } else aClipG->ClipRect(4, 0, mWidth-8, mHeight); bool hasfocus = mHasFocus || mDrawSelOverride; if (i == 1 && hasfocus) { aClipG->SetColor(mColors[COLOR_HILITE]); aClipG->FillRect(0, 0, mWidth, mHeight); } if (i == 0 || !hasfocus) aClipG->SetColor(mColors[COLOR_TEXT]); else aClipG->SetColor(mColors[COLOR_HILITE_TEXT]); aClipG->DrawString(aString.substr(mLeftPos), 4, (mHeight - mFont->GetHeight())/2 + mFont->GetAscent()); delete aClipG; } g->SetColor(mColors[COLOR_OUTLINE]); g->DrawRect(0, 0, mWidth-1, mHeight-1); } void EditWidget::UpdateCaretPos() { SexyAppBase *anApp = mWidgetManager->mApp; Point aPoint = GetAbsPos(); if (aPoint.mX<10) aPoint.mX = 10; else if (aPoint.mX>anApp->mWidth-10) aPoint.mX = anApp->mWidth-10; if (aPoint.mY<10) aPoint.mY = 10; else if (aPoint.mY>anApp->mHeight-10) aPoint.mY = anApp->mHeight-10; #if 0 SetCaretPos(aPoint.mX,aPoint.mY); #endif } void EditWidget::GotFocus() { Widget::GotFocus(); if (mWidgetManager && mWidgetManager->mApp->mTabletPC) { SexyAppBase *anApp = mWidgetManager->mApp; #if 0 CreateCaret(anApp->mHWnd,NULL,0,0); UpdateCaretPos(); ShowCaret(anApp->mHWnd); #endif } mShowingCursor = true; mBlinkAcc = 0; MarkDirty(); } void EditWidget::LostFocus() { Widget::LostFocus(); if (mWidgetManager && mWidgetManager->mApp->mTabletPC) { #if 0 HideCaret(mWidgetManager->mApp->mHWnd); DestroyCaret(); #endif } mShowingCursor = false; MarkDirty(); } void EditWidget::Update() { Widget::Update(); if (mHasFocus) { if (mWidgetManager->mApp->mTabletPC) { UpdateCaretPos(); } if (++mBlinkAcc > mBlinkDelay) { MarkDirty(); mBlinkAcc = 0; mShowingCursor = !mShowingCursor; } } } void EditWidget::EnforceMaxPixels() { if (mMaxPixels<=0 && mWidthCheckList.empty()) // no width checking in effect return; if (mWidthCheckList.empty()) { while (mFont->StringWidth(mString) > mMaxPixels) mString = mString.substr(0, mString.length()-1); return; } for (WidthCheckList::iterator anItr = mWidthCheckList.begin(); anItr != mWidthCheckList.end(); ++anItr) { int aWidth = anItr->mWidth; if (aWidth<=0) { aWidth = mMaxPixels; if (aWidth<=0) continue; } while (anItr->mFont->StringWidth(mString) > aWidth) mString = mString.substr(0,mString.length()-1); } } bool EditWidget::IsPartOfWord(SexyChar theChar) { #if 0 return (((theChar >= _S('A')) && (theChar <= _S('Z'))) || ((theChar >= _S('a')) && (theChar <= _S('z'))) || ((theChar >= _S('0')) && (theChar <= _S('9'))) || (((unsigned int)theChar >= (unsigned int)(L'')) && ((unsigned int)theChar <= (unsigned int)(L''))) || (theChar == _S('_'))); #else return false; #endif } void EditWidget::ProcessKey(SDLKey theKey, SexyChar theChar) { if ((theKey == SDLK_LSHIFT) || (theKey == SDLK_RSHIFT) || (theKey == SDLK_LCTRL) || (theKey == SDLK_RCTRL)) return; bool shiftDown = mWidgetManager->mKeyDown[SDLK_LSHIFT] || mWidgetManager->mKeyDown[SDLK_RSHIFT]; bool controlDown = mWidgetManager->mKeyDown[SDLK_LCTRL] || mWidgetManager->mKeyDown[SDLK_RCTRL]; bool bigChange = false; bool removeHilite = !shiftDown; if (shiftDown && (mHilitePos == -1)) mHilitePos = mCursorPos; SexyString anOldString = mString; int anOldCursorPos = mCursorPos; int anOldHilitePos = mHilitePos; if ((theChar == 3) || (theChar == 24)) { // Copy selection if ((mHilitePos != -1) && (mHilitePos != mCursorPos)) { #if 0 if (mCursorPos < mHilitePos) mWidgetManager->mApp->CopyToClipboard(SexyStringToString(GetDisplayString().substr(mCursorPos, mHilitePos))); else mWidgetManager->mApp->CopyToClipboard(SexyStringToString(GetDisplayString().substr(mHilitePos, mCursorPos))); #endif if (theChar == 3) { removeHilite = false; } else { mString = mString.substr(0, std::min(mCursorPos, mHilitePos)) + mString.substr(std::max(mCursorPos, mHilitePos)); mCursorPos = std::min(mCursorPos, mHilitePos); mHilitePos = -1; bigChange = true; } } } else if (theChar == 22) { // Paste selection #if 0 SexyString aBaseString = StringToSexyString(mWidgetManager->mApp->GetClipboard()); #else SexyString aBaseString; #endif if (aBaseString.length() > 0) { SexyString aString; for (uint32_t i = 0; i < aBaseString.length(); i++) { if ((aBaseString[i] == '\r') || (aBaseString[i] == '\n')) break; if (mFont->CharWidth(aBaseString[i]) != 0 && mEditListener->AllowChar(mId, aBaseString[i])) aString += aBaseString[i]; } if (mHilitePos == -1) { // Insert string where cursor is mString = mString.substr(0, mCursorPos) + aString + mString.substr(mCursorPos); } else { // Replace selection with new string mString = mString.substr(0, std::min(mCursorPos, mHilitePos)) + aString + mString.substr(std::max(mCursorPos, mHilitePos)); mCursorPos = std::min(mCursorPos, mHilitePos); mHilitePos = -1; } mCursorPos += aString.length(); bigChange = true; } } else if (theChar == 26) { // Undo mLastModifyIdx = -1; SexyString aSwapString = mString; int aSwapCursorPos = mCursorPos; int aSwapHilitePos = mHilitePos; mString = mUndoString; mCursorPos = mUndoCursor; mHilitePos = mUndoHilitePos; mUndoString = aSwapString; mUndoCursor = aSwapCursorPos; mUndoHilitePos = aSwapHilitePos; removeHilite = false; } else if (theKey == SDLK_LEFT) { if (controlDown) { // Get to a word while ((mCursorPos > 0) && (!IsPartOfWord(mString[mCursorPos-1]))) mCursorPos--; // Go beyond the word while ((mCursorPos > 0) && (IsPartOfWord(mString[mCursorPos-1]))) mCursorPos--; } else if (shiftDown || (mHilitePos == -1)) mCursorPos--; else mCursorPos = std::min(mCursorPos, mHilitePos); } else if (theKey == SDLK_RIGHT) { if (controlDown) { // Get to whitespace while ((mCursorPos < (int) mString.length()-1) && (IsPartOfWord(mString[mCursorPos+1]))) mCursorPos++; // Go beyond the whitespace while ((mCursorPos < (int) mString.length()-1) && (!IsPartOfWord(mString[mCursorPos+1]))) mCursorPos++; } if (shiftDown || (mHilitePos == -1)) mCursorPos++; else mCursorPos = std::max(mCursorPos, mHilitePos); } else if (theKey == SDLK_BACKSPACE) { if (mString.length() > 0) { if ((mHilitePos != -1) && (mHilitePos != mCursorPos)) { // Delete selection mString = mString.substr(0, std::min(mCursorPos, mHilitePos)) + mString.substr(std::max(mCursorPos, mHilitePos)); mCursorPos = std::min(mCursorPos, mHilitePos); mHilitePos = -1; bigChange = true; } else { // Delete char behind cursor if (mCursorPos > 0) mString = mString.substr(0, mCursorPos-1) + mString.substr(mCursorPos); else mString = mString.substr(mCursorPos); mCursorPos--; mHilitePos = -1; if (mCursorPos != mLastModifyIdx) bigChange = true; mLastModifyIdx = mCursorPos-1; } } } else if (theKey == SDLK_DELETE) { if (mString.length() > 0) { if ((mHilitePos != -1) && (mHilitePos != mCursorPos)) { // Delete selection mString = mString.substr(0, std::min(mCursorPos, mHilitePos)) + mString.substr(std::max(mCursorPos, mHilitePos)); mCursorPos = std::min(mCursorPos, mHilitePos); mHilitePos = -1; bigChange = true; } else { // Delete char in front of cursor if (mCursorPos < (int) mString.length()) mString = mString.substr(0, mCursorPos) + mString.substr(mCursorPos+1); if (mCursorPos != mLastModifyIdx) bigChange = true; mLastModifyIdx = mCursorPos; } } } else if (theKey == SDLK_HOME) { mCursorPos = 0; } else if (theKey == SDLK_END) { mCursorPos = mString.length(); } else if (theKey == SDLK_RETURN) { mEditListener->EditWidgetText(mId, mString); } else { SexyString aString = SexyString(1, theChar); unsigned int uTheChar = (unsigned int)theChar; unsigned int range = 127; if (gSexyAppBase->mbAllowExtendedChars) { range = 255; } if ((uTheChar >= 32) && (uTheChar <= range) && (mFont->StringWidth(aString) > 0) && mEditListener->AllowChar(mId, theChar)) { if ((mHilitePos != -1) && (mHilitePos != mCursorPos)) { // Replace selection with new character mString = mString.substr(0, std::min(mCursorPos, mHilitePos)) + SexyString(1, theChar) + mString.substr(std::max(mCursorPos, mHilitePos)); mCursorPos = std::min(mCursorPos, mHilitePos); mHilitePos = -1; bigChange = true; } else { // Insert character where cursor is mString = mString.substr(0, mCursorPos) + SexyString(1, theChar) + mString.substr(mCursorPos); if (mCursorPos != mLastModifyIdx+1) bigChange = true; mLastModifyIdx = mCursorPos; mHilitePos = -1; } mCursorPos++; FocusCursor(false); } else removeHilite = false; } if ((mMaxChars != -1) && ((int) mString.length() > mMaxChars)) mString = mString.substr(0, mMaxChars); EnforceMaxPixels(); if (mCursorPos < 0) mCursorPos = 0; else if (mCursorPos > (int) mString.length()) mCursorPos = mString.length(); if (anOldCursorPos != mCursorPos) { mBlinkAcc = 0; mShowingCursor = true; } FocusCursor(true); if (removeHilite || mHilitePos==mCursorPos) mHilitePos = -1; if (!mEditListener->AllowText(mId, mString)) { mString = anOldString; mCursorPos = anOldCursorPos; mHilitePos = anOldHilitePos; } else if (bigChange) { mUndoString = anOldString; mUndoCursor = anOldCursorPos; mUndoHilitePos = anOldHilitePos; } MarkDirty(); } //FIXME SDL takes care of modifying keys,etc so use it void EditWidget::KeyDown(SDLKey theKey) { if (((theKey < 'A') || (theKey >= 'Z')) && mEditListener->AllowKey(mId, theKey)) ProcessKey(theKey, 0); Widget::KeyDown(theKey); } void EditWidget::KeyChar(SexyChar theChar) { // if (mEditListener->AllowChar(mId, theChar)) ProcessKey(SDLK_UNKNOWN, theChar); Widget::KeyChar(theChar); } int EditWidget::GetCharAt(int x, int y) { int aPos = 0; SexyString &aString = GetDisplayString(); for (int i = mLeftPos; i < (int) aString.length(); i++) { SexyString aLoSubStr = aString.substr(mLeftPos, i-mLeftPos); SexyString aHiSubStr = aString.substr(mLeftPos, i-mLeftPos+1); int aLoLen = mFont->StringWidth(aLoSubStr); int aHiLen = mFont->StringWidth(aHiSubStr); if (x >= (aLoLen+aHiLen)/2 + 5) aPos = i+1; } return aPos; } void EditWidget::FocusCursor(bool bigJump) { while (mCursorPos < mLeftPos) { if (bigJump) mLeftPos = std::max(0, mLeftPos-10); else mLeftPos = std::max(0, mLeftPos-1); MarkDirty(); } if (mFont != NULL) { SexyString &aString = GetDisplayString(); while ((mWidth-8 > 0) && (mFont->StringWidth(aString.substr(0, mCursorPos)) - mFont->StringWidth(aString.substr(0, mLeftPos)) >= mWidth-8)) { if (bigJump) mLeftPos = std::min(mLeftPos + 10, (int) mString.length()-1); else mLeftPos = std::min(mLeftPos + 1, (int) mString.length()-1); MarkDirty(); } } } void EditWidget::MouseDown(int x, int y, int theBtnNum, int theClickCount) { Widget::MouseDown(x, y, theBtnNum, theClickCount); mHilitePos = -1; mCursorPos = GetCharAt(x, y); if (theClickCount > 1) { mHadDoubleClick = true; HiliteWord(); } MarkDirty(); FocusCursor(false); } void EditWidget::MouseUp(int x, int y, int theBtnNum, int theClickCount) { Widget::MouseUp(x,y,theBtnNum,theClickCount); if (mHilitePos==mCursorPos) mHilitePos = -1; if (mHadDoubleClick) { mHilitePos = -1; mCursorPos = GetCharAt(x, y); mHadDoubleClick = false; HiliteWord(); } MarkDirty(); } void EditWidget::HiliteWord() { SexyString &aString = GetDisplayString(); if (mCursorPos < (int) aString.length()) { // Find first space before word mHilitePos = mCursorPos; while ((mHilitePos > 0) && (IsPartOfWord(aString[mHilitePos-1]))) mHilitePos--; // Find first space after word while ((mCursorPos < (int) aString.length()-1) && (IsPartOfWord(aString[mCursorPos+1]))) mCursorPos++; if (mCursorPos < (int) aString.length()) mCursorPos++; } } void EditWidget::MouseDrag(int x, int y) { Widget::MouseDrag(x, y); if (mHilitePos == -1) mHilitePos = mCursorPos; mCursorPos = GetCharAt(x, y); MarkDirty(); FocusCursor(false); } void EditWidget::MouseEnter() { Widget::MouseEnter(); mWidgetManager->mApp->SetCursor(CURSOR_TEXT); } void EditWidget::MouseLeave() { Widget::MouseLeave(); mWidgetManager->mApp->SetCursor(CURSOR_POINTER); } void EditWidget::MarkDirty() { if (mColors[COLOR_BKG].mAlpha != 255) Widget::MarkDirtyFull(); else Widget::MarkDirty(); } libtuxcap-1.4.0/tuxcap/lib/SDLMixerSoundManager.cpp0000644000175000017500000001571011022277725022111 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "SDLMixerMusicInterface.h" #include "SDLMixerSoundManager.h" #include "SDLMixerSoundInstance.h" using namespace Sexy; SDLMixerSoundManager::SDLMixerSoundManager() { if(Mix_OpenAudio(44100, AUDIO_S16SYS, 2 , 1024)==-1) { printf("Mix_OpenAudio failed: %s\n", Mix_GetError()); } Mix_AllocateChannels(MAX_CHANNELS); for (int i = 0; i < MAX_SOURCE_SOUNDS; i++) { mSourceSounds[i] = NULL; mBaseVolumes[i] = 1; mBasePans[i] = 0; mBasePitches[i] = 1; } for (int i = 0; i < MAX_CHANNELS; i++) mPlayingSounds[i] = NULL; mMasterVolume = 1.0; mLastReleaseTick = SDL_GetTicks(); } SDLMixerSoundManager::~SDLMixerSoundManager() { StopAllSounds(); ReleaseChannels(); ReleaseSounds(); int numtimesopened, frequency, channels; Uint16 format; numtimesopened=Mix_QuerySpec(&frequency, &format, &channels); while(numtimesopened--) Mix_CloseAudio(); } int SDLMixerSoundManager::FindFreeChannel() { Uint32 aTick = SDL_GetTicks(); if (aTick - mLastReleaseTick > 1000) { ReleaseFreeChannels(); mLastReleaseTick = aTick; } for (int i = 0; i < MAX_CHANNELS; i++) { if (mPlayingSounds[i] == NULL) return i; if (mPlayingSounds[i]->IsReleased()) { delete mPlayingSounds[i]; mPlayingSounds[i] = NULL; return i; } } return -1; } bool SDLMixerSoundManager::Initialized() { int numtimesopened, frequency, channels; Uint16 format; numtimesopened=Mix_QuerySpec(&frequency, &format, &channels); return numtimesopened > 0; } void SDLMixerSoundManager::SetVolume(double theVolume) { mMasterVolume = (float)theVolume; for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] != NULL) mPlayingSounds[i]->RehupVolume(); } int SDLMixerSoundManager::LoadSound(const std::string& theFilename) { int id = GetFreeSoundId(); if (id != -1) { if (LoadSound(id, theFilename)) { return id; } } return -1; } bool SDLMixerSoundManager::LoadSound(unsigned int theSfxID, const std::string& theFilename) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; ReleaseSound(theSfxID); if (!Initialized()) return true; // sounds just won't play, but this is not treated as a failure condition std::string aFilename = ReplaceBackSlashes(GetAppResourceFolder() + theFilename); mSourceSounds[theSfxID] = Mix_LoadWAV(aFilename.c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = Mix_LoadWAV((aFilename + ".wav").c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = Mix_LoadWAV((aFilename + ".ogg").c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = Mix_LoadWAV((aFilename + ".mp3").c_str()); return mSourceSounds[theSfxID] != NULL; } void SDLMixerSoundManager::ReleaseSound(unsigned int theSfxID) { if (mSourceSounds[theSfxID] != NULL) { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] != NULL && mPlayingSounds[i]->mSample == mSourceSounds[theSfxID]) { mPlayingSounds[i]->Release(); break; } Mix_FreeChunk(mSourceSounds[theSfxID]); mSourceSounds[theSfxID] = NULL; } } bool SDLMixerSoundManager::SetBaseVolume(unsigned int theSfxID, double theBaseVolume) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBaseVolumes[theSfxID] = (float)theBaseVolume; return true; } bool SDLMixerSoundManager::SetBasePan(unsigned int theSfxID, int theBasePan) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBasePans[theSfxID] = theBasePan; return true; } bool SDLMixerSoundManager::SetBasePitch(unsigned int theSfxID, float theBasePitch) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBasePitches[theSfxID] = theBasePitch; return true; } SoundInstance* SDLMixerSoundManager::GetSoundInstance(unsigned int theSfxID) { if (theSfxID > MAX_SOURCE_SOUNDS) return NULL; int aFreeChannel = FindFreeChannel(); if (aFreeChannel < 0) return NULL; if (!Initialized()) { mPlayingSounds[aFreeChannel] = new SDLMixerSoundInstance(this, aFreeChannel, NULL); } else { if (!mSourceSounds[theSfxID]) return NULL; mPlayingSounds[aFreeChannel] = new SDLMixerSoundInstance(this, aFreeChannel, mSourceSounds[theSfxID]); } mPlayingSounds[aFreeChannel]->SetBasePan(mBasePans[theSfxID]); mPlayingSounds[aFreeChannel]->SetBaseVolume(mBaseVolumes[theSfxID]); mPlayingSounds[aFreeChannel]->AdjustBasePitch(mBasePitches[theSfxID]); return mPlayingSounds[aFreeChannel]; } void SDLMixerSoundManager::ReleaseSounds() { for (int i = 0; i < MAX_SOURCE_SOUNDS; i++) ReleaseSound(i); } void SDLMixerSoundManager::ReleaseChannels() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i]) { mPlayingSounds[i]->Release(); mPlayingSounds[i] = NULL; } } void SDLMixerSoundManager::ReleaseFreeChannels() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] && mPlayingSounds[i]->IsReleased()) mPlayingSounds[i] = NULL; } void SDLMixerSoundManager::StopAllSounds() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] != NULL) { bool isAutoRelease = mPlayingSounds[i]->mAutoRelease; mPlayingSounds[i]->Stop(); mPlayingSounds[i]->mAutoRelease = isAutoRelease; } } double SDLMixerSoundManager::GetMasterVolume() { return 0.0; } void SDLMixerSoundManager::SetMasterVolume(double theVolume) { } void SDLMixerSoundManager::Flush() { } void SDLMixerSoundManager::SetCooperativeWindow(HWND theHWnd, bool isWindowed) { } int SDLMixerSoundManager::GetFreeSoundId() { for (int i = 0; i < MAX_SOURCE_SOUNDS; ++i) { if (!mSourceSounds[i]) { return i; } } return -1; } int SDLMixerSoundManager::GetNumSounds() { int nr_sounds = 0; for (int i = 0; i < MAX_SOURCE_SOUNDS; ++i) { if (mSourceSounds[i]) { ++nr_sounds; } } return nr_sounds; } #undef SOUND_FLAGS libtuxcap-1.4.0/tuxcap/lib/DDInterface.cpp0000644000175000017500000007046211202747625020274 0ustar inniyahinniyah#define INITGUID #include "DDInterface.h" #include "DDImage.h" #include "D3DInterface.h" #if 0 #include #include "D3DTester.h" #include "AutoCrit.h" #include "PerfTimer.h" #include "Debug.h" #include "DirectXErrorString.h" #endif #include "SexyAppBase.h" #include "Graphics.h" #include "MemoryImage.h" using namespace Sexy; #if 0 typedef HRESULT (WINAPI *DirectDrawCreateFunc)(GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter); typedef HRESULT (WINAPI *DirectDrawCreateExFunc)(GUID FAR *lpGUID, LPVOID *lplpDD, REFIID iid, IUnknown FAR *pUnkOuter); extern HMODULE gDDrawDLL; static DirectDrawCreateFunc gDirectDrawCreateFunc = NULL; static DirectDrawCreateExFunc gDirectDrawCreateExFunc = NULL; #endif DDInterface::DDInterface(SexyAppBase* theApp) { mApp = theApp; mPrimarySurface = NULL; mDrawSurface = NULL; mSecondarySurface = NULL; mScreenImage = NULL; #if 0 mDD = NULL; mDD7 = NULL; #endif mRedAddTable = NULL; mGreenAddTable = NULL; mBlueAddTable = NULL; mInitialized = false; mVideoOnlyDraw = false; mScanLineFailCount = 0; //TODO: Standards, anyone? mCursorX = 0; mCursorY = 0; mCursorWidth = 64; mCursorHeight = 64; mCursorImage = NULL; mOldCursorArea = NULL; mHasOldCursorArea = false; mOldCursorAreaImage = NULL; mInitCount = 0; mRefreshRate = 60; mMillisecondsPerFrame = 1000/mRefreshRate; mD3DInterface = new D3DInterface; #if 0 mD3DTester = NULL; gDirectDrawCreateFunc = (DirectDrawCreateFunc)GetProcAddress(gDDrawDLL,"DirectDrawCreate"); gDirectDrawCreateExFunc = (DirectDrawCreateExFunc)GetProcAddress(gDDrawDLL,"DirectDrawCreateEx"); #endif } DDInterface::~DDInterface() { delete [] mRedAddTable; delete [] mGreenAddTable; delete [] mBlueAddTable; Cleanup(); delete mD3DInterface; #if 0 delete mD3DTester; #endif } std::string DDInterface::ResultToString(int theResult) { switch (theResult) { case RESULT_OK: return "RESULT_OK"; case RESULT_FAIL: return "RESULT_FAIL"; case RESULT_DD_CREATE_FAIL: return "RESULT_DD_CREATE_FAIL"; case RESULT_SURFACE_FAIL: return "RESULT_SURFACE_FAIL"; case RESULT_EXCLUSIVE_FAIL: return "RESULT_EXCLUSIVE_FAIL"; case RESULT_DISPCHANGE_FAIL: return "RESULT_DISPCHANGE_FAIL"; case RESULT_INVALID_COLORDEPTH: return "RESULT_INVALID_COLORDEPTH"; default: return "RESULT_UNKNOWN"; } } #if 0 bool DDInterface::GotDXError(HRESULT theResult, const char *theContext) { if (!SUCCEEDED(theResult)) { std::string anError = GetDirectXErrorString(theResult); mErrorString = StrFormat("%s: %s",theContext, anError.c_str()); return true; } else return false; } #endif DDImage* DDInterface::GetScreenImage() { return mScreenImage; } #if 0 void DDInterface::ClearSurface(LPDIRECTDRAWSURFACE theSurface) { if (theSurface) { DDSURFACEDESC desc; memset(&desc, 0, sizeof desc); desc.dwSize = sizeof desc; HRESULT hr = theSurface->Lock(NULL, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY, NULL); if ( DD_OK == hr ) { DWORD pixelSize = desc.ddpfPixelFormat.dwRGBBitCount / 8; unsigned char* p = (unsigned char*)desc.lpSurface; for ( DWORD row = 0; row < desc.dwHeight; ++row ) { memset(p, 0, pixelSize*desc.dwWidth); p += desc.lPitch; } theSurface->Unlock(NULL); } } } bool DDInterface::Do3DTest(HWND theHWND) { if (mD3DTester == NULL) { if (mApp->mTest3D || mApp->mAutoEnable3D) { mD3DTester = new D3DTester; mD3DTester->SetVidMemoryConstraints(mApp->mMinVidMemory3D, mApp->mRecommendedVidMemory3D); mD3DTester->TestD3D(theHWND, mDD7); if (mApp->mAutoEnable3D && mD3DTester->Is3DRecommended()) mIs3D = true; if (!mD3DTester->Is3DSupported()) mIs3D = false; if (mD3DTester->ResultsChanged() && !mD3DTester->Is3DRecommended()) mIs3D = false; return true; } } return false; } #endif int DDInterface::Init(HWND theWindow, bool IsWindowed) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif mInitialized = false; Cleanup(); #if 0 HRESULT aResult; DDSURFACEDESC2 aDesc; if (gDirectDrawCreateExFunc != NULL) { aResult = gDirectDrawCreateExFunc(NULL, (LPVOID*)&mDD7, IID_IDirectDraw7, NULL); if (GotDXError(aResult, "DirectDrawCreateEx")) return RESULT_DD_CREATE_FAIL; aResult = mDD7->QueryInterface(IID_IDirectDraw, (LPVOID*)&mDD); if (GotDXError(aResult, "QueryrInterface IID_IDirectDraw")) return RESULT_DD_CREATE_FAIL; } else { aResult = gDirectDrawCreateFunc(NULL, &mDD, NULL); } if (Do3DTest(theWindow)) { if (mD3DTester->ResultsChanged()) mApp->Done3dTesting(); } RECT aRect; GetClientRect(theWindow, &aRect); mHWnd = theWindow; #endif mWidth = mApp->mWidth; mHeight = mApp->mHeight; mAspect.Set(mWidth, mHeight); #if 0 mDesktopWidth = GetSystemMetrics(SM_CXSCREEN); mDesktopHeight = GetSystemMetrics(SM_CYSCREEN); mDesktopAspect.Set(mDesktopWidth, mDesktopHeight); #endif mDisplayWidth = mWidth; mDisplayHeight = mHeight; mDisplayAspect = mAspect; mPresentationRect = Rect( 0, 0, mWidth, mHeight ); mApp->mScreenBounds = mPresentationRect; mFullscreenBits = mApp->mFullscreenBits; mIsWindowed = IsWindowed; mHasOldCursorArea = false; #if 0 OutputDebug(_S("Application requests %4lu x %4lu [%2d:%2d]\n"), mWidth, mHeight, mAspect.mNumerator, mAspect.mDenominator); if (GotDXError(aResult, "DirectDrawCreate")) return RESULT_DD_CREATE_FAIL; if (IsWindowed) { OutputDebug(_S("Hack aspect is [%2d:%2d]\n"), mApp->mWindowAspect.mNumerator, mApp->mWindowAspect.mDenominator); if ( mApp->mEnableWindowAspect && mAspect < mApp->mWindowAspect ) { mIsWidescreen = true; // Setup the window at the hack aspect, // but with the height requested by the application. mDisplayWidth = mHeight * mApp->mWindowAspect; mDisplayHeight = mHeight; mDisplayAspect = mApp->mWindowAspect; // resize the window. RECT rc; POINT pt; WINDOWINFO info; ::GetWindowInfo(theWindow, &info); ::GetClientRect(theWindow, &rc); pt.x = rc.left; pt.y = rc.top; ::ClientToScreen(theWindow, &pt); rc.left = pt.x - (mDisplayWidth - mWidth) / 2; rc.top = pt.y - (mDisplayHeight - mHeight) / 2; rc.right = rc.left + mDisplayWidth; rc.bottom = rc.top + mDisplayHeight; ::AdjustWindowRectEx(&rc, info.dwStyle, false, info.dwExStyle); ::MoveWindow(theWindow, max(0, rc.left), max(0, rc.top), rc.right-rc.left, rc.bottom-rc.top, false); if ( mApp->mWidescreenAware ) { mWidth = mDisplayWidth; mHeight = mDisplayHeight; mAspect = mDisplayAspect; mPresentationRect.mWidth = mDisplayWidth; mPresentationRect.mHeight = mDisplayHeight; mPresentationRect.mX = 0; mPresentationRect.mY = 0; } else { // Set the dest rect for drawing the back buffer to the center of // the wide display. mPresentationRect.mWidth = mWidth; mPresentationRect.mHeight = mHeight; mPresentationRect.mX = ( mDisplayWidth - mPresentationRect.mWidth ) / 2; mPresentationRect.mY = 0; } } OutputDebug(_S("Window is %4lu x %4lu [%2d:%2d]\n"), mDisplayWidth, mDisplayHeight, mDisplayAspect.mNumerator, mDisplayAspect.mDenominator); aResult = mDD->SetCooperativeLevel(theWindow, DDSCL_NORMAL); ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_CAPS; aDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if (mIs3D) aDesc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; aDesc.dwBackBufferCount = 1; aResult = CreateSurface(&aDesc, &mPrimarySurface, NULL); if (aResult==DDERR_INVALIDPIXELFORMAT) // check for non 16 or 32 bit primary surface return RESULT_INVALID_COLORDEPTH; else if (GotDXError(aResult, "CreateSurface Windowed Primary")) return RESULT_SURFACE_FAIL; ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; aDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; if (mIs3D) aDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; aDesc.dwWidth = mWidth; aDesc.dwHeight = mHeight; aResult = CreateSurface(&aDesc, &mDrawSurface, NULL); if (GotDXError(aResult,"CreateSurface Windowed DrawSurface")) return RESULT_SURFACE_FAIL; IDirectDrawClipper* aClipper; aResult = mDD->CreateClipper(0, &aClipper, NULL); if (GotDXError(aResult,"CreateClipper Windowed")) return RESULT_FAIL; // Associate the clipper with the window aResult = aClipper->SetHWnd(0, theWindow); if (SUCCEEDED(aResult)) aResult = mPrimarySurface->SetClipper(aClipper); aClipper->Release(); } else { OutputDebug(_S("Desktop is %4lu x %4lu [%2d:%2d]\n"), mDesktopWidth, mDesktopHeight, mDesktopAspect.mNumerator, mDesktopAspect.mDenominator); if ( mIs3D && mAspect < mDesktopAspect ) { mIsWidescreen = true; // Set the display mode to the size of the desktop. mDisplayWidth = mDesktopWidth; mDisplayHeight = mDesktopHeight; mDisplayAspect = mDesktopAspect; if ( mApp->mWidescreenAware ) { // Setup the draw buffer(s) at the same aspect ratio as the desktop, // but with the height requested by the application. mAspect = mDisplayAspect; mWidth = mHeight * mAspect; mPresentationRect.mWidth = mDisplayWidth; mPresentationRect.mHeight = mDisplayHeight; mPresentationRect.mX = 0; mPresentationRect.mY = 0; } else { // Set the dest rect for drawing the back buffer to the center of // the wide display. mPresentationRect.mWidth = mWidth * mDisplayHeight / mHeight; mPresentationRect.mHeight = mDisplayHeight; mPresentationRect.mX = ( mDisplayWidth - mPresentationRect.mWidth ) / 2; mPresentationRect.mY = 0; } } OutputDebug(_S("Display is %4lu x %4lu [%2d:%2d]\n"), mDisplayWidth, mDisplayHeight, mDisplayAspect.mNumerator, mDisplayAspect.mDenominator); aResult = mDD->SetCooperativeLevel(theWindow, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); if (GotDXError(aResult,"SetCooperativeLevel FullScreen")) return RESULT_EXCLUSIVE_FAIL; aResult = mDD->SetDisplayMode(mDisplayWidth, mDisplayHeight, mFullscreenBits); if (GotDXError(aResult,"SetDisplayMode FullScreen")) return RESULT_DISPCHANGE_FAIL; ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; aDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX/* | ,DDSCAPS_FRONTBUFFER*/; aDesc.dwBackBufferCount = 1; if (mIs3D) aDesc.ddsCaps.dwCaps |= DDSCAPS_3DDEVICE; aResult = CreateSurface(&aDesc, &mPrimarySurface, NULL); if (GotDXError(aResult,"CreateSurface FullScreen Primary")) return RESULT_SURFACE_FAIL; DDSCAPS aCaps; ZeroMemory(&aCaps,sizeof(aCaps)); aCaps.dwCaps = DDSCAPS_BACKBUFFER; aResult = mPrimarySurface->GetAttachedSurface(&aCaps, &mSecondarySurface); if (GotDXError(aResult,"GetAttachedSurface")) return RESULT_SURFACE_FAIL; if (mIsWidescreen) { ClearSurface(mPrimarySurface); ClearSurface(mSecondarySurface); } ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; aDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; if (mIs3D) aDesc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; aDesc.dwWidth = mWidth; aDesc.dwHeight = mHeight; aResult = CreateSurface(&aDesc, &mDrawSurface, NULL); if (GotDXError(aResult, "CreateSurface FullScreen DrawSurface")) return RESULT_SURFACE_FAIL; IDirectDrawClipper* aClipper; aResult = mDD->CreateClipper(0, &aClipper, NULL); if (GotDXError(aResult,"CreateClipper FullScreen")) return RESULT_FAIL; // Associate the clipper with the window aResult = aClipper->SetHWnd(0, theWindow); if (SUCCEEDED(aResult)) aResult = mPrimarySurface->SetClipper(aClipper); aClipper->Release(); if (!mApp->mFullScreenPageFlip) mDD->FlipToGDISurface(); } OutputDebug(_S("Draw buffer is %4lu x %4lu [%2d:%2d]\n"), mWidth, mHeight, mAspect.mNumerator, mAspect.mDenominator); if (FAILED(mDD->GetMonitorFrequency(&mRefreshRate)) || mRefreshRate<60) { mApp->mVSyncBroken = true; mRefreshRate = 60; } if (mRefreshRate < 60) { mApp->mVSyncBroken = true; mRefreshRate = 60; } else if (mRefreshRate > 100) // We must have at least 1 Update per UpdateF for demo compatibility { mApp->mVSyncBroken = true; mRefreshRate = 100; } mMillisecondsPerFrame = 1000/mRefreshRate; #endif CreateSurface(&mOldCursorArea, mCursorWidth,mCursorHeight,true); SDL_SetAlpha(mOldCursorArea,0,0); mOldCursorAreaImage = new DDImage(this); mOldCursorAreaImage->SetSurface(mOldCursorArea); mOldCursorAreaImage->SetImageMode(false, false); #if 0 CreateSurface(&mPrimarySurface, mWidth,mHeight,true); CreateSurface(&mDrawSurface, mWidth,mHeight,true); #endif SetVideoOnlyDraw(mVideoOnlyDraw); // Get data from the primary surface if (mScreenImage->mSurface != NULL) { //FIXME SDL stores this for us in the surface, so use it! if ((mScreenImage->mSurface->format->BitsPerPixel != 16) && (mScreenImage->mSurface->format->BitsPerPixel != 32)) return RESULT_FAIL; mRGBBits = mScreenImage->mSurface->format->BitsPerPixel; mRedMask = mScreenImage->mSurface->format->Rmask; mGreenMask = mScreenImage->mSurface->format->Gmask; mBlueMask = mScreenImage->mSurface->format->Bmask; int i; #if 1 mRedShift = mScreenImage->mSurface->format->Rshift; mGreenShift = mScreenImage->mSurface->format->Gshift; mBlueShift = mScreenImage->mSurface->format->Bshift; #else for (i = 32; i >= 0; i--) { if (((mRedMask >> i) & 1) != 0) mRedShift = i; if (((mGreenMask >> i) & 1) != 0) mGreenShift = i; if (((mBlueMask >> i) & 1) != 0) mBlueShift = i; } #endif for (i = 0; i < 32; i++) { if ((i+mRedShift < 32) && ((mRedMask >> (i+mRedShift)) != 0)) mRedBits = i+1; if ((i+mGreenShift < 32) && ((mGreenMask >> (i+mGreenShift)) != 0)) mGreenBits = i+1; if ((i+mBlueShift < 32) && ((mBlueMask >> (i+mBlueShift)) != 0)) mBlueBits = i+1; } delete [] mRedAddTable; delete [] mGreenAddTable; delete [] mBlueAddTable; int aMaxR = (1<InitFromDDInterface(this)) { mErrorString = "3D init error: "; mErrorString += D3DInterface::mErrorString; return RESULT_3D_FAIL; } } mInitCount++; mInitialized = true; return RESULT_OK; } void DDInterface::SetVideoOnlyDraw(bool videoOnlyDraw) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif mVideoOnlyDraw = videoOnlyDraw; #if 0 if (mSecondarySurface == NULL) { if (CreateSurface(&mSecondarySurface, mWidth,mHeight,true) == RESULT_FAIL) mVideoOnlyDraw = false; } #endif bool useSecondary = mVideoOnlyDraw; delete mScreenImage; mScreenImage = new DDImage(this); //FIXME using sdl screensurface from sexyappbase created by sdl_setvideomode mScreenImage->SetSurface(gSexyAppBase->surface);/*useSecondary ? mSecondarySurface : mDrawSurface);*/ mScreenImage->mNoLock = mVideoOnlyDraw; mScreenImage->mVideoMemory = mVideoOnlyDraw; mScreenImage->SetImageMode(false, false); } void DDInterface::RemapMouse(int& theX, int& theY) { if (mInitialized) { theX = ( theX - mPresentationRect.mX ) * mWidth / mPresentationRect.mWidth; theY = ( theY - mPresentationRect.mY ) * mHeight / mPresentationRect.mHeight; } } uint32_t DDInterface::GetColorRef(uint32_t theRGB) { #if 0 DDSURFACEDESC aDesc; ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; HRESULT aResult = mPrimarySurface->GetSurfaceDesc(&aDesc); BYTE bRed = (BYTE) ((theRGB >> 16) & 0xFF); BYTE bGreen = (BYTE) ((theRGB >> 8) & 0xFF); BYTE bBlue = (BYTE) ((theRGB ) & 0xFF); uint32_t aColor; aColor = ((DWORD(((LONGLONG)bRed * (LONGLONG)aDesc.ddpfPixelFormat.dwRBitMask) / 255) & aDesc.ddpfPixelFormat.dwRBitMask) | (DWORD(((LONGLONG)bGreen * (LONGLONG)aDesc.ddpfPixelFormat.dwGBitMask) / 255) & aDesc.ddpfPixelFormat.dwGBitMask) | (DWORD(((LONGLONG)bBlue * (LONGLONG)aDesc.ddpfPixelFormat.dwBBitMask) / 255) & aDesc.ddpfPixelFormat.dwBBitMask)); return aColor; #else return 0x00000000; #endif } void DDInterface::AddDDImage(DDImage* theDDImage) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif mDDImageSet.insert(theDDImage); } void DDInterface::RemoveDDImage(DDImage* theDDImage) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif DDImageSet::iterator anItr = mDDImageSet.find(theDDImage); if (anItr != mDDImageSet.end()) mDDImageSet.erase(anItr); } void DDInterface::Remove3DData(MemoryImage* theImage) // for 3d texture cleanup { mD3DInterface->RemoveMemoryImage(theImage); } void DDInterface::Cleanup() { #if 0 AutoCrit anAutoCrit(mCritSect); #endif mInitialized = false; mD3DInterface->Cleanup(); if (mScreenImage != NULL) { delete mScreenImage; mScreenImage = NULL; } if (mDrawSurface != NULL) { SDL_FreeSurface(mDrawSurface); mDrawSurface = NULL; } if (mSecondarySurface != NULL) { SDL_FreeSurface(mSecondarySurface); mSecondarySurface = NULL; } if (mPrimarySurface != NULL) { SDL_FreeSurface(mPrimarySurface); mPrimarySurface = NULL; } if (mOldCursorAreaImage != NULL) { delete mOldCursorAreaImage; mOldCursorAreaImage = NULL; } #if 0 if (mDD != NULL) { mDD->SetCooperativeLevel(mHWnd, DDSCL_NORMAL); mDD->Release(); mDD = NULL; } if (mDD7 != NULL) { mDD7->Release(); mDD7 = NULL; } #endif } #if 0 bool DDInterface::CopyBitmap(LPDIRECTDRAWSURFACE theSurface, HBITMAP theBitmap, int theX, int theY, int theWidth, int theHeight) { AutoCrit anAutoCrit(mCritSect); HRESULT hr; if (theBitmap == NULL || theSurface == NULL) return false; // Make sure this surface is restored. theSurface->Restore(); // Get size of the bitmap BITMAP bmBitmap; GetObject(theBitmap, sizeof(bmBitmap), &bmBitmap); theWidth = (theWidth == 0) ? bmBitmap.bmWidth : theWidth; theHeight = (theHeight == 0) ? bmBitmap.bmHeight : theHeight; DDSURFACEDESC aDesc; ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH; hr = theSurface->GetSurfaceDesc(&aDesc); if (FAILED(hr)) return false; // Create memory DC HDC hdcImage = CreateCompatibleDC(NULL); if (hdcImage != NULL) { // Select bitmap into memory DC HBITMAP anOldBitmap = (HBITMAP)SelectObject(hdcImage, theBitmap); // Get surface DC HDC hdc; hr = theSurface->GetDC(&hdc); if (SUCCEEDED(hr)) { // Copy the bitmap. Use BitBlt, if possible, otherwise use // StretchBlt if (theWidth == aDesc.dwWidth && theHeight == aDesc.dwHeight) { BitBlt(hdc, 0, 0, theWidth, theHeight, hdcImage, theX, theY, SRCCOPY); } else { StretchBlt(hdc, 0, 0, aDesc.dwWidth, aDesc.dwHeight, hdcImage, theX, theY, theWidth, theHeight, SRCCOPY); } // Release surface DC theSurface->ReleaseDC(hdc); } // Select old bitmap into the memory DC and delete the DC SelectObject(hdcImage, anOldBitmap); DeleteDC(hdcImage); } else return false; return true; } extern std::fstream gStreamThing; #endif int DDInterface::CreateSurface(SDL_Surface** theSurface, int width, int height, bool mVideoMemory) { int aResult; //FIXME Uint32 flags;// = SDL_SRCCOLORKEY || SDL_DOUBLEBUF; if (mVideoMemory) flags |= SDL_HWSURFACE; else flags |= SDL_SWSURFACE; //FIXME fixed depth SDL_Surface* mSurface; mSurface = SDL_CreateRGBSurface(flags, width, height, 32, SDL_rmask, SDL_gmask, SDL_bmask, SDL_amask); if (mSurface == NULL) return RESULT_FAIL; *theSurface = mSurface; #ifdef OPTIMIZE_SOFTWARE_DRAWING // If things are stored blue low, green middle, red high, we can optimize a lot of our software rendering based on bit patterns. // This of course does not matter for native data which is already in the correct order (and can be optimized similarly). gOptimizeSoftwareDrawing = mSurface->format->Bmask < mSurface->format->Gmask && mSurface->format->Gmask < mSurface->format->Rmask; #endif return RESULT_OK; } bool DDInterface::Redraw(Rect* theClipRect) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif if (!mInitialized) return false; #if 0 DDBLTFX aBltFX; ZeroMemory(&aBltFX, sizeof(aBltFX)); aBltFX.dwSize = sizeof(aBltFX); #endif if(mIs3D) { if (!mD3DInterface->mErrorString.empty()) { mIs3D = false; return false; } mD3DInterface->Flush(); } Rect aDestRect; Rect aSrcRect; if (NULL == theClipRect || mIsWidescreen) { // ClipRect cannot be supported when the draw surface and // primary surface are not the same size in widescreen mode. aDestRect = mPresentationRect; aSrcRect = Rect(0, 0, mWidth, mHeight); } else { aDestRect = *theClipRect; aSrcRect = *theClipRect; } #if 0 if ( mIsWidescreen ) { aBltFX.dwDDFX = DDBLTFX_ARITHSTRETCHY; } Point aPoint = {0, 0}; ClientToScreen(mHWnd, &aPoint); OffsetRect(&aDestRect, aPoint.x, aPoint.y); DDSURFACEDESC aDesc; ZeroMemory(&aDesc,sizeof(&aDesc)); aDesc.dwSize=sizeof(aDesc); mDrawSurface->Lock(NULL,&aDesc,DDLOCK_SURFACEMEMORYPTR|DDLOCK_WAIT|DDLOCK_READONLY ,0); mDrawSurface->Unlock(NULL); #endif if (mIsWindowed) { #if 0 HRESULT aResult; int aScreenHeight = GetSystemMetrics(SM_CYSCREEN); #endif if (!mVideoOnlyDraw) { #if 0 if ((mApp->mWaitForVSync) && (!mApp->mSoftVSyncWait)) { bool scanLineFail = false; if (mScanLineFailCount >= 3) scanLineFail = true; if (!scanLineFail) { int aHalfMarkClient = mApp->mHeight / 2; int aHalfMarkScreen = aDestRect.top + aHalfMarkClient; int aBotMarkScreen = aDestRect.top + mHeight; DWORD aScanLine = 0x7FFFFFFF; bool wasLess = false; DWORD aTopStartTick = GetTickCount(); for (;;) { aResult = mDD->GetScanLine(&aScanLine); if (aResult == DD_OK) { // Wait until we scan below half way on the window int aHalfMarkDist = aHalfMarkScreen - aScanLine; if ((aHalfMarkDist <= 0) || ((int) aScanLine >= aScreenHeight)) { if (wasLess) break; } else { wasLess = true; } } else { if (aResult == DDERR_VERTICALBLANKINPROGRESS ) { if (wasLess) break; } else { scanLineFail = true; break; } } DWORD aTickNow = GetTickCount(); if (aTickNow - aTopStartTick >= 200) { // It shouldn't take this long scanLineFail = true; break; } } if (!scanLineFail) { mScanLineFailCount = 0; RECT aTopDestRect = {aDestRect.left, aDestRect.top, aDestRect.right, aHalfMarkScreen}; RECT aTopSrcRect = {aSrcRect.left, aSrcRect.top, aSrcRect.right, aHalfMarkClient}; aResult = mPrimarySurface->Blt(&aTopDestRect, mDrawSurface, &aTopSrcRect, DDBLT_WAIT, &aBltFX); DWORD aLastScanLine = aScanLine; for (;;) { if (SUCCEEDED(mDD->GetScanLine(&aScanLine))) { // Wait until we scan below the bottom of the window int aHalfMarkDist = aBotMarkScreen - aScanLine; if ((aScanLine < aLastScanLine) || (aHalfMarkDist <= 0)) break; } } RECT aBotDestRect = {aDestRect.left, aHalfMarkScreen, aDestRect.right, aDestRect.bottom}; RECT aBotSrcRect = {aSrcRect.left, aHalfMarkClient, aSrcRect.right, aSrcRect.bottom}; aResult = mPrimarySurface->Blt(&aBotDestRect, mDrawSurface, &aBotSrcRect, DDBLT_WAIT, &aBltFX); } else { mScanLineFailCount++; } } if (scanLineFail) { mDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); aResult = mPrimarySurface->Blt(&aDestRect, mDrawSurface, &aSrcRect, DDBLT_WAIT, &aBltFX); } #endif } #if 0 else { aResult = mPrimarySurface->Blt(&aDestRect, mDrawSurface, &aSrcRect, DDBLT_WAIT, &aBltFX); } #endif } #if 0 else { if ((mApp->mWaitForVSync) && (!mApp->mSoftVSyncWait)) mDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0); DrawCursorTo(mSecondarySurface, true); aResult = mPrimarySurface->Blt(&aDestRect, mSecondarySurface, &aSrcRect, DDBLT_WAIT, &aBltFX); #else DrawCursor(); if (mIs3D) SDL_GL_SwapBuffers(); else SDL_Flip(mScreenImage->mSurface); //restore custom cursor background RestoreOldCursorArea(); return true; #endif #if 0 } return !GotDXError(aResult,"Redraw Windowed"); return true; } else { // Don't flip away from the GDI surface during the TryMedia purchasing process if (!mApp->mNoDefer && mApp->mFullScreenPageFlip) { if (!mVideoOnlyDraw) HRESULT aResult = mSecondarySurface->Blt(&aDestRect, mDrawSurface, &aSrcRect, DDBLT_WAIT, &aBltFX); mCursorX = mNextCursorX; mCursorY = mNextCursorY; DrawCursorTo(mSecondarySurface, true); HRESULT aResult = mPrimarySurface->Flip(NULL, DDFLIP_WAIT); return !GotDXError(aResult,"Redraw FullScreen Flip"); } else { HRESULT aResult = mPrimarySurface->Blt(&aDestRect, mDrawSurface, &aSrcRect, DDBLT_WAIT, &aBltFX); return !GotDXError(aResult,"Redraw FullScreen Blt"); } } #endif } bool DDInterface::SetCursorImage(Image* theImage) { #if 0 AutoCrit anAutoCrit(mCritSect); #endif if (mCursorImage != theImage) { // Wait until next Redraw or cursor move to draw new cursor mCursorImage = theImage; return true; } else return false; } void DDInterface::RestoreOldCursorArea() { if ((mHasOldCursorArea)) { Rect aSexyScreenRect( mCursorX - (mCursorWidth / 2), mCursorY - (mCursorHeight / 2), mCursorWidth, mCursorHeight); SDL_Rect source = { 0,0,64,64 }; SDL_Rect destination = {aSexyScreenRect.mX, aSexyScreenRect.mY, aSexyScreenRect.mWidth, aSexyScreenRect.mHeight}; if (!mIs3D) SDL_BlitSurface(mOldCursorArea, &source, gSexyAppBase->surface, &destination); else { static Color c(255,255,255); mD3DInterface->BltOldCursorArea( aSexyScreenRect.mX , aSexyScreenRect.mY, c); } mHasOldCursorArea = false; } } void DDInterface::DrawCursor() { if ((mCursorImage != NULL)) { Rect aSexyScreenRect( mCursorX - (mCursorWidth / 2), mCursorY - (mCursorHeight / 2), mCursorWidth, mCursorHeight); SDL_Rect destination = { 0,0,64,64 }; SDL_Rect source = {aSexyScreenRect.mX, aSexyScreenRect.mY, aSexyScreenRect.mWidth, aSexyScreenRect.mHeight}; int res = 0; if (!mIs3D) res = SDL_BlitSurface(gSexyAppBase->surface, &source, mOldCursorArea, &destination); else { mD3DInterface->FillOldCursorAreaTexture(aSexyScreenRect.mX, mHeight - 64 - aSexyScreenRect.mY); } mHasOldCursorArea = (res == 0); Graphics g(mScreenImage); g.DrawImage(mCursorImage, mCursorX - (mCursorWidth / 2) + (mCursorWidth - mCursorImage->mWidth)/2, mCursorY - (mCursorHeight / 2) + (mCursorHeight - mCursorImage->mHeight)/2); } else mHasOldCursorArea = false; } libtuxcap-1.4.0/tuxcap/lib/NativeDisplay.cpp0000644000175000017500000000114110641010433020706 0ustar inniyahinniyah#include "NativeDisplay.h" using namespace Sexy; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// NativeDisplay::NativeDisplay() { mRGBBits = 0; mRedMask = 0; mGreenMask = 0; mBlueMask = 0; mRedBits = 0; mGreenBits = 0; mBlueBits = 0; mRedShift = 0; mGreenShift = 0; mBlueShift = 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// NativeDisplay::~NativeDisplay() { } libtuxcap-1.4.0/tuxcap/lib/HyperlinkWidget.cpp0000644000175000017500000000211710641010433021247 0ustar inniyahinniyah#include "HyperlinkWidget.h" #include "Graphics.h" #include "ImageFont.h" #if 0 #include "SysFont.h" #endif #include "WidgetManager.h" using namespace Sexy; HyperlinkWidget::HyperlinkWidget(int theId, ButtonListener* theButtonListener) : ButtonWidget(theId, theButtonListener), mColor(255, 255, 255), mOverColor(255, 255, 255) { mDoFinger = true; mUnderlineOffset = 3; mUnderlineSize = 1; } void HyperlinkWidget::Draw(Graphics* g) { #if 0 if (mFont == NULL) mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 10); //baz changed #endif int aFontX = (mWidth - mFont->StringWidth(mLabel))/2; int aFontY = (mHeight + mFont->GetAscent())/2 - 1; if (mIsOver) g->SetColor(mOverColor); else g->SetColor(mColor); g->SetFont(mFont); g->DrawString(mLabel, aFontX, aFontY); for (int i = 0; i < mUnderlineSize; i++) g->FillRect(aFontX, aFontY+mUnderlineOffset+i, mFont->StringWidth(mLabel), 1); } void HyperlinkWidget::MouseEnter() { ButtonWidget::MouseEnter(); MarkDirtyFull(); } void HyperlinkWidget::MouseLeave() { ButtonWidget::MouseLeave(); MarkDirtyFull(); } libtuxcap-1.4.0/tuxcap/lib/ButtonWidget.cpp0000644000175000017500000001472210641010442020562 0ustar inniyahinniyah#include "ButtonWidget.h" #include "Image.h" #if 0 #include "SysFont.h" #endif #include "Font.h" #include "WidgetManager.h" #include "ButtonListener.h" using namespace Sexy; static int gButtonWidgetColors[][3] = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {255, 255, 255}, {132, 132, 132}, {212, 212, 212}}; ButtonWidget::ButtonWidget(int theId, ButtonListener* theButtonListener) { mId = theId; mFont = NULL; mLabelJustify = BUTTON_LABEL_CENTER; mButtonImage = NULL; mOverImage = NULL; mDownImage = NULL; mDisabledImage = NULL; mInverted = false; mBtnNoDraw = false; mFrameNoDraw = false; mButtonListener = theButtonListener; mHasAlpha = true; mOverAlpha = 0; mOverAlphaSpeed = 0; mOverAlphaFadeInSpeed = 0; SetColors(gButtonWidgetColors, NUM_COLORS); } ButtonWidget::~ButtonWidget() { delete mFont; } void ButtonWidget::SetFont(Font* theFont) { delete mFont; mFont = theFont->Duplicate(); } bool ButtonWidget::IsButtonDown() { return mIsDown && mIsOver && !mDisabled; } bool ButtonWidget::HaveButtonImage(Image *theImage, const Rect &theRect) { return (theImage!=NULL || theRect.mWidth!=0); } void ButtonWidget::DrawButtonImage(Graphics *g, Image *theImage, const Rect &theRect, int x, int y) { if (theRect.mWidth != 0) g->DrawImage(mButtonImage,x,y,theRect); else g->DrawImage(theImage,x,y); } void ButtonWidget::Draw(Graphics* g) { if (mBtnNoDraw) return; #if 0 if ((mFont == NULL) && (mLabel.length() > 0)) mFont = new SysFont(mWidgetManager->mApp, "Arial Unicode MS", 10); #endif bool isDown = mIsDown && mIsOver && !mDisabled; isDown ^= mInverted; int aFontX = 0; // BUTTON_LABEL_LEFT int aFontY = 0; if (mFont != NULL) { if (mLabelJustify == BUTTON_LABEL_CENTER) aFontX = (mWidth - mFont->StringWidth(mLabel))/2; else if (mLabelJustify == BUTTON_LABEL_RIGHT) aFontX = mWidth - mFont->StringWidth(mLabel); aFontY = (mHeight + mFont->GetAscent() - mFont->GetAscent()/6 - 1)/2; } g->SetFont(mFont); if ((mButtonImage == NULL) && (mDownImage == NULL)) { if (!mFrameNoDraw) { g->SetColor(mColors[COLOR_BKG]); g->FillRect(0, 0, mWidth, mHeight); } if (isDown) { if (!mFrameNoDraw) { g->SetColor(mColors[COLOR_DARK_OUTLINE]); g->FillRect(0, 0, mWidth-1, 1); g->FillRect(0, 0, 1, mHeight-1); g->SetColor(mColors[COLOR_LIGHT_OUTLINE]); g->FillRect(0, mHeight - 1, mWidth, 1); g->FillRect(mWidth - 1, 0, 1, mHeight); g->SetColor(mColors[COLOR_MEDIUM_OUTLINE]); g->FillRect(1, 1, mWidth - 3, 1); g->FillRect(1, 1, 1, mHeight - 3); } if (mIsOver) g->SetColor(mColors[COLOR_LABEL_HILITE]); else g->SetColor(mColors[COLOR_LABEL]); g->DrawString(mLabel, aFontX+1, aFontY+1); } else { if (!mFrameNoDraw) { g->SetColor(mColors[COLOR_LIGHT_OUTLINE]); g->FillRect(0, 0, mWidth-1, 1); g->FillRect(0, 0, 1, mHeight-1); g->SetColor(mColors[COLOR_DARK_OUTLINE]); g->FillRect(0, mHeight - 1, mWidth, 1); g->FillRect(mWidth - 1, 0, 1, mHeight); g->SetColor(mColors[COLOR_MEDIUM_OUTLINE]); g->FillRect(1, mHeight - 2, mWidth - 2, 1); g->FillRect(mWidth - 2, 1, 1, mHeight - 2); } if (mIsOver) g->SetColor(mColors[COLOR_LABEL_HILITE]); else g->SetColor(mColors[COLOR_LABEL]); g->DrawString(mLabel, aFontX, aFontY); } } else { if (!isDown) { if (mDisabled && HaveButtonImage(mDisabledImage,mDisabledRect)) DrawButtonImage(g,mDisabledImage,mDisabledRect,0,0); else if ((mOverAlpha > 0) && HaveButtonImage(mOverImage,mOverRect)) { if (HaveButtonImage(mButtonImage, mNormalRect) && mOverAlpha<1) DrawButtonImage(g,mButtonImage,mNormalRect,0,0); g->SetColorizeImages(true); g->SetColor(Color(255,255,255,(int)(mOverAlpha * 255))); DrawButtonImage(g,mOverImage,mOverRect,0,0); g->SetColorizeImages(false); } else if ((mIsOver || mIsDown) && HaveButtonImage(mOverImage,mOverRect)) { DrawButtonImage(g,mOverImage,mOverRect,0,0); } else if (HaveButtonImage(mButtonImage,mNormalRect)) DrawButtonImage(g,mButtonImage,mNormalRect,0,0); if (mIsOver) g->SetColor(mColors[COLOR_LABEL_HILITE]); else g->SetColor(mColors[COLOR_LABEL]); g->DrawString(mLabel, aFontX, aFontY); } else { if (HaveButtonImage(mDownImage, mDownRect)) DrawButtonImage(g, mDownImage, mDownRect, 0, 0); else if (HaveButtonImage(mOverImage,mOverRect)) DrawButtonImage(g, mOverImage, mOverRect, 1, 1); else DrawButtonImage(g, mButtonImage, mNormalRect, 1, 1); g->SetColor(mColors[COLOR_LABEL_HILITE]); g->DrawString(mLabel, aFontX+1, aFontY+1); } } } void ButtonWidget::SetDisabled(bool isDisabled) { Widget::SetDisabled(isDisabled); if (HaveButtonImage(mDisabledImage,mDisabledRect)) MarkDirty(); } void ButtonWidget::MouseEnter() { Widget::MouseEnter(); if (mOverAlphaFadeInSpeed==0 && mOverAlpha>0) mOverAlpha = 0; if (mIsDown || (HaveButtonImage(mOverImage,mOverRect)) || (mColors[COLOR_LABEL_HILITE] != mColors[COLOR_LABEL])) MarkDirty(); mButtonListener->ButtonMouseEnter(mId); } void ButtonWidget::MouseLeave() { Widget::MouseLeave(); if (mOverAlphaSpeed==0 && mOverAlpha>0) mOverAlpha = 0; else if (mOverAlphaSpeed>0 && mOverAlpha==0) // fade out from full mOverAlpha = 1; if (mIsDown || HaveButtonImage(mOverImage,mOverRect) || (mColors[COLOR_LABEL_HILITE] != mColors[COLOR_LABEL])) MarkDirty(); mButtonListener->ButtonMouseLeave(mId); } void ButtonWidget::MouseMove(int theX, int theY) { Widget::MouseMove(theX, theY); mButtonListener->ButtonMouseMove(mId, theX, theY); } void ButtonWidget::MouseDown(int theX, int theY, int theBtnNum, int theClickCount) { Widget::MouseDown(theX, theY, theBtnNum, theClickCount); mButtonListener->ButtonPress(mId, theClickCount); MarkDirty(); } void ButtonWidget::MouseUp(int theX, int theY, int theBtnNum, int theClickCount) { Widget::MouseUp(theX, theY, theBtnNum, theClickCount); if (mIsOver && mWidgetManager->mHasFocus) mButtonListener->ButtonDepress(mId); MarkDirty(); } void ButtonWidget::Update() { Widget::Update(); if (mIsDown && mIsOver) mButtonListener->ButtonDownTick(mId); if (!mIsDown && !mIsOver && (mOverAlpha > 0)) { if (mOverAlphaSpeed>0) { mOverAlpha -= mOverAlphaSpeed; if (mOverAlpha < 0) mOverAlpha = 0; } else mOverAlpha = 0; MarkDirty(); } else if (mIsOver && mOverAlphaFadeInSpeed>0 && mOverAlpha<1) { mOverAlpha += mOverAlphaFadeInSpeed; if (mOverAlpha > 1) mOverAlpha = 1; MarkDirty(); } } libtuxcap-1.4.0/tuxcap/lib/SWTri_Pixel888.cpp0000644000175000017500000000275410641010432020565 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. #if defined(TEXTURED) { #include "SWTri_GetTexel.cpp" if (alpha > 0x08) { #include "SWTri_TexelARGB.cpp" #if defined(GLOBAL_ARGB) || defined (TEX_ALPHA) || defined(MOD_ARGB) { if (alpha < 0xf0) { unsigned int trb, tg; #if !defined(LINEAR_BLEND) { trb = (((tex&0xff00ff) * alpha) >> 8) & 0xff00ff; tg = (((tex&0x00ff00) * alpha) >> 8) & 0x00ff00; } #else { trb = tex&0xff00ff; tg = tex&0x00ff00; } #endif tex = *pix; alpha = 0xff - alpha; unsigned int prb = (((tex&0xff00ff) * alpha) >> 8) & 0xff00ff; unsigned int pg = (((tex&0x00ff00) * alpha) >> 8) & 0x00ff00; *pix = 0xFF000000 | ((trb|tg) + (prb|pg)); } else { *pix = 0xFF000000 | tex; } } #else { *pix = 0xFF000000 | tex; } #endif } } #elif defined(MOD_ARGB) { if (a > 0xf00000) { *pix = 0xFF000000 | ((r)&0xff0000)|((g>>8)&0xff00)|((b>>16)&0xff); } else if (a > 0x080000) { unsigned int alpha = a >> 16; unsigned int _rb = ((((r&0xff0000) | (b>>16)) * alpha)>> 8)&0xff00ff; unsigned int _g = (((g&0xff0000) * alpha)>>16)&0x00ff00; unsigned int p = *pix; alpha = 0xff - alpha; unsigned int prb = (((p&0xff00ff) * alpha) >> 8) & 0xff00ff; unsigned int pg = (((p&0x00ff00) * alpha) >> 8) & 0x00ff00; *pix = 0xFF000000 | (_rb|_g)+(prb|pg); } } #endif libtuxcap-1.4.0/tuxcap/lib/SexyMatrix.cpp0000644000175000017500000001717210641010432020261 0ustar inniyahinniyah#include "SexyMatrix.h" #include using namespace Sexy; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyMatrix3::SexyMatrix3() { } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyMatrix3::ZeroMatrix() { m00 = m01 = m02 = m10 = m11 = m12 = m20 = m21 = m22 = 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyMatrix3::LoadIdentity() { m01 = m02 = m10 = m12 = m20 = m21 = 0; m00 = m11 = m22 = 1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyMatrix3 SexyMatrix3::operator*(const SexyMatrix3 &theMat) const { SexyMatrix3 aResult; for(int i=0; i<3; i++) { for(int j=0; j<3; j++) { float x = 0; for(int k=0; k<3; k++) x += m[i][k]*theMat.m[k][j]; aResult.m[i][j] = x; } } return aResult; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyVector2 SexyMatrix3::operator*(const SexyVector2 &theVec) const { return SexyVector2( m00*theVec.x + m01*theVec.y + m02, m10*theVec.x + m11*theVec.y + m12); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyVector3 SexyMatrix3::operator*(const SexyVector3 &theVec) const { return SexyVector3( m00*theVec.x + m01*theVec.y + m02*theVec.z, m10*theVec.x + m11*theVec.y + m12*theVec.z, m20*theVec.x + m21*theVec.y + m22*theVec.z); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// const SexyMatrix3& SexyMatrix3::operator*=(const SexyMatrix3 &theMat) { return operator=(operator*(theMat)); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyTransform2D::SexyTransform2D() { LoadIdentity(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyTransform2D::SexyTransform2D(bool loadIdentity) { if (loadIdentity) LoadIdentity(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SexyTransform2D::SexyTransform2D(const SexyMatrix3& theMatrix) : SexyMatrix3(theMatrix) { } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// const SexyTransform2D& SexyTransform2D::operator=(const SexyMatrix3 &theMat) { SexyMatrix3::operator=(theMat); return *this; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyTransform2D::Translate(float tx, float ty) { SexyMatrix3 aMat; aMat.LoadIdentity(); aMat.m02 = tx; aMat.m12 = ty; aMat.m22 = 1; *this = aMat * (*this); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyTransform2D::RotateRad(float rot) { SexyMatrix3 aMat; aMat.LoadIdentity(); float sinRot = -sinf(rot); float cosRot = cosf(rot); aMat.m00 = cosRot; aMat.m01 = -sinRot; aMat.m10 = sinRot; aMat.m11 = cosRot; *this = aMat * (*this); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyTransform2D::RotateDeg(float rot) { RotateRad(3.1415926535897932384626433832795028841971f * rot / 180.0f); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void SexyTransform2D::Scale(float sx, float sy) { SexyMatrix3 aMat; aMat.LoadIdentity(); aMat.m00 = sx; aMat.m11 = sy; *this = aMat * (*this); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Transform::Transform() : mMatrix(false) { Reset(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::Reset() { mNeedCalcMatrix = true; mComplex = false; mTransX1 = mTransY1 = 0; mTransX2 = mTransY2 = 0; mScaleX = mScaleY = 1; mRot = 0; mHaveRot = false; mHaveScale = false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::Translate(float tx, float ty) { if (!mComplex) { mNeedCalcMatrix = true; if (mHaveRot || mHaveScale) { mTransX2 += tx; mTransY2 += ty; } else { mTransX1 += tx; mTransY1 += ty; } } else mMatrix.Translate(tx,ty); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::RotateRad(float rot) { if (!mComplex) { if (mHaveScale) { MakeComplex(); mMatrix.RotateRad(rot); } else { mNeedCalcMatrix = true; mHaveRot = true; mRot += rot; } } else mMatrix.RotateRad(rot); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::RotateDeg(float rot) { Transform::RotateRad(3.1415926535897932384626433832795028841971f * rot / 180.0f); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::Scale(float sx, float sy) { if (!mComplex) { if (mHaveRot || mTransX1!=0 || mTransY1!=0 || (sx<0 && mScaleX*sx!=-1) || sy<0) { MakeComplex(); mMatrix.Scale(sx,sy); } else { mNeedCalcMatrix = true; mHaveScale = true; mScaleX *= sx; mScaleY *= sy; } } else mMatrix.Scale(sx,sy); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::MakeComplex() { if (!mComplex) { mComplex = true; CalcMatrix(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void Transform::CalcMatrix() const { if (mNeedCalcMatrix) { mNeedCalcMatrix = false; mMatrix.LoadIdentity(); mMatrix.m02 = mTransX1; mMatrix.m12 = mTransY1; mMatrix.m22 = 1; if (mHaveScale) { mMatrix.m00 = mScaleX; mMatrix.m11 = mScaleY; } else if (mHaveRot) mMatrix.RotateRad(mRot); if (mTransX2!=0 || mTransY2!=0) mMatrix.Translate(mTransX2,mTransY2); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// const SexyTransform2D& Transform::GetMatrix() const { CalcMatrix(); return mMatrix; } libtuxcap-1.4.0/tuxcap/lib/DescParser.cpp0000644000175000017500000002603111202747625020210 0ustar inniyahinniyah#include #include "DescParser.h" #if 0 #include "..\PakLib\PakInterface.h" #endif using namespace Sexy; DescParser::DescParser() { mCmdSep = CMDSEP_SEMICOLON; } DescParser::~DescParser() { } bool DescParser::Error(const std::string& theError) { mError = theError; return false; } DataElement* DescParser::Dereference(const std::string& theString) { std::string aDefineName = StringToUpper(theString); DataElementMap::iterator anItr = mDefineMap.find(aDefineName); if (anItr != mDefineMap.end()) return anItr->second; else return NULL; } bool DescParser::IsImmediate(const std::string& theString) { return (((theString[0] >= '0') && (theString[0] <= '9')) || (theString[0] == '-') || (theString[0] == '+') || (theString[0] == '\'') || (theString[0] == '"')); } std::string DescParser::Unquote(const std::string& theQuotedString) { if ((theQuotedString[0] == '\'') || (theQuotedString[0] == '"')) { char aQuoteChar = theQuotedString[0]; std::string aLiteralString; bool lastWasQuote = false; for (uint32_t i = 0; i < theQuotedString.length(); i++) { if (theQuotedString[i] == aQuoteChar) { if (lastWasQuote) aLiteralString += aQuoteChar; lastWasQuote = true; } else { aLiteralString += theQuotedString[i]; lastWasQuote = false; } } return aLiteralString; } else return theQuotedString; } bool DescParser::GetValues(ListDataElement* theSource, ListDataElement* theValues) { theValues->mElementVector.clear(); for (uint32_t aSourceNum = 0; aSourceNum < theSource->mElementVector.size(); aSourceNum++) { if (theSource->mElementVector[aSourceNum]->mIsList) { ListDataElement* aChildList = new ListDataElement(); theValues->mElementVector.push_back(aChildList); if (!GetValues((ListDataElement*) theSource->mElementVector[aSourceNum], aChildList)) return false; } else { std::string aString = ((SingleDataElement*) theSource->mElementVector[aSourceNum])->mString; if (aString.length() > 0) { if ((aString[0] == '\'') || (aString[0] == '"')) { SingleDataElement* aChildData = new SingleDataElement(Unquote(aString)); theValues->mElementVector.push_back(aChildData); } else if (IsImmediate(aString)) { theValues->mElementVector.push_back(new SingleDataElement(aString)); } else { std::string aDefineName = StringToUpper(aString); DataElementMap::iterator anItr = mDefineMap.find(aDefineName); if (anItr == mDefineMap.end()) { Error("Unable to Dereference \"" + aString + "\""); return false; } theValues->mElementVector.push_back(anItr->second->Duplicate()); } } } } return true; } std::string DescParser::DataElementToString(DataElement* theDataElement) { if (theDataElement->mIsList) { ListDataElement* aListDataElement = (ListDataElement*) theDataElement; std::string aString = "("; for (uint32_t i = 0; i < aListDataElement->mElementVector.size(); i++) { if (i != 0) aString += ", "; aString += DataElementToString(aListDataElement->mElementVector[i]); } aString += ")"; return aString; } else { SingleDataElement* aSingleDataElement = (SingleDataElement*) theDataElement; return aSingleDataElement->mString; } } bool DescParser::DataToString(DataElement* theSource, std::string* theString) { *theString = ""; if (theSource->mIsList) return false; std::string aDefName = ((SingleDataElement*) theSource)->mString; DataElement* aDataElement = Dereference(aDefName); if (aDataElement != NULL) { if (aDataElement->mIsList) return false; *theString = Unquote(((SingleDataElement*) aDataElement)->mString); } else *theString = Unquote(aDefName); return true; } bool DescParser::DataToInt(DataElement* theSource, int* theInt) { *theInt = 0; std::string aTempString; if (!DataToString(theSource, &aTempString)) return false; if (!StringToInt(aTempString, theInt)) return false; return true; } bool DescParser::DataToStringVector(DataElement* theSource, StringVector* theStringVector) { theStringVector->clear(); ListDataElement aStaticValues; ListDataElement* aValues; if (theSource->mIsList) { if (!GetValues((ListDataElement*) theSource, &aStaticValues)) return false; aValues = &aStaticValues; } else { std::string aDefName = ((SingleDataElement*) theSource)->mString; DataElement* aDataElement = Dereference(aDefName); if (aDataElement == NULL) { Error("Unable to Dereference \"" + aDefName + "\""); return false; } if (!aDataElement->mIsList) return false; aValues = (ListDataElement*) aDataElement; } for (uint32_t i = 0; i < aValues->mElementVector.size(); i++) { if (aValues->mElementVector[i]->mIsList) { theStringVector->clear(); return false; } SingleDataElement* aSingleDataElement = (SingleDataElement*) aValues->mElementVector[i]; theStringVector->push_back(aSingleDataElement->mString); } return true; } bool DescParser::DataToList(DataElement* theSource, ListDataElement* theValues) { if (theSource->mIsList) { return GetValues((ListDataElement*) theSource, theValues); } DataElement* aDataElement = Dereference(((SingleDataElement*) theSource)->mString); if ((aDataElement == NULL) || (!aDataElement->mIsList)) return false; ListDataElement* aListElement = (ListDataElement*) aDataElement; *theValues = *aListElement; return true; } bool DescParser::DataToIntVector(DataElement* theSource, IntVector* theIntVector) { theIntVector->clear(); StringVector aStringVector; if (!DataToStringVector(theSource, &aStringVector)) return false; for (uint32_t i = 0; i < aStringVector.size(); i++) { int aIntVal; if (!StringToInt(aStringVector[i], &aIntVal)) return false; theIntVector->push_back(aIntVal); } return true; } bool DescParser::DataToDoubleVector(DataElement* theSource, DoubleVector* theDoubleVector) { theDoubleVector->clear(); StringVector aStringVector; if (!DataToStringVector(theSource, &aStringVector)) return false; for (uint32_t i = 0; i < aStringVector.size(); i++) { double aDoubleVal; if (!StringToDouble(aStringVector[i], &aDoubleVal)) return false; theDoubleVector->push_back(aDoubleVal); } return true; } bool DescParser::ParseToList(const std::string& theString, ListDataElement* theList, bool expectListEnd, int* theStringPos) { bool inSingleQuotes = false; bool inDoubleQuotes = false; bool escaped = false; SingleDataElement* aCurSingleDataElement = NULL; int aStringPos = 0; if (theStringPos == NULL) theStringPos = &aStringPos; while (*theStringPos < (int) theString.length()) { bool addSingleChar = false; char aChar = theString[(*theStringPos)++]; bool isSeperator = (aChar == ' ') || (aChar == '\t') || (aChar == '\n') || (aChar == ','); if (escaped) { addSingleChar = true; escaped = false; } else { if ((aChar == '\'') && (!inDoubleQuotes)) inSingleQuotes = !inSingleQuotes; else if ((aChar == '"') && (!inSingleQuotes)) inDoubleQuotes = !inDoubleQuotes; if (aChar == '\\') { escaped = true; } else if ((!inSingleQuotes) && (!inDoubleQuotes)) { if (aChar == ')') { if (expectListEnd) return true; else { Error("Unexpected List End"); return false; } } else if (aChar == '(') { if (aCurSingleDataElement != NULL) { Error("Unexpected List Start"); return false; } else { ListDataElement* aChildList = new ListDataElement(); if (!ParseToList(theString, aChildList, true, theStringPos)) return false; theList->mElementVector.push_back(aChildList); } } else if (isSeperator) { if (aCurSingleDataElement != NULL) aCurSingleDataElement = NULL; } else addSingleChar = true; } else addSingleChar = true; } if (addSingleChar) { if (aCurSingleDataElement == NULL) { aCurSingleDataElement = new SingleDataElement(); theList->mElementVector.push_back(aCurSingleDataElement); } aCurSingleDataElement->mString += aChar; } } if (inSingleQuotes) { Error("Unterminated Single Quotes"); return false; } if (inDoubleQuotes) { Error("Unterminated Double Quotes"); return false; } if (expectListEnd) { Error("Unterminated List"); return false; } return true; } bool DescParser::ParseDescriptorLine(const std::string& theDescriptorLine) { ListDataElement aParams; if (!ParseToList(theDescriptorLine, &aParams, false, NULL)) return false; if (aParams.mElementVector.size() > 0) { if (aParams.mElementVector[0]->mIsList) { Error("Missing Command"); return false; } if (!HandleCommand(aParams)) return false; } return true; } bool DescParser::LoadDescriptor(const std::string& theFileName) { mCurrentLineNum = 0; int aLineCount = 0; bool hasErrors = false; mError.clear(); FILE *aStream = fopen(theFileName.c_str(),"r"); if (aStream==NULL) return false; char aBuffChar = 0; while (!feof(aStream)) { int aChar; bool skipLine = false; bool atLineStart = true; bool inSingleQuotes = false; bool inDoubleQuotes = false; bool escaped = false; bool isIndented = false; for (;;) { if (aBuffChar != 0) { aChar = aBuffChar; aBuffChar = 0; } else { aChar = fgetc(aStream); if (aChar==EOF) break; } if (aChar != '\r') { if (aChar == '\n') aLineCount++; if (((aChar == ' ') || (aChar == '\t')) && (atLineStart)) isIndented = true; if ((!atLineStart) || ((aChar != ' ') && (aChar != '\t') && (aChar != '\n'))) { if (atLineStart) { if ((mCmdSep & CMDSEP_NO_INDENT) && (!isIndented) && (mCurrentLine.size() > 0)) { // Start a new non-indented line aBuffChar = aChar; break; } if (aChar == '#') skipLine = true; atLineStart = false; } if (aChar == '\n') { isIndented = false; atLineStart = true; } if ((aChar == '\n') && (skipLine)) { skipLine = false; } else if (!skipLine) { if (aChar == '\\' && (inSingleQuotes || inDoubleQuotes) && !escaped) escaped = true; else { if ((aChar == '\'') && (!inDoubleQuotes) && (!escaped)) inSingleQuotes = !inSingleQuotes; if ((aChar == '"') && (!inSingleQuotes) && (!escaped)) inDoubleQuotes = !inDoubleQuotes; if ((aChar == ';') && (mCmdSep & CMDSEP_SEMICOLON) && (!inSingleQuotes) && (!inDoubleQuotes)) break; if(escaped) // stay escaped for when this is actually parsed { mCurrentLine += '\\'; escaped = false; } if (mCurrentLine.size() == 0) mCurrentLineNum = aLineCount + 1; mCurrentLine += aChar; } } } } } if (mCurrentLine.length() > 0) { if (!ParseDescriptorLine(mCurrentLine)) { hasErrors = true; break; } mCurrentLine.clear(); } } mCurrentLine.clear(); mCurrentLineNum = 0; fclose(aStream); return !hasErrors; } libtuxcap-1.4.0/tuxcap/lib/Image.cpp0000644000175000017500000001461710641010435017172 0ustar inniyahinniyah#include "Image.h" #include "Graphics.h" using namespace Sexy; Image::Image() { mWidth = 0; mHeight = 0; mNumRows = 1; mNumCols = 1; mAnimInfo = NULL; mDrawn = false; } Image::Image(const Image& theImage) : mWidth(theImage.mWidth), mHeight(theImage.mHeight), mNumRows(theImage.mNumRows), mNumCols(theImage.mNumCols) { mDrawn = false; if (theImage.mAnimInfo != NULL) mAnimInfo = new AnimInfo(*theImage.mAnimInfo); else mAnimInfo = NULL; } Image::~Image() { delete mAnimInfo; } int Image::GetWidth() { return mWidth; } int Image::GetHeight() { return mHeight; } int Image::GetCelHeight() { return mHeight / mNumRows; } int Image::GetCelWidth() { return mWidth / mNumCols; } Rect Image::GetCelRect(int theCel) { int h = GetCelHeight(); int w = GetCelWidth(); int x = (theCel % mNumCols) * w; int y = (theCel / mNumCols) * h; return Rect(x, y, w, h); } Rect Image::GetCelRect(int theCol, int theRow) { int h = GetCelHeight(); int w = GetCelWidth(); int x = theCol * w; int y = theRow * h; return Rect(x, y, w, h); } AnimInfo::AnimInfo() { mAnimType = AnimType_None; mFrameDelay = 1; mNumCels = 1; } void AnimInfo::SetPerFrameDelay(int theFrame, int theTime) { if ((int)mPerFrameDelay.size()<=theFrame) mPerFrameDelay.resize(theFrame+1); mPerFrameDelay[theFrame] = theTime; } void AnimInfo::Compute(int theNumCels, int theBeginFrameTime, int theEndFrameTime) { int i; mNumCels = theNumCels; if (mNumCels<=0) mNumCels = 1; if (mFrameDelay<=0) mFrameDelay = 1; if (mAnimType==AnimType_PingPong && mNumCels>1) { mFrameMap.resize(theNumCels*2-2); int index = 0; for (i=0; i=1; i--) mFrameMap[index++] = i; } if (!mFrameMap.empty()) mNumCels = (int)mFrameMap.size(); if (theBeginFrameTime>0) SetPerFrameDelay(0,theBeginFrameTime); if (theEndFrameTime>0) SetPerFrameDelay(mNumCels-1,theEndFrameTime); if (!mPerFrameDelay.empty()) { mTotalAnimTime = 0; mPerFrameDelay.resize(mNumCels); for (i=0; i=mTotalAnimTime) { if (!mFrameMap.empty()) return mFrameMap[mFrameMap.size()-1]; else return mNumCels-1; } theTime = theTime%mTotalAnimTime; int aFrame; if (!mPerFrameDelay.empty()) aFrame = GetPerFrameCel(theTime); else aFrame = (theTime/mFrameDelay)%mNumCels; if (mFrameMap.empty()) return aFrame; else return mFrameMap[aFrame]; } int Image::GetAnimCel(int theTime) { if (mAnimInfo==NULL) return 0; else return mAnimInfo->GetCel(theTime); } Rect Image::GetAnimCelRect(int theTime) { Rect aRect; int aCel = GetAnimCel(theTime); int aCelWidth = GetCelWidth(); int aCelHeight = GetCelHeight(); if (mNumCols>1) return Rect(aCel*aCelWidth,0,aCelWidth,mHeight); else return Rect(0,aCel*aCelHeight,mWidth,aCelHeight); } void Image::CopyAttributes(Image *from) { mNumCols = from->mNumCols; mNumRows = from->mNumRows; delete mAnimInfo; mAnimInfo = NULL; if (from->mAnimInfo != NULL) mAnimInfo = new AnimInfo(*from->mAnimInfo); } Graphics* Image::GetGraphics() { Graphics* g = new Graphics(this); return g; } void Image::FillRect(const Rect& theRect, const Color& theColor, int theDrawMode) { } void Image::ClearRect(const Rect& theRect) { } void Image::DrawRect(const Rect& theRect, const Color& theColor, int theDrawMode) { FillRect(Rect(theRect.mX, theRect.mY, theRect.mWidth + 1, 1), theColor, theDrawMode); FillRect(Rect(theRect.mX, theRect.mY + theRect.mHeight, theRect.mWidth + 1, 1), theColor, theDrawMode); FillRect(Rect(theRect.mX, theRect.mY + 1, 1, theRect.mHeight - 1), theColor, theDrawMode); FillRect(Rect(theRect.mX + theRect.mWidth, theRect.mY + 1, 1, theRect.mHeight - 1), theColor, theDrawMode); } void Image::DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { } void Image::DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { } void Image::FillScanLines(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode) { for (int i = 0; i < theSpanCount; i++) { Span* aSpan = &theSpans[i]; FillRect(Rect(aSpan->mX, aSpan->mY, aSpan->mWidth, 1), theColor, theDrawMode); } } void Image::FillScanLinesWithCoverage(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode, const unsigned char* theCoverage, int theCoverX, int theCoverY, int theCoverWidth, int theCoverHeight) { } bool Image::PolyFill3D(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty, bool convex) { return false; } void Image::Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode) { } void Image::BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode) { } void Image::BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY) { } void Image::StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch) { } void Image::BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend) { } void Image::BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend) { } void Image::BltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode) { } void Image::StretchBltMirror(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch) { } libtuxcap-1.4.0/tuxcap/lib/SDLMixerMusicInterface.cpp0000644000175000017500000001705311062277265022434 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /* To be able to use midi, install package freepats which contains midi instruments */ #include "SDLMixerMusicInterface.h" #include "SexyAppBase.h" using namespace Sexy; SDLMixerMusicInfo::SDLMixerMusicInfo() { music = NULL;; mVolume = 1.0; mStopOnFade = false; mRepeats = false; mPosition = 0; mIsActive = false; } SDLMixerMusicInterface::SDLMixerMusicInterface(HWND theHWnd) { if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2 , 1024)==-1) { printf("Mix_OpenAudio failed: %s\n", Mix_GetError()); } mMasterVolume = 1.0; mCurrentMusic = -1; } SDLMixerMusicInterface::~SDLMixerMusicInterface() { StopAllMusic(); SDLMixerMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->music != NULL) { Mix_FreeMusic(aMusicInfo->music); aMusicInfo->music = NULL; } ++anItr; } int numtimesopened, frequency, channels; Uint16 format; numtimesopened=Mix_QuerySpec(&frequency, &format, &channels); while(numtimesopened--) Mix_CloseAudio(); } bool SDLMixerMusicInterface::LoadMusic(int theSongId, const std::string& theFileName) { SDLMixerMusicInfo aMusicInfo; std::string copy = Sexy::ReplaceBackSlashes(GetAppResourceFolder() + theFileName); int aLastDotPos = copy.rfind('.'); int aLastSlashPos = (int)copy.rfind('/'); Mix_Music* m = NULL; if (aLastDotPos > aLastSlashPos) { m = Mix_LoadMUS(copy.c_str()); } else { m = Mix_LoadMUS((copy + ".ogg").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".OGG").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".mp3").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".MP3").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".mid").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".MID").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".mod").c_str()); if (m == NULL) m = Mix_LoadMUS((copy + ".MOD").c_str()); } if (m != NULL) { aMusicInfo.music = m; mMusicMap.insert(SDLMixerMusicMap::value_type(theSongId, aMusicInfo)); return true; } return false; } void SDLMixerMusicInterface::UnloadMusic(int theSongId) { SDLMixerMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->music != NULL) Mix_FreeMusic(aMusicInfo->music); aMusicInfo->music = NULL; mMusicMap.erase(anItr); } } void SDLMixerMusicInterface::UnloadAllMusic() { SDLMixerMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->music != NULL) Mix_FreeMusic(aMusicInfo->music); aMusicInfo->music = NULL; ++anItr; } mMusicMap.clear(); } void SDLMixerMusicInterface::PauseAllMusic() { Mix_PauseMusic(); } void SDLMixerMusicInterface::ResumeAllMusic() { Mix_ResumeMusic(); } void SDLMixerMusicInterface::DeactivateAllMusic() { SDLMixerMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->music != NULL) aMusicInfo->mIsActive = false; ++anItr; } } void SDLMixerMusicInterface::PlayMusic(int theSongId, int theOffset, bool noLoop) { DeactivateAllMusic(); SDLMixerMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo != NULL) { aMusicInfo->mIsActive = true; Mix_PlayMusic(aMusicInfo->music, noLoop ? 1 : -1); if (theOffset != 0) { Mix_SetMusicPosition(theOffset); } Mix_VolumeMusic((int)((float)mMasterVolume * aMusicInfo->mVolume * 128)); mCurrentMusic = theSongId; } } } void SDLMixerMusicInterface::PauseMusic(int theSongId) { PauseAllMusic(); } void SDLMixerMusicInterface::ResumeMusic(int theSongId) { ResumeAllMusic(); } void SDLMixerMusicInterface::StopMusic(int theSongId) { StopAllMusic(); } void SDLMixerMusicInterface::StopAllMusic() { Mix_HaltMusic(); } void SDLMixerMusicInterface::FadeIn(int theSongId, int theOffset, double theSpeed, bool noLoop) { DeactivateAllMusic(); SDLMixerMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->music != NULL) { aMusicInfo->mIsActive = true; Mix_FadeInMusicPos(aMusicInfo->music, noLoop ? 1 : -1, (int)(1.0f / theSpeed), theOffset); mCurrentMusic = theSongId; } } } void SDLMixerMusicInterface::FadeOut(int theSongId, bool stopSong, double theSpeed) { FadeOutAll(true, theSpeed); } void SDLMixerMusicInterface::FadeOutAll(bool stopSong, double theSpeed) { Mix_FadeOutMusic((int)(1.0f / theSpeed)); } void SDLMixerMusicInterface::SetVolume(double theVolume) { mMasterVolume = (float)theVolume; SDLMixerMusicMap::iterator anItr = mMusicMap.find(mCurrentMusic); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mIsActive && Mix_PlayingMusic()) Mix_VolumeMusic((int)(mMasterVolume * aMusicInfo->mVolume * 128.0f)); } } void SDLMixerMusicInterface::SetSongVolume(int theSongId, double theVolume) { SDLMixerMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolume = (float)theVolume; if (aMusicInfo->mIsActive && Mix_PlayingMusic()) Mix_VolumeMusic((int)(mMasterVolume * aMusicInfo->mVolume * 128.0f)); } } bool SDLMixerMusicInterface::IsPlaying(int theSongId) { SDLMixerMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { SDLMixerMusicInfo* aMusicInfo = &anItr->second; return aMusicInfo->mIsActive && Mix_PlayingMusic(); } return false; } void SDLMixerMusicInterface::Update() { } libtuxcap-1.4.0/tuxcap/lib/SWTri_DrawTriangle.cpp0000644000175000017500000001563611202747627021643 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. #if (TRI0==0) #define PTYPE uint32_t #define PIXEL_INCLUDE "SWTri_Pixel8888.cpp" #define NAME0 8888 #elif (TRI0==1) #define PTYPE uint32_t #define PIXEL_INCLUDE "SWTri_Pixel888.cpp" #define NAME0 0888 #elif (TRI0==2) #define PTYPE unsigned short #define PIXEL_INCLUDE "SWTri_Pixel565.cpp" #define NAME0 0565 #elif (TRI0==3) #define PTYPE unsigned short #define PIXEL_INCLUDE "SWTri_Pixel555.cpp" #define NAME0 0555 #endif #if (TRI1==1) #define TEXTURED #define NAME1 TEX1 #else #define NAME1 TEX0 #endif #if (TRI2==1) #define TEX_ALPHA #define NAME2 TALPHA1 #else #define NAME2 TALPHA0 #endif #if (TRI3==1) #define MOD_ARGB #define NAME3 MOD1 #else #define NAME3 MOD0 #endif #if (TRI4==1) #define GLOBAL_ARGB #define NAME4 GLOB1 #else #define NAME4 GLOB0 #endif #if (TRI5==1) #define LINEAR_BLEND #define NAME5 BLEND1 #else #define NAME5 BLEND0 #endif #define funcname2(t0,t1,t2,t3,t4,t5) DrawTriangle_##t0##_##t1##_##t2##_##t3##_##t4##_##t5 #define funcname1(t0,t1,t2,t3,t4,t5) funcname2(t0,t1,t2,t3,t4,t5) #define funcname funcname1(NAME0,NAME1,NAME2,NAME3,NAME4,NAME5) void Sexy::funcname(SWHelper::SWVertex * pVerts, void * pFrameBuffer, const unsigned int bytepitch, const SWHelper::SWTextureInfo * textureInfo, SWHelper::SWDiffuse & globalDiffuse) { const int pitch = bytepitch/sizeof(PTYPE); const int tex_pitch = textureInfo->pitch; const int tex_height = textureInfo->height; const unsigned int tex_endpos = textureInfo->endpos; const int64_t bigOne = static_cast(1) << 48; #define swap(a,b,type) {type tmp = a; a = b; b = tmp;} const unsigned int * pTexture; unsigned int vShift, uMask, vMask; #if defined(TEXTURED) { pTexture = textureInfo->pTexture; vShift = textureInfo->vShift; vMask = textureInfo->vMask; uMask = textureInfo->uMask; } #endif // Sort vertices by Y component SWHelper::SWVertex * v0 = pVerts+0; SWHelper::SWVertex * v1 = pVerts+1; SWHelper::SWVertex * v2 = pVerts+2; if (v0->y > v1->y) swap(v0,v1,SWHelper::SWVertex *); if (v1->y > v2->y) swap(v1,v2,SWHelper::SWVertex *); if (v0->y > v1->y) swap(v0,v1,SWHelper::SWVertex *); #if defined(MOD_ARGB) && defined(GLOBAL_ARGB) { v0->a = (v0->a * globalDiffuse.a) >> 8; v0->r = (v0->r * globalDiffuse.r) >> 8; v0->g = (v0->g * globalDiffuse.g) >> 8; v0->b = (v0->b * globalDiffuse.b) >> 8; v1->a = (v1->a * globalDiffuse.a) >> 8; v1->r = (v1->r * globalDiffuse.r) >> 8; v1->g = (v1->g * globalDiffuse.g) >> 8; v1->b = (v1->b * globalDiffuse.b) >> 8; v2->a = (v2->a * globalDiffuse.a) >> 8; v2->r = (v2->r * globalDiffuse.r) >> 8; v2->g = (v2->g * globalDiffuse.g) >> 8; v2->b = (v2->b * globalDiffuse.b) >> 8; } #endif // Integer Y values (using a quick form of ceil() for positive values) int y0 = (v0->y + 0xffff) >> 16; int y2 = (v2->y + 0xffff) >> 16; if (y0 == y2) return; // Null polygon (no height)? int y1 = (v1->y + 0xffff) >> 16; // Calculate long-edge deltas int64_t oneOverHeight = bigOne / (v2->y - v0->y); int ldx, ldr, ldg, ldb, lda, ldu, ldv; ldx = static_cast(((v2->x - v0->x) * oneOverHeight) >> 32); #if defined(MOD_ARGB) lda = static_cast(((v2->a - v0->a) * oneOverHeight) >> 32); ldr = static_cast(((v2->r - v0->r) * oneOverHeight) >> 32); ldg = static_cast(((v2->g - v0->g) * oneOverHeight) >> 32); ldb = static_cast(((v2->b - v0->b) * oneOverHeight) >> 32); #endif #if defined(TEXTURED) ldu = static_cast(((v2->u - v0->u) * oneOverHeight) >> 32); ldv = static_cast(((v2->v - v0->v) * oneOverHeight) >> 32); #endif // Long-edge midpoint int64_t topHeight = v1->y - v0->y; int mid = v0->x + static_cast((topHeight * ldx)>>16); if (v1->x == mid) return; // Null polygon (no width)? // Edge variables (long) int64_t subPix = (y0<<16) - v0->y; int lx, lr, lg, lb, la, lu, lv; lx = v0->x + static_cast((ldx * subPix)>>16); #if defined(MOD_ARGB) la = v0->a + static_cast((lda * subPix)>>16); lr = v0->r + static_cast((ldr * subPix)>>16); lg = v0->g + static_cast((ldg * subPix)>>16); lb = v0->b + static_cast((ldb * subPix)>>16); #endif #if defined(TEXTURED) lu = v0->u + static_cast((ldu * subPix)>>16); lv = v0->v + static_cast((ldv * subPix)>>16); #endif // Scanline deltas int64_t oneOverWidth; int dr, dg, db, da, du, dv; #if defined(TEXTURED) || defined(MOD_ARGB) oneOverWidth = bigOne / (v1->x - mid); #endif #if defined (MOD_ARGB) da = static_cast(((v1->a - (v0->a + ((topHeight * lda)>>16))) * oneOverWidth)>>32); dr = static_cast(((v1->r - (v0->r + ((topHeight * ldr)>>16))) * oneOverWidth)>>32); dg = static_cast(((v1->g - (v0->g + ((topHeight * ldg)>>16))) * oneOverWidth)>>32); db = static_cast(((v1->b - (v0->b + ((topHeight * ldb)>>16))) * oneOverWidth)>>32); #endif #if defined (TEXTURED) du = static_cast(((v1->u - (v0->u + ((topHeight * ldu)>>16))) * oneOverWidth)>>32); dv = static_cast(((v1->v - (v0->v + ((topHeight * ldv)>>16))) * oneOverWidth)>>32); #endif // Screen info unsigned int offset = y0 * pitch; PTYPE * fb = reinterpret_cast(pFrameBuffer) + offset; int iHeight = y1 - y0; if (iHeight) { // Short edge delta X oneOverHeight = bigOne / topHeight; int sdx = static_cast(((v1->x - v0->x) * oneOverHeight) >> 32); // Edge variables (short) int sx = v0->x + static_cast((sdx * subPix)>>16); // Scan-convert the top half if (mid < v1->x) { while(iHeight-- > 0) { // Integer (ceil()) left and right X components int x0 = (lx + 0xffff) & 0xffff0000; int x1 = (sx + 0xffff) & 0xffff0000; #include "SWTri_Loop.cpp" } } else if (mid > v1->x) { while(iHeight-- > 0) { // Integer (ceil()) left and right X components int x0 = (sx + 0xffff) & 0xffff0000; int x1 = (lx + 0xffff) & 0xffff0000; #include "SWTri_Loop.cpp" } } } // Done? iHeight = y2 - y1; if (!iHeight) return; // Short edge along bottom half oneOverHeight = bigOne / (v2->y - v1->y); int sdx = static_cast(((v2->x - v1->x) * oneOverHeight) >> 32); subPix = (y1<<16) - v1->y; int sx = v1->x + static_cast((sdx * subPix)>>16); // Scan-convert the bottom half if (mid < v1->x) { while(iHeight-- > 0) { // Integer (ceil()) left and right X components int x0 = (lx + 0xffff) & 0xffff0000; int x1 = (sx + 0xffff) & 0xffff0000; #include "SWTri_Loop.cpp" } } else if (mid > v1->x) { while(iHeight-- > 0) { // Integer (ceil()) left and right X components int x0 = (sx + 0xffff) & 0xffff0000; int x1 = (lx + 0xffff) & 0xffff0000; #include "SWTri_Loop.cpp" } } } #undef funcname2 #undef funcname1 #undef funcname #undef PTYPE #undef PIXEL_INCLUDE #undef TEXTURED #undef TEX_ALPHA #undef MOD_ARGB #undef GLOBAL_ARGB #undef LINEAR_BLEND #undef NAME0 #undef NAME1 #undef NAME2 #undef NAME3 #undef NAME4 #undef NAME5 libtuxcap-1.4.0/tuxcap/lib/XMLWriter.cpp0000644000175000017500000001352610654427350020017 0ustar inniyahinniyah// XMLWriter.cpp: implementation of the XMLWriter class by James Poag // ////////////////////////////////////////////////////////////////////// #include "XMLWriter.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// using namespace Sexy; XMLWriter::XMLWriter() { mFile = NULL; mLineNum = 0; mAllowComments = false; mOpenAttributes = false; } XMLWriter::~XMLWriter() { if (mFile != NULL) fclose(mFile); } void XMLWriter::Fail(const std::string& theErrorText) { mHasFailed = true; mErrorText = theErrorText; } void XMLWriter::Warn(const std::string &theWarning) { mWarningStack.push("WARNING: " + theWarning); } void XMLWriter::Comment(const std::string &theComment) { mWarningStack.push(theComment); } void XMLWriter::Init() { mLineNum = 1; mHasFailed = false; mErrorText = ""; } bool XMLWriter::OpenFile(const std::string& theFileName) { mFile = fopen(theFileName.c_str(), "w"); if (mFile == NULL) { mLineNum = 0; Fail("Unable to open file " + theFileName); return false; } mFileName = theFileName.c_str(); Init(); //write header fprintf(mFile, "\n"); mLineNum++; return true; } bool XMLWriter::HasFailed() { return mHasFailed; } std::string XMLWriter::GetErrorText() { return mErrorText; } int XMLWriter::GetCurrentLineNum() { return mLineNum; } std::string XMLWriter::GetFileName() { return mFileName; } /* Used as a tool to add attributes to XMLElement Nodes. */ bool XMLWriter::AddAttribute(XMLElement* theElement, const std::string& theAttributeKey, const std::string& theAttributeValue) { std::pair aRet; aRet = theElement->mAttributes.insert(XMLParamMap::value_type(theAttributeKey, theAttributeValue)); if (!aRet.second) aRet.first->second = theAttributeValue; if (theAttributeKey != "/") theElement->mAttributeIteratorList.push_back(aRet.first); return aRet.second; } /* Pushes the Element onto the section stack and creates a new Node with an Attributes section */ bool XMLWriter::StartElement(const std::string &theElementName) { CheckFileOpen(); if(mHasFailed) return false; if(mOpenAttributes) { // Close Previous Element Attribute section fprintf(mFile, ">\n"); mLineNum++; } if(!ValidateElementNodeName(theElementName)) { Warn(theElementName + " is an Invalid Node Name."); } while(!mWarningStack.empty()) { fprintf(mFile, "\n", mWarningStack.top().c_str()); mWarningStack.pop(); } mSectionStack.push(theElementName); for(unsigned int i = 1; i < mSectionStack.size(); i++) { fprintf(mFile, "\t"); } fprintf(mFile, "<%s", theElementName.c_str()); mOpenAttributes = true; return true; } /* Pushes theElement->Value onto the stack and adds all of theElements->mAttributes to the Attribute section */ bool XMLWriter::StartElement(XMLElement *theElement) { if(StartElement(theElement->mValue.c_str()) == false) return false; std::map::iterator map_itr; map_itr = theElement->mAttributes.begin(); for( ; map_itr != theElement->mAttributes.end(); map_itr++) { if(!WriteAttribute(map_itr->first, map_itr->second)) return false; } return true; } /* Closes the previously open Node and pops it from the stack. Also Closes the Attributes Writing until StartElement is called. */ bool XMLWriter::StopElement() { CheckFileOpen(); if(mHasFailed) return false; if(mSectionStack.empty()) { Fail("Stop Element Calls do not match StartElement Calls."); return false; } const std::string aNodeName = mSectionStack.top(); mSectionStack.pop(); if(mOpenAttributes) { // Close Previous Element Attribute section fprintf(mFile, "/>\n"); mLineNum++; } else { // Otherwise close element section for(unsigned int i = 0; i < mSectionStack.size(); i++) { fprintf(mFile, "\t"); } fprintf(mFile, "\n", aNodeName.c_str()); } mOpenAttributes = false; while(!mWarningStack.empty()) { fprintf(mFile, "\n", mWarningStack.top().c_str()); mWarningStack.pop(); } return true; } /* Adds an attribute to the Current Element. If No element is open, then it returns false. */ bool XMLWriter::WriteAttribute(const std::string& aAttributeKey, const std::string& aAttributeValue) { CheckFileOpen(); if(mHasFailed) return false; if(mOpenAttributes) { if(!ValidateElementNodeName(aAttributeKey)) { Warn(aAttributeKey + " is an invalid Attribute Name."); } fprintf(mFile, " %s=\"%s\"", aAttributeKey.c_str(), XMLEncodeString(aAttributeValue).c_str()); return true; } if(mSectionStack.size()) Fail("Attributes Section already closed for " + mSectionStack.top()); else Fail("No Element Nodes Open for Writing Attributes."); return false; } bool XMLWriter::WriteAttribute(const std::string &aAttributeKey, const int &aAttributeValue) { return WriteAttribute(aAttributeKey, StrFormat("%d", aAttributeValue)); } bool XMLWriter::WriteAttribute(const std::string &aAttributeKey, const float &aAttributeValue) { return WriteAttribute(aAttributeKey, StrFormat("%f", aAttributeValue)); } bool XMLWriter::CloseFile() { while(!mSectionStack.empty()) { StopElement(); } if (mFile != NULL) { fclose(mFile); mFile = NULL; return true; } Fail("File not Open"); return false; } bool XMLWriter::ValidateElementNodeName(const std::string &theNodeName) { const char* aNodeName = theNodeName.c_str(); for(unsigned int i = 0; i < theNodeName.size(); i++) { if( aNodeName[i] < '0' || (aNodeName[i] > '9' && aNodeName[i] < 'A') || (aNodeName[i] > 'Z' && aNodeName[i] < '_') || (aNodeName[i] > '_' && aNodeName[i] < 'a') || aNodeName[i] > 'z') { return false; } } return true; } bool XMLWriter::CheckFileOpen() { if (mFile != NULL) { return true; } Fail("No File Opened for writing"); return false; } libtuxcap-1.4.0/tuxcap/lib/SWTri_TexelARGB.cpp0000644000175000017500000000241110641010434020741 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. { int premult; #if defined(MOD_ARGB) && defined(GLOBAL_ARGB) { premult = ((globalDiffuse.a*a)>>24); alpha = (alpha * premult) >> 8; tex = ((((tex&0xff0000)*((globalDiffuse.r*r)>>24))>>8)&0xff0000)| ((((tex&0x00ff00)*((globalDiffuse.g*g)>>24))>>8)&0x00ff00)| ((((tex&0x0000ff)*((globalDiffuse.b*b)>>24))>>8)&0x0000ff); } #elif !defined(MOD_ARGB) && defined(GLOBAL_ARGB) { premult = globalDiffuse.a; alpha = (alpha * premult) >> 8; tex = ((((tex&0xff0000)*globalDiffuse.r)>>8)&0xff0000)| ((((tex&0x00ff00)*globalDiffuse.g)>>8)&0x00ff00)| ((((tex&0x0000ff)*globalDiffuse.b)>>8)&0x0000ff); } #elif defined(MOD_ARGB) && !defined(GLOBAL_ARGB) { premult = a>>16; alpha = (alpha * premult) >> 8; tex = ((((tex&0xff0000)*(r>>16))>>8)&0xff0000)| ((((tex&0x00ff00)*(g>>16))>>8)&0x00ff00)| ((((tex&0x0000ff)*(b>>16))>>8)&0x0000ff); } #endif // linear blend expects pixel to already be premultiplied by alpha #if defined(LINEAR_BLEND) && (defined(MOD_ARGB) || defined(GLOBAL_ARGB)) { int r = (((tex&0xff0000)*premult)>>8)&0xff0000; int g = (((tex&0x00ff00)*premult)>>8)&0x00ff00; int b = (((tex&0x0000ff)*premult)>>8)&0x0000ff; tex = r|g|b; } #endif } libtuxcap-1.4.0/tuxcap/lib/Color.cpp0000644000175000017500000000476411202747625017244 0ustar inniyahinniyah#include "Color.h" using namespace Sexy; Color Color::Black(0, 0, 0); Color Color::White(255, 255, 255); Color::Color() : mRed(0), mGreen(0), mBlue(0), mAlpha(255) { } Color::Color(int theColor) : mAlpha((theColor >> 24) & 0xFF), mRed((theColor >> 16) & 0xFF), mGreen((theColor >> 8 ) & 0xFF), mBlue((theColor ) & 0xFF) { if(mAlpha==0) mAlpha = 0xff; } Color::Color(int theColor, int theAlpha) : mRed((theColor >> 16) & 0xFF), mGreen((theColor >> 8 ) & 0xFF), mBlue((theColor ) & 0xFF), mAlpha(theAlpha) { } Color::Color(int theRed, int theGreen, int theBlue) : mRed(theRed), mGreen(theGreen), mBlue(theBlue), mAlpha(0xFF) { } Color::Color(int theRed, int theGreen, int theBlue, int theAlpha) : mRed(theRed), mGreen(theGreen), mBlue(theBlue), mAlpha(theAlpha) { } Color::Color(const SexyRGBA &theColor) : mRed(theColor.r), mGreen(theColor.g), mBlue(theColor.b), mAlpha(theColor.a) { } Color::Color(const uchar* theElements) : mRed(theElements[0]), mGreen(theElements[1]), mBlue(theElements[2]), mAlpha(0xFF) { } Color::Color(const int* theElements) : mRed(theElements[0]), mGreen(theElements[1]), mBlue(theElements[2]), mAlpha(0xFF) { } int Color::GetRed() const { return mRed; } int Color::GetGreen() const { return mGreen; } int Color::GetBlue() const { return mBlue; } int Color::GetAlpha() const { return mAlpha; } int& Color::operator[](int theIdx) { static int aJunk = 0; switch (theIdx) { case 0: return mRed; case 1: return mGreen; case 2: return mBlue; case 3: return mAlpha; default: return aJunk; } } int Color::operator[](int theIdx) const { switch (theIdx) { case 0: return mRed; case 1: return mGreen; case 2: return mBlue; case 3: return mAlpha; default: return 0; } } uint32_t Color::ToInt() const { return (mAlpha << 24) | (mRed << 16) | (mGreen << 8) | (mBlue); } SexyRGBA Color::ToRGBA() const { SexyRGBA anRGBA; anRGBA.r = mRed; anRGBA.g = mGreen; anRGBA.b = mBlue; anRGBA.a = mAlpha; return anRGBA; } bool Sexy::operator==(const Color& theColor1, const Color& theColor2) { return (theColor1.mRed == theColor2.mRed) && (theColor1.mGreen == theColor2.mGreen) && (theColor1.mBlue == theColor2.mBlue) && (theColor1.mAlpha == theColor2.mAlpha); } bool Sexy::operator!=(const Color& theColor1, const Color& theColor2) { return (theColor1.mRed != theColor2.mRed) || (theColor1.mGreen != theColor2.mGreen) || (theColor1.mBlue != theColor2.mBlue) || (theColor1.mAlpha != theColor2.mAlpha); } libtuxcap-1.4.0/tuxcap/lib/AudiereSoundManager.cpp0000644000175000017500000001625710766713353022055 0ustar inniyahinniyah/* Original Audiere Sound Manager by Rheenen 2005 */ #include "AudiereMusicInterface.h" #include "AudiereSoundManager.h" #include "AudiereSoundInstance.h" #include "AudiereLoader.h" #include "audiere.h" using namespace Sexy; using namespace audiere; AudiereSoundManager::AudiereSoundManager() { mDevice = getAudiereDevice(); for (int i = 0; i < MAX_SOURCE_SOUNDS; i++) { mSourceSounds[i] = NULL; mBaseVolumes[i] = 1; mBasePans[i] = 0; mBasePitches[i] = 1; } for (int i = 0; i < MAX_CHANNELS; i++) mPlayingSounds[i] = NULL; mMasterVolume = 1.0; } AudiereSoundManager::~AudiereSoundManager() { ReleaseChannels(); ReleaseSounds(); } int AudiereSoundManager::FindFreeChannel() { Uint32 aTick = SDL_GetTicks(); if (aTick-mLastReleaseTick > 1000) { ReleaseFreeChannels(); mLastReleaseTick = aTick; } for (int i = 0; i < MAX_CHANNELS; i++) { if (mPlayingSounds[i] == NULL) return i; if (mPlayingSounds[i]->IsReleased()) { mPlayingSounds[i] = NULL; return i; } } return -1; } bool AudiereSoundManager::Initialized() { return (mDevice.get() != NULL); } void AudiereSoundManager::SetVolume(double theVolume) { mMasterVolume = (float)theVolume; for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] != NULL) mPlayingSounds[i]->RehupVolume(); } int AudiereSoundManager::LoadSound(const std::string& theFilename) { int id = GetFreeSoundId(); if (id != -1) { if (LoadSound(id, theFilename)) { return id; } } return -1; } bool AudiereSoundManager::LoadSound(unsigned int theSfxID, const std::string& theFilename) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; ReleaseSound(theSfxID); if (!mDevice) return true; // sounds just won't play, but this is not treated as a failure condition std::string aFilename = theFilename; int aLastDotPos = aFilename.rfind('.'); int aLastSlashPos = std::max((int) aFilename.rfind('\\'), (int) aFilename.rfind('/')); if (aLastSlashPos < 0) aLastSlashPos = 0; mSourceSounds[theSfxID] = OpenSampleSource(aFilename.c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = OpenSampleSource((aFilename + ".wav").c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = OpenSampleSource((aFilename + ".ogg").c_str()); if (!mSourceSounds[theSfxID]) mSourceSounds[theSfxID] = OpenSampleSource((aFilename + ".mp3").c_str()); return (mSourceSounds[theSfxID]); } void AudiereSoundManager::ReleaseSound(unsigned int theSfxID) { mSourceSounds[theSfxID] = NULL; } bool AudiereSoundManager::SetBaseVolume(unsigned int theSfxID, double theBaseVolume) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBaseVolumes[theSfxID] = (float)theBaseVolume; return true; } bool AudiereSoundManager::SetBasePan(unsigned int theSfxID, int theBasePan) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBasePans[theSfxID] = theBasePan; return true; } bool AudiereSoundManager::SetBasePitch(unsigned int theSfxID, float theBasePitch) { if ((theSfxID < 0) || (theSfxID >= MAX_SOURCE_SOUNDS)) return false; mBasePitches[theSfxID] = theBasePitch; return true; } SoundInstance* AudiereSoundManager::GetSoundInstance(unsigned int theSfxID) { if (theSfxID > MAX_SOURCE_SOUNDS) return NULL; int aFreeChannel = FindFreeChannel(); if (aFreeChannel < 0) return NULL; if (!mDevice) { mPlayingSounds[aFreeChannel] = new AudiereSoundInstance(this, NULL); } else { if (!mSourceSounds[theSfxID]) return NULL; mPlayingSounds[aFreeChannel] = new AudiereSoundInstance(this, mSourceSounds[theSfxID]); } mPlayingSounds[aFreeChannel]->SetBasePan(mBasePans[theSfxID]); mPlayingSounds[aFreeChannel]->SetBaseVolume(mBaseVolumes[theSfxID]); mPlayingSounds[aFreeChannel]->AdjustBasePitch(mBasePitches[theSfxID]); return mPlayingSounds[aFreeChannel]; } void AudiereSoundManager::ReleaseSounds() { for (int i = 0; i < MAX_SOURCE_SOUNDS; i++) if (mSourceSounds[i]) mSourceSounds[i] = NULL; } void AudiereSoundManager::ReleaseChannels() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i]) { mPlayingSounds[i]->Release(); mPlayingSounds[i] = NULL; } } void AudiereSoundManager::ReleaseFreeChannels() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] && mPlayingSounds[i]->IsReleased()) mPlayingSounds[i] = NULL; } void AudiereSoundManager::StopAllSounds() { for (int i = 0; i < MAX_CHANNELS; i++) if (mPlayingSounds[i] != NULL) { bool isAutoRelease = mPlayingSounds[i]->mAutoRelease; mPlayingSounds[i]->Stop(); mPlayingSounds[i]->mAutoRelease = isAutoRelease; } } double AudiereSoundManager::GetMasterVolume() { #if 0 MIXERCONTROLDETAILS mcd; MIXERCONTROLDETAILS_UNSIGNED mxcd_u; MIXERLINECONTROLS mxlc; MIXERCONTROL mlct; MIXERLINE mixerLine; HMIXER hmx; MIXERCAPS pmxcaps; mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER); mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps)); mxlc.cbStruct = sizeof(mxlc); mxlc.cbmxctrl = sizeof(mlct); mxlc.pamxctrl = &mlct; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mixerLine.cbStruct = sizeof(mixerLine); mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE); mxlc.dwLineID = mixerLine.dwLineID; mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE); mcd.cbStruct = sizeof(mcd); mcd.dwControlID = mlct.dwControlID; mcd.cChannels = 1; mcd.cMultipleItems = 0; mcd.cbDetails = sizeof(mxcd_u); mcd.paDetails = &mxcd_u; mixerGetControlDetails((HMIXEROBJ) hmx, &mcd, 0L); mixerClose(hmx); return mxcd_u.dwValue / (double) 0xFFFF; #else return 0.0; #endif } void AudiereSoundManager::SetMasterVolume(double theVolume) { #if 0 MIXERCONTROLDETAILS mcd; MIXERCONTROLDETAILS_UNSIGNED mxcd_u; MIXERLINECONTROLS mxlc; MIXERCONTROL mlct; MIXERLINE mixerLine; HMIXER hmx; MIXERCAPS pmxcaps; mixerOpen((HMIXER*) &hmx, 0, 0, 0, MIXER_OBJECTF_MIXER); mixerGetDevCaps(0, &pmxcaps, sizeof(pmxcaps)); mxlc.cbStruct = sizeof(mxlc); mxlc.cbmxctrl = sizeof(mlct); mxlc.pamxctrl = &mlct; mxlc.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mixerLine.cbStruct = sizeof(mixerLine); mixerLine.dwComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; mixerGetLineInfo((HMIXEROBJ) hmx, &mixerLine, MIXER_GETLINEINFOF_COMPONENTTYPE); mxlc.dwLineID = mixerLine.dwLineID; mixerGetLineControls((HMIXEROBJ) hmx, &mxlc, MIXER_GETLINECONTROLSF_ONEBYTYPE); mcd.cbStruct = sizeof(mcd); mcd.dwControlID = mlct.dwControlID; mcd.cChannels = 1; mcd.cMultipleItems = 0; mcd.cbDetails = sizeof(mxcd_u); mcd.paDetails = &mxcd_u; mxcd_u.dwValue = (int) (0xFFFF * theVolume); mixerSetControlDetails((HMIXEROBJ) hmx, &mcd, 0L); mixerClose(hmx); #endif } void AudiereSoundManager::Flush() { } void AudiereSoundManager::SetCooperativeWindow(HWND theHWnd, bool isWindowed) { } int AudiereSoundManager::GetFreeSoundId() { for (int i = 0; i < MAX_SOURCE_SOUNDS; ++i) { if (!mSourceSounds[i]) { return i; } } return -1; } int AudiereSoundManager::GetNumSounds() { int nr_sounds = 0; for (int i = 0; i < MAX_SOURCE_SOUNDS; ++i) { if (mSourceSounds[i]) { ++nr_sounds; } } return nr_sounds; } #undef SOUND_FLAGS libtuxcap-1.4.0/tuxcap/lib/SWTri_DrawTriangleInc2.cpp0000644000175000017500000004076510641010433022340 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. int aType = (blend?1:0) | (global_argb?2:0) | (mod_argb?4:0) | (talpha?8:0) | (textured?16:0); switch (thePixelFormat) { case 0x8888: aType |= 0<<5; break; case 0x888: aType |= 1<<5; break; case 0x565: aType |= 2<<5; break; case 0x555: aType |= 3<<5; break; } switch (aType) { case 0: DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 1: DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 2: DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 3: DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 4: DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 5: DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 6: DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 7: DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 8: DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 9: DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 10: DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 11: DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 12: DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 13: DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 14: DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 15: DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 16: DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 17: DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 18: DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 19: DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 20: DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 21: DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 22: DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 23: DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 24: DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 25: DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 26: DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 27: DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 28: DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 29: DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 30: DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 31: DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 32: DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 33: DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 34: DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 35: DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 36: DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 37: DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 38: DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 39: DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 40: DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 41: DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 42: DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 43: DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 44: DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 45: DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 46: DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 47: DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 48: DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 49: DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 50: DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 51: DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 52: DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 53: DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 54: DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 55: DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 56: DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 57: DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 58: DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 59: DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 60: DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 61: DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 62: DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 63: DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 64: DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 65: DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 66: DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 67: DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 68: DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 69: DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 70: DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 71: DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 72: DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 73: DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 74: DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 75: DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 76: DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 77: DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 78: DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 79: DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 80: DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 81: DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 82: DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 83: DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 84: DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 85: DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 86: DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 87: DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 88: DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 89: DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 90: DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 91: DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 92: DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 93: DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 94: DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 95: DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 96: DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 97: DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 98: DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 99: DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 100: DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 101: DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 102: DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 103: DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 104: DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 105: DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 106: DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 107: DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 108: DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 109: DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 110: DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 111: DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 112: DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 113: DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 114: DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 115: DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 116: DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 117: DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 118: DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 119: DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 120: DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 121: DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 122: DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 123: DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 124: DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 125: DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 126: DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND0(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; case 127: DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND1(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); break; } libtuxcap-1.4.0/tuxcap/lib/TextWidget.cpp0000644000175000017500000002365610654431553020257 0ustar inniyahinniyah#include "TextWidget.h" #include "Graphics.h" #include "ScrollbarWidget.h" #include "WidgetManager.h" #include "Font.h" using namespace Sexy; TextWidget::TextWidget() { mFont = NULL; mPosition = 0; mPageSize = 0; mStickToBottom = true; mMaxLines = 2048; mScrollbar = NULL; } SexyStringVector TextWidget::GetLines() { return mLogicalLines; } void TextWidget::SetLines(SexyStringVector theNewLines) { mLogicalLines = theNewLines; } void TextWidget::Clear() { mLogicalLines.clear(); mPhysicalLines.clear(); mPosition = 0.0; mScrollbar->SetMaxValue(0.0); MarkDirty(); } void TextWidget::DrawColorString(Graphics* g, const SexyString& theString, int x, int y, bool useColors) { int aWidth = 0; if (useColors) g->SetColor(Color(0, 0, 0)); SexyString aCurString = _S(""); for (int i = 0; i < (int)theString.length(); i++) { wchar_t t = theString[i]; if (t == 0x100) { if (aCurString.length() > 0) g->DrawString(aCurString, x + aWidth, y); aWidth += g->GetFont()->StringWidth(aCurString); aCurString = _S(""); if (useColors) g->SetColor(Color(theString[i+1], theString[i+2], theString[i+3])); i += 3; } else aCurString += theString[i]; } if (aCurString.length() > 0) g->DrawString(aCurString, x + aWidth, y); } void TextWidget::DrawColorStringHilited(Graphics* g, const SexyString& theString, int x, int y, int theStartPos, int theEndPos) { DrawColorString(g, theString, x, y, true); if (theEndPos > theStartPos) { int aXOfs = GetColorStringWidth(theString.substr(0, theStartPos)); int aWidth = GetColorStringWidth(theString.substr(0, theEndPos)) - aXOfs; Graphics aClipG(*g); aClipG.ClipRect(x + aXOfs, y - g->GetFont()->GetAscent(), aWidth, g->GetFont()->GetHeight()); g->SetColor(Color(0, 0, 128)); g->FillRect(x + aXOfs, y - g->GetFont()->GetAscent(), aWidth, g->GetFont()->GetHeight()); aClipG.SetColor(Color(255, 255, 255)); DrawColorString(&aClipG, theString, x, y, false); } } int TextWidget::GetStringIndex(const SexyString& theString, int thePixel) { int aPos = 0; for (int i = 0; i < (int)theString.length(); i++) { SexyString aLoSubStr = theString.substr(0, i); SexyString aHiSubStr = theString.substr(0, i+1); int aLoLen = GetColorStringWidth(aLoSubStr); int aHiLen = GetColorStringWidth(aHiSubStr); if (thePixel >= (aLoLen+aHiLen)/2) aPos = i+1; } return aPos; } //UNICODE int TextWidget::GetColorStringWidth(const SexyString& theString) { int aWidth = 0; SexyString aTempString; for (int i = 0; i < (int)theString.length(); i++) { wchar_t t = theString[i]; if (t == 0x100) { aWidth += mFont->StringWidth(aTempString); aTempString = _S(""); i += 3; } else aTempString += theString[i]; } aWidth += mFont->StringWidth(aTempString); return aWidth; } void TextWidget::Resize(int theX, int theY, int theWidth, int theHeight) { Widget::Resize(theX, theY, theWidth, theHeight); double aPageSize = 1; if (mHeight > mFont->GetHeight()+16) aPageSize = (mHeight - 8.0) / mFont->GetHeight(); int aLogValue = 0; if (mLineMap.size() > 0) { //IntIntMap::iterator anItr = mLineMap.find(mScrollbar->mValue); aLogValue = mLineMap[(int) mScrollbar->mValue]; } int aNewPhysValue = 0; mLineMap.clear(); mPhysicalLines.clear(); for (int i = 0; i < (int)mLogicalLines.size(); i++) { if (i == aLogValue) aNewPhysValue = mPhysicalLines.size(); AddToPhysicalLines(i, mLogicalLines[i]); } bool atBottom = mScrollbar->AtBottom(); mPageSize = aPageSize; mScrollbar->SetMaxValue(mPhysicalLines.size()); mScrollbar->SetPageSize((int) aPageSize); mScrollbar->SetValue(aNewPhysValue); if ((mStickToBottom) && (atBottom)) mScrollbar->GoToBottom(); } //UNICODE Color TextWidget::GetLastColor(const SexyString& theString) { int anIdx = theString.rfind((char)0xFF); if (anIdx < 0) return Color(0, 0, 0); return Color(theString[anIdx+1], theString[anIdx+2], theString[anIdx+3]); } //UNICODE void TextWidget::AddToPhysicalLines(int theIdx, const SexyString& theLine) { SexyString aCurString = _S(""); if (GetColorStringWidth(theLine) <= mWidth - 8) { aCurString = theLine; } else { int aCurPos = 0; while (aCurPos < (int)theLine.length()) { int aNextCheckPos = aCurPos; while ((aNextCheckPos < (int)theLine.length()) && (theLine[aNextCheckPos] == ' ')) aNextCheckPos++; int aSpacePos = theLine.find(_S(" "), aNextCheckPos); if (aSpacePos == -1) aSpacePos = theLine.length(); SexyString aNewString = aCurString + theLine.substr(aCurPos, aSpacePos - aCurPos); if (GetColorStringWidth(aNewString) > mWidth-8) { mPhysicalLines.push_back(aCurString); mLineMap.push_back(theIdx); Color aColor = GetLastColor(aCurString); aCurString = _S(" ") + SexyChar(0xFF) + (SexyChar) aColor.mRed + (SexyChar) aColor.mGreen + (SexyChar) aColor.mBlue + theLine.substr(aNextCheckPos, aSpacePos - aNextCheckPos); } else aCurString = aNewString; aCurPos = aSpacePos; } } if ((aCurString.compare(_S("")) != 0) || (theLine.compare(_S("")) == 0)) { mPhysicalLines.push_back(aCurString); mLineMap.push_back(theIdx); } } //UNICODE void TextWidget::AddLine(const SexyString& theLine) { SexyString aLine = theLine; if (aLine.compare(_S("")) == 0) aLine = _S(" "); bool atBottom = mScrollbar->AtBottom(); mLogicalLines.push_back(aLine); if ((int)mLogicalLines.size() > mMaxLines) { // Remove an extra 10 lines, for safty int aNumLinesToRemove = mLogicalLines.size() - mMaxLines + 10; mLogicalLines.erase(mLogicalLines.begin(), mLogicalLines.begin() + aNumLinesToRemove); int aPhysLineRemoveCount = 0; // Remove all physical lines and linemap entries relating to deleted logical lines while (mLineMap[aPhysLineRemoveCount] < aNumLinesToRemove) { aPhysLineRemoveCount++; } mLineMap.erase(mLineMap.begin(), mLineMap.begin() + aPhysLineRemoveCount); mPhysicalLines.erase(mPhysicalLines.begin(), mPhysicalLines.begin() + aPhysLineRemoveCount); // Offset the line map numbers int i; for (i = 0; i < (int)mLineMap.size(); i++) { mLineMap[i] -= aNumLinesToRemove; } //mLineMap.setElementAt(new Integer(((Integer) mLineMap.elementAt(i)).intValue() - aNumLinesToRemove), i); // Move the hilited area for (i = 0; i < 2; i++) { mHiliteArea[i][1] -= aNumLinesToRemove; if (mHiliteArea[i][1] < 0) { mHiliteArea[i][0] = 0; mHiliteArea[i][1] = 0; } } mScrollbar->SetValue(mScrollbar->mValue - aNumLinesToRemove); } AddToPhysicalLines(mLogicalLines.size()-1, aLine); mScrollbar->SetMaxValue(mPhysicalLines.size()); if (atBottom) mScrollbar->GoToBottom(); MarkDirty(); } bool TextWidget::SelectionReversed() { return ((mHiliteArea[1][1] < mHiliteArea[0][1]) || ((mHiliteArea[1][1] == mHiliteArea[0][1]) && (mHiliteArea[1][0] < mHiliteArea[0][0]))); } void TextWidget::GetSelectedIndices(int theLineIdx, int* theIndices) { int aXor = SelectionReversed() ? 1 : 0; for (int aPosIdx = 0; aPosIdx < 2; aPosIdx++) { int aVal; if (mHiliteArea[aPosIdx][1] < theLineIdx) aVal = 0; else if (mHiliteArea[aPosIdx][1] == theLineIdx) aVal = mHiliteArea[aPosIdx][0]; else aVal = mPhysicalLines[theLineIdx].length(); theIndices[aPosIdx ^ aXor] = aVal; } } void TextWidget::Draw(Graphics* g) { g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); Graphics aClipG(*g); aClipG.ClipRect(4, 4, mWidth - 8, mHeight - 8); aClipG.SetColor(Color(0, 0, 0)); aClipG.SetFont(mFont); int aFirstLine = (int) mPosition; int aLastLine = std::min((int) mPhysicalLines.size()-1, (int) mPosition + (int) mPageSize + 1); for (int i = aFirstLine; i <= aLastLine; i++) { int aYPos = 4 + (int) ((i - (int) mPosition)*mFont->GetHeight()) + mFont->GetAscent(); SexyString aString = mPhysicalLines[i]; int aHilitePos[2]; GetSelectedIndices(i, aHilitePos); DrawColorStringHilited(&aClipG, aString, 4, aYPos, aHilitePos[0], aHilitePos[1]); } } void TextWidget::ScrollPosition(int theId, double thePosition) { mPosition = thePosition; MarkDirty(); } void TextWidget::GetTextIndexAt(int x, int y, int* thePosArray) { int aLineNum = (int) (mScrollbar->mValue + (y / (double) mFont->GetHeight())); if (y < 0) { thePosArray[0] = 0; thePosArray[1] = 0; } else if (aLineNum < (int)mPhysicalLines.size()) { thePosArray[0] = GetStringIndex(mPhysicalLines[aLineNum], x); thePosArray[1] = aLineNum; } else { if (mPhysicalLines.size() > 0) { thePosArray[0] = mPhysicalLines[mPhysicalLines.size()-1].length(); thePosArray[1] = mPhysicalLines.size() - 1; } } } void TextWidget::MouseDown(int x, int y, int theClickCount) { Widget::MouseDown(x, y, theClickCount); GetTextIndexAt(x-4, y-4, mHiliteArea[0]); mHiliteArea[1][0] = mHiliteArea[0][0]; mHiliteArea[1][1] = mHiliteArea[0][1]; MarkDirty(); } void TextWidget::MouseDrag(int x, int y) { Widget::MouseDrag(x, y); GetTextIndexAt(x-4, y-4, mHiliteArea[1]); MarkDirty(); } SexyString TextWidget::GetSelection() { SexyString aSelString = _S(""); int aSelIndices[2]; bool first = true; bool reverse = SelectionReversed(); for (int aLineNum = mHiliteArea[reverse ? 1 : 0][1]; aLineNum <= mHiliteArea[reverse ? 0 : 1][1]; aLineNum++) { SexyString aString = mPhysicalLines[aLineNum]; GetSelectedIndices(aLineNum, aSelIndices); if (!first) aSelString += _S("\r\n"); for (int aStrIdx = aSelIndices[0]; aStrIdx < aSelIndices[1]; aStrIdx++) { wchar_t aChar = aString[aStrIdx]; if (aChar != 0x100) aSelString += aChar; else aStrIdx += 3; } first = false; } return aSelString; } void TextWidget::KeyDown(KeyCode theKey) { /*if (theKey == 3) { // Control-C mWidgetManager.mApplet.CopyToClipboard(GetSelection()); } else { if (mEditWidget != null) { mWidgetManager.SetFocus(mEditWidget); mEditWidget.KeyDown(theKey, shiftDown, controlDown); } }*/ } libtuxcap-1.4.0/tuxcap/lib/ScrollbarWidget.cpp0000644000175000017500000001701210641010442021225 0ustar inniyahinniyah#include "ScrollbarWidget.h" #include "WidgetManager.h" #include "ScrollListener.h" #include "ScrollbuttonWidget.h" using namespace Sexy; ScrollbarWidget::ScrollbarWidget(int theId, ScrollListener* theScrollListener) { mId = theId; mScrollListener = theScrollListener; SetDisabled(true); mUpButton = new ScrollbuttonWidget(0, this); mUpButton->SetDisabled(true); mDownButton = new ScrollbuttonWidget(1, this); mDownButton->SetDisabled(true); mInvisIfNoScroll = false; mPressedOnThumb = false; mValue = 0; mMaxValue = 0; mPageSize = 0; mUpdateAcc = 0; mButtonAcc = 0; mUpdateMode = 0; mHorizontal = false; AddWidget(mUpButton); AddWidget(mDownButton); } ScrollbarWidget::~ScrollbarWidget() { RemoveAllWidgets(true); } void ScrollbarWidget::SetInvisIfNoScroll(bool invisIfNoScroll) { mInvisIfNoScroll = invisIfNoScroll; if (mInvisIfNoScroll) { SetVisible(false); mDownButton->SetVisible(false); mUpButton->SetVisible(false); } } void ScrollbarWidget::SetHorizontal(bool isHorizontal) { mHorizontal = isHorizontal; mDownButton->mHorizontal = mHorizontal; mUpButton->mHorizontal = mHorizontal; } void ScrollbarWidget::ResizeScrollbar(int theX, int theY, int theWidth, int theHeight) { Resize(theX, theY, theWidth, theHeight); if (mHorizontal) { theX = theY = 0; // Use New Container Stuff mUpButton->Resize(theX, theY, theHeight, theHeight); mDownButton->Resize(theX + theWidth - theHeight, theY, theHeight, theHeight); } else { theX = theY = 0; // Use New Container Stuff mUpButton->Resize(theX, theY, theWidth, theWidth); mDownButton->Resize(theX, theY + theHeight - theWidth, theWidth, theWidth); } } void ScrollbarWidget::SetMaxValue(double theNewMaxValue) { mMaxValue = theNewMaxValue; ClampValue(); MarkDirty(); } void ScrollbarWidget::SetPageSize(double theNewPageSize) { mPageSize = theNewPageSize; ClampValue(); MarkDirty(); } void ScrollbarWidget::SetValue(double theNewValue) { mValue = theNewValue; ClampValue(); mScrollListener->ScrollPosition(mId, mValue); MarkDirty(); } bool ScrollbarWidget::AtBottom() { return mMaxValue - mPageSize - mValue <= 1.0; } void ScrollbarWidget::GoToBottom() { mValue = mMaxValue - mPageSize; ClampValue(); SetValue(mValue); } void ScrollbarWidget::DrawThumb(Graphics *g, int theX, int theY, int theWidth, int theHeight) { g->SetColor(Color(212, 212, 212)); g->FillRect(theX, theY, theWidth, theHeight); g->SetColor(Color(255, 255, 255)); g->FillRect(theX + 1, theY + 1, theWidth-2, 1); g->FillRect(theX + 1, theY + 1, 1, theHeight-2); g->SetColor(Color::Black); g->FillRect(theX, theY + theHeight - 1, theWidth, 1); g->FillRect(theX + theWidth - 1, theY, 1, theHeight); g->SetColor(Color(132, 132, 132)); g->FillRect(theX + 1, theY + theHeight - 2, theWidth - 2, 1); g->FillRect(theX + theWidth - 2, theY + 1, 1, theHeight - 2); } int ScrollbarWidget::GetTrackSize() { if (mHorizontal) return mWidth-2*mUpButton->mWidth; else return mHeight-2*mUpButton->mWidth; } int ScrollbarWidget::GetThumbSize() { if (mPageSize > mMaxValue) return 0; int aThumbSize = (int) ((double) ((GetTrackSize() * mPageSize / mMaxValue)) + 0.5); return std::max(8, aThumbSize); } int ScrollbarWidget::GetThumbPosition() { if (mPageSize > mMaxValue) return mUpButton->mWidth; return (int) ((double) (((mValue * (GetTrackSize() - GetThumbSize())) / (mMaxValue - mPageSize))) + 0.5) + mUpButton->mWidth; } void ScrollbarWidget::Draw(Graphics *g) { int aThumbSize = GetThumbSize(); int aThumbPosition = GetThumbPosition(); if (mHorizontal) { if (mUpdateMode == UPDATE_MODE_PGUP) g->SetColor(Color(48, 48, 48)); else g->SetColor(Color(232, 232, 232)); g->FillRect(0, 0, aThumbPosition, mHeight); if (aThumbSize > 0) DrawThumb(g, aThumbPosition, 0, aThumbSize, mHeight); if (mUpdateMode == UPDATE_MODE_PGDN) g->SetColor(Color(48, 48, 48)); else g->SetColor(Color(232, 232, 232)); g->FillRect(aThumbPosition + aThumbSize, 0, mWidth - aThumbPosition - aThumbSize, mHeight); } else { if (mUpdateMode == UPDATE_MODE_PGUP) g->SetColor(Color(48, 48, 48)); else g->SetColor(Color(232, 232, 232)); g->FillRect(0, 0, mWidth, aThumbPosition); if (aThumbSize > 0) DrawThumb(g, 0, aThumbPosition, mWidth, aThumbSize); if (mUpdateMode == UPDATE_MODE_PGDN) g->SetColor(Color(48, 48, 48)); else g->SetColor(Color(232, 232, 232)); g->FillRect(0, aThumbPosition + aThumbSize, mWidth, mHeight - aThumbPosition - aThumbSize); } } void ScrollbarWidget::ClampValue() { double anOldValue = mValue; if (mValue > mMaxValue - mPageSize) mValue = mMaxValue - mPageSize; if (mValue < 0.0) mValue = 0.0; bool canScroll = mPageSize < mMaxValue; SetDisabled(!canScroll); mUpButton->SetDisabled(!canScroll); mDownButton->SetDisabled(!canScroll); if (mInvisIfNoScroll) { SetVisible(canScroll); mDownButton->SetVisible(canScroll); mUpButton->SetVisible(canScroll); } if (mValue != anOldValue) mScrollListener->ScrollPosition(mId, mValue); } void ScrollbarWidget::SetThumbPosition(int thePosition) { SetValue(((thePosition-mUpButton->mWidth) * (mMaxValue - mPageSize)) / (GetTrackSize() - GetThumbSize())); } void ScrollbarWidget::ButtonPress(int theId) { mButtonAcc = 0; if (theId == 0) SetValue(mValue-1); else SetValue(mValue+1); } void ScrollbarWidget::ButtonDepress(int theId) { } void ScrollbarWidget::ButtonDownTick(int theId) { if (theId == 0) { if (++mButtonAcc >= 25) { SetValue(mValue-1); mButtonAcc = 24; } } else { if (++mButtonAcc >= 25) { SetValue(mValue+1); mButtonAcc = 24; } } } void ScrollbarWidget::Update() { Widget::Update(); switch (mUpdateMode) { case UPDATE_MODE_PGUP: if (ThumbCompare(mLastMouseX, mLastMouseY) != -1) { mUpdateMode = UPDATE_MODE_IDLE; MarkDirty(); } else if (++mUpdateAcc >= 25) { SetValue(mValue - mPageSize); mUpdateAcc = 20; } break; case UPDATE_MODE_PGDN: if (ThumbCompare(mLastMouseX, mLastMouseY) != 1) { mUpdateMode = UPDATE_MODE_IDLE; MarkDirty(); } else if (++mUpdateAcc >= 25) { SetValue(mValue + mPageSize); mUpdateAcc = 20; } break; } } int ScrollbarWidget::ThumbCompare(int x, int y) { int aTrackPosition; if (mHorizontal) aTrackPosition = x; else aTrackPosition = y; if (aTrackPosition < GetThumbPosition()) return -1; if (aTrackPosition >= GetThumbPosition() + GetThumbSize()) return 1; return 0; } void ScrollbarWidget::MouseDown(int x, int y, int theBtnNum, int theClickCount) { Widget::MouseDown(x, y, theBtnNum, theClickCount); if (!mDisabled) { switch (ThumbCompare(x, y)) { case -1: SetValue(mValue - mPageSize); mUpdateMode = UPDATE_MODE_PGUP; mUpdateAcc = 0; break; case 0: mPressedOnThumb = true; mMouseDownThumbPos = GetThumbPosition(); mMouseDownX = x; mMouseDownY = y; break; case 1: SetValue(mValue + mPageSize); mUpdateMode = UPDATE_MODE_PGDN; mUpdateAcc = 0; break; } } mLastMouseX = x; mLastMouseY = y; } void ScrollbarWidget::MouseUp(int x, int y, int theBtnNum, int theClickCount) { Widget::MouseUp(x, y, theBtnNum, theClickCount); mUpdateMode = 0; mPressedOnThumb = false; MarkDirty(); } void ScrollbarWidget::MouseDrag(int x, int y) { Widget::MouseDrag(x, y); if (mPressedOnThumb) { if (mHorizontal) SetThumbPosition(mMouseDownThumbPos + x - mMouseDownX); else SetThumbPosition(mMouseDownThumbPos + y - mMouseDownY); } mLastMouseX = x; mLastMouseY = y; } libtuxcap-1.4.0/tuxcap/lib/WidgetContainer.cpp0000644000175000017500000003257610712171657021257 0ustar inniyahinniyah#include "WidgetContainer.h" #include "WidgetManager.h" #include "Widget.h" #if 0 #include "Debug.h" #endif #include #include using namespace Sexy; WidgetContainer::WidgetContainer() { mX = 0; mY = 0; mWidth = 0; mHeight = 0; mParent = NULL; mWidgetManager = NULL; mUpdateIteratorModified = false; mUpdateIterator = mWidgets.end(); mLastWMUpdateCount = 0; mUpdateCnt = 0; mDirty = false; mHasAlpha = false; mClip = true; mPriority = 0; mZOrder = 0; } WidgetContainer::~WidgetContainer() { // call RemoveWidget before you delete it! assert(mParent == NULL); assert(mWidgets.empty()); } void WidgetContainer::RemoveAllWidgets(bool doDelete, bool recursive) { while (!mWidgets.empty()) { Widget *aWidget = mWidgets.front(); RemoveWidget(aWidget); if (recursive) aWidget->RemoveAllWidgets(doDelete,recursive); if (doDelete) delete aWidget; } } Rect WidgetContainer::GetRect() { return Rect(mX, mY, mWidth, mHeight); } bool WidgetContainer::Intersects(WidgetContainer* theWidget) { return GetRect().Intersects(theWidget->GetRect()); } void WidgetContainer::AddWidget(Widget* theWidget) { if (std::find(mWidgets.begin(), mWidgets.end(), theWidget) == mWidgets.end()) { InsertWidgetHelper(mWidgets.end(),theWidget); theWidget->mWidgetManager = mWidgetManager; theWidget->mParent = this; if (mWidgetManager != NULL) { theWidget->AddedToManager(mWidgetManager); theWidget->MarkDirtyFull(); mWidgetManager->RehupMouse(); } MarkDirty(); } } bool WidgetContainer::HasWidget(Widget* theWidget) { return std::find(mWidgets.begin(), mWidgets.end(), theWidget) != mWidgets.end(); } void WidgetContainer::RemoveWidget(Widget* theWidget) { WidgetList::iterator anItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (anItr != mWidgets.end()) { theWidget->WidgetRemovedHelper(); theWidget->mParent = NULL; bool erasedCur = (anItr == mUpdateIterator); mWidgets.erase(anItr++); if (erasedCur) { mUpdateIterator = anItr; mUpdateIteratorModified = true; } } } Widget* WidgetContainer::GetWidgetAtHelper(int x, int y, int theFlags, bool* found, int* theWidgetX, int* theWidgetY) { bool belowModal = false; ModFlags(theFlags, mWidgetFlagsMod); WidgetList::reverse_iterator anItr = mWidgets.rbegin(); while (anItr != mWidgets.rend()) { Widget* aWidget = *anItr; int aCurFlags = theFlags; ModFlags(aCurFlags, aWidget->mWidgetFlagsMod); if (belowModal) ModFlags(aCurFlags, mWidgetManager->mBelowModalFlagsMod); if (aCurFlags & WIDGETFLAGS_ALLOW_MOUSE) { if (aWidget->mVisible) { bool childFound; Widget* aCheckWidget = aWidget->GetWidgetAtHelper(x - aWidget->mX, y - aWidget->mY, aCurFlags, &childFound, theWidgetX, theWidgetY); if ((aCheckWidget != NULL) || (childFound)) { *found = true; return aCheckWidget; } if ((aWidget->mMouseVisible) && (aWidget->GetInsetRect().Contains(x, y))) { *found = true; if (aWidget->IsPointVisible(x-aWidget->mX,y-aWidget->mY)) { if (theWidgetX) *theWidgetX = x - aWidget->mX; if (theWidgetY) *theWidgetY = y - aWidget->mY; return aWidget; } } } } belowModal |= aWidget == mWidgetManager->mBaseModalWidget; ++anItr; } *found = false; return NULL; } bool WidgetContainer::IsBelowHelper(Widget* theWidget1, Widget* theWidget2, bool* found) { WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget == theWidget1) { *found = true; return true; } else if (aWidget == theWidget2) { *found = true; return false; } bool result = aWidget->IsBelowHelper(theWidget1, theWidget2, found); if (*found) return result; ++anItr; } return false; } bool WidgetContainer::IsBelow(Widget* theWidget1, Widget* theWidget2) { bool found = false; return IsBelowHelper(theWidget1, theWidget2, &found); } void WidgetContainer::MarkAllDirty() { MarkDirty(); WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { (*anItr)->mDirty = true; (*anItr)->MarkAllDirty(); ++anItr; } } void WidgetContainer::InsertWidgetHelper(const WidgetList::iterator &where, Widget *theWidget) { // Search forwards WidgetList::iterator anItr = where; while (anItr!=mWidgets.end()) { Widget *aWidget = *anItr; if (aWidget->mZOrder >= theWidget->mZOrder) { if (anItr!=mWidgets.begin()) { WidgetList::iterator anItr2 = anItr; anItr2--; aWidget = *anItr; if (aWidget->mZOrder>theWidget->mZOrder) // need to search backwards break; } mWidgets.insert(anItr,theWidget); return; } ++anItr; } // Search backwards while (anItr!=mWidgets.begin()) { --anItr; Widget *aWidget = *anItr; if (aWidget->mZOrder <= theWidget->mZOrder) { mWidgets.insert(++anItr,theWidget); return; } } // It goes at the beginning mWidgets.push_front(theWidget); } void WidgetContainer::BringToFront(Widget* theWidget) { WidgetList::iterator anItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (anItr != mWidgets.end()) { if (anItr == mUpdateIterator) { mUpdateIterator++; mUpdateIteratorModified = true; } mWidgets.erase(anItr); InsertWidgetHelper(mWidgets.end(),theWidget); theWidget->OrderInManagerChanged(); } } void WidgetContainer::BringToBack(Widget* theWidget) { WidgetList::iterator anItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (anItr != mWidgets.end()) { if (anItr == mUpdateIterator) { mUpdateIterator++; mUpdateIteratorModified = true; } mWidgets.erase(anItr); InsertWidgetHelper(mWidgets.begin(),theWidget); theWidget->OrderInManagerChanged(); } } void WidgetContainer::PutBehind(Widget* theWidget, Widget* theRefWidget) { WidgetList::iterator anItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (anItr != mWidgets.end()) { if (anItr == mUpdateIterator) { mUpdateIterator++; mUpdateIteratorModified = true; } mWidgets.erase(anItr); anItr = std::find(mWidgets.begin(), mWidgets.end(), theRefWidget); InsertWidgetHelper(anItr, theWidget); theWidget->OrderInManagerChanged(); } } void WidgetContainer::PutInfront(Widget* theWidget, Widget* theRefWidget) { WidgetList::iterator anItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (anItr != mWidgets.end()) { if (anItr == mUpdateIterator) { mUpdateIterator++; mUpdateIteratorModified = true; } mWidgets.erase(anItr); anItr = std::find(mWidgets.begin(), mWidgets.end(), theRefWidget); if (anItr != mWidgets.end()) anItr++; InsertWidgetHelper(anItr, theWidget); theWidget->OrderInManagerChanged(); } } Point WidgetContainer::GetAbsPos() // relative to top level { if (mParent==NULL) return Point(mX,mY); else return Point(mX,mY) + mParent->GetAbsPos(); } void WidgetContainer::AddedToManager(WidgetManager* theWidgetManager) { WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* theWidget = *anItr; theWidget->mWidgetManager = theWidgetManager; theWidget->AddedToManager(theWidgetManager); ++anItr; MarkDirty(); } } void WidgetContainer::RemovedFromManager(WidgetManager* theWidgetManager) { for (WidgetList::iterator anItr = mWidgets.begin(); anItr != mWidgets.end(); ++anItr) { Widget* aWidget = *anItr; theWidgetManager->DisableWidget(aWidget); aWidget->RemovedFromManager(theWidgetManager); aWidget->mWidgetManager = NULL; } if (theWidgetManager->mPopupCommandWidget==this) theWidgetManager->mPopupCommandWidget = NULL; } void WidgetContainer::MarkDirty() { if (mParent != NULL) mParent->MarkDirty(this); else mDirty = true; } void WidgetContainer::MarkDirtyFull() { if (mParent != NULL) mParent->MarkDirtyFull(this); else mDirty = true; } void WidgetContainer::MarkDirtyFull(WidgetContainer* theWidget) { // Mark all things dirty that are under or over this widget // Mark ourselves dirty MarkDirtyFull(); theWidget->mDirty = true; // Top-level windows are treated differently, as marking a child dirty always // causes a parent redraw which always causes all children to redraw if (mParent != NULL) return; WidgetList::iterator aFoundWidgetItr = std::find(mWidgets.begin(), mWidgets.end(), theWidget); if (aFoundWidgetItr == mWidgets.end()) return; WidgetList::iterator anItr = aFoundWidgetItr; if (anItr != mWidgets.begin()) { anItr--; for (;;) { Widget* aWidget = *anItr; if (aWidget->mVisible) { if ((!aWidget->mHasTransparencies) && (!aWidget->mHasAlpha)) { // Clip the widget's bounds to the screen and check if it fully overlapped by this non-transparent widget underneath it // If it is fully overlapped then we can stop marking dirty underneath it since it's not transparent. Rect aRect = Rect(theWidget->mX,theWidget->mY,theWidget->mWidth,theWidget->mHeight).Intersection(Rect(0,0,mWidth,mHeight)); if ((aWidget->Contains(aRect.mX, aRect.mY) && (aWidget->Contains(aRect.mX + aRect.mWidth - 1, aRect.mY + aRect.mHeight - 1)))) { // If this widget is fully contained within a lower widget, there is no need to dig down // any deeper. aWidget->MarkDirty(); break; } } if (aWidget->Intersects(theWidget)) MarkDirty(aWidget); } if (anItr == mWidgets.begin()) break; --anItr; } } anItr = aFoundWidgetItr; while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if ((aWidget->mVisible) && (aWidget->Intersects(theWidget))) MarkDirty(aWidget); ++anItr; } } void WidgetContainer::MarkDirty(WidgetContainer* theWidget) { if (theWidget->mDirty) return; // Only mark things dirty that are on top of this widget // Mark ourselves dirty MarkDirty(); theWidget->mDirty = true; // Top-level windows are treated differently, as marking a child dirty always // causes a parent redraw which always causes all children to redraw if (mParent != NULL) return; if (theWidget->mHasAlpha) MarkDirtyFull(theWidget); else { bool found = false; WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget == theWidget) found = true; else if (found) { if ((aWidget->mVisible) && (aWidget->Intersects(theWidget))) MarkDirty(aWidget); } ++anItr; } } } void WidgetContainer::Update() { mUpdateCnt++; } void WidgetContainer::UpdateAll(ModalFlags* theFlags) { AutoModalFlags anAutoModalFlags(theFlags, mWidgetFlagsMod); if (theFlags->GetFlags() & WIDGETFLAGS_MARK_DIRTY) MarkDirty(); // Can update? WidgetManager *aWidgetManager = mWidgetManager; if (aWidgetManager==NULL) return; if (theFlags->GetFlags() & WIDGETFLAGS_UPDATE) { if (mLastWMUpdateCount != mWidgetManager->mUpdateCnt) { mLastWMUpdateCount = mWidgetManager->mUpdateCnt; Update(); } } mUpdateIterator = mWidgets.begin(); while (mUpdateIterator != mWidgets.end()) { mUpdateIteratorModified = false; Widget* aWidget = *mUpdateIterator; if (aWidget == aWidgetManager->mBaseModalWidget) theFlags->mIsOver = true; aWidget->UpdateAll(theFlags); if (!mUpdateIteratorModified) ++mUpdateIterator; } mUpdateIteratorModified = true; // prevent incrementing iterator off the end of the list } void WidgetContainer::UpdateF(float theFrac) { } void WidgetContainer::UpdateFAll(ModalFlags* theFlags, float theFrac) { AutoModalFlags anAutoModalFlags(theFlags, mWidgetFlagsMod); // Can update? if (theFlags->GetFlags() & WIDGETFLAGS_UPDATE) { UpdateF(theFrac); } mUpdateIterator = mWidgets.begin(); while (mUpdateIterator != mWidgets.end()) { mUpdateIteratorModified = false; Widget* aWidget = *mUpdateIterator; if (aWidget == mWidgetManager->mBaseModalWidget) theFlags->mIsOver = true; aWidget->UpdateFAll(theFlags, theFrac); if (!mUpdateIteratorModified) ++mUpdateIterator; } mUpdateIteratorModified = true; // prevent incrementing iterator off the end of the list } void WidgetContainer::Draw(Graphics* g) { } void WidgetContainer::DrawAll(ModalFlags* theFlags, Graphics* g) { if (mPriority > mWidgetManager->mMinDeferredOverlayPriority) mWidgetManager->FlushDeferredOverlayWidgets(mPriority); AutoModalFlags anAutoModalFlags(theFlags, mWidgetFlagsMod); if ((mClip) && (theFlags->GetFlags() & WIDGETFLAGS_CLIP)) g->ClipRect(0, 0, mWidth, mHeight); if (mWidgets.size() == 0) { if (theFlags->GetFlags() & WIDGETFLAGS_DRAW) Draw(g); return; } if (theFlags->GetFlags() & WIDGETFLAGS_DRAW) { g->PushState(); Draw(g); g->PopState(); } WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget->mVisible) { if (aWidget == mWidgetManager->mBaseModalWidget) theFlags->mIsOver = true; Graphics aClipG(*g); aClipG.Translate(aWidget->mX, aWidget->mY); aWidget->DrawAll(theFlags, &aClipG); aWidget->mDirty = false; } ++anItr; } } void WidgetContainer::SysColorChanged() { } void WidgetContainer::SysColorChangedAll() { SysColorChanged(); static int aDepthCount = 0; if (mWidgets.size() > 0) aDepthCount++; WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; aWidget->SysColorChangedAll(); ++anItr; } } void WidgetContainer::DisableWidget(Widget* theWidget) { } void WidgetContainer::SetFocus(Widget* theWidget) { } libtuxcap-1.4.0/tuxcap/lib/ResourceManager.cpp0000644000175000017500000011243211202747627021242 0ustar inniyahinniyah #include "ResourceManager.h" #include "XMLParser.h" #include "SoundManager.h" #ifdef USE_AUDIERE #include "AudiereSoundManager.h" #else #include "SDLMixerSoundManager.h" #endif #include "DDImage.h" #if 0 #include "D3DInterface.h" #include "SysFont.h" //#define SEXY_PERF_ENABLED #include "PerfTimer.h" #endif #include "ImageFont.h" #include "ImageLib.h" #include using namespace Sexy; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::ImageRes::DeleteResource() { mImage.Release(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::SoundRes::DeleteResource() { if (mSoundId >= 0) gSexyAppBase->mSoundManager->ReleaseSound(mSoundId); mSoundId = -1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::FontRes::DeleteResource() { delete mFont; mFont = NULL; delete mImage; mImage = NULL; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ResourceManager::ResourceManager(SexyAppBase *theApp) { mApp = theApp; mHasFailed = false; mXMLParser = NULL; mAllowMissingProgramResources = false; mAllowAlreadyDefinedResources = false; mCurResGroupList = NULL; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// ResourceManager::~ResourceManager() { DeleteMap(mImageMap); DeleteMap(mSoundMap); DeleteMap(mFontMap); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::IsGroupLoaded(const std::string &theGroup) { return mLoadedGroups.find(theGroup)!=mLoadedGroups.end(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteMap(ResMap &theMap) { for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr) { anItr->second->DeleteResource(); delete anItr->second; } theMap.clear(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteResources(ResMap &theMap, const std::string &theGroup) { for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr) { if (theGroup.empty() || anItr->second->mResGroup==theGroup) anItr->second->DeleteResource(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteResources(const std::string &theGroup) { DeleteResources(mImageMap,theGroup); DeleteResources(mSoundMap,theGroup); DeleteResources(mFontMap,theGroup); mLoadedGroups.erase(theGroup); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteExtraImageBuffers(const std::string &theGroup) { for (ResMap::iterator anItr = mImageMap.begin(); anItr != mImageMap.end(); ++anItr) { if (theGroup.empty() || anItr->second->mResGroup==theGroup) { ImageRes *aRes = (ImageRes*)anItr->second; MemoryImage *anImage = (MemoryImage*)aRes->mImage; if (anImage != NULL) anImage->DeleteExtraBuffers(); } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// std::string ResourceManager::GetErrorText() { return mError; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::HadError() { return mHasFailed; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::Fail(const std::string& theErrorText) { if (!mHasFailed) { mHasFailed = true; if (mXMLParser==NULL) { mError = theErrorText; return false; } int aLineNum = mXMLParser->GetCurrentLineNum(); char aLineNumStr[16]; sprintf(aLineNumStr, "%d", aLineNum); mError = theErrorText; if (aLineNum > 0) mError += std::string(" on Line ") + aLineNumStr; if (mXMLParser->GetFileName().length() > 0) mError += " in File '" + mXMLParser->GetFileName() + "'"; } return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseCommonResource(XMLElement &theElement, BaseRes *theRes, ResMap &theMap) { mHadAlreadyDefinedError = false; const SexyString &aPath = theElement.mAttributes[_S("path")]; if (aPath.empty()) return Fail("No path specified."); theRes->mXMLAttributes = theElement.mAttributes; theRes->mFromProgram = false; if (aPath[0]==_S('!')) { theRes->mPath = SexyStringToStringFast(aPath); if (aPath==_S("!program")) theRes->mFromProgram = true; } else theRes->mPath = mDefaultPath + SexyStringToStringFast(aPath); std::string anId; XMLParamMap::iterator anItr = theElement.mAttributes.find(_S("id")); if (anItr == theElement.mAttributes.end()) anId = mDefaultIdPrefix + GetFileName(theRes->mPath,true); else anId = mDefaultIdPrefix + SexyStringToStringFast(anItr->second); theRes->mResGroup = mCurResGroup; theRes->mId = anId; std::pair aRet = theMap.insert(ResMap::value_type(anId,theRes)); if (!aRet.second) { mHadAlreadyDefinedError = true; return Fail("Resource already defined."); } mCurResGroupList->push_back(theRes); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseSoundResource(XMLElement &theElement) { SoundRes *aRes = new SoundRes; aRes->mSoundId = -1; aRes->mVolume = -1; aRes->mPanning = 0; if (!ParseCommonResource(theElement, aRes, mSoundMap)) { if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources) { mError = ""; mHasFailed = false; SoundRes *oldRes = aRes; aRes = (SoundRes*)mSoundMap[oldRes->mId]; aRes->mPath = oldRes->mPath; aRes->mXMLAttributes = oldRes->mXMLAttributes; delete oldRes; } else { delete aRes; return false; } } XMLParamMap::iterator anItr; anItr = theElement.mAttributes.find(_S("volume")); if (anItr != theElement.mAttributes.end()) sexysscanf(anItr->second.c_str(),_S("%lf"),&aRes->mVolume); anItr = theElement.mAttributes.find(_S("pan")); if (anItr != theElement.mAttributes.end()) sexysscanf(anItr->second.c_str(),_S("%d"),&aRes->mPanning); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void ReadIntVector(const SexyString &theVal, std::vector &theVector) { theVector.clear(); std::string::size_type aPos = 0; while (true) { theVector.push_back(sexyatoi(theVal.c_str()+aPos)); aPos = theVal.find_first_of(_S(','),aPos); if (aPos==std::string::npos) break; aPos++; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseImageResource(XMLElement &theElement) { ImageRes *aRes = new ImageRes; if (!ParseCommonResource(theElement, aRes, mImageMap)) { if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources) { mError = ""; mHasFailed = false; ImageRes *oldRes = aRes; aRes = (ImageRes*)mImageMap[oldRes->mId]; aRes->mPath = oldRes->mPath; aRes->mXMLAttributes = oldRes->mXMLAttributes; delete oldRes; } else { delete aRes; return false; } } aRes->mPalletize = theElement.mAttributes.find(_S("nopal")) == theElement.mAttributes.end(); aRes->mA4R4G4B4 = theElement.mAttributes.find(_S("a4r4g4b4")) != theElement.mAttributes.end(); aRes->mDDSurface = theElement.mAttributes.find(_S("ddsurface")) != theElement.mAttributes.end(); aRes->mPurgeBits = (theElement.mAttributes.find(_S("nobits")) != theElement.mAttributes.end()) || ((mApp->Is3DAccelerated()) && (theElement.mAttributes.find(_S("nobits3d")) != theElement.mAttributes.end())) || ((!mApp->Is3DAccelerated()) && (theElement.mAttributes.find(_S("nobits2d")) != theElement.mAttributes.end())); aRes->mA8R8G8B8 = theElement.mAttributes.find(_S("a8r8g8b8")) != theElement.mAttributes.end(); aRes->mMinimizeSubdivisions = theElement.mAttributes.find(_S("minsubdivide")) != theElement.mAttributes.end(); aRes->mAutoFindAlpha = theElement.mAttributes.find(_S("noalpha")) == theElement.mAttributes.end(); XMLParamMap::iterator anItr; anItr = theElement.mAttributes.find(_S("alphaimage")); if (anItr != theElement.mAttributes.end()) aRes->mAlphaImage = mDefaultPath + SexyStringToStringFast(anItr->second); aRes->mAlphaColor = 0xFFFFFF; anItr = theElement.mAttributes.find(_S("alphacolor")); if (anItr != theElement.mAttributes.end()) sexysscanf(anItr->second.c_str(),_S("%x"),(unsigned int*)&aRes->mAlphaColor); anItr = theElement.mAttributes.find(_S("variant")); if (anItr != theElement.mAttributes.end()) aRes->mVariant = SexyStringToStringFast(anItr->second); anItr = theElement.mAttributes.find(_S("alphagrid")); if (anItr != theElement.mAttributes.end()) aRes->mAlphaGridImage = mDefaultPath + SexyStringToStringFast(anItr->second); anItr = theElement.mAttributes.find(_S("rows")); if (anItr != theElement.mAttributes.end()) aRes->mRows = sexyatoi(anItr->second.c_str()); else aRes->mRows = 1; anItr = theElement.mAttributes.find(_S("cols")); if (anItr != theElement.mAttributes.end()) aRes->mCols = sexyatoi(anItr->second.c_str()); else aRes->mCols = 1; anItr = theElement.mAttributes.find(_S("anim")); AnimType anAnimType = AnimType_None; if (anItr != theElement.mAttributes.end()) { const SexyChar *aType = anItr->second.c_str(); if (sexystricmp(aType,_S("none"))==0) anAnimType = AnimType_None; else if (sexystricmp(aType,_S("once"))==0) anAnimType = AnimType_Once; else if (sexystricmp(aType,_S("loop"))==0) anAnimType = AnimType_Loop; else if (sexystricmp(aType,_S("pingpong"))==0) anAnimType = AnimType_PingPong; else { Fail("Invalid animation type."); return false; } } aRes->mAnimInfo.mAnimType = anAnimType; if (anAnimType != AnimType_None) { int aNumCels = std::max(aRes->mRows,aRes->mCols); int aBeginDelay = 0, anEndDelay = 0; anItr = theElement.mAttributes.find(_S("framedelay")); if (anItr != theElement.mAttributes.end()) aRes->mAnimInfo.mFrameDelay = sexyatoi(anItr->second.c_str()); anItr = theElement.mAttributes.find(_S("begindelay")); if (anItr != theElement.mAttributes.end()) aBeginDelay = sexyatoi(anItr->second.c_str()); anItr = theElement.mAttributes.find(_S("enddelay")); if (anItr != theElement.mAttributes.end()) anEndDelay = sexyatoi(anItr->second.c_str()); anItr = theElement.mAttributes.find(_S("perframedelay")); if (anItr != theElement.mAttributes.end()) ReadIntVector(anItr->second,aRes->mAnimInfo.mPerFrameDelay); anItr = theElement.mAttributes.find(_S("framemap")); if (anItr != theElement.mAttributes.end()) ReadIntVector(anItr->second,aRes->mAnimInfo.mFrameMap); aRes->mAnimInfo.Compute(aNumCels,aBeginDelay,anEndDelay); } return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseFontResource(XMLElement &theElement) { FontRes *aRes = new FontRes; aRes->mFont = NULL; aRes->mImage = NULL; if (!ParseCommonResource(theElement, aRes, mFontMap)) { if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources) { mError = ""; mHasFailed = false; FontRes *oldRes = aRes; aRes = (FontRes*)mFontMap[oldRes->mId]; aRes->mPath = oldRes->mPath; aRes->mXMLAttributes = oldRes->mXMLAttributes; delete oldRes; } else { delete aRes; return false; } } XMLParamMap::iterator anItr; anItr = theElement.mAttributes.find(_S("image")); if (anItr != theElement.mAttributes.end()) aRes->mImagePath = SexyStringToStringFast(anItr->second); anItr = theElement.mAttributes.find(_S("tags")); if (anItr != theElement.mAttributes.end()) aRes->mTags = SexyStringToStringFast(anItr->second); if (strncmp(aRes->mPath.c_str(),"!sys:",5)==0) { aRes->mSysFont = true; aRes->mPath = aRes->mPath.substr(5); anItr = theElement.mAttributes.find(_S("size")); if (anItr==theElement.mAttributes.end()) return Fail("SysFont needs point size"); aRes->mSize = sexyatoi(anItr->second.c_str()); if (aRes->mSize<=0) return Fail("SysFont needs point size"); aRes->mBold = theElement.mAttributes.find(_S("bold"))!=theElement.mAttributes.end(); aRes->mItalic = theElement.mAttributes.find(_S("italic"))!=theElement.mAttributes.end(); aRes->mShadow = theElement.mAttributes.find(_S("shadow"))!=theElement.mAttributes.end(); aRes->mUnderline = theElement.mAttributes.find(_S("underline"))!=theElement.mAttributes.end(); } else aRes->mSysFont = false; return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseSetDefaults(XMLElement &theElement) { XMLParamMap::iterator anItr; anItr = theElement.mAttributes.find(_S("path")); if (anItr != theElement.mAttributes.end()) mDefaultPath = RemoveTrailingSlash(SexyStringToStringFast(anItr->second)) + '/'; anItr = theElement.mAttributes.find(_S("idprefix")); if (anItr != theElement.mAttributes.end()) mDefaultIdPrefix = RemoveTrailingSlash(SexyStringToStringFast(anItr->second)); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseResources() { for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue == _S("Image")) { if (!ParseImageResource(aXMLElement)) return false; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType != XMLElement::TYPE_END) return Fail("Unexpected element found."); } else if (aXMLElement.mValue == _S("Sound")) { if (!ParseSoundResource(aXMLElement)) return false; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType != XMLElement::TYPE_END) return Fail("Unexpected element found."); } else if (aXMLElement.mValue == _S("Font")) { if (!ParseFontResource(aXMLElement)) return false; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType != XMLElement::TYPE_END) return Fail("Unexpected element found."); } else if (aXMLElement.mValue == _S("SetDefaults")) { if (!ParseSetDefaults(aXMLElement)) return false; if (!mXMLParser->NextElement(&aXMLElement)) return false; if (aXMLElement.mType != XMLElement::TYPE_END) return Fail("Unexpected element found."); } else { Fail("Invalid Section '" + SexyStringToStringFast(aXMLElement.mValue) + "'"); return false; } } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { Fail("Element Not Expected '" + SexyStringToStringFast(aXMLElement.mValue) + "'"); return false; } else if (aXMLElement.mType == XMLElement::TYPE_END) { return true; } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::DoParseResources() { if (!mXMLParser->HasFailed()) { for (;;) { XMLElement aXMLElement; if (!mXMLParser->NextElement(&aXMLElement)) break; if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue == _S("Resources")) { mCurResGroup = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]); mCurResGroupList = &mResGroupMap[mCurResGroup]; if (mCurResGroup.empty()) { Fail("No id specified."); break; } if (!ParseResources()) break; } else { Fail("Invalid Section '" + SexyStringToStringFast(aXMLElement.mValue) + "'"); break; } } else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT) { Fail("Element Not Expected '" + SexyStringToStringFast(aXMLElement.mValue) + "'"); break; } } } if (mXMLParser->HasFailed()) Fail(SexyStringToStringFast(mXMLParser->GetErrorText())); delete mXMLParser; mXMLParser = NULL; return !mHasFailed; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ParseResourcesFile(const std::string& theFilename) { mXMLParser = new XMLParser(); if (!mXMLParser->OpenFile(GetAppResourceFolder() + theFilename)) Fail("Resource file not found: " + GetAppResourceFolder() + theFilename); XMLElement aXMLElement; while (!mXMLParser->HasFailed()) { if (!mXMLParser->NextElement(&aXMLElement)) Fail(SexyStringToStringFast(mXMLParser->GetErrorText())); if (aXMLElement.mType == XMLElement::TYPE_START) { if (aXMLElement.mValue != _S("ResourceManifest")) break; else return DoParseResources(); } } Fail("Expecting ResourceManifest tag"); return DoParseResources(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ReparseResourcesFile(const std::string& theFilename) { bool oldDefined = mAllowAlreadyDefinedResources; mAllowAlreadyDefinedResources = true; bool aResult = ParseResourcesFile(theFilename); mAllowAlreadyDefinedResources = oldDefined; return aResult; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::LoadAlphaGridImage(ImageRes *theRes, DDImage *theImage) { ImageLib::Image* anAlphaImage = ImageLib::GetImage(theRes->mAlphaGridImage,true); if (anAlphaImage==NULL) return Fail(StrFormat("Failed to load image: %s",theRes->mAlphaGridImage.c_str())); std::auto_ptr aDelAlphaImage(anAlphaImage); int aNumRows = theRes->mRows; int aNumCols = theRes->mCols; int aCelWidth = theImage->mWidth/aNumCols; int aCelHeight = theImage->mHeight/aNumRows; if (anAlphaImage->mWidth!=aCelWidth || anAlphaImage->mHeight!=aCelHeight) return Fail(StrFormat("GridAlphaImage size mismatch between %s and %s",theRes->mPath.c_str(),theRes->mAlphaGridImage.c_str())); uint32_t *aMasterRowPtr = theImage->mBits; for (int i=0; i < aNumRows; i++) { uint32_t *aMasterColPtr = aMasterRowPtr; for (int j=0; j < aNumCols; j++) { uint32_t* aRowPtr = aMasterColPtr; uint32_t* anAlphaBits = anAlphaImage->mBits; for (int y=0; ymWidth; } aMasterColPtr += aCelWidth; } aMasterRowPtr += aCelHeight*theImage->mWidth; } theImage->BitsChanged(); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::LoadAlphaImage(ImageRes *theRes, DDImage *theImage) { #if 0 SEXY_PERF_BEGIN("ResourceManager::GetImage"); #endif ImageLib::Image* anAlphaImage = ImageLib::GetImage(theRes->mAlphaImage,true); #if 0 SEXY_PERF_END("ResourceManager::GetImage"); #endif if (anAlphaImage==NULL) return Fail(StrFormat("Failed to load image: %s",theRes->mAlphaImage.c_str())); std::auto_ptr aDelAlphaImage(anAlphaImage); if (anAlphaImage->mWidth!=theImage->mWidth || anAlphaImage->mHeight!=theImage->mHeight) return Fail(StrFormat("AlphaImage size mismatch between %s and %s",theRes->mPath.c_str(),theRes->mAlphaImage.c_str())); uint32_t* aBits1 = theImage->mBits; uint32_t* aBits2 = anAlphaImage->mBits; int aSize = theImage->mWidth*theImage->mHeight; for (int i = 0; i < aSize; i++) { *aBits1 = (*aBits1 & 0x00FFFFFF) | ((*aBits2 & 0xFF) << 24); ++aBits1; ++aBits2; } theImage->BitsChanged(); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::DoLoadImage(ImageRes *theRes) { bool lookForAlpha = theRes->mAlphaImage.empty() && theRes->mAlphaGridImage.empty() && theRes->mAutoFindAlpha; #if 0 SEXY_PERF_BEGIN("ResourceManager:GetImage"); #endif //ImageLib::Image *anImage = ImageLib::GetImage(theRes->mPath, lookForAlpha); //SEXY_PERF_END("ResourceManager:GetImage"); bool isNew; ImageLib::gAlphaComposeColor = theRes->mAlphaColor; SharedImageRef aSharedImageRef = gSexyAppBase->GetSharedImage(theRes->mPath, theRes->mVariant, &isNew); ImageLib::gAlphaComposeColor = 0xFFFFFF; DDImage* aDDImage = (DDImage*) aSharedImageRef; if (aDDImage == NULL) return Fail(StrFormat("Failed to load image: %s",theRes->mPath.c_str())); if (isNew) { if (!theRes->mAlphaImage.empty()) { if (!LoadAlphaImage(theRes, aSharedImageRef)) return false; } if (!theRes->mAlphaGridImage.empty()) { if (!LoadAlphaGridImage(theRes, aSharedImageRef)) return false; } } aDDImage->CommitBits(); theRes->mImage = aSharedImageRef; aDDImage->mPurgeBits = theRes->mPurgeBits; if (theRes->mDDSurface) { #if 0 SEXY_PERF_BEGIN("ResourceManager:DDSurface"); #endif aDDImage->CommitBits(); if (!aDDImage->mHasAlpha) { aDDImage->mWantDDSurface = true; aDDImage->mPurgeBits = true; } #if 0 SEXY_PERF_END("ResourceManager:DDSurface"); #endif } if (theRes->mPalletize) { #if 0 SEXY_PERF_BEGIN("ResourceManager:Palletize"); #endif if (aDDImage->mSurface==NULL) aDDImage->Palletize(); else aDDImage->mWantPal = true; #if 0 SEXY_PERF_END("ResourceManager:Palletize"); #endif } #if 0 if (theRes->mA4R4G4B4) aDDImage->mD3DFlags |= D3DImageFlag_UseA4R4G4B4; if (theRes->mA8R8G8B8) aDDImage->mD3DFlags |= D3DImageFlag_UseA8R8G8B8; if (theRes->mMinimizeSubdivisions) aDDImage->mD3DFlags |= D3DImageFlag_MinimizeNumSubdivisions; #endif if (theRes->mAnimInfo.mAnimType != AnimType_None) aDDImage->mAnimInfo = new AnimInfo(theRes->mAnimInfo); aDDImage->mNumRows = theRes->mRows; aDDImage->mNumCols = theRes->mCols; if (aDDImage->mPurgeBits) aDDImage->PurgeBits(); ResourceLoadedHook(theRes); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteImage(const std::string &theName) { ReplaceImage(theName,NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SharedImageRef ResourceManager::LoadImage(const std::string &theName) { ResMap::iterator anItr = mImageMap.find(theName); if (anItr == mImageMap.end()) return NULL; ImageRes *aRes = (ImageRes*)anItr->second; if ((DDImage*) aRes->mImage != NULL) return aRes->mImage; if (aRes->mFromProgram) return NULL; if (!DoLoadImage(aRes)) return NULL; return aRes->mImage; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::DoLoadSound(SoundRes* theRes) { SoundRes *aRes = theRes; #if 0 SEXY_PERF_BEGIN("ResourceManager:LoadSound"); #endif int aSoundId = mApp->mSoundManager->GetFreeSoundId(); if (aSoundId<0) return Fail("Out of free sound ids"); if(!mApp->mSoundManager->LoadSound(aSoundId, aRes->mPath)) return Fail(StrFormat("Failed to load sound: %s",aRes->mPath.c_str())); #if 0 SEXY_PERF_END("ResourceManager:LoadSound"); #endif if (aRes->mVolume >= 0) mApp->mSoundManager->SetBaseVolume(aSoundId, aRes->mVolume); if (aRes->mPanning != 0) mApp->mSoundManager->SetBasePan(aSoundId, aRes->mPanning); aRes->mSoundId = aSoundId; ResourceLoadedHook(theRes); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::DoLoadFont(FontRes* theRes) { Font *aFont = NULL; #if 0 SEXY_PERF_BEGIN("ResourceManager:DoLoadFont"); #endif if (theRes->mSysFont) { bool bold = theRes->mBold, simulateBold = false; #if 0 if (Sexy::CheckFor98Mill()) { simulateBold = bold; bold = false; } aFont = new SysFont(theRes->mPath,theRes->mSize,bold,theRes->mItalic,theRes->mUnderline); SysFont* aSysFont = (SysFont*)aFont; aSysFont->mDrawShadow = theRes->mShadow; aSysFont->mSimulateBold = simulateBold; #endif } else if (theRes->mImagePath.empty()) { if (strncmp(theRes->mPath.c_str(),"!ref:",5)==0) { std::string aRefName = theRes->mPath.substr(5); Font *aRefFont = GetFont(aRefName); if (aRefFont==NULL) return Fail("Ref font not found: " + aRefName); aFont = aRefFont->Duplicate(); } else aFont = new ImageFont(mApp, theRes->mPath); } else { Image *anImage = mApp->GetImage(theRes->mImagePath); if (anImage==NULL) return Fail(StrFormat("Failed to load image: %s",theRes->mImagePath.c_str())); theRes->mImage = anImage; aFont = new ImageFont(anImage, theRes->mPath); } ImageFont *anImageFont = dynamic_cast(aFont); if (anImageFont!=NULL) { if (anImageFont->mFontData==NULL || !anImageFont->mFontData->mInitialized) { delete aFont; return Fail(StrFormat("Failed to load font: %s",theRes->mPath.c_str())); } if (!theRes->mTags.empty()) { char aBuf[1024]; strcpy(aBuf,theRes->mTags.c_str()); const char *aPtr = strtok(aBuf,", \r\n\t"); while (aPtr != NULL) { anImageFont->AddTag(aPtr); aPtr = strtok(NULL,", \r\n\t"); } anImageFont->Prepare(); } } theRes->mFont = aFont; #if 0 SEXY_PERF_END("ResourceManager:DoLoadFont"); #endif ResourceLoadedHook(theRes); return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Font* ResourceManager::LoadFont(const std::string &theName) { ResMap::iterator anItr = mFontMap.find(theName); if (anItr == mFontMap.end()) return NULL; FontRes *aRes = (FontRes*)anItr->second; if (aRes->mFont != NULL) return aRes->mFont; if (aRes->mFromProgram) return NULL; if (!DoLoadFont(aRes)) return NULL; return aRes->mFont; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::DeleteFont(const std::string &theName) { ReplaceFont(theName,NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::LoadNextResource() { if (HadError()) return false; if (mCurResGroupList==NULL) return false; while (mCurResGroupListItr!=mCurResGroupList->end()) { BaseRes *aRes = *mCurResGroupListItr++; if (aRes->mFromProgram) continue; switch (aRes->mType) { case ResType_Image: { ImageRes *anImageRes = (ImageRes*)aRes; if ((DDImage*)anImageRes->mImage!=NULL) continue; return DoLoadImage(anImageRes); } case ResType_Sound: { SoundRes *aSoundRes = (SoundRes*)aRes; if (aSoundRes->mSoundId!=-1) continue; return DoLoadSound(aSoundRes); } case ResType_Font: { FontRes *aFontRes = (FontRes*)aRes; if (aFontRes->mFont!=NULL) continue; return DoLoadFont(aFontRes); } } } return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::ResourceLoadedHook(BaseRes *theRes) { } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::StartLoadResources(const std::string &theGroup) { mError = ""; mHasFailed = false; mCurResGroup = theGroup; mCurResGroupList = &mResGroupMap[theGroup]; mCurResGroupListItr = mCurResGroupList->begin(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void ResourceManager::DumpCurResGroup(std::string& theDestStr) { const ResList* rl = &mResGroupMap.find(mCurResGroup)->second; ResList::const_iterator it = rl->begin(); theDestStr = StrFormat("About to dump %d elements from current res group name %s\r\n", rl->size(), mCurResGroup.c_str()); ResList::const_iterator rl_end = rl->end(); while (it != rl_end) { BaseRes* br = *it++; std::string prefix = StrFormat("%s: %s\r\n", br->mId.c_str(), br->mPath.c_str()); theDestStr += prefix; if (br->mFromProgram) theDestStr += std::string(" res is from program\r\n"); else if (br->mType == ResType_Image) theDestStr += std::string(" res is an image\r\n"); else if (br->mType == ResType_Sound) theDestStr += std::string(" res is a sound\r\n"); else if (br->mType == ResType_Font) theDestStr += std::string(" res is a font\r\n"); if (it == mCurResGroupListItr) theDestStr += std::string("iterator has reached mCurResGroupItr\r\n"); } theDestStr += std::string("Done dumping resources\r\n"); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::LoadResources(const std::string &theGroup) { mError = ""; mHasFailed = false; StartLoadResources(theGroup); while (LoadNextResource()) { } if (!HadError()) { mLoadedGroups.insert(theGroup); return true; } else return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetNumResources(const std::string &theGroup, ResMap &theMap) { if (theGroup.empty()) return theMap.size(); int aCount = 0; for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr) { BaseRes *aRes = anItr->second; if (aRes->mResGroup==theGroup && !aRes->mFromProgram) ++aCount; } return aCount; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetNumImages(const std::string &theGroup) { return GetNumResources(theGroup, mImageMap); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetNumSounds(const std::string &theGroup) { return GetNumResources(theGroup,mSoundMap); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetNumFonts(const std::string &theGroup) { return GetNumResources(theGroup, mFontMap); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetNumResources(const std::string &theGroup) { return GetNumImages(theGroup) + GetNumSounds(theGroup) + GetNumFonts(theGroup); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SharedImageRef ResourceManager::GetImage(const std::string &theId) { ResMap::iterator anItr = mImageMap.find(theId); if (anItr != mImageMap.end()) return ((ImageRes*)anItr->second)->mImage; else return NULL; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetSound(const std::string &theId) { ResMap::iterator anItr = mSoundMap.find(theId); if (anItr != mSoundMap.end()) return ((SoundRes*)anItr->second)->mSoundId; else return -1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Font* ResourceManager::GetFont(const std::string &theId) { ResMap::iterator anItr = mFontMap.find(theId); if (anItr != mFontMap.end()) return ((FontRes*)anItr->second)->mFont; else return NULL; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SharedImageRef ResourceManager::GetImageThrow(const std::string &theId) { ResMap::iterator anItr = mImageMap.find(theId); if (anItr != mImageMap.end()) { ImageRes *aRes = (ImageRes*)anItr->second; if ((MemoryImage*) aRes->mImage != NULL) return aRes->mImage; if (mAllowMissingProgramResources && aRes->mFromProgram) return NULL; } Fail(StrFormat("Image resource not found: %s",theId.c_str())); throw ResourceManagerException(GetErrorText()); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ResourceManager::GetSoundThrow(const std::string &theId) { ResMap::iterator anItr = mSoundMap.find(theId); if (anItr != mSoundMap.end()) { SoundRes *aRes = (SoundRes*)anItr->second; if (aRes->mSoundId!=-1) return aRes->mSoundId; if (mAllowMissingProgramResources && aRes->mFromProgram) return -1; } Fail(StrFormat("Sound resource not found: %s",theId.c_str())); throw ResourceManagerException(GetErrorText()); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// Font* ResourceManager::GetFontThrow(const std::string &theId) { ResMap::iterator anItr = mFontMap.find(theId); if (anItr != mFontMap.end()) { FontRes *aRes = (FontRes*)anItr->second; if (aRes->mFont!=NULL) return aRes->mFont; if (mAllowMissingProgramResources && aRes->mFromProgram) return NULL; } Fail(StrFormat("Font resource not found: %s",theId.c_str())); throw ResourceManagerException(GetErrorText()); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void ResourceManager::SetAllowMissingProgramImages(bool allow) { mAllowMissingProgramResources = allow; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ReplaceImage(const std::string &theId, Image *theImage) { ResMap::iterator anItr = mImageMap.find(theId); if (anItr != mImageMap.end()) { anItr->second->DeleteResource(); ((ImageRes*)anItr->second)->mImage = (MemoryImage*) theImage; ((ImageRes*)anItr->second)->mImage.mOwnsUnshared = true; return true; } else return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ReplaceSound(const std::string &theId, int theSound) { ResMap::iterator anItr = mSoundMap.find(theId); if (anItr != mSoundMap.end()) { anItr->second->DeleteResource(); ((SoundRes*)anItr->second)->mSoundId = theSound; return true; } else return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool ResourceManager::ReplaceFont(const std::string &theId, Font *theFont) { ResMap::iterator anItr = mFontMap.find(theId); if (anItr != mFontMap.end()) { anItr->second->DeleteResource(); ((FontRes*)anItr->second)->mFont = theFont; return true; } else return false; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// const XMLParamMap& ResourceManager::GetImageAttributes(const std::string &theId) { static XMLParamMap aStrMap; ResMap::iterator anItr = mImageMap.find(theId); if (anItr != mImageMap.end()) return anItr->second->mXMLAttributes; else return aStrMap; } libtuxcap-1.4.0/tuxcap/lib/DDImage.cpp0000644000175000017500000031064711202747625017420 0ustar inniyahinniyah#include "DDImage.h" #include #include "DDInterface.h" #include "Rect.h" #include "Graphics.h" #include "SexyAppBase.h" #include "D3DInterface.h" #if 0 #include "Debug.h" #include "PerfTimer.h" #endif #include using namespace Sexy; extern bool gOptimizeSoftwareDrawing; DDImage::DDImage(DDInterface* theDDInterface) : MemoryImage(theDDInterface->mApp) { mDDInterface = theDDInterface; Init(); } DDImage::DDImage() : MemoryImage(gSexyAppBase) { mDDInterface = gSexyAppBase->mDDInterface; Init(); } DDImage::~DDImage() { //FIXME HACK if (mSurface != NULL && mSurface != gSexyAppBase->surface) SDL_FreeSurface(mSurface); mDDInterface->RemoveDDImage(this); assert(mLockCount == 0); } void DDImage::Init() { mSurface = NULL; mDDInterface->AddDDImage(this); mNoLock = false; mVideoMemory = false; mFirstPixelTrans = false; mWantDDSurface = false; mDrawToBits = false; mSurfaceSet = false; mLockCount = 0; } bool DDImage::Check3D(Image *theImage) { DDImage *anImage = dynamic_cast(theImage); if (anImage!=NULL) return Check3D(anImage); else return false; } bool DDImage::Check3D(DDImage *theImage) { //FIXME not using gSexyAppBase->surface in original code return theImage->mDDInterface->mIs3D && theImage->mSurface==gSexyAppBase->surface; } bool DDImage::LockSurface() { if (Check3D(this)) return false; if (mLockCount == 0) { if ( SDL_MUSTLOCK(mSurface) ) { if ( SDL_LockSurface(mSurface) < 0 ) { return false; } } } mLockCount++; assert(mLockCount < 8); return true; } bool DDImage::UnlockSurface() { if (Check3D(this)) return false; --mLockCount; if (mLockCount == 0) { if ( SDL_MUSTLOCK(mSurface) ) { SDL_UnlockSurface(mSurface); } } assert(mLockCount >= 0); return true; } void DDImage::SetSurface(SDL_Surface* theSurface) { mSurfaceSet = true; mSurface = theSurface; mWidth = mSurface->w; mHeight = mSurface->h; mNoLock = false; } bool DDImage::GenerateDDSurface() { if (mSurface != NULL) return true; CommitBits(); if (mHasAlpha) return false; mWantDDSurface = true; // Force into non-palletized mode for this if (mColorTable != NULL) GetBits(); bool aResult; #if 0 AutoCrit aCrit(mDDInterface->mCritSect); // prevent mSurface from being released while we're in this code #endif aResult = mDDInterface->CreateSurface(&mSurface, mWidth, mHeight, mVideoMemory); if (!aResult) return false; if (!LockSurface()) return false; const int rRightShift = 16 + (8-mDDInterface->mRedBits); const int gRightShift = 8 + (8-mDDInterface->mGreenBits); const int bRightShift = 0 + (8-mDDInterface->mBlueBits); const int rLeftShift = mDDInterface->mRedShift; const int gLeftShift = mDDInterface->mGreenShift; const int bLeftShift = mDDInterface->mBlueShift; const int rMask = mDDInterface->mRedMask; const int gMask = mDDInterface->mGreenMask; const int bMask = mDDInterface->mBlueMask; int aNumBits = gSexyAppBase->surface->format->BitsPerPixel; #if 0 const int rMask = mSurface->format->Rmask; const int gMask = mSurface->format->Gmask; const int bMask = mSurface->format->Bmask; int aNumBits = mSurface->format->BitsPerPixel; #endif if (aNumBits == 16) { Uint16* mSurfaceBits = (Uint16*) mSurface->pixels; if (mSurfaceBits != NULL) { int i; bool firstTrans = true; Uint16* a16Bits = NULL; Uint16 aTransColor = 0; if (mBits != NULL) { a16Bits = new Uint16[mWidth*mHeight]; Uint32* aSrcPtr = (Uint32*)mBits; Uint16* a16SrcPtr = a16Bits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); *a16SrcPtr = (((val>>rRightShift)<>gRightShift)<>bRightShift)<> 24; if ((firstTrans) && (anAlpha < 255)) { firstTrans = false; aTransColor = *a16SrcPtr; } ++a16SrcPtr; } } if ((mHasTrans) && (mBits != NULL)) { if (mFirstPixelTrans) { aTransColor = *a16Bits; if (a16Bits != NULL) { Uint16* aDestPtr = mSurfaceBits; Uint16* a16SrcPtr = a16Bits; for (int aRow = 0; aRow < mHeight; aRow++) { for (int aCol = 0; aCol < mWidth; aCol++) { *(aDestPtr++) = *a16SrcPtr; ++a16SrcPtr; } aDestPtr += mSurface->pitch/2 - mWidth; } } } else { bool needNewColor = false; Uint32* aSrcPtr = (Uint32*)mBits; Uint16* a16SrcPtr = a16Bits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); Uint16 a16Val = *(a16SrcPtr++); int anAlpha = val >> 24; if ((anAlpha == 255) && (aTransColor == a16Val)) { needNewColor = true; break; } } if (needNewColor) { int* aUsedColorArray = new int[2048]; memset(aUsedColorArray,0,2048*sizeof(int)); aSrcPtr = (Uint32*)mBits; a16SrcPtr = a16Bits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); Uint16 a16Val = *(a16SrcPtr++); int anAlpha = val >> 24; if (anAlpha > 0) aUsedColorArray[a16Val/32] |= (1<<(a16Val%32)); } bool done = false; for (int i = 0; i < 2048; i++) { if (aUsedColorArray[i] != 0xFFFF) { for (int aBit = 0; aBit < 32; aBit++) { if ((aUsedColorArray[i] & (1<> 24; if (anAlpha < 255) *(aDestPtr++) = aTransColor; else *(aDestPtr++) = *a16SrcPtr; ++a16SrcPtr; } aDestPtr += mSurface->pitch/2 - mWidth; } } } } else { if (a16Bits != NULL) { Uint16* aDestPtr = mSurfaceBits; Uint16* a16SrcPtr = a16Bits; for (int aRow = 0; aRow < mHeight; aRow++) { for (int aCol = 0; aCol < mWidth; aCol++) { *(aDestPtr++) = *a16SrcPtr; ++a16SrcPtr; } aDestPtr += mSurface->pitch/2 - mWidth; } } } delete a16Bits; if (mHasTrans) { SDL_SetColorKey(mSurface, SDL_SRCCOLORKEY /*SDL_RLEACCEL*/, aTransColor); } } } else if (aNumBits == 32) { Uint32* mSurfaceBits = (Uint32*) mSurface->pixels; if (mSurfaceBits != NULL) { int i; bool firstTrans = true; Uint32 aTransColor = 0; if ((mHasTrans) && (mBits != NULL)) { if (mFirstPixelTrans) { Uint32 val = *mBits; aTransColor = (((val>>rRightShift)<>gRightShift)<>bRightShift)<>rRightShift)<>gRightShift)<>bRightShift)<pitch/4 - mWidth; } } } else { Uint32* aSrcPtr = (Uint32*)mBits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); int anAlpha = val >> 24; if ((firstTrans) && (anAlpha < 255)) { firstTrans = false; aTransColor = val; } } bool needNewColor = false; aSrcPtr = (Uint32*)mBits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); int anAlpha = val >> 24; if ((anAlpha == 255) && (aTransColor == (val & 0x00FFFFFF))) { needNewColor = true; break; } } if (needNewColor) { int* aUsedColorArray = new int[0x80000]; memset(aUsedColorArray,0,0x80000*sizeof(int)); aSrcPtr = (Uint32*)mBits; for (i = 0; i < mWidth*mHeight; i++) { Uint32 val = *(aSrcPtr++); int anAlpha = val >> 24; if (anAlpha > 0) aUsedColorArray[(val & 0xFFFFFF)/32] |= (1<<(val%32)); } bool done = false; for (int i = 0; i < 0x80000; i++) { if (aUsedColorArray[i] != 0xFFFF) { for (int aBit = 0; aBit < 32; aBit++) { if ((aUsedColorArray[i] & (1<> 24; if (anAlpha < 255) *(aDestPtr++) = aTransColor; else { *(aDestPtr++) = (((val>>rRightShift)<>gRightShift)<>bRightShift)<pitch/4 - mWidth; } } } SDL_SetColorKey(mSurface, SDL_SRCCOLORKEY/* | SDL_RLEACCEL*/, aTransColor); } else { if (mBits != NULL) { Uint32* aDestPtr = mSurfaceBits; Uint32* aSrcPtr = (Uint32*)mBits; for (int aRow = 0; aRow < mHeight; aRow++) { for (int aCol = 0; aCol < mWidth; aCol++) { Uint32 val = *(aSrcPtr++); *(aDestPtr++) = (((val>>rRightShift)<>gRightShift)<>bRightShift)<pitch/4 - mWidth; } } } } } else { return false; } UnlockSurface(); return true; } void DDImage::DeleteDDSurface() { if (mSurface != NULL) { if ((mColorTable == NULL) && (mBits == NULL) && (mD3DData == NULL)) GetBits(); SDL_FreeSurface(mSurface); mSurface = NULL; } } void DDImage::ReInit() { MemoryImage::ReInit(); if (mWantDDSurface) GenerateDDSurface(); } void DDImage::PurgeBits() { if (mSurfaceSet) return; mPurgeBits = true; CommitBits(); //FIXME if (true)//!mApp->Is3DAccelerated()) { if ((mWantDDSurface) && true)//GenerateDDSurface()) { delete [] mBits; mBits = NULL; delete [] mColorIndices; mColorIndices = NULL; delete [] mColorTable; mColorTable = NULL; return; } } else // Accelerated { if (mSurface != NULL) { GetBits(); DeleteDDSurface(); } } MemoryImage::PurgeBits(); } void DDImage::DeleteAllNonSurfaceData() { delete [] mBits; mBits = NULL; delete [] mNativeAlphaData; mNativeAlphaData = NULL; delete [] mRLAdditiveData; mRLAdditiveData = NULL; delete [] mRLAlphaData; mRLAlphaData = NULL; delete [] mColorTable; mColorTable = NULL; delete [] mColorIndices; mColorIndices = NULL; } void DDImage::DeleteNativeData() { if (mSurfaceSet) return; MemoryImage::DeleteNativeData(); DeleteDDSurface(); } void DDImage::DeleteExtraBuffers() { if (mSurfaceSet) return; MemoryImage::DeleteExtraBuffers(); DeleteDDSurface(); } void DDImage::SetVideoMemory(bool wantVideoMemory) { if (wantVideoMemory != mVideoMemory) { mVideoMemory = wantVideoMemory; // Make sure that we have the bits GetBits(); DeleteDDSurface(); } } #if 0 void DDImage::RehupFirstPixelTrans() { if (!GenerateDDSurface()) return; if ((mNoLock) || (!mHasTrans) || (!mFirstPixelTrans)) return; // TDDSurfaceDesc aDesc; DDSURFACEDESC aDesc; ZeroMemory(&aDesc, sizeof(aDesc)); aDesc.dwSize = sizeof(aDesc); aDesc.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; HRESULT aResult = mDDInterface->mPrimarySurface->GetSurfaceDesc(&aDesc); if (FAILED(aResult)) return; int aNumBits = aDesc.ddpfPixelFormat.dwRGBBitCount; if (aNumBits == 16) { if (!LockSurface()) return; ushort* aSurfaceBits = (ushort*) mLockedSurfaceDesc.lpSurface; ushort aTransColor = *aSurfaceBits; DDCOLORKEY aColorKey = {aTransColor, aTransColor}; mSurface->SetColorKey(DDCKEY_SRCBLT, &aColorKey); UnlockSurface(); } else if ((aNumBits == 24) || (aNumBits == 32)) { if (!LockSurface()) return; Uint32* aSurfaceBits = (Uint32*) mLockedSurfaceDesc.lpSurface; Uint32 aTransColor = *aSurfaceBits; DDCOLORKEY aColorKey = {aTransColor, aTransColor}; mSurface->SetColorKey(DDCKEY_SRCBLT, &aColorKey); UnlockSurface(); } } #endif SDL_Surface* DDImage::GetSurface() { //TODO: Log if generate surface fails if (mSurface == NULL) GenerateDDSurface(); return mSurface; } bool DDImage::PolyFill3D(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty, bool convex) { if (Check3D(this)) { mDDInterface->mD3DInterface->FillPoly(theVertices,theNumVertices,theClipRect,theColor,theDrawMode,tx,ty); return true; } else return false; } void DDImage::FillRect(const Rect& theRect, const Color& theColor, int theDrawMode) { if (Check3D(this)) { mDDInterface->mD3DInterface->FillRect(theRect,theColor,theDrawMode); return; } CommitBits(); if ((mDrawToBits) || (mHasAlpha) || ((mHasTrans) && (!mFirstPixelTrans)) || (mDDInterface->mIs3D)) { MemoryImage::FillRect(theRect, theColor, theDrawMode); return; } switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalFillRect(theRect, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveFillRect(theRect, theColor); break; } DeleteAllNonSurfaceData(); } void DDImage::NormalDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { if (mNoLock) return; double aMinX = std::min(theStartX, theEndX); double aMinY = std::min(theStartY, theEndY); double aMaxX = std::max(theStartX, theEndX); double aMaxY = std::max(theStartY, theEndY); if (!LockSurface()) return; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (mSurface->format->BitsPerPixel == 16) { if (theColor.mAlpha == 255) { ushort aColor = (ushort) (((((theColor.mRed * aRMask) + aRRoundAdd) >> 8) & aRMask) | ((((theColor.mGreen * aGMask) + aGRoundAdd) >> 8) & aGMask) | ((((theColor.mBlue * aBMask) + aBRoundAdd) >> 8) & aBMask)); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mSurface->pitch/2; int aRowAdd = aRowWidth; if (fabs(dv) < fabs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } ushort* aDestPixels = ((ushort*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; *aDestPixels = aColor; aDestPixels++; aCurY = (int) theStartY; aCurX = (int) theStartX + 1; G = (int)(2 * dv - dh); DeltaG1 = (int)(2 * (dv - dh)); DeltaG2 = (int)(2 * dv); G += (int)(DeltaG2 * (theStartY - (int) theStartY)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurX++; aDestPixels++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } ushort* aDestPixels = ((ushort*) mSurface->pixels) + ((int) theStartY * mSurface->pitch/2) + (int) theStartX; *aDestPixels = aColor; aDestPixels += aRowAdd; aCurX = (int)(theStartX); aCurY = (int)(theStartY + 1); G = (int)(2 * dh - dv); minG = maxG = G; DeltaG1 = (int)(2 * ( dh - dv )); DeltaG2 = (int)(2 * dh); G += (int)(DeltaG2 * (theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurY++; aDestPixels += aRowAdd; } } } else { ushort src = ((((((theColor.mRed * theColor.mAlpha + 0x80) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask) + ((((((theColor.mGreen * theColor.mAlpha + 0x80) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) + ((((((theColor.mBlue * theColor.mAlpha + 0x80) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask); int oma = 256 - theColor.mAlpha; double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mSurface->pitch/2; int aRowAdd = aRowWidth; if (fabs(dv) < fabs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } ushort* aDestPixels = ((ushort*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; ushort dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY = (int)(theStartY); aCurX = (int)(theStartX + 1); G = (int)(2 * dv - dh); DeltaG1 = (int)(2 * (dv - dh)); DeltaG2 = (int)(2 * dv); G += (int)(DeltaG2 * (theStartY - (int) theStartY)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } ushort* aDestPixels = ((ushort*) mSurface->pixels) + ((int) theStartY * mSurface->pitch/2) + (int) theStartX; ushort dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aDestPixels += aRowAdd; aCurX = (int)(theStartX); aCurY = (int)(theStartY + 1); G = (int)(2 * dh - dv); minG = maxG = G; DeltaG1 = (int)(2 * ( dh - dv )); DeltaG2 = (int)(2 * dh); G += (int)(DeltaG2 * (theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY++; aDestPixels += aRowAdd; } } } } else if (mSurface->format->BitsPerPixel == 32) { if (theColor.mAlpha == 255) { uint32_t aColor = ((((theColor.mRed * aRMask) + aRRoundAdd) >> 8) & aRMask) | ((((theColor.mGreen * aGMask) + aGRoundAdd) >> 8) & aGMask) | ((((theColor.mBlue * aBMask) + aBRoundAdd) >> 8) & aBMask); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mSurface->pitch/4; int aRowAdd = aRowWidth;; if (fabs(dv) < fabs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; *aDestPixels = aColor; aDestPixels++; aCurY = (int)(theStartY); aCurX = (int)(theStartX + 1); G = (int)(2 * dv - dh); DeltaG1 = (int)(2 * (dv - dh)); DeltaG2 = (int)(2 * dv); G += (int)(DeltaG2 * (theStartY - (int) theStartY)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurX++; aDestPixels++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; *aDestPixels = aColor; aDestPixels += aRowAdd; aCurX = (int)(theStartX); aCurY = (int)(theStartY + 1); G = (int)(2 * dh - dv); minG = maxG = G; DeltaG1 = (int)(2 * ( dh - dv )); DeltaG2 = (int)(2 * dh); G += (int)(DeltaG2 * (theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; *aDestPixels = aColor; aCurY++; aDestPixels += aRowAdd; } } } else { uint32_t src = ((((((theColor.mRed * theColor.mAlpha + 0x80) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask) + ((((((theColor.mGreen * theColor.mAlpha + 0x80) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) + ((((((theColor.mBlue * theColor.mAlpha + 0x80) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask); int oma = 256 - theColor.mAlpha; double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mSurface->pitch/4; int aRowAdd = aRowWidth; if (fabs(dv) < fabs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY = (int)(theStartY); aCurX = (int)(theStartX + 1); G = (int)(2 * dv - dh); DeltaG1 = (int)(2 * (dv - dh)); DeltaG2 = (int)(2 * dv); G += (int)(DeltaG2 * (theStartX - (int) theStartX)); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) mSurface->pixels) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aDestPixels += aRowAdd; aCurX = (int)(theStartX); aCurY = (int)(theStartY + 1); G = (int)(2 * dh - dv); minG = maxG = G; DeltaG1 = (int)(2 * ( dh - dv )); DeltaG2 = (int)(2 * dh); G += (int)(DeltaG2 * (theStartX - (int) theStartX)); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; *aDestPixels = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); aCurY++; aDestPixels += aRowAdd; } } } } UnlockSurface(); } void DDImage::AdditiveDrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { if (mNoLock) return; double aMinX = std::min(theStartX, theEndX); double aMinY = std::min(theStartY, theEndY); double aMaxX = std::max(theStartX, theEndX); double aMaxY = std::max(theStartY, theEndY); //NOT IMPLEMENTED YET assert(false); #if 0 LPDIRECTDRAWSURFACE aSurface = GetSurface(); if (!LockSurface()) return; uint32_t aRMask = mLockedSurfaceDesc.ddpfPixelFormat.dwRBitMask; uint32_t aGMask = mLockedSurfaceDesc.ddpfPixelFormat.dwGBitMask; uint32_t aBMask = mLockedSurfaceDesc.ddpfPixelFormat.dwBBitMask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; int aRedShift = mDDInterface->mRedShift; int aGreenShift = mDDInterface->mGreenShift; int aBlueShift = mDDInterface->mBlueShift; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; if (mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 16) { ushort rc = ((theColor.mRed * theColor.mAlpha) / 255) >> (8-mDDInterface->mRedBits); ushort gc = ((theColor.mGreen * theColor.mAlpha) / 255) >> (8-mDDInterface->mGreenBits); ushort bc = ((theColor.mBlue * theColor.mAlpha) / 255) >> (8-mDDInterface->mBlueBits); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mLockedSurfaceDesc.lPitch/2; int aRowAdd = aRowWidth; if (abs(dv) < abs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } ushort* aDestPixels = ((ushort*) mLockedSurfaceDesc.lpSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; ushort dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY = theStartY; aCurX = theStartX + 1; G = 2 * dv - dh; DeltaG1 = 2 * (dv - dh); DeltaG2 = 2 * dv; G += DeltaG2 * (theStartY - (int) theStartY); while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } ushort* aDestPixels = ((ushort*) mLockedSurfaceDesc.lpSurface) + ((int) theStartY * mLockedSurfaceDesc.lPitch/2) + (int) theStartX; ushort dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aDestPixels += aRowAdd; aCurX = theStartX; aCurY = theStartY + 1; G = 2 * dh - dv; minG = maxG = G; DeltaG1 = 2 * ( dh - dv ); DeltaG2 = 2 * dh; G += DeltaG2 * (theStartX - (int) theStartX); while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY++; aDestPixels += aRowAdd; } } } else if (mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 32) { uint32_t rc = ((theColor.mRed * theColor.mAlpha) / 255) >> (8-mDDInterface->mRedBits); uint32_t gc = ((theColor.mGreen * theColor.mAlpha) / 255) >> (8-mDDInterface->mGreenBits); uint32_t bc = ((theColor.mBlue * theColor.mAlpha) / 255) >> (8-mDDInterface->mBlueBits); double dv = theEndY - theStartY; double dh = theEndX - theStartX; int minG, maxG, G, DeltaG1, DeltaG2; double swap; int inc = 1; int aCurX; int aCurY; int aRowWidth = mLockedSurfaceDesc.lPitch/4; int aRowAdd = aRowWidth; if (abs(dv) < abs(dh)) { // Mostly horizontal if (dh < 0) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dv < 0) { dv = -dv; inc = -1; aRowAdd = -aRowAdd; } uint32_t* aDestPixels = ((uint32_t*) mLockedSurfaceDesc.lpSurface) + ((int) theStartY * aRowWidth) + (int) theStartX; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY = theStartY; aCurX = theStartX + 1; G = 2 * dv - dh; DeltaG1 = 2 * (dv - dh); DeltaG2 = 2 * dv; while (aCurX <= theEndX) { if (G > 0) { G += DeltaG1; aCurY += inc; aDestPixels += aRowAdd; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurX++; } } else { // Mostly vertical if ( dv < 0 ) { dh = -dh; dv = -dv; swap = theEndY; theEndY = theStartY; theStartY = swap; swap = theEndX; theEndX = theStartX; theStartX = swap; } if (dh < 0) { dh = -dh; inc = -1; } uint32_t* aDestPixels = ((uint32_t*) mLockedSurfaceDesc.lpSurface) + ((int) theStartY * mLockedSurfaceDesc.lPitch/4) + (int) theStartX; uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aDestPixels += aRowAdd; aCurX = theStartX; aCurY = theStartY + 1; G = 2 * dh - dv; minG = maxG = G; DeltaG1 = 2 * ( dh - dv ); DeltaG2 = 2 * dh; while (aCurY <= theEndY) { if ( G > 0 ) { G += DeltaG1; aCurX += inc; aDestPixels += inc; if (aCurXaMaxX || aCurY>aMaxY) break; } else G += DeltaG2; dest = *aDestPixels; r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *aDestPixels = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); aCurY++; aDestPixels += aRowAdd; } } } UnlockSurface(); #endif } void DDImage::DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { if (Check3D(this)) { mDDInterface->mD3DInterface->DrawLine(theStartX,theStartY,theEndX,theEndY,theColor,theDrawMode); return; } if ((mDrawToBits) || (mHasAlpha) || (mHasTrans) || (mDDInterface->mIs3D)) { MemoryImage::DrawLine(theStartX, theStartY, theEndX, theEndY, theColor, theDrawMode); return; } if (theStartY == theEndY) { int aStartX = (int)std::min(theStartX, theEndX); int aEndX = (int)std::max(theStartX, theEndX); FillRect(Rect(aStartX, (int)theStartY, aEndX-aStartX+1, (int)(theEndY-theStartY+1)), theColor, theDrawMode); return; } else if (theStartX == theEndX) { int aStartY = (int)std::min(theStartY, theEndY); int aEndY = (int)std::max(theStartY, theEndY); FillRect(Rect((int)theStartX, aStartY, (int)(theEndX-theStartX+1), aEndY-aStartY+1), theColor, theDrawMode); return; } CommitBits(); switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalDrawLine(theStartX, theStartY, theEndX, theEndY, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveDrawLine(theStartX, theStartY, theEndX, theEndY, theColor); break; } DeleteAllNonSurfaceData(); } void DDImage::NormalDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { SDL_Surface* aSurface = GetSurface(); if (!LockSurface()) return; uint32_t aRMask = aSurface->format->Rmask; uint32_t aGMask = aSurface->format->Gmask; uint32_t aBMask = aSurface->format->Bmask; uint32_t color = (((theColor.mRed * aRMask) >> 8) & aRMask) | (((theColor.mGreen * aGMask) >> 8) & aGMask) | (((theColor.mBlue * aBMask) >> 8) & aBMask); int aX0 = (int)theStartX, aX1 = (int)theEndX; int aY0 = (int)theStartY, aY1 = (int)theEndY; int aXinc = 1; if (aY0 > aY1) { int aTempX = aX0, aTempY = aY0; aX0 = aX1; aY0 = aY1; aX1 = aTempX; aY1 = aTempY; double aTempXd = theStartX, aTempYd = theStartY; theStartX = theEndX; theStartY = theEndY; theEndX = aTempXd; theEndY = aTempYd; } int dx = aX1 - aX0; int dy = aY1 - aY0; double dxd = theEndX - theStartX; double dyd = theEndY - theStartY; if (dx < 0) { dx = -dx; aXinc = -1; dxd = -dxd; } if (aSurface->format->BitsPerPixel == 32) { uint32_t* aBits = (uint32_t*)aSurface->pixels; #ifdef OPTIMIZE_SOFTWARE_DRAWING if (theColor.mAlpha != 255) { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & 0xFF00FF) * a + (dest & 0xFF00FF) * oma) >> 8) & 0xFF00FF) |\ ((((color & 0x00FF00) * a + (dest & 0x00FF00) * oma) >> 8) & 0x00FF00); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } else { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (w) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & 0xFF00FF) * a + (dest & 0xFF00FF) * oma) >> 8) & 0xFF00FF) |\ ((((color & 0x00FF00) * a + (dest & 0x00FF00) * oma) >> 8) & 0x00FF00); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } #else if (theColor.mAlpha != 255) { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & aRMask) * a + (dest & aRMask) * oma) >> 8) & aRMask) |\ ((((color & aGMask) * a + (dest & aGMask) * oma) >> 8) & aGMask) |\ ((((color & aBMask) * a + (dest & aBMask) * oma) >> 8) & aBMask); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } else { #define PIXEL_TYPE uint32_t #define CALC_WEIGHT_A(w) (w) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & aRMask) * a + (dest & aRMask) * oma) >> 8) & aRMask) |\ ((((color & aGMask) * a + (dest & aGMask) * oma) >> 8) & aGMask) |\ ((((color & aBMask) * a + (dest & aBMask) * oma) >> 8) & aBMask); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } #endif } else if (aSurface->format->BitsPerPixel == 32) { ushort* aBits = (ushort*)aSurface->pixels; #ifdef OPTIMIZE_SOFTWARE_DRAWING if (aGMask == 0x3E0) // 5-5-5 { #define PIXEL_TYPE ushort #define BLEND_PIXEL(p) \ {\ a >>= 3;\ oma >>= 3;\ uint32_t _src = (((color | (color << 16)) & 0x3E07C1F) * a >> 5) & 0x3E07C1F;\ uint32_t _dest = (((dest | (dest << 16)) & 0x3E07C1F) * oma >> 5) & 0x3E07C1F;\ *(p) = (_src | (_src>>16)) + (_dest | (_dest>>16));\ } const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); if (theColor.mAlpha != 255) { #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #include "GENERIC_DrawLineAA.inc" #undef CALC_WEIGHT_A } else { #define CALC_WEIGHT_A(w) (w) #include "GENERIC_DrawLineAA.inc" #undef CALC_WEIGHT_A } #undef PIXEL_TYPE #undef BLEND_PIXEL } else if (aGMask == 0x7E0) // 5-6-5 { #define PIXEL_TYPE ushort #define BLEND_PIXEL(p) \ {\ a >>= 3;\ oma >>= 3;\ uint32_t _src = (((color | (color << 16)) & 0x7E0F81F) * a >> 5) & 0x7E0F81F;\ uint32_t _dest = (((dest | (dest << 16)) & 0x7E0F81F) * oma >> 5) & 0x7E0F81F;\ *(p) = (_src | (_src>>16)) + (_dest | (_dest>>16));\ } const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); if (theColor.mAlpha != 255) { #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #include "GENERIC_DrawLineAA.inc" #undef CALC_WEIGHT_A } else { #define CALC_WEIGHT_A(w) (w) #include "GENERIC_DrawLineAA.inc" #undef CALC_WEIGHT_A } #undef PIXEL_TYPE #undef BLEND_PIXEL } else { #endif if (theColor.mAlpha != 255) { #define PIXEL_TYPE ushort #define CALC_WEIGHT_A(w) (((w) * (theColor.mAlpha+1)) >> 8) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & aRMask) * a + (dest & aRMask) * oma) >> 8) & aRMask) |\ ((((color & aGMask) * a + (dest & aGMask) * oma) >> 8) & aGMask) |\ ((((color & aBMask) * a + (dest & aBMask) * oma) >> 8) & aBMask); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } else { #define PIXEL_TYPE ushort #define CALC_WEIGHT_A(w) (w) #define BLEND_PIXEL(p) \ *(p) = \ ((((color & aRMask) * a + (dest & aRMask) * oma) >> 8) & aRMask) |\ ((((color & aGMask) * a + (dest & aGMask) * oma) >> 8) & aGMask) |\ ((((color & aBMask) * a + (dest & aBMask) * oma) >> 8) & aBMask); const int STRIDE = aSurface->pitch / sizeof(PIXEL_TYPE); #include "GENERIC_DrawLineAA.inc" #undef PIXEL_TYPE #undef CALC_WEIGHT_A #undef BLEND_PIXEL } #ifdef OPTIMIZE_SOFTWARE_DRAWING } #endif } UnlockSurface(); } void DDImage::AdditiveDrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor) { } void DDImage::DrawLineAA(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { if (Check3D(this)) { mDDInterface->mD3DInterface->DrawLine(theStartX,theStartY,theEndX,theEndY,theColor,theDrawMode); return; } if ((mDrawToBits) || (mHasAlpha) || (mHasTrans) || (mDDInterface->mIs3D)) { MemoryImage::DrawLine(theStartX, theStartY, theEndX, theEndY, theColor, theDrawMode); return; } if (theStartY == theEndY) { int aStartX = (int)(std::min(theStartX, theEndX)); int aEndX = (int)(std::max(theStartX, theEndX)); FillRect(Rect(aStartX, (int)theStartY, aEndX-aStartX+1, (int)(theEndY-theStartY+1)), theColor, theDrawMode); return; } else if (theStartX == theEndX) { int aStartY = (int)(std::min(theStartY, theEndY)); int aEndY = (int)(std::max(theStartY, theEndY)); FillRect(Rect((int)theStartX, aStartY, (int)(theEndX-theStartX+1), aEndY-aStartY+1), theColor, theDrawMode); return; } CommitBits(); switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalDrawLineAA(theStartX, theStartY, theEndX, theEndY, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveDrawLineAA(theStartX, theStartY, theEndX, theEndY, theColor); break; } DeleteAllNonSurfaceData(); } void DDImage::CommitBits() { if (mSurface == NULL) { MemoryImage::CommitBits(); return; } } void DDImage::Create(int theWidth, int theHeight) { delete [] mBits; mWidth = theWidth; mHeight = theHeight; mBits = NULL; BitsChanged(); } void DDImage::BitsChanged() { MemoryImage::BitsChanged(); if (mSurface != NULL) SDL_FreeSurface(mSurface); mSurface = NULL; } uint32_t* DDImage::GetBits() { if (mBits == NULL) { if (mSurface == NULL) return MemoryImage::GetBits(); if (mNoLock) return NULL; if (!LockSurface()) return NULL; mBits = new uint32_t[mWidth*mHeight + 1]; mBits[mWidth*mHeight] = MEMORYCHECK_ID; int aRRound = (1 << (7 - mDDInterface->mRedBits)); int aGRound = (1 << (7 - mDDInterface->mGreenBits)); int aBRound = (1 << (7 - mDDInterface->mBlueBits)); if (mSurface->format->BitsPerPixel == 16) { ushort* aSrcPixelsRow = (ushort*)mSurface->pixels; uint32_t* aDest = mBits; for (int y = 0; y < mHeight; y++) { ushort* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < mWidth; x++) { uint32_t src = *(aSrcPixels++); int r = ((src >> mSurface->format->Rshift << (8 - mDDInterface->mRedBits)) & 0xFF); int g = ((src >> mSurface->format->Gshift << (8 - mDDInterface->mGreenBits)) & 0xFF); int b = ((src >> mSurface->format->Bshift << (8 - mDDInterface->mBlueBits)) & 0xFF); *aDest++ = 0xFF000000 | (r << 16) | (g << 8) | (b); } aSrcPixelsRow += mSurface->pitch/2; } } else if (mSurface->format->BitsPerPixel== 32) { uint32_t* aSrcPixelsRow = (uint32_t*) mSurface->pixels; uint32_t* aDest = mBits; for (int y = 0; y < mHeight; y++) { uint32_t* aSrcPixels = aSrcPixelsRow; for (int x = 0; x < mWidth; x++) { uint32_t src = *(aSrcPixels++); int r = (src >> mSurface->format->Rshift << (8 - mDDInterface->mRedBits)) & 0xFF; int g = (src >> mSurface->format->Gshift << (8 - mDDInterface->mGreenBits)) & 0xFF; int b = (src >> mSurface->format->Bshift << (8 - mDDInterface->mBlueBits)) & 0xFF; *aDest++ = 0xFF000000 | (r << 16) | (g << 8) | (b); } aSrcPixelsRow += mSurface->pitch/4; } } UnlockSurface(); } return mBits; } void DDImage::NormalFillRect(const Rect& theRect, const Color& theColor) { if (mNoLock) return; SDL_Surface* aSurface = GetSurface(); if (!LockSurface()) return; //FIXME change to Uint32 and Uint16 respectively uint32_t aRMask = aSurface->format->Rmask; uint32_t aGMask = aSurface->format->Gmask; uint32_t aBMask = aSurface->format->Bmask; uint32_t aRRoundAdd = aRMask; uint32_t aGRoundAdd = aGMask; uint32_t aBRoundAdd = aBMask; if (aSurface->format->BitsPerPixel == 16) { if (theColor.mAlpha == 255) { ushort aColor = ((((theColor.mRed * aRMask) + aRRoundAdd) >> 8) & aRMask) | ((((theColor.mGreen * aGMask) + aGRoundAdd) >> 8) & aGMask) | ((((theColor.mBlue * aBMask) + aBRoundAdd) >> 8) & aBMask); ushort* aDestPixelsRow = ((ushort*) aSurface->pixels) + (theRect.mY * aSurface->pitch/2) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) *(aDestPixels++) = aColor; aDestPixelsRow += aSurface->pitch/2; } } else { ushort src = ((((((theColor.mRed * theColor.mAlpha + 0x80) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask) + ((((((theColor.mGreen * theColor.mAlpha + 0x80) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) + ((((((theColor.mBlue * theColor.mAlpha + 0x80) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask); int oma = 256 - theColor.mAlpha; ushort* aDestPixelsRow = ((ushort*) aSurface->pixels) + (theRect.mY * aSurface->pitch/2) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) { ushort dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma) + aRRoundAdd) >> 8) & aRMask) + (((((dest & aGMask) * oma) + aGRoundAdd) >> 8) & aGMask) + (((((dest & aBMask) * oma) + aBRoundAdd) >> 8) & aBMask); } aDestPixelsRow += aSurface->pitch/2; } } } else if (aSurface->format->BitsPerPixel == 32) { if (theColor.mAlpha == 255) { uint32_t aColor = ((((theColor.mRed * aRMask)) >> 8) & aRMask) | ((((theColor.mGreen * aGMask)) >> 8) & aGMask) | ((((theColor.mBlue * aBMask)) >> 8) & aBMask); uint32_t* aDestPixelsRow = ((uint32_t*) aSurface->pixels) + (theRect.mY * aSurface->pitch/4) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) *(aDestPixels++) = aColor; aDestPixelsRow += aSurface->pitch/4; } } else { uint32_t src = ((((((theColor.mRed * theColor.mAlpha + 0x7F) >> 8) * aRMask) + aRRoundAdd) >> 8) & aRMask) + ((((((theColor.mGreen * theColor.mAlpha + 0x7F) >> 8) * aGMask) + aGRoundAdd) >> 8) & aGMask) + ((((((theColor.mBlue * theColor.mAlpha + 0x7F) >> 8) * aBMask) + aBRoundAdd) >> 8) & aBMask); int oma = 256 - theColor.mAlpha; uint32_t* aDestPixelsRow = ((uint32_t*) aSurface->pixels) + (theRect.mY * aSurface->pitch/4) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) { uint32_t dest = *aDestPixels; *(aDestPixels++) = src + (((((dest & aRMask) * oma)) >> 8) & aRMask) + (((((dest & aGMask) * oma)) >> 8) & aGMask) + (((((dest & aBMask) * oma)) >> 8) & aBMask); } aDestPixelsRow += aSurface->pitch/4; } } } UnlockSurface(); } void DDImage::AdditiveFillRect(const Rect& theRect, const Color& theColor) { if (mNoLock) return; // SDL_Surface* aSurface = GetSurface(); if (!LockSurface()) return; uint32_t aRMask = mSurface->format->Rmask; uint32_t aGMask = mSurface->format->Gmask; uint32_t aBMask = mSurface->format->Bmask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; int aRedShift = mSurface->format->Rshift; int aGreenShift = mSurface->format->Gshift; int aBlueShift = mSurface->format->Bshift; int* aMaxRedTable = mDDInterface->mRedAddTable; int* aMaxGreenTable = mDDInterface->mGreenAddTable; int* aMaxBlueTable = mDDInterface->mBlueAddTable; if (mSurface->format->BitsPerPixel == 16) { ushort rc = ((theColor.mRed * theColor.mAlpha) / 255) >> (8-mDDInterface->mRedBits); ushort gc = ((theColor.mGreen * theColor.mAlpha) / 255) >> (8-mDDInterface->mGreenBits); ushort bc = ((theColor.mBlue * theColor.mAlpha) / 255) >> (8-mDDInterface->mBlueBits); ushort* aDestPixelsRow = ((ushort*) mSurface->pixels) + (theRect.mY * mSurface->pitch/2) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { ushort* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) { ushort dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } aDestPixelsRow += mSurface->pitch/2; } } else if (mSurface->format->BitsPerPixel == 32) { uint32_t rc = ((theColor.mRed * theColor.mAlpha) / 255) >> (8-mDDInterface->mRedBits); uint32_t gc = ((theColor.mGreen * theColor.mAlpha) / 255) >> (8-mDDInterface->mGreenBits); uint32_t bc = ((theColor.mBlue * theColor.mAlpha) / 255) >> (8-mDDInterface->mBlueBits); uint32_t* aDestPixelsRow = ((uint32_t*) mSurface->pixels) + (theRect.mY * mSurface->pitch/4) + theRect.mX; for (int y = 0; y < theRect.mHeight; y++) { uint32_t* aDestPixels = aDestPixelsRow; for (int x = 0; x < theRect.mWidth; x++) { uint32_t dest = *aDestPixels; int r = aMaxRedTable[((dest & aRMask) >> aRedShift) + rc]; int g = aMaxGreenTable[((dest & aGMask) >> aGreenShift) + gc]; int b = aMaxBlueTable[((dest & aBMask) >> aBlueShift) + bc]; *(aDestPixels++) = (r << aRedShift) | (g << aGreenShift) | (b << aBlueShift); } aDestPixelsRow += mSurface->pitch/4; } } UnlockSurface(); } void DDImage::NormalBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor) { theImage->mDrawn = true; MemoryImage* aMemoryImage = dynamic_cast(theImage); DDImage* aDDImage = dynamic_cast(theImage); if (aMemoryImage != NULL) { aMemoryImage->CommitBits(); Rect aDestRect(theX, theY, theX + theSrcRect.mWidth, theY + theSrcRect.mHeight); SDL_Rect aSDLDestRect = {theX, theY, theX + theSrcRect.mWidth, theY + theSrcRect.mHeight}; Rect aSrcRect(theSrcRect.mX, theSrcRect.mY, theSrcRect.mX + theSrcRect.mWidth, theSrcRect.mY + theSrcRect.mHeight); SDL_Rect aSDLSrcRect = {theSrcRect.mX, theSrcRect.mY, theSrcRect.mX + theSrcRect.mWidth, theSrcRect.mY + theSrcRect.mHeight}; //TODO: if ((aMemoryImage->mIsVolatile) && ((aDDImage == NULL) || (aDDImage->mSurface == NULL)) && (!mNoLock) && (theColor == Color::White)) { if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aMemoryImage->GetBits(); #define SRC_TYPE uint32_t #define NEXT_SRC_COLOR (*(aSrcPixels++)) #include "DDI_NormalBlt_Volatile.inc" #undef SRC_TYPE #undef NEXT_SRC_COLOR } else { uint32_t* aColorTable = aMemoryImage->mColorTable; uchar* aSrcBits = aMemoryImage->mColorIndices; #define SRC_TYPE uchar #define NEXT_SRC_COLOR (aColorTable[*(aSrcPixels++)]) #include "DDI_NormalBlt_Volatile.inc" #undef SRC_TYPE #undef NEXT_SRC_COLOR } } else if (((aMemoryImage->mHasAlpha) || (theColor != Color::White))) { if (mNoLock) return; if (!LockSurface()) return; // Ensure NativeAlphaData is calculated void *aNativeData = aMemoryImage->GetNativeAlphaData(mDDInterface); // Ensure RunLength data is calculated uchar* aSrcRLAlphaData = aMemoryImage->GetRLAlphaData(); #define _PLUSPLUS ++ #define _PLUSEQUALS += if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aNativeData) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t* aSrcPixels; #define NEXT_SRC_COLOR (*(aSrcPixels++)) #define PEEK_SRC_COLOR (*aSrcPixels) #include "DDI_AlphaBlt.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } else { uint32_t* aNativeColorTable = (uint32_t*) aNativeData; uchar* aSrcPixelsRow = aMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uchar* aSrcPixels; #define NEXT_SRC_COLOR (aNativeColorTable[*(aSrcPixels++)]) #define PEEK_SRC_COLOR (aNativeColorTable[*aSrcPixels]) #include "DDI_AlphaBlt.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } #undef _PLUSPLUS #undef _PLUSEQUALS UnlockSurface(); } else if ((aDDImage == NULL) || (aDDImage->mSurface == NULL) || ((!mVideoMemory) && (aDDImage->mVideoMemory))) { if (mNoLock) return; //TODO: Have some sort of cool thing here if (!LockSurface()) return; void* aNativeAlphaData = aMemoryImage->GetNativeAlphaData(mDDInterface); if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aNativeAlphaData) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t* aSrcPixels; #define NEXT_SRC_COLOR (*(aSrcPixels++)) #define PEEK_SRC_COLOR (*aSrcPixels) #include "DDI_FastBlt_NoAlpha.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } else { uint32_t* aNativeAlphaColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcPixelsRow = aMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uchar* aSrcPixels; #define NEXT_SRC_COLOR (aNativeAlphaColorTable[*(aSrcPixels++)]) #define PEEK_SRC_COLOR (aNativeAlphaColorTable[*aSrcPixels]) #include "DDI_FastBlt_NoAlpha.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } } else { if (mLockCount > 0) SDL_UnlockSurface(mSurface); if (aDDImage->mHasTrans) { SDL_SetColorKey(mSurface,SDL_SRCCOLORKEY, 0); } SDL_BlitSurface(aDDImage->GetSurface(),&aSDLSrcRect, mSurface, &aSDLDestRect); if (mLockCount > 0) SDL_LockSurface(mSurface); } } } void DDImage::NormalBltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRectOrig, const Color& theColor) { theImage->mDrawn = true; Rect theSrcRect = theSrcRectOrig; theX += theSrcRect.mWidth-1; MemoryImage* aMemoryImage = dynamic_cast(theImage); DDImage* aDDImage = dynamic_cast(theImage); if (aMemoryImage != NULL) { aMemoryImage->CommitBits(); if (mNoLock) return; if (!LockSurface()) return; // Ensure NativeAlphaData is calculated void *aNativeData = aMemoryImage->GetNativeAlphaData(mDDInterface); // Ensure RunLength data is calculated uchar* aSrcRLAlphaData = aMemoryImage->GetRLAlphaData(); #define _PLUSPLUS -- #define _PLUSEQUALS -= if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aNativeData) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t* aSrcPixels; #define NEXT_SRC_COLOR (*(aSrcPixels++)) #define PEEK_SRC_COLOR (*aSrcPixels) #include "DDI_AlphaBlt.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } else { uint32_t* aNativeColorTable = (uint32_t*) aNativeData; uchar* aSrcPixelsRow = aMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uchar* aSrcPixels; #define NEXT_SRC_COLOR (aNativeColorTable[*(aSrcPixels++)]) #define PEEK_SRC_COLOR (aNativeColorTable[*aSrcPixels]) #include "DDI_AlphaBlt.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } #undef _PLUSPLUS #undef _PLUSEQUALS UnlockSurface(); } } void DDImage::AdditiveBlt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor) { theImage->mDrawn = true; if (mNoLock) return; MemoryImage* aMemoryImage = dynamic_cast(theImage); DDImage* aDDImage = dynamic_cast(theImage); if (aMemoryImage != NULL) { if (!LockSurface()) return; // Ensure NativeAlphaData is calculated void* aNativeAlphaData = aMemoryImage->GetNativeAlphaData(mDDInterface); #define _PLUSPLUS ++ #define _PLUSEQUALS += if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aNativeAlphaData) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t* aSrcPixels; #define NEXT_SRC_COLOR (*(aSrcPixels++)) #define PEEK_SRC_COLOR (*aSrcPixels) #include "DDI_Additive.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } else { uint32_t* aNativeAlphaColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcPixelsRow = aMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uchar* aSrcPixels; #define NEXT_SRC_COLOR (aNativeAlphaColorTable[*(aSrcPixels++)]) #define PEEK_SRC_COLOR (aNativeAlphaColorTable[*aSrcPixels]) #include "DDI_Additive.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } #undef _PLUSPLUS #undef _PLUSEQUALS UnlockSurface(); } } void DDImage::AdditiveBltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRectOrig, const Color& theColor) { theImage->mDrawn = true; if (mNoLock) return; Rect theSrcRect = theSrcRectOrig; theX += theSrcRect.mWidth-1; MemoryImage* aMemoryImage = dynamic_cast(theImage); DDImage* aDDImage = dynamic_cast(theImage); if (aMemoryImage != NULL) { if (!LockSurface()) return; // Ensure NativeAlphaData is calculated void* aNativeAlphaData = aMemoryImage->GetNativeAlphaData(mDDInterface); #define _PLUSPLUS -- #define _PLUSEQUALS -= if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcPixelsRow = ((uint32_t*) aNativeAlphaData) + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uint32_t* aSrcPixels; #define NEXT_SRC_COLOR (*(aSrcPixels++)) #define PEEK_SRC_COLOR (*aSrcPixels) #include "DDI_Additive.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } else { uint32_t* aNativeAlphaColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcPixelsRow = aMemoryImage->mColorIndices + (theSrcRect.mY * theImage->mWidth) + theSrcRect.mX; uchar* aSrcPixels; #define NEXT_SRC_COLOR (aNativeAlphaColorTable[*(aSrcPixels++)]) #define PEEK_SRC_COLOR (aNativeAlphaColorTable[*aSrcPixels]) #include "DDI_Additive.inc" #undef NEXT_SRC_COLOR #undef PEEK_SRC_COLOR } #undef _PLUSPLUS #undef _PLUSEQUALS UnlockSurface(); } } void DDImage::Blt(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; assert((theColor.mRed >= 0) && (theColor.mRed <= 255)); assert((theColor.mGreen >= 0) && (theColor.mGreen <= 255)); assert((theColor.mBlue >= 0) && (theColor.mBlue <= 255)); assert((theColor.mAlpha >= 0) && (theColor.mAlpha <= 255)); CommitBits(); if (Check3D(this)) { DDImage* aDDImage = dynamic_cast(theImage); // Special short-circuit if ((aDDImage != NULL) && (aDDImage->mSurface != NULL) && (mDDInterface->mD3DInterface->mTransformStack.empty()) && (theDrawMode == Graphics::DRAWMODE_NORMAL) && (theColor == Color::White) && (!aDDImage->mHasAlpha)) { if (mLockCount > 0) SDL_UnlockSurface(mSurface); SDL_Rect aSDLDestRect = {theX, theY, theX + theSrcRect.mWidth, theY + theSrcRect.mHeight}; SDL_Rect aSDLSrcRect = {theSrcRect.mX, theSrcRect.mY, theSrcRect.mX + theSrcRect.mWidth, theSrcRect.mY + theSrcRect.mHeight}; if (aDDImage->mHasTrans) { SDL_SetColorKey(mSurface,SDL_SRCCOLORKEY, 0); } SDL_BlitSurface(aDDImage->GetSurface(),&aSDLSrcRect, mSurface, &aSDLDestRect); if (mLockCount > 0) SDL_LockSurface(mSurface); return; } mDDInterface->mD3DInterface->Blt(theImage,theX,theY,theSrcRect,theColor,theDrawMode); return; } if ((mDrawToBits) || (mHasAlpha) || ((mHasTrans) && (!mFirstPixelTrans)) || (mDDInterface->mIs3D && this!=mDDInterface->mOldCursorAreaImage)) { MemoryImage::Blt(theImage, theX, theY, theSrcRect, theColor, theDrawMode); return; } switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalBlt(theImage, theX, theY, theSrcRect, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveBlt(theImage, theX, theY, theSrcRect, theColor); break; } DeleteAllNonSurfaceData(); } void DDImage::BltMirror(Image* theImage, int theX, int theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode) { assert((theColor.mRed >= 0) && (theColor.mRed <= 255)); assert((theColor.mGreen >= 0) && (theColor.mGreen <= 255)); assert((theColor.mBlue >= 0) && (theColor.mBlue <= 255)); assert((theColor.mAlpha >= 0) && (theColor.mAlpha <= 255)); CommitBits(); if (Check3D(this)) { mDDInterface->mD3DInterface->BltMirror(theImage,theX,theY,theSrcRect,theColor,theDrawMode); return; } switch (theDrawMode) { case Graphics::DRAWMODE_NORMAL: NormalBltMirror(theImage, theX, theY, theSrcRect, theColor); break; case Graphics::DRAWMODE_ADDITIVE: AdditiveBltMirror(theImage, theX, theY, theSrcRect, theColor); break; } DeleteAllNonSurfaceData(); } void DDImage::BltF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect &theClipRect, const Color& theColor, int theDrawMode) { theImage->mDrawn = true; if (Check3D(this)) { FRect aClipRect(theClipRect.mX,theClipRect.mY,theClipRect.mWidth,theClipRect.mHeight); FRect aDestRect(theX,theY,theSrcRect.mWidth,theSrcRect.mHeight); FRect anIntersect = aDestRect.Intersection(aClipRect); if (anIntersect.mWidth!=aDestRect.mWidth || anIntersect.mHeight!=aDestRect.mHeight) { if (anIntersect.mWidth!=0 && anIntersect.mHeight!=0) mDDInterface->mD3DInterface->BltClipF(theImage,theX,theY,theSrcRect,&theClipRect,theColor,theDrawMode); } else mDDInterface->mD3DInterface->Blt(theImage,theX,theY,theSrcRect,theColor,theDrawMode,true); return; } else BltRotated(theImage,theX,theY,theSrcRect,theClipRect,theColor,theDrawMode,0,0,0); } void DDImage::BltRotated(Image* theImage, float theX, float theY, const Rect &theSrcRect, const Rect& theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY) { theImage->mDrawn = true; if (mNoLock) return; CommitBits(); if (Check3D(this)) { mDDInterface->mD3DInterface->BltRotated(theImage,theX,theY,&theClipRect,theColor,theDrawMode,theRot,theRotCenterX,theRotCenterY,theSrcRect); return; } if ((mDrawToBits) || (mHasAlpha) || ((mHasTrans) && (!mFirstPixelTrans)) || (mDDInterface->mIs3D)) { MemoryImage::BltRotated(theImage, theX, theY, theSrcRect, theClipRect, theColor, theDrawMode, theRot, theRotCenterX, theRotCenterY); return; } // This BltRotatedClipHelper clipping used to happen in Graphics::DrawImageRotated FRect aDestRect; if (!BltRotatedClipHelper(theX, theY, theSrcRect, theClipRect, theRot, aDestRect,theRotCenterX,theRotCenterY)) return; MemoryImage* aMemoryImage = dynamic_cast(theImage); DDImage* aDDImage = dynamic_cast(theImage); if (aMemoryImage != NULL) { aMemoryImage->CommitBits(); if (theDrawMode == Graphics::DRAWMODE_NORMAL) { if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aMemoryImage->GetBits() + theSrcRect.mX + theSrcRect.mY*aMemoryImage->GetWidth(); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_BltRotated.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = aMemoryImage->mColorTable; uchar* aSrcBits = aMemoryImage->mColorIndices + theSrcRect.mX + theSrcRect.mY*aMemoryImage->GetWidth(); #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_BltRotated.inc" #undef SRC_TYPE #undef READ_COLOR } } else { if (aMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = aMemoryImage->GetBits() + theSrcRect.mX + theSrcRect.mY*aMemoryImage->GetWidth(); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_BltRotated_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = aMemoryImage->mColorTable; uchar* aSrcBits = aMemoryImage->mColorIndices + theSrcRect.mX + theSrcRect.mY*aMemoryImage->GetWidth(); #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_BltRotated_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } } } DeleteAllNonSurfaceData(); } void DDImage::StretchBlt(Image* theImage, const Rect& theDestRectOrig, const Rect& theSrcRectOrig, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch) { theImage->mDrawn = true; DDImage* aSrcDDImage = dynamic_cast(theImage); MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); CommitBits(); if (Check3D(this)) { mDDInterface->mD3DInterface->StretchBlt(theImage,theDestRectOrig,theSrcRectOrig,&theClipRect,theColor,theDrawMode,fastStretch); return; } Rect theDestRect; FRect theSrcRect; if (!StretchBltClipHelper(theSrcRectOrig,theClipRect,theDestRectOrig,theSrcRect,theDestRect)) return; //TODO investigate why StretchBltClipHelpder doesn't catch this if (theDestRect.mWidth == 0 || theDestRect.mHeight == 0 || theSrcRect.mWidth == 0 || theSrcRect.mHeight == 0) return; if (fastStretch) { if ((aSrcDDImage != NULL) && (theColor == Color::White) && (theDrawMode == Graphics::DRAWMODE_NORMAL) && (!aSrcDDImage->mHasAlpha) && (aSrcDDImage->GetSurface() != NULL)) { SDL_Surface* aSrcSurface = aSrcDDImage->GetSurface(); SDL_Rect aDestRect = {(Sint16)theDestRect.mX, (Sint16)theDestRect.mY, (Uint16)(theDestRect.mX + theDestRect.mWidth), (Uint16)(theDestRect.mY + theDestRect.mHeight)}; SDL_Rect aSrcRect = {(Sint16)theSrcRect.mX, (Sint16)theSrcRect.mY, (Uint16)(theSrcRect.mX + theSrcRect.mWidth), (Uint16)(theSrcRect.mY + theSrcRect.mHeight)}; if (mLockCount > 0) SDL_UnlockSurface(mSurface); if (aSrcDDImage->mHasTrans) { SDL_SetColorKey(mSurface,SDL_SRCCOLORKEY, 0); } SDL_BlitSurface(mSurface,&aSrcRect, mSurface, &aDestRect); if (mLockCount > 0) SDL_LockSurface(mSurface); } else { if (aSrcMemoryImage != NULL) { aSrcMemoryImage->CommitBits(); // Ensure NativeAlphaData is calculated void *aNativeAlphaData = aSrcMemoryImage->GetNativeAlphaData(mDDInterface); #define _PLUSPLUS ++ if (theDrawMode == Graphics::DRAWMODE_NORMAL) { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = ((uint32_t*) aNativeAlphaData); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_FastStretch.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_FastStretch.inc" #undef SRC_TYPE #undef READ_COLOR } } else { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = ((uint32_t*) aNativeAlphaData); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_FastStretch_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_FastStretch_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } } #undef _PLUSPLUS } } } else { if ((mDrawToBits) || (mHasAlpha) || (mHasTrans) || (mDDInterface->mIs3D)) { MemoryImage::StretchBlt(theImage, theDestRectOrig, theSrcRectOrig, theClipRect, theColor, theDrawMode, fastStretch); return; } // Stretch it to a temporary image MemoryImage aTempImage(mApp); Rect aTempRect(0, 0, theDestRect.mWidth, theDestRect.mHeight); aTempImage.Create(theDestRect.mWidth, theDestRect.mHeight); if (fastStretch) aTempImage.FastStretchBlt(theImage, aTempRect, theSrcRect, theColor, 0); else aTempImage.SlowStretchBlt(theImage, aTempRect, theSrcRect, theColor, 0); Blt(&aTempImage, theDestRect.mX, theDestRect.mY, aTempRect, theColor, theDrawMode); } DeleteAllNonSurfaceData(); } void DDImage::StretchBltMirror(Image* theImage, const Rect& theDestRectOrig, const Rect& theSrcRectOrig, const Rect& theClipRect, const Color& theColor, int theDrawMode, bool fastStretch) { theImage->mDrawn = true; DDImage* aSrcDDImage = dynamic_cast(theImage); MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); CommitBits(); if (Check3D(this)) { mDDInterface->mD3DInterface->StretchBlt(theImage,theDestRectOrig,theSrcRectOrig,&theClipRect,theColor,theDrawMode,fastStretch,true); return; } FRect theSrcRect; Rect theDestRect; if (!StretchBltMirrorClipHelper(theSrcRectOrig,theClipRect,theDestRectOrig,theSrcRect,theDestRect)) return; theDestRect.mX += theDestRect.mWidth-1; if (aSrcMemoryImage != NULL) { aSrcMemoryImage->CommitBits(); // Ensure NativeAlphaData is calculated void *aNativeAlphaData = aSrcMemoryImage->GetNativeAlphaData(mDDInterface); #define _PLUSPLUS -- if (theDrawMode == Graphics::DRAWMODE_NORMAL) { if (aSrcMemoryImage->mColorTable == NULL) { uint32_t* aSrcBits = ((uint32_t*) aNativeAlphaData); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_FastStretch.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_FastStretch.inc" #undef SRC_TYPE #undef READ_COLOR } } else { //NOT IMPLEMENTED YET assert(false); #if 0 if (aSrcMemoryImage->mColorTable == NULL) { //uint32_t* aSrcBits = aSrcMemoryImage->GetBits(); uint32_t* aSrcBits = ((uint32_t*) aNativeAlphaData); #define SRC_TYPE uint32_t #define READ_COLOR(ptr) (*(ptr)) #include "DDI_FastStretch_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } else { uint32_t* aColorTable = (uint32_t*) aNativeAlphaData; uchar* aSrcBits = aSrcMemoryImage->mColorIndices; #define SRC_TYPE uchar #define READ_COLOR(ptr) (aColorTable[*(ptr)]) #include "DDI_FastStretch_Additive.inc" #undef SRC_TYPE #undef READ_COLOR } #endif } #undef _PLUSPLUS } DeleteAllNonSurfaceData(); } void DDImage::BltMatrix(Image* theImage, float x, float y, const SexyMatrix3 &theMatrix, const Rect& theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, bool blend) { theImage->mDrawn = true; if (Check3D(this)) { mDDInterface->mD3DInterface->BltTransformed(theImage,&theClipRect,theColor,theDrawMode,theSrcRect,theMatrix,blend,x,y,true); return; } if (!LockSurface()) return; int aPixelFormat; if (mSurface->format->BitsPerPixel == 32) aPixelFormat = 0x888; else if (mDDInterface->mRedMask == 0xf800 && mDDInterface->mGreenMask == 0x07e0 && mDDInterface->mBlueMask == 0x001f) aPixelFormat = 0x565; else if (mDDInterface->mRedMask == 0x7c00 && mDDInterface->mGreenMask == 0x03e0 && mDDInterface->mBlueMask == 0x001f) aPixelFormat = 0x555; else assert(false); BltMatrixHelper(theImage,x,y,theMatrix,theClipRect,theColor,theDrawMode,theSrcRect,mSurface,mSurface->pitch,aPixelFormat,blend); UnlockSurface(); DeleteAllNonSurfaceData(); } void DDImage::BltTrianglesTex(Image *theTexture, const TriVertex theVertices[][3], int theNumTriangles, const Rect& theClipRect, const Color &theColor, int theDrawMode, float tx, float ty, bool blend) { theTexture->mDrawn = true; if (Check3D(this)) { mDDInterface->mD3DInterface->DrawTrianglesTex(theVertices,theNumTriangles,theColor,theDrawMode,theTexture,tx,ty,blend); return; } //NOT IMPLEMENTED YET assert(false); #if 0 LPDIRECTDRAWSURFACE aSurface = GetSurface(); if (!LockSurface()) return; int aPixelFormat; if (mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 32) aPixelFormat = 0x888; else if (mLockedSurfaceDesc.ddpfPixelFormat.dwRBitMask == 0xf800 && mLockedSurfaceDesc.ddpfPixelFormat.dwGBitMask == 0x07e0 && mLockedSurfaceDesc.ddpfPixelFormat.dwBBitMask == 0x001f) aPixelFormat = 0x565; else if (mLockedSurfaceDesc.ddpfPixelFormat.dwRBitMask == 0x7c00 && mLockedSurfaceDesc.ddpfPixelFormat.dwGBitMask == 0x03e0 && mLockedSurfaceDesc.ddpfPixelFormat.dwBBitMask == 0x001f) aPixelFormat = 0x555; else assert(FALSE); BltTrianglesTexHelper(theTexture,theVertices,theNumTriangles,theClipRect,theColor,theDrawMode,mLockedSurfaceDesc.lpSurface,mLockedSurfaceDesc.lPitch,aPixelFormat,tx,ty,blend); UnlockSurface(); #endif DeleteAllNonSurfaceData(); } bool DDImage::Palletize() { if (MemoryImage::Palletize()) { // Don't keep around the DDSurface if we palletize the image, that // would be a waste of memory DeleteDDSurface(); return true; } else { return false; } } void DDImage::FillScanLinesWithCoverage(Span* theSpans, int theSpanCount, const Color& theColor, int theDrawMode, const unsigned char* theCoverage, int theCoverX, int theCoverY, int theCoverWidth, int theCoverHeight) { if (theSpanCount == 0) return; //NOT IMPLEMENTED YET assert(false); #if 0 if (Check3D(this)) { // ugh!#@$ int l = theSpans[0].mX, t = theSpans[0].mY; int r = l + theSpans[0].mWidth, b = t; for (int i = 1; i < theSpanCount; ++i) { l = min(theSpans[i].mX, l); r = max(theSpans[i].mX + theSpans[i].mWidth - 1, r); t = min(theSpans[i].mY, t); b = max(theSpans[i].mY, b); } for (int i = 0; i < theSpanCount; ++i) { theSpans[i].mX -= l; theSpans[i].mY -= t; } MemoryImage aTempImage; aTempImage.Create(r-l+1, b-t+1); aTempImage.FillScanLinesWithCoverage(theSpans, theSpanCount, theColor, theDrawMode, theCoverage, theCoverX - l, theCoverY - t, theCoverWidth, theCoverHeight); Blt(&aTempImage, l, t, Rect(0, 0, r-l+1, b-t+1), Color::White, theDrawMode); return; } LPDIRECTDRAWSURFACE aSurface = GetSurface(); if (!LockSurface()) return; uint32_t aRMask = mLockedSurfaceDesc.ddpfPixelFormat.dwRBitMask; uint32_t aGMask = mLockedSurfaceDesc.ddpfPixelFormat.dwGBitMask; uint32_t aBMask = mLockedSurfaceDesc.ddpfPixelFormat.dwBBitMask; uint32_t aRRoundAdd = aRMask >> 1; uint32_t aGRoundAdd = aGMask >> 1; uint32_t aBRoundAdd = aBMask >> 1; if (mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 16) { //ushort src_red = (((theColor.mRed * (theColor.mAlpha+1)) >> 8) * aRMask) & aRMask; //ushort src_green = (((theColor.mGreen * (theColor.mAlpha+1)) >> 8) * aGMask) & aGMask; //ushort src_blue = (((theColor.mBlue * (theColor.mAlpha+1)) >> 8) * aBMask) & aBMask; ushort src = (((theColor.mRed * aRMask) >> 8) & aRMask) | (((theColor.mGreen * aGMask) >> 8) & aGMask) | (((theColor.mBlue * aBMask) >> 8) & aBMask); ushort* theBits = (ushort*)mLockedSurfaceDesc.lpSurface; for (int i = 0; i < theSpanCount; ++i) { Span* aSpan = &theSpans[i]; int x = aSpan->mX - theCoverX; int y = aSpan->mY - theCoverY; ushort* aDestPixels = &theBits[aSpan->mY*mWidth + aSpan->mX]; const BYTE* aCoverBits = &theCoverage[y*theCoverWidth+x]; for (int w = 0; w < aSpan->mWidth; ++w) { int cover = *aCoverBits++; int a = ((cover+1) * theColor.mAlpha) >> 8; int oma = 256 - a; ushort dest = *aDestPixels; *(aDestPixels++) = ((((dest & aRMask) * oma + (src & aRMask) * a) >> 8) & aRMask) | ((((dest & aGMask) * oma + (src & aGMask) * a) >> 8) & aGMask) | ((((dest & aBMask) * oma + (src & aBMask) * a) >> 8) & aBMask); } } } else if (mLockedSurfaceDesc.ddpfPixelFormat.dwRGBBitCount == 32) { //uint32_t src_red = (((theColor.mRed * (theColor.mAlpha+1)) >> 8) * aRMask) & aRMask; //uint32_t src_green = (((theColor.mGreen * (theColor.mAlpha+1)) >> 8) * aGMask) & aGMask; //uint32_t src_blue = (((theColor.mBlue * (theColor.mAlpha+1)) >> 8) * aBMask) & aBMask; uint32_t src = (((theColor.mRed * aRMask) >> 8) & aRMask) | (((theColor.mGreen * aGMask) >> 8) & aGMask) | (((theColor.mBlue * aBMask) >> 8) & aBMask); uint32_t* theBits = (uint32_t*)mLockedSurfaceDesc.lpSurface; for (int i = 0; i < theSpanCount; ++i) { Span* aSpan = &theSpans[i]; int x = aSpan->mX - theCoverX; int y = aSpan->mY - theCoverY; uint32_t* aDestPixels = &theBits[aSpan->mY*mWidth + aSpan->mX]; const BYTE* aCoverBits = &theCoverage[y*theCoverWidth+x]; for (int w = 0; w < aSpan->mWidth; ++w) { int cover = *aCoverBits++; int a = ((cover+1) * theColor.mAlpha) >> 8; int oma = 256 - a; uint32_t dest = *aDestPixels; *(aDestPixels++) = ((((dest & aRMask) * oma + (src & aRMask) * a) >> 8) & aRMask) | ((((dest & aGMask) * oma + (src & aGMask) * a) >> 8) & aGMask) | ((((dest & aBMask) * oma + (src & aBMask) * a) >> 8) & aBMask); } } } UnlockSurface(); #endif DeleteAllNonSurfaceData(); } libtuxcap-1.4.0/tuxcap/lib/SWTri_GetTexel.cpp0000644000175000017500000000352311202747627020771 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. unsigned int tex; #if !defined(LINEAR_BLEND) { unsigned int t_pos = ((v)>>16)*tex_pitch + ((u)>>16); tex = t_pos>16)*tex_pitch + (umidfloor>>16); unsigned int t00 = t_pos> 24) * ((uint32_t) ((0x10000 - aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a10 = ((t10 >> 24) * ((uint32_t) (( aUFactor) * (0x10000 - aVFactor)) >> 16)) >> 16; int a01 = ((t01 >> 24) * ((uint32_t) ((0x10000 - aUFactor) * ( aVFactor)) >> 16)) >> 16; int a11 = ((t11 >> 24) * ((uint32_t) (( aUFactor) * ( aVFactor)) >> 16)) >> 16; unsigned int r = (((t00&0x00FF0000)*a00 + (t10&0x00FF0000)*a10 + (t01&0x00FF0000)*a01 + (t11&0x00FF0000)*a11)>>8)&0xFF0000; unsigned int g = (((t00&0x0000FF00)*a00 + (t10&0x0000FF00)*a10 + (t01&0x0000FF00)*a01 + (t11&0x0000FF00)*a11)>>8)&0x00FF00; unsigned int b = (((t00&0x000000FF)*a00 + (t10&0x000000FF)*a10 + (t01&0x000000FF)*a01 + (t11&0x000000FF)*a11)>>8)&0x0000FF; unsigned int a = ((a00 + a10 + a01 + a11)<<24)&0xFF000000; tex = a|r|g|b; } #endif unsigned int alpha; #if defined (TEX_ALPHA) alpha = tex>>24; #else alpha = 0xFF; #endif libtuxcap-1.4.0/tuxcap/lib/AudiereSoundInstance.cpp0000644000175000017500000000525510766713353022243 0ustar inniyahinniyah/* Original Audiere Sound Instance class by Rheenen 2005 */ #include "AudiereMusicInterface.h" #include "AudiereSoundInstance.h" #include "AudiereSoundManager.h" #include "audiere.h" using namespace Sexy; using namespace audiere; AudiereSoundInstance::AudiereSoundInstance(AudiereSoundManager* theSoundManager, SampleSourcePtr theSourceSound) { mAudiereSoundManagerP = theSoundManager; mStream = mAudiereSoundManagerP->mDevice->openStream(theSourceSound.get()); mReleased = false; mAutoRelease = false; mHasPlayed = false; mBaseVolume = 1.0; mBasePan = 0.0; mVolume = 1.0; mPan = 0.0; mPitch = 1.0; mHasPlayed = false; RehupVolume(); } AudiereSoundInstance::~AudiereSoundInstance() { Release(); mStream = NULL; } void AudiereSoundInstance::RehupVolume() { if (mStream) mStream->setVolume(mBaseVolume * mVolume * mAudiereSoundManagerP->mMasterVolume); } void AudiereSoundInstance::RehupPan() { if (mStream) { float aPan = /*float(mBasePan/100) * */float(mPan/100); if (aPan > 1.0) mStream->setPan(1.0); else if (aPan < -1.0) mStream->setPan(-1.0); else mStream->setPan(aPan); } } void AudiereSoundInstance::RehupPitch() { if (mStream) mStream->setPitchShift(mBasePitch * mPitch); } void AudiereSoundInstance::Release() { Stop(); mStream = NULL; mReleased = true; } void AudiereSoundInstance::SetVolume(double theVolume) // 0.0 to 1.0 { mVolume = (float)theVolume; RehupVolume(); } void AudiereSoundInstance::SetPan(int thePosition) //-100 to +100 = left to right { mPan = float(thePosition/100); RehupPan(); } void AudiereSoundInstance::AdjustPitch(double theNumSteps) //+0.5 to +2.0 = lower to higher { mPitch = (float)theNumSteps; RehupPitch(); } void AudiereSoundInstance::SetBaseVolume(double theBaseVolume) { mBaseVolume = (float)theBaseVolume; RehupVolume(); } void AudiereSoundInstance::SetBasePan(int theBasePan) { mBasePan = float(theBasePan/100); RehupPan(); } void AudiereSoundInstance::AdjustBasePitch(float thePitch) { mBasePitch = thePitch; RehupPitch(); } bool AudiereSoundInstance::Play(bool looping, bool autoRelease) { Stop(); mAutoRelease = autoRelease; if (!mStream) return false; mStream->setRepeat(looping); mStream->play(); mHasPlayed = true; return true; } void AudiereSoundInstance::Stop() { if (mStream) { mStream->stop(); mStream->setPosition(0); mAutoRelease = false; } } bool AudiereSoundInstance::IsPlaying() { return (mStream.get() != NULL) && (mStream->isPlaying()); } bool AudiereSoundInstance::IsReleased() { if ((!mReleased) && (mAutoRelease) && (mHasPlayed) && (!IsPlaying())) Release(); return mReleased; } double AudiereSoundInstance::GetVolume() { return mVolume; } libtuxcap-1.4.0/tuxcap/lib/ListWidget.cpp0000644000175000017500000002615411202747626020243 0ustar inniyahinniyah#include "ListWidget.h" #include "Font.h" #include "WidgetManager.h" #include "ScrollbarWidget.h" #include "ListListener.h" #include "SexyAppBase.h" using namespace Sexy; static int gInitialListWidgetColors[][3] = {{255, 255, 255}, {255, 255, 255}, {0, 0, 0}, {0, 192, 0}, {0, 0, 128}, {255, 255, 255}}; ListWidget::ListWidget(int theId, Font *theFont, ListListener *theListListener) { mJustify = JUSTIFY_LEFT; mHiliteIdx = -1; mSelectIdx = -1; if (theFont != NULL) mItemHeight = theFont->GetHeight(); else mItemHeight = -1; SetColors(gInitialListWidgetColors, 6); mId = theId; mFont = theFont; mListListener = theListListener; mParent = NULL; mChild = NULL; mScrollbar = NULL; mPosition = 0; mPageSize = 0; mSortFromChild = false; mDrawOutline = true; mMaxNumericPlaces = 0; mDrawSelectWhenHilited = false; mDoFingerWhenHilited = true; } ListWidget::~ListWidget() { } void ListWidget::RemovedFromManager(WidgetManager *theManager) { Widget::RemovedFromManager(theManager); if (mListListener) mListListener->ListClosed(mId); } SexyString ListWidget::GetSortKey(int theIdx) { SexyString aString = mLines[theIdx]; while (aString.length() < (uint32_t) mMaxNumericPlaces) aString = _S("0") + aString; if (mSortFromChild) return mChild->GetSortKey(theIdx) + aString; else { if (mChild == NULL) return aString; else return aString + mChild->GetSortKey(theIdx); } return _S(""); } void ListWidget::Sort(bool ascending) { int aCount = mLines.size(); int* aMap = new int[aCount]; SexyString* aKeys = new SexyString[aCount]; int i; for (i = 0; i < aCount; i++) { aMap[i] = i; aKeys[i] = GetSortKey(i); } for (i = 1; i < aCount; i++) for (int j = 0; j < aCount - i; j++) { int aComp = aKeys[j].compare(aKeys[j+1]); if ((ascending && (aComp > 0)) || (!ascending && (aComp < 0))) { int aSwapInt = aMap[j]; aMap[j] = aMap[j+1]; aMap[j+1] = aSwapInt; SexyString aSwapKey = aKeys[j]; aKeys[j] = aKeys[j+1]; aKeys[j+1] = aSwapKey; } } ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { SexyStringVector aNewLines; ColorVector aNewLineColors; for (int i = 0; i < aCount; i++) { aNewLines.push_back(aListWidget->mLines[aMap[i]]); aNewLineColors.push_back(aListWidget->mLineColors[aMap[i]]); } aListWidget->mLines = aNewLines; aListWidget->mLineColors = aNewLineColors; aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } delete[] aMap; delete[] aKeys; } SexyString ListWidget::GetStringAt(int theIdx) { return mLines[theIdx]; } void ListWidget::Resize(int theX, int theY, int theWidth, int theHeight) { Widget::Resize(theX, theY, theWidth, theHeight); double aPageSize = 1; int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight(); if (mHeight > anItemHeight+8) aPageSize = (mHeight - 8.0) / anItemHeight; mPageSize = aPageSize; if (mScrollbar != NULL) mScrollbar->SetPageSize(aPageSize); } int ListWidget::AddLine(const SexyString& theLine, bool alphabetical) { int anIdx = -1; bool inserted = false; if (alphabetical) { for (int i = 0; i < (int) mLines.size(); i++) if (sexystrcmp(theLine.c_str(), mLines[i].c_str()) < 0) { anIdx = i; ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { if (aListWidget == this) aListWidget->mLines.insert(aListWidget->mLines.begin() + i, theLine); else aListWidget->mLines.insert(aListWidget->mLines.begin() + i, _S("-")); aListWidget->mLineColors.insert(aListWidget->mLineColors.begin() + i, mColors[COLOR_TEXT]); aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } inserted = true; break; } } if (!inserted) { anIdx = mLines.size(); ListWidget *aListWidget = this; while (aListWidget->mParent!=NULL) aListWidget = aListWidget->mParent; while (aListWidget!=NULL) { if (aListWidget==this) aListWidget->mLines.push_back(theLine); else aListWidget->mLines.push_back(_S("-")); aListWidget->mLineColors.push_back(mColors[COLOR_TEXT]); aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } } if (mScrollbar!=NULL) mScrollbar->SetMaxValue(mLines.size()); return anIdx; } void ListWidget::SetLine(int theIdx, const SexyString& theString) { mLines[theIdx] = theString; MarkDirty(); } int ListWidget::GetLineCount() { return mLines.size(); } int ListWidget::GetLineIdx(const SexyString& theLine) { for (uint32_t i = 0; i < mLines.size(); i++) if (sexystrcmp(mLines[i].c_str(), theLine.c_str()) == 0) return i; return -1; } void ListWidget::SetColor(const SexyString& theLine, const Color& theColor) { int anIdx = GetLineIdx(theLine); SetLineColor(anIdx, theColor); } void ListWidget::SetColor(int theIdx, const Color& theColor) { Widget::SetColor(theIdx, theColor); } void ListWidget::SetLineColor(int theIdx, const Color& theColor) { if ((theIdx >= 0) && (theIdx < (int)mLines.size())) { ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->mLineColors[theIdx] = theColor; aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } } } void ListWidget::RemoveLine(int theIdx) { if (theIdx != -1) { ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->mLines.erase(aListWidget->mLines.begin() + theIdx); aListWidget->mLineColors.erase(aListWidget->mLineColors.begin() + theIdx); aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } } if (mScrollbar != NULL) mScrollbar->SetMaxValue(mLines.size()); } void ListWidget::RemoveAll() { ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->mLines.clear(); aListWidget->mLineColors.clear(); aListWidget->mSelectIdx = -1; aListWidget->mHiliteIdx = -1; aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } if (mScrollbar != NULL) mScrollbar->SetMaxValue(mLines.size()); } int ListWidget::GetOptimalWidth() { int aMaxWidth = 0; for (uint32_t i = 0; i < mLines.size(); i++) aMaxWidth = std::max(aMaxWidth, mFont->StringWidth(mLines[i])); return aMaxWidth + 16; } int ListWidget::GetOptimalHeight() { int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight(); return anItemHeight * mLines.size() + 8; } void ListWidget::OrderInManagerChanged() { Widget::OrderInManagerChanged(); if (mChild != NULL) gSexyAppBase->mWidgetManager->PutInfront(mChild, this); if (mScrollbar != NULL) gSexyAppBase->mWidgetManager->PutInfront(mScrollbar, this); } void ListWidget::Draw(Graphics *g) { g->SetColor(mColors[COLOR_BKG]); g->FillRect(0, 0, mWidth, mHeight); Graphics aClipG(*g); aClipG.ClipRect(4, 4, mWidth - 8, mHeight - 8); Graphics aSelectClipG(*g); aSelectClipG.ClipRect(0, 4, mWidth, mHeight - 8); aClipG.SetFont(mFont); int aFirstLine = (int) mPosition; int aLastLine = std::min((int) mLines.size()-1, (int) mPosition + (int) mPageSize + 1); int anItemHeight, anItemOffset; if (mItemHeight != -1) { anItemHeight = mItemHeight; anItemOffset = (anItemHeight-mFont->GetHeight())/2; } else { anItemHeight = mFont->GetHeight(); anItemOffset = 0; } for (int i = aFirstLine; i <= aLastLine; i++) { int aDrawY = 4 + (int) ((i - mPosition)*anItemHeight); if (i == mSelectIdx || (i==mHiliteIdx && mDrawSelectWhenHilited)) { aSelectClipG.SetColor(mColors[COLOR_SELECT]); aSelectClipG.FillRect(0, aDrawY, mWidth, anItemHeight); } if (i == mHiliteIdx) aClipG.SetColor(mColors[COLOR_HILITE]); else if ((i == mSelectIdx) && (mColors.size() > COLOR_SELECT_TEXT)) aClipG.SetColor(mColors[COLOR_SELECT_TEXT]); else aClipG.SetColor(mLineColors[i]); SexyString aString = mLines[i]; int aFontX; switch (mJustify) { case JUSTIFY_LEFT: aFontX = 4; break; case JUSTIFY_CENTER: aFontX = (mWidth - mFont->StringWidth(aString))/2; break; default: aFontX = mWidth - mFont->StringWidth(aString) - 4; break; } aClipG.DrawString(aString, aFontX, aDrawY + mFont->GetAscent() + anItemOffset); } if (mDrawOutline) { g->SetColor(mColors[COLOR_OUTLINE]); g->DrawRect(0, 0, mWidth-1, mHeight-1); } } void ListWidget::ScrollPosition(int theId, double thePosition) { if (mChild != NULL) mChild->ScrollPosition(theId, thePosition); mPosition = thePosition; MarkDirty(); } void ListWidget::SetHilite(int theHiliteIdx, bool notifyListener) { int anOldIdx = mHiliteIdx; mHiliteIdx = theHiliteIdx; if (anOldIdx!=mHiliteIdx && notifyListener && mListListener!=NULL) mListListener->ListHiliteChanged(mId,anOldIdx,mHiliteIdx); } void ListWidget::MouseMove(int x, int y) { int anItemHeight = (mItemHeight != -1) ? mItemHeight : mFont->GetHeight(); int aNewHilite = (int) (((y - 4) / (double) anItemHeight) + mPosition); if ((aNewHilite < 0) || (aNewHilite >= (int) mLines.size())) aNewHilite = -1; if (aNewHilite != mHiliteIdx) { ListWidget* aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->SetHilite(aNewHilite,true); aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } if (mHiliteIdx == -1 || !mDoFingerWhenHilited) mWidgetManager->mApp->SetCursor(CURSOR_POINTER); else mWidgetManager->mApp->SetCursor(CURSOR_HAND); } } void ListWidget::MouseDown(int x, int y, int theBtnNum, int theClickCount) { if ((mHiliteIdx != -1) && (mListListener != NULL)) mListListener->ListClicked(mId, mHiliteIdx, theClickCount); } void ListWidget::MouseLeave() { ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->SetHilite(-1,true); aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } mWidgetManager->mApp->SetCursor(CURSOR_POINTER); } void ListWidget::SetSelect(int theSelectIdx) { ListWidget *aListWidget = this; while (aListWidget->mParent != NULL) aListWidget = aListWidget->mParent; while (aListWidget != NULL) { aListWidget->mSelectIdx = theSelectIdx; aListWidget->MarkDirty(); aListWidget = aListWidget->mChild; } } void ListWidget::MouseWheel(int theDelta) { if (mScrollbar != NULL) { int aScrollAmount = 5; if (theDelta > 0) { mScrollbar->SetValue(mScrollbar->mValue - aScrollAmount); // mScrollbar->mUpdateMode = ScrollbarWidget::UPDATE_MODE_PGUP; // mScrollbar->mUpdateAcc = 0; } else if (theDelta < 0) { mScrollbar->SetValue(mScrollbar->mValue + aScrollAmount); // mScrollbar->mUpdateMode = ScrollbarWidget::UPDATE_MODE_PGDN; // mScrollbar->mUpdateAcc = 0; } } } libtuxcap-1.4.0/tuxcap/lib/Checkbox.cpp0000644000175000017500000000336510642176156017712 0ustar inniyahinniyah#include "Checkbox.h" #include "CheckboxListener.h" #include "Graphics.h" using namespace Sexy; Checkbox::Checkbox(Image* theUncheckedImage, Image* theCheckedImage, int theId, CheckboxListener* theCheckboxListener) : mUncheckedImage(theUncheckedImage), mCheckedImage(theCheckedImage), mId(theId), mListener(theCheckboxListener), mChecked(false) , mOutlineColor(Color::White), mBkgColor(Color(80, 80, 80)), mCheckColor(Color(255, 255, 0)) { mDoFinger = true; } void Checkbox::SetChecked(bool checked, bool tellListener) { mChecked = checked; if (tellListener && mListener) mListener->CheckboxChecked(mId, mChecked); MarkDirty(); } bool Checkbox::IsChecked() { return mChecked; } void Checkbox::Draw(Graphics* g) { Widget::Draw(g); if ((mCheckedRect.mWidth == 0) && (mCheckedImage != NULL) && (mUncheckedImage != NULL)) { if (mChecked) g->DrawImage(mCheckedImage, 0, 0); else g->DrawImage(mUncheckedImage, 0, 0); } else if ((mCheckedRect.mWidth != 0) && (mUncheckedImage != NULL)) { if (mChecked) g->DrawImage(mUncheckedImage, 0, 0, mCheckedRect); else g->DrawImage(mUncheckedImage, 0, 0, mUncheckedRect); } else if ((mUncheckedImage == NULL) && (mCheckedImage == NULL)) { // No image, default draw method g->SetColor(mOutlineColor); g->FillRect(0, 0, mWidth, mHeight); g->SetColor(mBkgColor); g->FillRect(1, 1, mWidth - 2, mHeight - 2); if (mChecked) { g->SetColor(mCheckColor); g->DrawLine(1, 1, mWidth - 2, mHeight - 2); g->DrawLine(mWidth - 1, 1, 1, mHeight - 2); } } } void Checkbox::MouseDown(int x, int y, int theBtnNum, int theClickCount) { Widget::MouseDown(x, y, theBtnNum, theClickCount); mChecked = !mChecked; if (mListener) mListener->CheckboxChecked(mId, mChecked); MarkDirty(); } libtuxcap-1.4.0/tuxcap/lib/Insets.cpp0000644000175000017500000000064710641010432017410 0ustar inniyahinniyah#include "Insets.h" using namespace Sexy; Insets::Insets() : mLeft(0), mTop(0), mRight(0), mBottom(0) { int a = 0; } Insets::Insets(int theLeft, int theTop, int theRight, int theBottom) : mLeft(theLeft), mTop(theTop), mRight(theRight), mBottom(theBottom) { } Insets::Insets(const Insets& theInsets) : mLeft(theInsets.mLeft), mTop(theInsets.mTop), mRight(theInsets.mRight), mBottom(theInsets.mBottom) { } libtuxcap-1.4.0/tuxcap/lib/ImageFont.cpp0000644000175000017500000012637711202747626020045 0ustar inniyahinniyah#include "ImageFont.h" #include "Graphics.h" #include "Image.h" #include "SexyAppBase.h" #include "MemoryImage.h" #if 0 #include "..\SexyAppFramework\AutoCrit.h" #endif using namespace Sexy; //// DataElement::DataElement() : mIsList(false) { } DataElement::~DataElement() { } SingleDataElement::SingleDataElement() { mIsList = false; } SingleDataElement::SingleDataElement(const std::string theString) : mString(theString) { mIsList = false; } SingleDataElement::~SingleDataElement() { } DataElement* SingleDataElement::Duplicate() { SingleDataElement* aSingleDataElement = new SingleDataElement(*this); return aSingleDataElement; } ListDataElement::ListDataElement() { mIsList = true; } ListDataElement::~ListDataElement() { for (uint32_t i = 0; i < mElementVector.size(); i++) delete mElementVector[i]; } ListDataElement::ListDataElement(const ListDataElement& theListDataElement) { mIsList = true; for (uint32_t i = 0; i < theListDataElement.mElementVector.size(); i++) mElementVector.push_back(theListDataElement.mElementVector[i]->Duplicate()); } ListDataElement& ListDataElement::operator=(const ListDataElement& theListDataElement) { uint32_t i; for (i = 0; i < mElementVector.size(); i++) delete mElementVector[i]; mElementVector.clear(); for (i = 0; i < theListDataElement.mElementVector.size(); i++) mElementVector.push_back(theListDataElement.mElementVector[i]->Duplicate()); return *this; } DataElement* ListDataElement::Duplicate() { ListDataElement* aListDataElement = new ListDataElement(*this); return aListDataElement; } /// CharData::CharData() { mWidth = 0; mOrder = 0; for (uint32_t i = 0; i < 256; i++) mKerningOffsets[i] = 0; } FontLayer::FontLayer(FontData* theFontData) { mFontData = theFontData; mDrawMode = -1; mSpacing = 0; mPointSize = 0; mAscent = 0; mAscentPadding = 0; mMinPointSize = -1; mMaxPointSize = -1; mHeight = 0; mDefaultHeight = 0; mColorMult = Color::White; mColorAdd = Color(0, 0, 0, 0); mLineSpacingOffset = 0; mBaseOrder = 0; } FontLayer::FontLayer(const FontLayer& theFontLayer) : mFontData(theFontLayer.mFontData), mRequiredTags(theFontLayer.mRequiredTags), mExcludedTags(theFontLayer.mExcludedTags), mImage(theFontLayer.mImage), mDrawMode(theFontLayer.mDrawMode), mOffset(theFontLayer.mOffset), mSpacing(theFontLayer.mSpacing), mMinPointSize(theFontLayer.mMinPointSize), mMaxPointSize(theFontLayer.mMaxPointSize), mPointSize(theFontLayer.mPointSize), mAscent(theFontLayer.mAscent), mAscentPadding(theFontLayer.mAscentPadding), mHeight(theFontLayer.mHeight), mDefaultHeight(theFontLayer.mDefaultHeight), mColorMult(theFontLayer.mColorMult), mColorAdd(theFontLayer.mColorAdd), mLineSpacingOffset(theFontLayer.mLineSpacingOffset), mBaseOrder(theFontLayer.mBaseOrder) { uint32_t i; for (i = 0; i < 256; i++) mCharData[i] = theFontLayer.mCharData[i]; } FontData::FontData() { mInitialized = false; mApp = NULL; mRefCount = 0; mDefaultPointSize = 0; for (uint32_t i = 0; i < 256; i++) mCharMap[i] = (uchar) i; } FontData::~FontData() { DataElementMap::iterator anItr = mDefineMap.begin(); while (anItr != mDefineMap.end()) { std::string aDefineName = anItr->first; DataElement* aDataElement = anItr->second; delete aDataElement; ++anItr; } } void FontData::Ref() { mRefCount++; } void FontData::DeRef() { if (--mRefCount == 0) { delete this; } } bool FontData::Error(const std::string& theError) { if (mApp != NULL) { std::string anErrorString = mFontErrorHeader + theError; if (mCurrentLine.length() > 0) { anErrorString += " on Line " + StrFormat("%d:\r\n\r\n", mCurrentLineNum) + mCurrentLine; } #if 0 mApp->Popup(anErrorString); #endif } return false; } bool FontData::DataToLayer(DataElement* theSource, FontLayer** theFontLayer) { *theFontLayer = NULL; if (theSource->mIsList) return false; std::string aLayerName = StringToUpper(((SingleDataElement*) theSource)->mString); FontLayerMap::iterator anItr = mFontLayerMap.find(aLayerName); if (anItr == mFontLayerMap.end()) { Error("Undefined Layer"); return false; } *theFontLayer = anItr->second; return true; } bool FontData::GetColorFromDataElement(DataElement *theElement, Color &theColor) { if (theElement->mIsList) { DoubleVector aFactorVector; if (!DataToDoubleVector(theElement, &aFactorVector) && (aFactorVector.size() == 4)) return false; theColor = Color( (int) (aFactorVector[0] * 255), (int) (aFactorVector[1] * 255), (int) (aFactorVector[2] * 255), (int) (aFactorVector[3] * 255)); return true; } int aColor = 0; if (!StringToInt(((SingleDataElement*) theElement)->mString, &aColor)) return false; theColor = aColor; return true; } bool FontData::HandleCommand(const ListDataElement& theParams) { std::string aCmd = ((SingleDataElement*) theParams.mElementVector[0])->mString; bool invalidNumParams = false; bool invalidParamFormat = false; bool literalError = false; bool sizeMismatch = false; if (!strcasecmp(aCmd.c_str(), "Define")) { if (theParams.mElementVector.size() == 3) { if (!theParams.mElementVector[1]->mIsList) { std::string aDefineName = StringToUpper(((SingleDataElement*) theParams.mElementVector[1])->mString); if (!IsImmediate(aDefineName)) { DataElementMap::iterator anItr = mDefineMap.find(aDefineName); if (anItr != mDefineMap.end()) { delete anItr->second; mDefineMap.erase(anItr); } if (theParams.mElementVector[2]->mIsList) { ListDataElement* aValues = new ListDataElement(); if (!GetValues(((ListDataElement*) theParams.mElementVector[2]), aValues)) { delete aValues; return false; } mDefineMap.insert(DataElementMap::value_type(aDefineName, aValues)); } else { SingleDataElement* aDefParam = (SingleDataElement*) theParams.mElementVector[2]; DataElement* aDerefVal = Dereference(aDefParam->mString); if (aDerefVal) mDefineMap.insert(DataElementMap::value_type(aDefineName, aDerefVal->Duplicate())); else mDefineMap.insert(DataElementMap::value_type(aDefineName, aDefParam->Duplicate())); } } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "CreateHorzSpanRectList")) { if (theParams.mElementVector.size() == 4) { IntVector aRectIntVector; IntVector aWidthsVector; if ((!theParams.mElementVector[1]->mIsList) && (DataToIntVector(theParams.mElementVector[2], &aRectIntVector)) && (aRectIntVector.size() == 4) && (DataToIntVector(theParams.mElementVector[3], &aWidthsVector))) { std::string aDefineName = StringToUpper(((SingleDataElement*) theParams.mElementVector[1])->mString); int aXPos = 0; ListDataElement* aRectList = new ListDataElement(); for (uint32_t aWidthNum = 0; aWidthNum < aWidthsVector.size(); aWidthNum++) { ListDataElement* aRectElement = new ListDataElement(); aRectList->mElementVector.push_back(aRectElement); char aStr[256]; sprintf(aStr, "%d", aRectIntVector[0] + aXPos); aRectElement->mElementVector.push_back(new SingleDataElement(aStr)); sprintf(aStr, "%d", aRectIntVector[1]); aRectElement->mElementVector.push_back(new SingleDataElement(aStr)); sprintf(aStr, "%d", aWidthsVector[aWidthNum]); aRectElement->mElementVector.push_back(new SingleDataElement(aStr)); sprintf(aStr, "%d", aRectIntVector[3]); aRectElement->mElementVector.push_back(new SingleDataElement(aStr)); aXPos += aWidthsVector[aWidthNum]; } DataElementMap::iterator anItr = mDefineMap.find(aDefineName); if (anItr != mDefineMap.end()) { delete anItr->second; mDefineMap.erase(anItr); } mDefineMap.insert(DataElementMap::value_type(aDefineName, aRectList)); } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "SetDefaultPointSize")) { if (theParams.mElementVector.size() == 2) { int aPointSize; if ((!theParams.mElementVector[1]->mIsList) && (StringToInt(((SingleDataElement*) theParams.mElementVector[1])->mString, &aPointSize))) { mDefaultPointSize = aPointSize; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "SetCharMap")) { if (theParams.mElementVector.size() == 3) { StringVector aFromVector; StringVector aToVector; if ((DataToStringVector(theParams.mElementVector[1], &aFromVector)) && (DataToStringVector(theParams.mElementVector[2], &aToVector))) { if (aFromVector.size() == aToVector.size()) { for (uint32_t aMapIdx = 0; aMapIdx < aFromVector.size(); aMapIdx++) { if ((aFromVector[aMapIdx].length() == 1) && (aToVector[aMapIdx].length() == 1)) { mCharMap[(uchar) aFromVector[aMapIdx][0]] = (uchar) aToVector[aMapIdx][0]; } else invalidParamFormat = true; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "CreateLayer")) { if (theParams.mElementVector.size() == 2) { if (!theParams.mElementVector[1]->mIsList) { std::string aLayerName = StringToUpper(((SingleDataElement*) theParams.mElementVector[1])->mString); mFontLayerList.push_back(FontLayer(this)); FontLayer* aFontLayer = &mFontLayerList.back(); if (!mFontLayerMap.insert(FontLayerMap::value_type(aLayerName, aFontLayer)).second) { Error("Layer Already Exists"); } } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "CreateLayerFrom")) { if (theParams.mElementVector.size() == 3) { FontLayer* aSourceLayer; if ((!theParams.mElementVector[1]->mIsList) && (DataToLayer(theParams.mElementVector[2], &aSourceLayer))) { std::string aLayerName = StringToUpper(((SingleDataElement*) theParams.mElementVector[1])->mString); mFontLayerList.push_back(FontLayer(*aSourceLayer)); FontLayer* aFontLayer = &mFontLayerList.back(); if (!mFontLayerMap.insert(FontLayerMap::value_type(aLayerName, aFontLayer)).second) { Error("Layer Already Exists"); } } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "LayerRequireTags") ) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; StringVector aStringVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aStringVector))) { for (uint32_t i = 0; i < aStringVector.size(); i++) aLayer->mRequiredTags.push_back(StringToUpper(aStringVector[i])); } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "LayerExcludeTags") ) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; StringVector aStringVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aStringVector))) { for (uint32_t i = 0; i < aStringVector.size(); i++) aLayer->mExcludedTags.push_back(StringToUpper(aStringVector[i])); } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "LayerPointRange") ) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList) && (!theParams.mElementVector[3]->mIsList)) { int aMinPointSize; int aMaxPointSize; if ((StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &aMinPointSize)) && (StringToInt(((SingleDataElement*) theParams.mElementVector[3])->mString, &aMaxPointSize))) { aLayer->mMinPointSize = aMinPointSize; aLayer->mMaxPointSize = aMaxPointSize; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "LayerSetPointSize")) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int aPointSize; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &aPointSize)) { aLayer->mPointSize = aPointSize; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (!strcasecmp(aCmd.c_str(), "LayerSetHeight") ) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int aHeight; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &aHeight)) { aLayer->mHeight = aHeight; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetImage") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; std::string aFileNameString; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToString(theParams.mElementVector[2], &aFileNameString))) { std::string aFileName = GetPathFrom(aFileNameString, GetFileDir(mSourceFile)); bool isNew; SharedImageRef anImage = mApp->GetSharedImage(aFileName, "", &isNew); if ((Image*)anImage!= NULL) { if (isNew) anImage->Palletize(); aLayer->mImage = anImage; } else { Error("Failed to Load Image"); return false; } } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetDrawMode") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int anDrawMode; if ((StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &anDrawMode)) && (anDrawMode >= 0) && (anDrawMode <= 1)) { aLayer->mDrawMode = anDrawMode; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetColorMult") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if (DataToLayer(theParams.mElementVector[1], &aLayer)) { if (!GetColorFromDataElement(theParams.mElementVector[2],aLayer->mColorMult)) invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetColorAdd") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if (DataToLayer(theParams.mElementVector[1], &aLayer)) { if (!GetColorFromDataElement(theParams.mElementVector[2],aLayer->mColorAdd)) invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetAscent") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int anAscent; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &anAscent)) { aLayer->mAscent = anAscent; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetAscentPadding") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int anAscent; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &anAscent)) { aLayer->mAscentPadding = anAscent; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetLineSpacingOffset") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int anAscent; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &anAscent)) { aLayer->mLineSpacingOffset = anAscent; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetOffset") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; IntVector anOffset; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToIntVector(theParams.mElementVector[2], &anOffset)) && (anOffset.size() == 2)) { aLayer->mOffset.mX = anOffset[0]; aLayer->mOffset.mY = anOffset[1]; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetCharWidths") == 0) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; StringVector aCharsVector; IntVector aCharWidthsVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && (DataToIntVector(theParams.mElementVector[3], &aCharWidthsVector))) { if (aCharsVector.size() == aCharWidthsVector.size()) { for (uint32_t i = 0; i < aCharsVector.size(); i++) { if (aCharsVector[i].length() == 1) { aLayer->mCharData[(uchar) aCharsVector[i][0]].mWidth = aCharWidthsVector[i]; } else invalidParamFormat = true; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetSpacing") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; IntVector anOffset; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int aSpacing; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &aSpacing)) { aLayer->mSpacing = aSpacing; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetImageMap") == 0) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; StringVector aCharsVector; ListDataElement aRectList; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && (DataToList(theParams.mElementVector[3], &aRectList))) { if (aCharsVector.size() == aRectList.mElementVector.size()) { if ((Image*) aLayer->mImage != NULL) { int anImageWidth = aLayer->mImage->GetWidth(); int anImageHeight = aLayer->mImage->GetHeight(); for (uint32_t i = 0; i < aCharsVector.size(); i++) { IntVector aRectElement; if ((aCharsVector[i].length() == 1) && (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && (aRectElement.size() == 4)) { Rect aRect = Rect(aRectElement[0], aRectElement[1], aRectElement[2], aRectElement[3]); if ((aRect.mX < 0) || (aRect.mY < 0) || (aRect.mX + aRect.mWidth > anImageWidth) || (aRect.mY + aRect.mHeight > anImageHeight)) { Error("Image rectangle out of bounds"); return false; } aLayer->mCharData[(uchar) aCharsVector[i][0]].mImageRect = aRect;; } else invalidParamFormat = true; } aLayer->mDefaultHeight = 0; for (int aCharNum = 0; aCharNum < 256; aCharNum++) if (aLayer->mCharData[aCharNum].mImageRect.mHeight + aLayer->mCharData[aCharNum].mOffset.mY > aLayer->mDefaultHeight) aLayer->mDefaultHeight = aLayer->mCharData[aCharNum].mImageRect.mHeight + aLayer->mCharData[aCharNum].mOffset.mY; } else { Error("Layer image not set"); return false; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetCharOffsets") == 0) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; StringVector aCharsVector; ListDataElement aRectList; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && (DataToList(theParams.mElementVector[3], &aRectList))) { if (aCharsVector.size() == aRectList.mElementVector.size()) { for (uint32_t i = 0; i < aCharsVector.size(); i++) { IntVector aRectElement; if ((aCharsVector[i].length() == 1) && (DataToIntVector(aRectList.mElementVector[i], &aRectElement)) && (aRectElement.size() == 2)) { aLayer->mCharData[(uchar) aCharsVector[i][0]].mOffset = Point(aRectElement[0], aRectElement[1]); } else invalidParamFormat = true; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetKerningPairs") == 0) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; StringVector aPairsVector; IntVector anOffsetsVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aPairsVector)) && (DataToIntVector(theParams.mElementVector[3], &anOffsetsVector))) { if (aPairsVector.size() == anOffsetsVector.size()) { for (uint32_t i = 0; i < aPairsVector.size(); i++) { if (aPairsVector[i].length() == 2) { aLayer->mCharData[(uchar) aPairsVector[i][0]].mKerningOffsets [(uchar) aPairsVector[i][1]] = anOffsetsVector[i]; } else invalidParamFormat = true; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetBaseOrder") == 0) { if (theParams.mElementVector.size() == 3) { FontLayer* aLayer; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (!theParams.mElementVector[2]->mIsList)) { int aBaseOrder; if (StringToInt(((SingleDataElement*) theParams.mElementVector[2])->mString, &aBaseOrder)) { aLayer->mBaseOrder = aBaseOrder; } else invalidParamFormat = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else if (strcasecmp(aCmd.c_str(), "LayerSetCharOrders") == 0) { if (theParams.mElementVector.size() == 4) { FontLayer* aLayer; StringVector aCharsVector; IntVector aCharOrdersVector; if ((DataToLayer(theParams.mElementVector[1], &aLayer)) && (DataToStringVector(theParams.mElementVector[2], &aCharsVector)) && (DataToIntVector(theParams.mElementVector[3], &aCharOrdersVector))) { if (aCharsVector.size() == aCharOrdersVector.size()) { for (uint32_t i = 0; i < aCharsVector.size(); i++) { if (aCharsVector[i].length() == 1) { aLayer->mCharData[(uchar) aCharsVector[i][0]].mOrder = aCharOrdersVector[i]; } else invalidParamFormat = true; } } else sizeMismatch = true; } else invalidParamFormat = true; } else invalidNumParams = true; } else { Error("Unknown Command"); return false; } if (invalidNumParams) { Error("Invalid Number of Parameters"); return false; } if (invalidParamFormat) { Error("Invalid Paramater Type"); return false; } if (literalError) { Error("Undefined Value"); return false; } if (sizeMismatch) { Error("List Size Mismatch"); return false; } return true; } bool FontData::Load(SexyAppBase* theSexyApp, const std::string& theFontDescFileName) { if (mInitialized) return false; bool hasErrors = false; std::string daFontDescFileName = GetAppResourceFolder() + theFontDescFileName; daFontDescFileName = ReplaceBackSlashes(daFontDescFileName); mApp = theSexyApp; mCurrentLine = ""; mFontErrorHeader = "Font Descriptor Error in " + daFontDescFileName + "\r\n"; mSourceFile = daFontDescFileName; mInitialized = LoadDescriptor(daFontDescFileName); ; return !hasErrors; } bool FontData::LoadLegacy(Image* theFontImage, const std::string& theFontDescFileName) { if (mInitialized) return false; mFontLayerList.push_back(FontLayer(this)); FontLayer* aFontLayer = &mFontLayerList.back(); FontLayerMap::iterator anItr = mFontLayerMap.insert(FontLayerMap::value_type("", aFontLayer)).first; if (anItr == mFontLayerMap.end()) return false; aFontLayer->mImage = (MemoryImage*) theFontImage; aFontLayer->mDefaultHeight = aFontLayer->mImage->GetHeight(); aFontLayer->mAscent = aFontLayer->mImage->GetHeight(); std::string daFontDescFileName = GetAppResourceFolder() + theFontDescFileName; daFontDescFileName = ReplaceBackSlashes(daFontDescFileName); int aCharPos = 0; FILE *aStream = fopen(daFontDescFileName.c_str(), "r"); if (aStream==NULL) return false; mSourceFile = daFontDescFileName; int aSpaceWidth = 0; int input_items = fscanf(aStream,"%d%d",&aFontLayer->mCharData[' '].mWidth,&aFontLayer->mAscent); if (input_items != 2) return false; while (!feof(aStream)) { char aBuf[2] = { 0, 0 }; // needed because fscanf will null terminate the string it reads char aChar = 0; int aWidth = 0; int input_items = fscanf(aStream,"%1s%d",aBuf,&aWidth); if (input_items != 2) return false; aChar = aBuf[0]; if (aChar == 0) break; aFontLayer->mCharData[(uchar) aChar].mImageRect = Rect(aCharPos, 0, aWidth, aFontLayer->mImage->GetHeight()); aFontLayer->mCharData[(uchar) aChar].mWidth = aWidth; aCharPos += aWidth; } char c; for (c = 'A'; c <= 'Z'; c++) if ((aFontLayer->mCharData[c].mWidth == 0) && (aFontLayer->mCharData[c - 'A' + 'a'].mWidth != 0)) mCharMap[c] = c - 'A' + 'a'; for (c = 'a'; c <= 'z'; c++) if ((aFontLayer->mCharData[c].mWidth == 0) && (aFontLayer->mCharData[c - 'a' + 'A'].mWidth != 0)) mCharMap[c] = c - 'a' + 'A'; mInitialized = true; fclose(aStream); return true; } //// ActiveFontLayer::ActiveFontLayer() { mScaledImage = NULL; mOwnsImage = false; } ActiveFontLayer::ActiveFontLayer(const ActiveFontLayer& theActiveFontLayer) : mBaseFontLayer(theActiveFontLayer.mBaseFontLayer), mScaledImage(theActiveFontLayer.mScaledImage), mOwnsImage(theActiveFontLayer.mOwnsImage) { if (mOwnsImage) mScaledImage = (Image*)mBaseFontLayer->mFontData->mApp->CopyImage(mScaledImage); for (int aCharNum = 0; aCharNum < 256; aCharNum++) mScaledCharImageRects[aCharNum] = theActiveFontLayer.mScaledCharImageRects[aCharNum]; } ActiveFontLayer::~ActiveFontLayer() { if (mOwnsImage) delete mScaledImage; } //// ImageFont::ImageFont(SexyAppBase* theSexyApp, std::string theFontDescFileName) { mScale = 1.0; mFontData = new FontData(); mFontData->Ref(); mFontData->Load(theSexyApp, theFontDescFileName); mPointSize = mFontData->mDefaultPointSize; GenerateActiveFontLayers(); mActiveListValid = true; mForceScaledImagesWhite = false; } ImageFont::ImageFont(Image *theFontImage) { mScale = 1.0; mFontData = new FontData(); mFontData->Ref(); mFontData->mInitialized = true; mPointSize = mFontData->mDefaultPointSize; mActiveListValid = false; mForceScaledImagesWhite = false; mFontData->mFontLayerList.push_back(FontLayer(mFontData)); FontLayer* aFontLayer = &mFontData->mFontLayerList.back(); mFontData->mFontLayerMap.insert(FontLayerMap::value_type("", aFontLayer)).first; aFontLayer->mImage = (MemoryImage*) theFontImage; aFontLayer->mDefaultHeight = aFontLayer->mImage->GetHeight(); aFontLayer->mAscent = aFontLayer->mImage->GetHeight(); } ImageFont::ImageFont(const ImageFont& theImageFont) : Font(theImageFont), mScale(theImageFont.mScale), mFontData(theImageFont.mFontData), mPointSize(theImageFont.mPointSize), mTagVector(theImageFont.mTagVector), mActiveListValid(theImageFont.mActiveListValid), mForceScaledImagesWhite(theImageFont.mForceScaledImagesWhite) { mFontData->Ref(); if (mActiveListValid) mActiveLayerList = theImageFont.mActiveLayerList; } ImageFont::ImageFont(Image* theFontImage, const std::string& theFontDescFileName) { mScale = 1.0; mFontData = new FontData(); mFontData->Ref(); mFontData->LoadLegacy(theFontImage, theFontDescFileName); mPointSize = mFontData->mDefaultPointSize; GenerateActiveFontLayers(); mActiveListValid = true; } ImageFont::~ImageFont() { mFontData->DeRef(); } /*ImageFont::ImageFont(const ImageFont& theImageFont, Image* theImage) : Font(theImageFont), mImage(theImage) { for (int i = 0; i < 256; i++) { mCharPos[i] = theImageFont.mCharPos[i]; mCharWidth[i] = theImageFont.mCharWidth[i]; } }*/ void ImageFont::GenerateActiveFontLayers() { if (!mFontData->mInitialized) return; mActiveLayerList.clear(); uint32_t i; mAscent = 0; mAscentPadding = 0; mHeight = 0; mLineSpacingOffset = 0; FontLayerList::iterator anItr = mFontData->mFontLayerList.begin(); bool firstLayer = true; while (anItr != mFontData->mFontLayerList.end()) { FontLayer* aFontLayer = &*anItr; if ((mPointSize >= aFontLayer->mMinPointSize) && ((mPointSize <= aFontLayer->mMaxPointSize) || (aFontLayer->mMaxPointSize == -1))) { bool active = true; // Make sure all required tags are included for (i = 0; i < aFontLayer->mRequiredTags.size(); i++) if (std::find(mTagVector.begin(), mTagVector.end(), aFontLayer->mRequiredTags[i]) == mTagVector.end()) active = false; // Make sure no excluded tags are included for (i = 0; i < mTagVector.size(); i++) if (std::find(aFontLayer->mExcludedTags.begin(), aFontLayer->mExcludedTags.end(), mTagVector[i]) != aFontLayer->mExcludedTags.end()) active = false; if (active) { mActiveLayerList.push_back(ActiveFontLayer()); ActiveFontLayer* anActiveFontLayer = &mActiveLayerList.back(); anActiveFontLayer->mBaseFontLayer = aFontLayer; double aLayerPointSize = 1; double aPointSize = mScale; if ((mScale == 1.0) && ((aFontLayer->mPointSize == 0) || (mPointSize == aFontLayer->mPointSize))) { anActiveFontLayer->mScaledImage = aFontLayer->mImage; anActiveFontLayer->mOwnsImage = false; // Use the specified point size for (int aCharNum = 0; aCharNum < 256; aCharNum++) anActiveFontLayer->mScaledCharImageRects[aCharNum] = aFontLayer->mCharData[aCharNum].mImageRect; } else { if (aFontLayer->mPointSize != 0) { aLayerPointSize = aFontLayer->mPointSize; aPointSize = mPointSize * mScale; } // Resize font elements int aCharNum; MemoryImage* aMemoryImage = new MemoryImage(mFontData->mApp); int aCurX = 0; int aMaxHeight = 0; for (aCharNum = 0; aCharNum < 256; aCharNum++) { Rect* anOrigRect = &aFontLayer->mCharData[aCharNum].mImageRect; Rect aScaledRect(aCurX, 0, (int) ((anOrigRect->mWidth * aPointSize) / aLayerPointSize), (int) ((anOrigRect->mHeight * aPointSize) / aLayerPointSize)); anActiveFontLayer->mScaledCharImageRects[aCharNum] = aScaledRect; if (aScaledRect.mHeight > aMaxHeight) aMaxHeight = aScaledRect.mHeight; aCurX += aScaledRect.mWidth; } anActiveFontLayer->mScaledImage = aMemoryImage; anActiveFontLayer->mOwnsImage = true; // Create the image now aMemoryImage->Create(aCurX, aMaxHeight); Graphics g(aMemoryImage); for (aCharNum = 0; aCharNum < 256; aCharNum++) { if ((Image*) aFontLayer->mImage != NULL) g.DrawImage(aFontLayer->mImage, anActiveFontLayer->mScaledCharImageRects[aCharNum], aFontLayer->mCharData[aCharNum].mImageRect); } if (mForceScaledImagesWhite) { int aCount = aMemoryImage->mWidth*aMemoryImage->mHeight; uint32_t* aBits = aMemoryImage->GetBits(); for (int i = 0; i < aCount; i++) *(aBits++) = *aBits | 0x00FFFFFF; } aMemoryImage->Palletize(); } int aLayerAscent = (int)((aFontLayer->mAscent * aPointSize) / aLayerPointSize); if (aLayerAscent > mAscent) mAscent = aLayerAscent; if (aFontLayer->mHeight != 0) { int aLayerHeight = (int)((aFontLayer->mHeight * aPointSize) / aLayerPointSize); if (aLayerHeight > mHeight) mHeight = aLayerHeight; } else { int aLayerHeight = (int)((aFontLayer->mDefaultHeight * aPointSize) / aLayerPointSize); if (aLayerHeight > mHeight) mHeight = aLayerHeight; } int anAscentPadding = (int)((aFontLayer->mAscentPadding * aPointSize) / aLayerPointSize); if ((firstLayer) || (anAscentPadding < mAscentPadding)) mAscentPadding = anAscentPadding; int aLineSpacingOffset = (int)((aFontLayer->mLineSpacingOffset * aPointSize) / aLayerPointSize); if ((firstLayer) || (aLineSpacingOffset > mLineSpacingOffset)) mLineSpacingOffset = aLineSpacingOffset; firstLayer = false; } } ++anItr; } } int ImageFont::StringWidth(const SexyString& theString) { int aWidth = 0; char aPrevChar = 0; for(int i=0; i<(int)theString.length(); i++) { char aChar = theString[i]; aWidth += CharWidthKern(aChar,aPrevChar); aPrevChar = aChar; } return aWidth; } int ImageFont::CharWidthKern(char theChar, char thePrevChar) { Prepare(); int aMaxXPos = 0; double aPointSize = mPointSize * mScale; theChar = mFontData->mCharMap[(uchar)theChar]; if (thePrevChar != 0) thePrevChar = mFontData->mCharMap[(uchar)thePrevChar]; ActiveFontLayerList::iterator anItr = mActiveLayerList.begin(); while (anItr != mActiveLayerList.end()) { ActiveFontLayer* anActiveFontLayer = &*anItr; int aLayerXPos = 0; int aCharWidth; int aSpacing; int aLayerPointSize = anActiveFontLayer->mBaseFontLayer->mPointSize; if (aLayerPointSize == 0) { aCharWidth = (int)(anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) theChar].mWidth * mScale); if (thePrevChar != 0) { aSpacing = (int)((anActiveFontLayer->mBaseFontLayer->mSpacing + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) thePrevChar].mKerningOffsets[(uchar) theChar]) * mScale); } else aSpacing = 0; } else { aCharWidth = (int)(anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) theChar].mWidth * aPointSize / aLayerPointSize); if (thePrevChar != 0) { aSpacing = (int)((anActiveFontLayer->mBaseFontLayer->mSpacing + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) thePrevChar].mKerningOffsets[(uchar) theChar]) * aPointSize / aLayerPointSize); } else aSpacing = 0; } aLayerXPos += aCharWidth + aSpacing; if (aLayerXPos > aMaxXPos) aMaxXPos = aLayerXPos; ++anItr; } return aMaxXPos; } int ImageFont::CharWidth(char theChar) { return CharWidthKern(theChar,0); } #if 0 CritSect gRenderCritSec; #endif static const int POOL_SIZE = 4096; static RenderCommand gRenderCommandPool[POOL_SIZE]; static RenderCommand* gRenderTail[256]; static RenderCommand* gRenderHead[256]; void ImageFont::DrawStringEx(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect* theClipRect, RectList* theDrawnAreas, int* theWidth) { #if 0 AutoCrit anAutoCrit(gRenderCritSec); #endif int aPoolIdx; for (aPoolIdx = 0; aPoolIdx < 256; aPoolIdx++) { gRenderHead[aPoolIdx] = NULL; gRenderTail[aPoolIdx] = NULL; } int aXPos = theX; if (theDrawnAreas != NULL) theDrawnAreas->clear(); if (!mFontData->mInitialized) { if (theWidth != NULL) *theWidth = 0; return; } Prepare(); bool colorizeImages = g->GetColorizeImages(); g->SetColorizeImages(true); int aCurXPos = theX; int aCurPoolIdx = 0; for (uint32_t aCharNum = 0; aCharNum < theString.length(); aCharNum++) { char aChar = mFontData->mCharMap[(uchar) theString[aCharNum]]; char aNextChar = 0; if (aCharNum < theString.length() - 1) aNextChar = mFontData->mCharMap[(uchar) theString[aCharNum+1]]; int aMaxXPos = aCurXPos; ActiveFontLayerList::iterator anItr = mActiveLayerList.begin(); while (anItr != mActiveLayerList.end()) { ActiveFontLayer* anActiveFontLayer = &*anItr; int aLayerXPos = aCurXPos; int anImageX; int anImageY; int aCharWidth; int aSpacing; int aLayerPointSize = anActiveFontLayer->mBaseFontLayer->mPointSize; double aScale = mScale; if (aLayerPointSize != 0) aScale *= mPointSize / aLayerPointSize; if (aScale == 1.0) { anImageX = aLayerXPos + anActiveFontLayer->mBaseFontLayer->mOffset.mX + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mOffset.mX; anImageY = theY - (anActiveFontLayer->mBaseFontLayer->mAscent - anActiveFontLayer->mBaseFontLayer->mOffset.mY - anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mOffset.mY); aCharWidth = anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mWidth; if (aNextChar != 0) { aSpacing = anActiveFontLayer->mBaseFontLayer->mSpacing + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mKerningOffsets[(uchar) aNextChar]; } else aSpacing = 0; } else { anImageX = aLayerXPos + (int) ((anActiveFontLayer->mBaseFontLayer->mOffset.mX + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mOffset.mX) * aScale); anImageY = theY - (int) ((anActiveFontLayer->mBaseFontLayer->mAscent - anActiveFontLayer->mBaseFontLayer->mOffset.mY - anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mOffset.mY) * aScale); aCharWidth = (int)(anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mWidth * aScale); if (aNextChar != 0) { aSpacing = (int) ((anActiveFontLayer->mBaseFontLayer->mSpacing + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mKerningOffsets[(uchar) aNextChar]) * aScale); } else aSpacing = 0; } Color aColor; aColor.mRed = std::min((theColor.mRed * anActiveFontLayer->mBaseFontLayer->mColorMult.mRed / 255) + anActiveFontLayer->mBaseFontLayer->mColorAdd.mRed, 255); aColor.mGreen = std::min((theColor.mGreen * anActiveFontLayer->mBaseFontLayer->mColorMult.mGreen / 255) + anActiveFontLayer->mBaseFontLayer->mColorAdd.mGreen, 255); aColor.mBlue = std::min((theColor.mBlue * anActiveFontLayer->mBaseFontLayer->mColorMult.mBlue / 255) + anActiveFontLayer->mBaseFontLayer->mColorAdd.mBlue, 255); aColor.mAlpha = std::min((theColor.mAlpha * anActiveFontLayer->mBaseFontLayer->mColorMult.mAlpha / 255) + anActiveFontLayer->mBaseFontLayer->mColorAdd.mAlpha, 255); int anOrder = anActiveFontLayer->mBaseFontLayer->mBaseOrder + anActiveFontLayer->mBaseFontLayer->mCharData[(uchar) aChar].mOrder; if (aCurPoolIdx >= POOL_SIZE) break; RenderCommand* aRenderCommand = &gRenderCommandPool[aCurPoolIdx++]; aRenderCommand->mImage = anActiveFontLayer->mScaledImage; aRenderCommand->mColor = aColor; aRenderCommand->mDest[0] = anImageX; aRenderCommand->mDest[1] = anImageY; aRenderCommand->mSrc[0] = anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mX; aRenderCommand->mSrc[1] = anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mY; aRenderCommand->mSrc[2] = anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mWidth; aRenderCommand->mSrc[3] = anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mHeight; aRenderCommand->mMode = anActiveFontLayer->mBaseFontLayer->mDrawMode; aRenderCommand->mNext = NULL; int anOrderIdx = std::min(std::max(anOrder + 128, 0), 255); if (gRenderTail[anOrderIdx] == NULL) { gRenderTail[anOrderIdx] = aRenderCommand; gRenderHead[anOrderIdx] = aRenderCommand; } else { gRenderTail[anOrderIdx]->mNext = aRenderCommand; gRenderTail[anOrderIdx] = aRenderCommand; } if (theDrawnAreas != NULL) { Rect aDestRect = Rect(anImageX, anImageY, anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mWidth, anActiveFontLayer->mScaledCharImageRects[(uchar) aChar].mHeight); theDrawnAreas->push_back(aDestRect); } aLayerXPos += aCharWidth + aSpacing; if (aLayerXPos > aMaxXPos) aMaxXPos = aLayerXPos; ++anItr; } aCurXPos = aMaxXPos; } if (theWidth != NULL) *theWidth = aCurXPos - theX; Color anOrigColor = g->GetColor(); for (aPoolIdx = 0; aPoolIdx < 256; aPoolIdx++) { RenderCommand* aRenderCommand = gRenderHead[aPoolIdx]; while (aRenderCommand != NULL) { int anOldDrawMode = g->GetDrawMode(); if (aRenderCommand->mMode != -1) g->SetDrawMode(aRenderCommand->mMode); g->SetColor(Color(aRenderCommand->mColor)); if (aRenderCommand->mImage != NULL) g->DrawImage(aRenderCommand->mImage, aRenderCommand->mDest[0], aRenderCommand->mDest[1], Rect(aRenderCommand->mSrc[0], aRenderCommand->mSrc[1], aRenderCommand->mSrc[2], aRenderCommand->mSrc[3])); g->SetDrawMode(anOldDrawMode); aRenderCommand = aRenderCommand->mNext; } } g->SetColor(anOrigColor); g->SetColorizeImages(colorizeImages); } void ImageFont::DrawString(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect& theClipRect) { DrawStringEx(g, theX, theY, theString, theColor, &theClipRect, NULL, NULL); } Font* ImageFont::Duplicate() { return new ImageFont(*this); } void ImageFont::SetPointSize(int thePointSize) { mPointSize = thePointSize; mActiveListValid = false; } void ImageFont::SetScale(double theScale) { mScale = theScale; mActiveListValid = false; } int ImageFont::GetPointSize() { return mPointSize; } int ImageFont::GetDefaultPointSize() { return mFontData->mDefaultPointSize; } bool ImageFont::AddTag(const std::string& theTagName) { if (HasTag(theTagName)) return false; std::string aTagName = StringToUpper(theTagName); mTagVector.push_back(aTagName); mActiveListValid = false; return true; } bool ImageFont::RemoveTag(const std::string& theTagName) { std::string aTagName = StringToUpper(theTagName); StringVector::iterator anItr = std::find(mTagVector.begin(), mTagVector.end(), aTagName); if (anItr == mTagVector.end()) return false; mTagVector.erase(anItr); mActiveListValid = false; return true; } bool ImageFont::HasTag(const std::string& theTagName) { StringVector::iterator anItr = std::find(mTagVector.begin(), mTagVector.end(), theTagName); return anItr != mTagVector.end(); } std::string ImageFont::GetDefine(const std::string& theName) { DataElement* aDataElement = mFontData->Dereference(theName); if (aDataElement == NULL) return ""; return mFontData->DataElementToString(aDataElement); } void ImageFont::Prepare() { if (!mActiveListValid) { GenerateActiveFontLayers(); mActiveListValid = true; } } libtuxcap-1.4.0/tuxcap/lib/MTRand.cpp0000644000175000017500000001216611202747626017307 0ustar inniyahinniyah/* Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The names of its contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Any feedback is very welcome. http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ #include "MTRand.h" #if 0 #include "Debug.h" #endif #include #include #include using namespace Sexy; /* Period parameters */ #define MTRAND_M 397 #define MATRIX_A 0x9908b0dfUL /* constant vector a */ #define UPPER_MASK 0x80000000UL /* most significant w-r bits */ #define LOWER_MASK 0x7fffffffUL /* least significant r bits */ /* Tempering parameters */ #define TEMPERING_MASK_B 0x9d2c5680 #define TEMPERING_MASK_C 0xefc60000 #define TEMPERING_SHIFT_U(y) (y >> 11) #define TEMPERING_SHIFT_S(y) (y << 7) #define TEMPERING_SHIFT_T(y) (y << 15) #define TEMPERING_SHIFT_L(y) (y >> 18) MTRand::MTRand(const std::string& theSerialData) { SRand(theSerialData); mti=MTRAND_N+1; /* mti==MTRAND_N+1 means mt[MTRAND_N] is not initialized */ } MTRand::MTRand(uint32_t seed) { SRand(seed); } MTRand::MTRand() { SRand(4357); } static int gRandAllowed = 0; void MTRand::SetRandAllowed(bool allowed) { if (allowed) { if (gRandAllowed>0) gRandAllowed--; else assert(false); // mismatched calls } else gRandAllowed++; } void MTRand::SRand(const std::string& theSerialData) { if (theSerialData.size() == MTRAND_N*4) { memcpy(mt, theSerialData.c_str(), MTRAND_N*4); } else SRand(4357); } void MTRand::SRand(uint32_t seed) { if (seed == 0) seed = 4357; /* setting initial seeds to mt[MTRAND_N] using */ /* the generator Line 25 of Table 1 in */ /* [KNUTH 1981, The Art of Computer Programming */ /* Vol. 2 (2nd Ed.), pp102] */ mt[0]= seed & 0xffffffffUL; for (mti=1; mti< MTRAND_N; mti++) { mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti); /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ /* 2002/01/09 modified by Makoto Matsumoto */ mt[mti] &= 0xffffffffUL; /* for >32 bit machines */ } } uint32_t MTRand::Next() { assert(gRandAllowed==0); return NextNoAssert(); } uint32_t MTRand::NextNoAssert() { uint32_t y; static uint32_t mag01[2]={0x0, MATRIX_A}; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (mti >= MTRAND_N) { /* generate MTRAND_N words at one time */ int kk; for (kk=0;kk> 1) ^ mag01[y & 0x1UL]; } for (;kk> 1) ^ mag01[y & 0x1UL]; } y = (mt[MTRAND_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK); mt[MTRAND_N-1] = mt[MTRAND_M-1] ^ (y >> 1) ^ mag01[y & 0x1UL]; mti = 0; } y = mt[mti++]; y ^= TEMPERING_SHIFT_U(y); y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B; y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C; y ^= TEMPERING_SHIFT_L(y); y &= 0x7FFFFFFF; /*char aStr[256]; sprintf(aStr, "Rand=%d\r\n", y); OutputDebugString(aStr);*/ return y; } uint32_t MTRand::NextNoAssert(uint32_t range) { return NextNoAssert() % range; } uint32_t MTRand::Next(uint32_t range) { assert(gRandAllowed==0); return NextNoAssert( range ); } float MTRand::NextNoAssert(float range) { return (float) ((double)NextNoAssert() / (double)0x7FFFFFFF * range); } float MTRand::Next(float range) { assert(gRandAllowed==0); return NextNoAssert(range); } std::string MTRand::Serialize() { std::string aString; aString.resize(MTRAND_N*4); memcpy((char*) aString.c_str(), mt, MTRAND_N*4); return aString; } libtuxcap-1.4.0/tuxcap/lib/Font.cpp0000644000175000017500000000211310641010435017042 0ustar inniyahinniyah#include "Font.h" #include "Image.h" using namespace Sexy; Font::Font() { mAscent = 0; mHeight = 0; mAscentPadding = 0; mLineSpacingOffset = 0; } Font::Font(const Font& theFont) : mAscent(theFont.mAscent), mHeight(theFont.mHeight), mAscentPadding(theFont.mAscentPadding), mLineSpacingOffset(theFont.mLineSpacingOffset) { } Font::~Font() { } int Font::GetAscent() { return mAscent; } int Font::GetAscentPadding() { return mAscentPadding; } int Font::GetDescent() { return mHeight - mAscent; } int Font::GetHeight() { return mHeight; } int Font::GetLineSpacingOffset() { return mLineSpacingOffset; } int Font::GetLineSpacing() { return mHeight + mLineSpacingOffset; } int Font::StringWidth(const SexyString& theString) { return 0; } int Font::CharWidth(SexyChar theChar) { SexyString aString(1, theChar); return StringWidth(aString); } int Font::CharWidthKern(SexyChar theChar, SexyChar thePrevChar) { return CharWidth(theChar); } void Font::DrawString(Graphics* g, int theX, int theY, const SexyString& theString, const Color& theColor, const Rect& theClipRect) { } libtuxcap-1.4.0/tuxcap/lib/AudiereMusicInterface.cpp0000644000175000017500000002215310766713353022363 0ustar inniyahinniyah/* Original Audiere Music Interface by Rheenen 2005 */ #include "AudiereMusicInterface.h" #include "AudiereLoader.h" #include "SexyAppBase.h" using namespace Sexy; using namespace audiere; AudiereMusicInfo::AudiereMusicInfo() { mStream = NULL; mMIDIStream = NULL; mVolume = 0.0; mVolumeAdd = 0.0; mVolumeCap = 1.0; mStopOnFade = false; mRepeats = false; mPosition = 0; } AudiereMusicInterface::AudiereMusicInterface(HWND theHWnd) { mDevice = getAudiereDevice(); mMIDIDevice = getAudiereMIDIDevice(); mMasterVolume = 1.0; } AudiereMusicInterface::~AudiereMusicInterface() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mStream = NULL; aMusicInfo->mMIDIStream = NULL; ++anItr; } } bool AudiereMusicInterface::LoadMusic(int theSongId, const std::string& theFileName) { AudiereMusicInfo aMusicInfo; if (theFileName.find(".mid") != std::string::npos) { aMusicInfo.mMIDIStream = mMIDIDevice->openStream(theFileName.c_str()); if (aMusicInfo.mMIDIStream) return false; } else { aMusicInfo.mStream = OpenSound(mDevice, theFileName.c_str(), true); if (!aMusicInfo.mStream) return false; } mMusicMap.insert(AudiereMusicMap::value_type(theSongId, aMusicInfo)); return true; } void AudiereMusicInterface::UnloadMusic(int theSongId) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mStream->stop(); aMusicInfo->mStream = NULL; } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->stop(); aMusicInfo->mMIDIStream = NULL; } mMusicMap.erase(anItr); } } void AudiereMusicInterface::UnloadAllMusic() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mStream->stop(); aMusicInfo->mStream = NULL; } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->stop(); aMusicInfo->mMIDIStream = NULL; } ++anItr; } mMusicMap.clear(); } void AudiereMusicInterface::PauseAllMusic() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mPosition = aMusicInfo->mStream->getPosition(); aMusicInfo->mStream->stop(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mPosition = aMusicInfo->mMIDIStream->getPosition(); aMusicInfo->mMIDIStream->pause(); } ++anItr; } } void AudiereMusicInterface::ResumeAllMusic() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mStream->play(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->setPosition(aMusicInfo->mPosition); aMusicInfo->mMIDIStream->play(); } ++anItr; } } void AudiereMusicInterface::PlayMusic(int theSongId, int theOffset, bool noLoop) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolume = aMusicInfo->mVolumeCap; aMusicInfo->mVolumeAdd = 0.0f; if (aMusicInfo->mStream) { OutputStreamPtr aStream = aMusicInfo->mStream; aStream->setVolume(float(mMasterVolume * aMusicInfo->mVolume)); aStream->setRepeat(!noLoop); if (theOffset != 0) aStream->setPosition(theOffset); aStream->play(); } else if (aMusicInfo->mMIDIStream) { MIDIStreamPtr aStream = aMusicInfo->mMIDIStream; aStream->setRepeat(!noLoop); if (theOffset != 0) aStream->setPosition(theOffset); aStream->play(); } } } void AudiereMusicInterface::PauseMusic(int theSongId) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mPosition = aMusicInfo->mStream->getPosition(); aMusicInfo->mStream->stop(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mPosition = aMusicInfo->mMIDIStream->getPosition(); aMusicInfo->mMIDIStream->pause(); } } } void AudiereMusicInterface::ResumeMusic(int theSongId) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mStream->play(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->setPosition(aMusicInfo->mPosition); aMusicInfo->mMIDIStream->play(); } } } void AudiereMusicInterface::StopMusic(int theSongId) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { aMusicInfo->mStream->stop(); aMusicInfo->mStream->reset(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->stop(); } aMusicInfo->mPosition = 0; } } void AudiereMusicInterface::StopAllMusic() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolume = 0.0; if (aMusicInfo->mStream) { aMusicInfo->mStream->stop(); aMusicInfo->mStream->reset(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->stop(); } aMusicInfo->mPosition = 0; ++anItr; } } void AudiereMusicInterface::FadeIn(int theSongId, int theOffset, double theSpeed, bool noLoop) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolumeAdd = (float)theSpeed * 10.0f; if (aMusicInfo->mStream) { aMusicInfo->mStream->setVolume(float(mMasterVolume * aMusicInfo->mVolume)); aMusicInfo->mStream->setRepeat(!noLoop); if (theOffset != 0) aMusicInfo->mStream->setPosition(theOffset); aMusicInfo->mStream->play(); } else if (aMusicInfo->mMIDIStream) { aMusicInfo->mMIDIStream->setRepeat(!noLoop); if (theOffset != 0) aMusicInfo->mMIDIStream->setPosition(theOffset); aMusicInfo->mMIDIStream->play(); } } } void AudiereMusicInterface::FadeOut(int theSongId, bool stopSong, double theSpeed) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolumeAdd = -(float)theSpeed * 10.0f; aMusicInfo->mStopOnFade = stopSong; } } void AudiereMusicInterface::FadeOutAll(bool stopSong, double theSpeed) { AudiereMusicMap::iterator anItr = mMusicMap.begin(); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolumeAdd = -(float)theSpeed * 10.0f; aMusicInfo->mStopOnFade = stopSong; ++anItr; } } void AudiereMusicInterface::SetVolume(double theVolume) { mMasterVolume = (float)theVolume; AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { // aMusicInfo->mStream->stop(); //aMusicInfo->mStream->reset(); aMusicInfo->mStream->setVolume(mMasterVolume * aMusicInfo->mVolume); } ++anItr; } } void AudiereMusicInterface::SetSongVolume(int theSongId, double theVolume) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; aMusicInfo->mVolume = (float)theVolume; if (aMusicInfo->mStream) { aMusicInfo->mStream->setVolume(mMasterVolume * aMusicInfo->mVolume); } } } bool AudiereMusicInterface::IsPlaying(int theSongId) { AudiereMusicMap::iterator anItr = mMusicMap.find(theSongId); if (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mStream) { return aMusicInfo->mStream->isPlaying(); } else if (aMusicInfo->mMIDIStream) { return aMusicInfo->mMIDIStream->isPlaying(); } } return false; } void AudiereMusicInterface::Update() { AudiereMusicMap::iterator anItr = mMusicMap.begin(); while (anItr != mMusicMap.end()) { AudiereMusicInfo* aMusicInfo = &anItr->second; if (aMusicInfo->mVolumeAdd != 0.0) { aMusicInfo->mVolume += aMusicInfo->mVolumeAdd; if (aMusicInfo->mVolume > aMusicInfo->mVolumeCap) { aMusicInfo->mVolume = aMusicInfo->mVolumeCap; aMusicInfo->mVolumeAdd = 0.0; } else if (aMusicInfo->mVolume < 0.0) { aMusicInfo->mVolume = 0.0; aMusicInfo->mVolumeAdd = 0.0; if (aMusicInfo->mStopOnFade) { if (aMusicInfo->mStream) { if (aMusicInfo->mStream->isPlaying()) { aMusicInfo->mStream->stop(); aMusicInfo->mStream->reset(); } } else if (aMusicInfo->mMIDIStream) { if (aMusicInfo->mMIDIStream->isPlaying()) { aMusicInfo->mMIDIStream->stop(); } } } } if (aMusicInfo->mStream) aMusicInfo->mStream->setVolume(mMasterVolume * aMusicInfo->mVolume); } ++anItr; } mDevice->update(); } libtuxcap-1.4.0/tuxcap/lib/Flags.cpp0000644000175000017500000000002410641010433017165 0ustar inniyahinniyah#include "Flags.h" libtuxcap-1.4.0/tuxcap/lib/SWTri_DrawTriangleInc1.cpp0000644000175000017500000002615510641010435022336 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. #define TRI0 0 #define TRI1 0 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #define TRI1 1 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #undef TRI0 #define TRI0 1 #define TRI1 0 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #define TRI1 1 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #undef TRI0 #define TRI0 2 #define TRI1 0 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #define TRI1 1 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #undef TRI0 #define TRI0 3 #define TRI1 0 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #define TRI1 1 #define TRI2 0 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #define TRI2 1 #define TRI3 0 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #define TRI3 1 #define TRI4 0 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #define TRI4 1 #define TRI5 0 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #define TRI5 1 #include "SWTri_DrawTriangle.cpp" #undef TRI5 #undef TRI4 #undef TRI3 #undef TRI2 #undef TRI1 #undef TRI0 libtuxcap-1.4.0/tuxcap/lib/D3DInterface.cpp0000644000175000017500000021426111212512234020337 0ustar inniyahinniyah#include "D3DInterface.h" #include "DDInterface.h" #include "Graphics.h" #include "Color.h" #if 0 #include "DirectXErrorString.h" #endif #include "SexyMatrix.h" #include "SexyAppBase.h" #include "TriVertex.h" #include #include using namespace Sexy; static int gMinTextureWidth; static int gMinTextureHeight; static int gMaxTextureWidth; static int gMaxTextureHeight; static int gMaxTextureAspectRatio; static Uint32 gSupportedPixelFormats; static bool gTextureSizeMustBePow2; static const int MAX_TEXTURE_SIZE = 1024; static bool gLinearFilter = false; #ifndef WIN32 typedef struct { GLfloat tu; GLfloat tv; SexyRGBA color; GLfloat sx; GLfloat sy; GLfloat sz; } D3DTLVERTEX; #endif std::string D3DInterface::mErrorString; #if 0 static const int gVertexType = D3DFVF_TLVERTEX; #endif static void SetLinearFilter(bool linearFilter) { if (gLinearFilter != linearFilter) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, linearFilter ? GL_LINEAR:GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, linearFilter ? GL_LINEAR:GL_NEAREST); gLinearFilter = linearFilter; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static SDL_Surface* CreateTextureSurface(int theWidth, int theHeight/*, PixelFormat theFormat*/) { SDL_Surface* aSurface = SDL_CreateRGBSurface( SDL_HWSURFACE, theWidth, theHeight, 32, SDL_rmask, SDL_gmask, SDL_bmask, SDL_amask); return aSurface; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static int GetClosestPowerOf2Above(int theNum) { int aPower2 = 1; while (aPower2 < theNum) aPower2<<=1; return aPower2; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static bool IsPowerOf2(int theNum) { int aNumBits = 0; while (theNum>0) { aNumBits += theNum&1; theNum >>= 1; } return aNumBits==1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyImageToSurface8888(void *theDest, Uint32 theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight, bool rightPad) { if (theImage->mColorTable == NULL) { uint32_t *srcRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; char *dstRow = (char*)theDest; for(int y=0; yGetWidth(); dstRow += theDestPitch; } } else // palette { uchar *srcRow = (uchar*)theImage->mColorIndices + offy * theImage->GetWidth() + offx; uchar *dstRow = (uchar*)theDest; uint32_t *palette = theImage->mColorTable; for(int y=0; yGetWidth(); dstRow += theDestPitch; } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyImageToSurface(MemoryImage *theImage, SDL_Surface* surface, int offx, int offy, int texWidth, int texHeight) { if (surface==NULL) return; int aWidth = std::min(texWidth,(theImage->GetWidth()-offx)); int aHeight = std::min(texHeight,(theImage->GetHeight()-offy)); bool rightPad = aWidth0 && aHeight>0) { CopyImageToSurface8888((Uint32*)surface->pixels, surface->pitch, theImage, offx, offy, aWidth, aHeight, rightPad); } if (bottomPad) { uchar *dstrow = ((uchar*)surface->pixels)+surface->pitch*aHeight; memcpy(dstrow,dstrow-surface->pitch,surface->pitch); } } /* original taken from a post by Sam Lantinga, thanks Sam for this and for SDL :-)*/ static GLuint CreateTexture(MemoryImage* memImage, int x, int y, int width, int height) { GLuint texture; int w, h; static SDL_Surface *image = NULL; /* Use the texture width and height expanded to powers of 2 */ w = GetClosestPowerOf2Above(width); h = GetClosestPowerOf2Above(height); if (image != NULL) { if (image->w != w || image-> h != h) { SDL_FreeSurface(image); image = SDL_CreateRGBSurface( SDL_HWSURFACE, w, h, 32, SDL_bmask, SDL_gmask, SDL_rmask, SDL_amask ); assert(image != NULL ); } else { //FIXME maybe better to clear the current image just in case } } else { image = SDL_CreateRGBSurface( SDL_HWSURFACE, w, h, 32, SDL_bmask, SDL_gmask, SDL_rmask, SDL_amask ); assert(image != NULL ); } CopyImageToSurface(memImage, image, x, y, w, h); /* Create an OpenGL texture for the image */ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, image->pixels); return texture; } void D3DInterface::FillOldCursorAreaTexture(GLint x, GLint y) { glBindTexture(GL_TEXTURE_2D, custom_cursor_texture); glCopyTexSubImage2D(GL_TEXTURE_2D, 0,0,0,x,y,64,64); } void D3DInterface::BltOldCursorArea(GLfloat x, GLfloat y, const Color& theColor) { glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); SetLinearFilter(false); SexyRGBA rgba = theColor.ToRGBA(); glColor4ub(rgba.r, rgba.g, rgba.b, rgba.a); glBindTexture(GL_TEXTURE_2D, custom_cursor_texture); glBegin(GL_QUADS); glTexCoord2f(0.0f, 1.0f); glVertex2f(x,y); glTexCoord2f(0.0f, 0.0f); glVertex2f(x,y + 64); glTexCoord2f(1.0f, 0.0f); glVertex2f(x + 64,y + 64); glTexCoord2f(1.0f,1.0f); glVertex2f(x+64,y); glEnd(); glEnable(GL_BLEND); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopySurface8888ToImage(void *theDest, Uint32 theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight) { char *srcRow = (char*)theDest; uint32_t *dstRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; for(int y=0; yGetWidth(); srcRow += theDestPitch; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void GetBestTextureDimensions(int &theWidth, int &theHeight, bool isEdge, bool usePow2, Uint32 theImageFlags) { if (theImageFlags & D3DImageFlag_Use64By64Subdivisions) { theWidth = theHeight = 64; return; } static int aGoodTextureSize[MAX_TEXTURE_SIZE]; static bool haveInited = false; if (!haveInited) { haveInited = true; int i; int aPow2 = 1; for (i=0; i aPow2) aPow2 <<= 1; int aGoodValue = aPow2; if ((aGoodValue - i ) > 64) { aGoodValue >>= 1; while (true) { int aLeftOver = i % aGoodValue; if (aLeftOver<64 || IsPowerOf2(aLeftOver)) break; aGoodValue >>= 1; } } aGoodTextureSize[i] = aGoodValue; } } int aWidth = theWidth; int aHeight = theHeight; if (usePow2) { if (isEdge || (theImageFlags & D3DImageFlag_MinimizeNumSubdivisions)) { aWidth = aWidth >= gMaxTextureWidth ? gMaxTextureWidth : GetClosestPowerOf2Above(aWidth); aHeight = aHeight >= gMaxTextureHeight ? gMaxTextureHeight : GetClosestPowerOf2Above(aHeight); } else { aWidth = aWidth >= gMaxTextureWidth ? gMaxTextureWidth : aGoodTextureSize[aWidth]; aHeight = aHeight >= gMaxTextureHeight ? gMaxTextureHeight : aGoodTextureSize[aHeight]; } } if (aWidth < gMinTextureWidth) aWidth = gMinTextureWidth; if (aHeight < gMinTextureHeight) aHeight = gMinTextureHeight; if (aWidth > aHeight) { while (aWidth > gMaxTextureAspectRatio*aHeight) aHeight <<= 1; } else if (aHeight > aWidth) { while (aHeight > gMaxTextureAspectRatio*aWidth) aWidth <<= 1; } theWidth = aWidth; theHeight = aHeight; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// TextureData::TextureData() { mWidth = 0; mHeight = 0; mTexVecWidth = 0; mTexVecHeight = 0; mBitsChangedCount = 0; mTexMemSize = 0; mTexPieceWidth = 64; mTexPieceHeight = 64; #if 0 mPalette = NULL; #endif mPixelFormat = PixelFormat_Unknown; mImageFlags = 0; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// TextureData::~TextureData() { ReleaseTextures(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::ReleaseTextures() { for(int i=0; i<(int)mTextures.size(); i++) { // if (glIsTexture(mTextures[i].mTexture) == GL_TRUE) glDeleteTextures(1, &mTextures[i].mTexture); } mTextures.clear(); mTexMemSize = 0; #if 0 if (mPalette!=NULL) { mPalette->Release(); mPalette = NULL; } #endif } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::CreateTextureDimensions(MemoryImage *theImage) { int aWidth = theImage->GetWidth(); int aHeight = theImage->GetHeight(); int i; /**/ // Calculate inner piece sizes mTexPieceWidth = aWidth; mTexPieceHeight = aHeight; bool usePow2 = true; //gTextureSizeMustBePow2 || mPixelFormat==PixelFormat_Palette8; GetBestTextureDimensions(mTexPieceWidth, mTexPieceHeight,false,usePow2,mImageFlags); // Calculate right boundary piece sizes int aRightWidth = aWidth%mTexPieceWidth; int aRightHeight = mTexPieceHeight; if (aRightWidth > 0) GetBestTextureDimensions(aRightWidth, aRightHeight,true,usePow2,mImageFlags); else aRightWidth = mTexPieceWidth; // Calculate bottom boundary piece sizes int aBottomWidth = mTexPieceWidth; int aBottomHeight = aHeight%mTexPieceHeight; if (aBottomHeight > 0) GetBestTextureDimensions(aBottomWidth, aBottomHeight,true,usePow2,mImageFlags); else aBottomHeight = mTexPieceHeight; // Calculate corner piece size int aCornerWidth = aRightWidth; int aCornerHeight = aBottomHeight; GetBestTextureDimensions(aCornerWidth, aCornerHeight,true,usePow2,mImageFlags); /**/ // Allocate texture array mTexVecWidth = (aWidth + mTexPieceWidth - 1)/mTexPieceWidth; mTexVecHeight = (aHeight + mTexPieceHeight - 1)/mTexPieceHeight; mTextures.resize(mTexVecWidth*mTexVecHeight); // Assign inner pieces for(i=0; i<(int)mTextures.size(); i++) { TextureDataPiece &aPiece = mTextures[i]; aPiece.mTexture = 0; aPiece.mWidth = mTexPieceWidth; aPiece.mHeight = mTexPieceHeight; } // Assign right pieces /**/ for(i=mTexVecWidth-1; i<(int)mTextures.size(); i+=mTexVecWidth) { TextureDataPiece &aPiece = mTextures[i]; aPiece.mWidth = aRightWidth; aPiece.mHeight = aRightHeight; } // Assign bottom pieces for(i=mTexVecWidth*(mTexVecHeight-1); i<(int)mTextures.size(); i++) { TextureDataPiece &aPiece = mTextures[i]; aPiece.mWidth = aBottomWidth; aPiece.mHeight = aBottomHeight; } // Assign corner piece mTextures.back().mWidth = aCornerWidth; mTextures.back().mHeight = aCornerHeight; /**/ mMaxTotalU = aWidth/(float)mTexPieceWidth; mMaxTotalV = aHeight/(float)mTexPieceHeight; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// GLuint TextureData::GetTexture(int x, int y, int &width, int &height, float &u1, float &v1, float &u2, float &v2) { int tx = x/mTexPieceWidth; int ty = y/mTexPieceHeight; TextureDataPiece &aPiece = mTextures[ty*mTexVecWidth + tx]; int left = x%mTexPieceWidth; int top = y%mTexPieceHeight; int right = left+width; int bottom = top+height; if(right > aPiece.mWidth) right = aPiece.mWidth; if(bottom > aPiece.mHeight) bottom = aPiece.mHeight; width = right-left; height = bottom-top; u1 = left/(float)aPiece.mWidth; v1 = top/(float)aPiece.mHeight; u2 = right/(float)aPiece.mWidth; v2 = bottom/(float)aPiece.mHeight; return aPiece.mTexture; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// GLuint TextureData::GetTextureF(float x, float y, float &width, float &height, float &u1, float &v1, float &u2, float &v2) { int tx = (int)(x/mTexPieceWidth); int ty = (int)(y/mTexPieceHeight); TextureDataPiece &aPiece = mTextures[ty*mTexVecWidth + tx]; float left = x - tx*mTexPieceWidth; float top = y - ty*mTexPieceHeight; float right = left+width; float bottom = top+height; if(right > aPiece.mWidth) right = aPiece.mWidth; if(bottom > aPiece.mHeight) bottom = aPiece.mHeight; width = right-left; height = bottom-top; u1 = left/aPiece.mWidth; v1 = top/aPiece.mHeight; u2 = right/aPiece.mWidth; v2 = bottom/aPiece.mHeight; return aPiece.mTexture; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::CreateTextures(MemoryImage *theImage) { theImage->DeleteSWBuffers(); // don't need these buffers for 3d drawing theImage->CommitBits(); // Release texture if image size has changed bool createTextures = false; if (mWidth!=theImage->mWidth || mHeight!=theImage->mHeight || theImage->mD3DFlags!=mImageFlags) { ReleaseTextures(); mImageFlags = theImage->mD3DFlags; CreateTextureDimensions(theImage); createTextures = true; } int i,x,y; int aHeight = theImage->GetHeight(); int aWidth = theImage->GetWidth(); int aFormatSize = 4; #if 0 if (aFormat==PixelFormat_Palette8) aFormatSize = 1; else if (aFormat==PixelFormat_R5G6B5) aFormatSize = 2; else if (aFormat==PixelFormat_A4R4G4B4) aFormatSize = 2; #endif i=0; for(y=0; ySetPalette(mPalette); #endif mTexMemSize += aPiece.mWidth*aPiece.mHeight*aFormatSize; } } } mWidth = theImage->mWidth; mHeight = theImage->mHeight; mBitsChangedCount = theImage->mBitsChangedCount; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::CheckCreateTextures(MemoryImage *theImage) { if(theImage->mWidth != mWidth || theImage->mHeight != mHeight || theImage->mBitsChangedCount != mBitsChangedCount || theImage->mD3DFlags != mImageFlags) CreateTextures(theImage); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::Blt(float theX, float theY, const Rect& theSrcRect, const Color& theColor) { glEnable(GL_TEXTURE_2D); int srcLeft = theSrcRect.mX; int srcTop = theSrcRect.mY; int srcRight = srcLeft + theSrcRect.mWidth; int srcBottom = srcTop + theSrcRect.mHeight; int srcX, srcY; float dstX, dstY; int aWidth,aHeight; float u1,v1,u2,v2; srcY = srcTop; dstY = theY; SexyRGBA rgba = theColor.ToRGBA(); glColor4ub(rgba.r, rgba.g, rgba.b, rgba.a); if ((srcLeft >= srcRight) || (srcTop >= srcBottom)) return; while(srcY < srcBottom) { srcX = srcLeft; dstX = theX; while(srcX < srcRight) { aWidth = srcRight-srcX; aHeight = srcBottom-srcY; GLuint aTexture = GetTexture(srcX, srcY, aWidth, aHeight, u1, v1, u2, v2); float x = dstX;// - 0.5f; float y = dstY;// 0.5f; glBindTexture(GL_TEXTURE_2D, aTexture); glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(u1, v1); glVertex2f(x,y); glTexCoord2f(u1, v2); glVertex2f(x,y + aHeight); glTexCoord2f(u2, v1); glVertex2f(x + aWidth,y); glTexCoord2f(u2, v2); glVertex2f(x + aWidth,y + aHeight); glEnd(); srcX += aWidth; dstX += aWidth; } srcY += aHeight; dstY += aHeight; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// struct VertexList { enum { MAX_STACK_VERTS = 100 }; D3DTLVERTEX mStackVerts[MAX_STACK_VERTS]; D3DTLVERTEX *mVerts; int mSize; int mCapacity; typedef int size_type; VertexList() : mSize(0), mCapacity(MAX_STACK_VERTS), mVerts(mStackVerts) { } VertexList(const VertexList &theList) : mSize(theList.mSize), mCapacity(MAX_STACK_VERTS), mVerts(mStackVerts) { reserve(mSize); memcpy(mVerts,theList.mVerts,mSize*sizeof(mVerts[0])); } ~VertexList() { if (mVerts != mStackVerts) delete mVerts; } void reserve(int theCapacity) { if (mCapacity < theCapacity) { mCapacity = theCapacity; D3DTLVERTEX *aNewList = new D3DTLVERTEX[theCapacity]; memcpy(aNewList,mVerts,mSize*sizeof(mVerts[0])); if (mVerts != mStackVerts) delete mVerts; mVerts = aNewList; } } void push_back(const D3DTLVERTEX &theVert) { if (mSize==mCapacity) reserve(mCapacity*2); mVerts[mSize++] = theVert; } void operator=(const VertexList &theList) { reserve(theList.mSize); mSize = theList.mSize; memcpy(mVerts,theList.mVerts,mSize*sizeof(mVerts[0])); } D3DTLVERTEX& operator[](int thePos) { return mVerts[thePos]; } int size() { return mSize; } void clear() { mSize = 0; } }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static inline float GetCoord(const D3DTLVERTEX &theVertex, int theCoord) { switch (theCoord) { case 0: return theVertex.sx; case 1: return theVertex.sy; case 2: return theVertex.sz; case 3: return theVertex.tu; case 4: return theVertex.tv; default: return 0; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static inline D3DTLVERTEX Interpolate(const D3DTLVERTEX &v1, const D3DTLVERTEX &v2, float t) { D3DTLVERTEX aVertex = v1; aVertex.sx = v1.sx + t*(v2.sx-v1.sx); aVertex.sy = v1.sy + t*(v2.sy-v1.sy); aVertex.tu = v1.tu + t*(v2.tu-v1.tu); aVertex.tv = v1.tv + t*(v2.tv-v1.tv); if (v1.color!=v2.color) //FIXME check all members individually { int r = v1.color.r + (int)(t*(v2.color.r - v1.color.r)); int g = v1.color.g +(int)( t*(v2.color.g - v1.color.g)); int b = v1.color.b + (int)(t*(v2.color.b - v1.color.b)); int a = v1.color.a + (int)(t*(v2.color.a - v1.color.a)); aVertex.color = Color(r,g,b,a).ToRGBA(); } return aVertex; } #if 0 /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void DisplayError(HRESULT theError, const char *theMsg) { static bool hadError = false; if (!hadError) { std::string aMsg; std::string anError = GetDirectXErrorString(theError); aMsg = theMsg; aMsg += ": "; aMsg += anError; hadError = true; int aResult = MessageBoxA(NULL,aMsg.c_str(),"Error",MB_ABORTRETRYIGNORE); if (aResult==IDABORT) exit(0); else if (aResult==IDRETRY) _asm int 3; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool D3DInterface::CheckDXError(HRESULT theError, const char *theMsg) { if(FAILED(theError)) { std::string aMsg; std::string anError = GetDirectXErrorString(theError); aMsg = theMsg; aMsg += ": "; aMsg += anError; mErrorString = aMsg; gSexyAppBase->RegistryWriteString("Test3D\\RuntimeError",aMsg); // DisplayError(theError,theMsg); return true; } else return false; } #endif /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// D3DInterface::D3DInterface() { #if 0 mHWnd = NULL; mDD = NULL; mD3D = NULL; mD3DDevice = NULL; #endif mWidth = 640; mHeight = 480; custom_cursor_texture = 0; mDDSDrawSurface = NULL; mZBuffer = NULL; mSceneBegun = false; mIsWindowed = true; gMinTextureWidth = 64; gMinTextureHeight = 64; gMaxTextureWidth = 64; gMaxTextureHeight = 64; gMaxTextureAspectRatio = 1; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// D3DInterface::~D3DInterface() { Cleanup(); } #if 0 /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::MakeDDPixelFormat(PixelFormat theFormatType, DDPIXELFORMAT* theFormat) { ZeroMemory(theFormat,sizeof(DDPIXELFORMAT)); theFormat->dwSize = sizeof(DDPIXELFORMAT); switch(theFormatType) { case PixelFormat_A8R8G8B8: theFormat->dwFlags = DDPF_ALPHAPIXELS | DDPF_RGB; theFormat->dwRGBBitCount = 32; theFormat->dwRGBAlphaBitMask = 0xFF000000; theFormat->dwRBitMask = 0x00FF0000; theFormat->dwGBitMask = 0x0000FF00; theFormat->dwBBitMask = 0x000000FF; break; case PixelFormat_A4R4G4B4: theFormat->dwFlags = DDPF_ALPHAPIXELS | DDPF_RGB; theFormat->dwRGBBitCount = 16; theFormat->dwRGBAlphaBitMask = 0xF000; theFormat->dwRBitMask = 0x0F00; theFormat->dwGBitMask = 0x00F0; theFormat->dwBBitMask = 0x000F; break; case PixelFormat_R5G6B5: theFormat->dwFlags = DDPF_RGB; theFormat->dwRGBBitCount = 16; theFormat->dwRBitMask = 0xF800; theFormat->dwGBitMask = 0x07E0; theFormat->dwBBitMask = 0x001F; break; case PixelFormat_Palette8: theFormat->dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8; theFormat->dwRGBBitCount = 8; break; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// PixelFormat D3DInterface::GetDDPixelFormat(LPDDPIXELFORMAT theFormat) { if (theFormat->dwFlags == (DDPF_ALPHAPIXELS | DDPF_RGB) && theFormat->dwRGBBitCount == 32 && theFormat->dwRGBAlphaBitMask == 0xFF000000 && theFormat->dwRBitMask == 0x00FF0000 && theFormat->dwGBitMask == 0x0000FF00 && theFormat->dwBBitMask == 0x000000FF) { return PixelFormat_A8R8G8B8; } if (theFormat->dwFlags == (DDPF_ALPHAPIXELS | DDPF_RGB) && theFormat->dwRGBBitCount == 16 && theFormat->dwRGBAlphaBitMask == 0xF000 && theFormat->dwRBitMask == 0x0F00 && theFormat->dwGBitMask == 0x00F0 && theFormat->dwBBitMask == 0x000F) { return PixelFormat_A4R4G4B4; } if (theFormat->dwFlags == DDPF_RGB && theFormat->dwRGBBitCount == 16 && theFormat->dwRGBAlphaBitMask == 0x0000 && theFormat->dwRBitMask == 0xF800 && theFormat->dwGBitMask == 0x07E0 && theFormat->dwBBitMask == 0x001F) { return PixelFormat_R5G6B5; } if (theFormat->dwFlags == (DDPF_RGB | DDPF_PALETTEINDEXED8) && theFormat->dwRGBBitCount == 8) { return PixelFormat_Palette8; } return PixelFormat_Unknown; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// HRESULT CALLBACK D3DInterface::PixelFormatsCallback(LPDDPIXELFORMAT theFormat, LPVOID lpContext) { gSupportedPixelFormats |= D3DInterface::GetDDPixelFormat(theFormat); return D3DENUMRET_OK; } #endif /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::UpdateViewport() { #if 0 HRESULT hr; RECT aRect; GetClientRect(mHWnd, &aRect); POINT aTopLeft = {aRect.left, aRect.top}; POINT aBotRight = {aRect.right, aRect.bottom}; ::ClientToScreen(mHWnd, &aTopLeft); ::ClientToScreen(mHWnd, &aBotRight); RECT aScreenRect = {aTopLeft.x, aTopLeft.y, aBotRight.x, aBotRight.y}; D3DVIEWPORT7 &aD3DViewport = mD3DViewport; aD3DViewport.dwX = 0; aD3DViewport.dwY = 0; aD3DViewport.dwWidth = aScreenRect.right - aScreenRect.left; aD3DViewport.dwHeight = aScreenRect.bottom - aScreenRect.top; aD3DViewport.dvMinZ = 0; //-2048.0f; aD3DViewport.dvMaxZ = 1; //2048.0f; hr = mD3DDevice->SetViewport(&mD3DViewport); #endif glViewport(0,0, gSexyAppBase->mWidth, gSexyAppBase->mHeight); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool D3DInterface::InitD3D() { GLint minimum_width = 1; GLint minimum_height = 1; while (true) { glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, minimum_width, minimum_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GLint width = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); GLint height = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); if (width == 0) minimum_width <<= 1; if (height == 0) minimum_height <<= 1; if (width != 0 && height != 0) break; } GLint try_width = minimum_width; GLint try_height = minimum_height; while (true) { glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, try_width << 1, try_height << 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GLint width = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); GLint height = 0; glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); if (width != 0) try_width <<= 1; if (height != 0) try_height <<= 1; if (width == 0 && height == 0) break; } gMinTextureWidth = minimum_width; gMinTextureHeight = minimum_height; gMaxTextureWidth = try_width; gMaxTextureHeight = try_height; //FIXME gMaxTextureAspectRatio = 1; if (gMaxTextureWidth > MAX_TEXTURE_SIZE) gMaxTextureWidth = MAX_TEXTURE_SIZE; if (gMaxTextureHeight > MAX_TEXTURE_SIZE) gMaxTextureHeight = MAX_TEXTURE_SIZE; if (gMaxTextureAspectRatio==0) gMaxTextureAspectRatio = 65536; #if 0 if (gMinTextureWidth > gMaxTextureWidth) gMinTextureWidth = 64; if (gMinTextureHeight > gMaxTextureHeight) gMinTextureHeight = 64; #endif #if 0 gSupportedPixelFormats = 0; mD3DDevice->EnumTextureFormats(PixelFormatsCallback,NULL); if (!(aCaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)) // need alpha in palettes gSupportedPixelFormats &= ~PixelFormat_Palette8; #endif // glEnable(GL_LINE_SMOOTH); glEnable(GL_BLEND); //glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE); glLineWidth (1.5); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glDisable(GL_NORMALIZE); glDisable(GL_CULL_FACE); glShadeModel (GL_FLAT); glReadBuffer(GL_BACK); glPixelStorei( GL_PACK_ROW_LENGTH, 0 ) ; glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ) ; glClear(GL_COLOR_BUFFER_BIT); glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glClearColor (0.0, 0.0, 0.0, 0.0); UpdateViewport(); glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluOrtho2D( 0, gSexyAppBase->mWidth, gSexyAppBase->mHeight, 0 ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity(); //create texture for mOldCursorArea glGenTextures(1, &custom_cursor_texture); glBindTexture(GL_TEXTURE_2D, custom_cursor_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); unsigned char tmp[64*64*4]; memset(tmp,0,64*64*4); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp); gLinearFilter = false; #if 0 // Create ZBuffer DDPIXELFORMAT ddpfZBuffer; mD3D->EnumZBufferFormats( IID_IDirect3DHALDevice, EnumZBufferCallback, (VOID*)&ddpfZBuffer ); DDSURFACEDESC2 ddsd; ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) ); ddsd.dwSize = sizeof(DDSURFACEDESC2); ddsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY; ddsd.dwWidth = mD3DViewport.dwWidth; ddsd.dwHeight = mD3DViewport.dwHeight; memcpy( &ddsd.ddpfPixelFormat, &ddpfZBuffer, sizeof(DDPIXELFORMAT) ); mD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET ,0xff000000, 1.0f, 0L); #endif return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool D3DInterface::InitFromDDInterface(DDInterface *theInterface) { mErrorString.erase(); #if 0 mDD = theInterface->mDD7; mHWnd = theInterface->mHWnd; #endif mWidth = theInterface->mWidth; mHeight = theInterface->mHeight; // mIsWindowed = true; //FIXME return InitD3D(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool gD3DInterfacePreDrawError = false; bool D3DInterface::PreDraw() { if (gSexyAppBase->mPhysMinimized) return false; if (!mSceneBegun) { #if 0 HRESULT hr; if (!SUCCEEDED(mD3DDevice->SetRenderTarget(mDDSDrawSurface, 0))) // this happens when there's been a mode switch (this caused the nvidia screensaver bluescreen) { gD3DInterfacePreDrawError = true; return false; } else #endif gD3DInterfacePreDrawError = false; #if 0 hr = mD3DDevice->BeginScene(); #endif #if 0 // alphablend states mD3DDevice->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE); mD3DDevice->SetRenderState(D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); mD3DDevice->SetRenderState(D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA); mD3DDevice->SetRenderState(D3DRENDERSTATE_LIGHTING , FALSE); // filter states mD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER, D3DTFG_POINT); mD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER, D3DTFG_POINT); mD3DDevice->SetTextureStageState(0,D3DTSS_MIPFILTER, D3DTFG_POINT); mD3DDevice->SetTextureStageState(0,D3DTSS_ALPHAOP, D3DTOP_MODULATE ); mD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP); hr = mD3DDevice->SetTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP); // Setup non-texture render states mD3DDevice->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE); mD3DDevice->SetRenderState(D3DRENDERSTATE_SPECULARENABLE, FALSE); mD3DDevice->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE); mD3DDevice->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE); hr = mD3DDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); #endif mSceneBegun = true; gLinearFilter = false; } return true; } #if 0 /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyImageToTexture4444(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight, bool rightPad) { if (theImage->mColorTable == NULL) { DWORD *srcRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; char *dstRow = (char*)theDest; for(int y=0; y>16)&0xF000) | ((aPixel>>12)&0x0F00) | ((aPixel>>8)&0x00F0) | ((aPixel>>4)&0x000F); } if (rightPad) *dst = *(dst-1); srcRow += theImage->GetWidth(); dstRow += theDestPitch; } } else // palette { uchar *srcRow = (uchar*)theImage->mColorIndices + offy * theImage->GetWidth() + offx; uchar *dstRow = (uchar*)theDest; DWORD *palette = theImage->mColorTable; for(int y=0; y>16)&0xF000) | ((aPixel>>12)&0x0F00) | ((aPixel>>8)&0x00F0) | ((aPixel>>4)&0x000F); } if (rightPad) *dst = *(dst-1); srcRow += theImage->GetWidth(); dstRow += theDestPitch; } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyTexture4444ToImage(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight) { char *srcRow = (char*)theDest; DWORD *dstRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; for(int y=0; yGetWidth(); srcRow += theDestPitch; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyImageToTexture565(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight, bool rightPad) { if (theImage->mColorTable == NULL) { DWORD *srcRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; char *dstRow = (char*)theDest; for(int y=0; y>8)&0xF800) | ((aPixel>>5)&0x07E0) | ((aPixel>>3)&0x001F); } if (rightPad) *dst = *(dst-1); srcRow += theImage->GetWidth(); dstRow += theDestPitch; } } else // palette { uchar *srcRow = (uchar*)theImage->mColorIndices + offy * theImage->GetWidth() + offx; uchar *dstRow = (uchar*)theDest; DWORD *palette = theImage->mColorTable; for(int y=0; y>8)&0xF800) | ((aPixel>>5)&0x07E0) | ((aPixel>>3)&0x001F); } if (rightPad) *dst = *(dst-1); srcRow += theImage->GetWidth(); dstRow += theDestPitch; } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyTexture565ToImage(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight) { char *srcRow = (char*)theDest; DWORD *dstRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; for(int y=0; yGetWidth(); srcRow += theDestPitch; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyImageToTexturePalette8(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight, bool rightPad) { uchar *srcRow = (uchar*)theImage->mColorIndices + offy * theImage->GetWidth() + offx; uchar *dstRow = (uchar*)theDest; for(int y=0; yGetWidth(); dstRow += theDestPitch; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void CopyTexturePalette8ToImage(void *theDest, DWORD theDestPitch, MemoryImage *theImage, int offx, int offy, int theWidth, int theHeight, LPDIRECTDRAWPALETTE thePalette) { char *srcRow = (char*)theDest; DWORD *dstRow = theImage->GetBits() + offy * theImage->GetWidth() + offx; PALETTEENTRY aPaletteEntries[256]; thePalette->GetEntries(0, 0, 256, aPaletteEntries); for(int y=0; y>16)&0xFF) | ((aPixel<<16)&0xFF0000); } dstRow += theImage->GetWidth(); srcRow += theDestPitch; } } #endif /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template struct PointClipper { Pred mPred; void ClipPoint(int n, float clipVal, const D3DTLVERTEX &v1, const D3DTLVERTEX &v2, VertexList &out); void ClipPoints(int n, float clipVal, VertexList &in, VertexList &out); }; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template void PointClipper::ClipPoint(int n, float clipVal, const D3DTLVERTEX &v1, const D3DTLVERTEX &v2, VertexList &out) { if (!mPred(GetCoord(v1,n), clipVal)) { if (!mPred(GetCoord(v2,n), clipVal)) // both inside out.push_back(v2); else // inside -> outside { float t = (clipVal - GetCoord(v1,n))/(GetCoord(v2,n)-GetCoord(v1,n)); out.push_back(Interpolate(v1,v2,t)); } } else { if (!mPred(GetCoord(v2,n), clipVal)) // outside -> inside { float t = (clipVal - GetCoord(v1, n))/(GetCoord(v2,n)-GetCoord(v1,n)); out.push_back(Interpolate(v1,v2,t)); out.push_back(v2); } // else // outside -> outside } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// template void PointClipper::ClipPoints(int n, float clipVal, VertexList &in, VertexList &out) { if(in.size()<2) return; ClipPoint(n,clipVal,in[in.size()-1],in[0],out); for(VertexList::size_type i=0; imX; int right = left + theClipRect->mWidth; int top = theClipRect->mY; int bottom = top + theClipRect->mHeight; VertexList *in = &l1, *out = &l2; PointClipper > aLessClipper; PointClipper > aGreaterClipper; aLessClipper.ClipPoints(0,left,*in,*out); std::swap(in,out); out->clear(); aLessClipper.ClipPoints(1,top,*in,*out); std::swap(in,out); out->clear(); aGreaterClipper.ClipPoints(0,right,*in,*out); std::swap(in,out); out->clear(); aGreaterClipper.ClipPoints(1,bottom,*in,*out); VertexList &aList = *out; if (aList.size() >= 3) { glBegin(GL_TRIANGLE_FAN); for (int i = 0; i < aList.size(); ++i) { glColor4ub(aList[i].color.r, aList[i].color.g, aList[i].color.b, aList[i].color.a); glTexCoord2f(aList[i].tu, aList[i].tv); glVertex2f(aList[i].sx, aList[i].sy); } glEnd(); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static void DoPolyTextureClip(VertexList &theList) { VertexList l2; float left = 0; float right = 1; float top = 0; float bottom = 1; VertexList *in = &theList, *out = &l2; PointClipper > aLessClipper; PointClipper > aGreaterClipper; aLessClipper.ClipPoints(3,left,*in,*out); std::swap(in,out); out->clear(); aLessClipper.ClipPoints(4,top,*in,*out); std::swap(in,out); out->clear(); aGreaterClipper.ClipPoints(3,right,*in,*out); std::swap(in,out); out->clear(); aGreaterClipper.ClipPoints(4,bottom,*in,*out); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::BltTransformed(const SexyMatrix3 &theTrans, const Rect& theSrcRect, const Color& theColor, const Rect *theClipRect, float theX, float theY, bool center) { int srcLeft = theSrcRect.mX; int srcTop = theSrcRect.mY; int srcRight = srcLeft + theSrcRect.mWidth; int srcBottom = srcTop + theSrcRect.mHeight; int srcX, srcY; float dstX, dstY; int aWidth; int aHeight; float u1,v1,u2,v2; float startx = 0, starty = 0; float pixelcorrect = 0.0f;//0.5f; if (center) { startx = -theSrcRect.mWidth/2.0f; starty = -theSrcRect.mHeight/2.0f; pixelcorrect = 0.0f; } srcY = srcTop; dstY = starty; SexyRGBA rgba = theColor.ToRGBA(); if ((srcLeft >= srcRight) || (srcTop >= srcBottom)) return; glEnable(GL_TEXTURE_2D); glColor4ub(rgba.r, rgba.g, rgba.b, rgba.a); while(srcY < srcBottom) { srcX = srcLeft; dstX = startx; while(srcX < srcRight) { aWidth = srcRight-srcX; aHeight = srcBottom-srcY; GLuint aTexture = GetTexture(srcX, srcY, aWidth, aHeight, u1, v1, u2, v2); float x = dstX;// - pixelcorrect; // - 0.5f; //FIXME correct?? float y = dstY;// - pixelcorrect; // - 0.5f; SexyVector2 p[4] = { SexyVector2(x, y), SexyVector2(x,y+aHeight), SexyVector2(x+aWidth, y) , SexyVector2(x+aWidth, y+aHeight) }; SexyVector2 tp[4]; int i; for (i=0; i<4; i++) { tp[i] = theTrans*p[i]; tp[i].x -= pixelcorrect - theX; tp[i].y -= pixelcorrect - theY; } bool clipped = false; if (theClipRect != NULL) { int left = theClipRect->mX; int right = left + theClipRect->mWidth; int top = theClipRect->mY; int bottom = top + theClipRect->mHeight; for (i=0; i<4; i++) { if (tp[i].x=right || tp[i].y=bottom) { clipped = true; break; } } } glBindTexture(GL_TEXTURE_2D, aTexture); if (!clipped) { glBegin(GL_TRIANGLE_STRIP); glTexCoord2f(u1, v1); glVertex2f(tp[0].x,tp[0].y); glTexCoord2f(u1, v2); glVertex2f(tp[1].x,tp[1].y); glTexCoord2f(u2, v1); glVertex2f(tp[2].x,tp[2].y); glTexCoord2f(u2, v2); glVertex2f(tp[3].x,tp[3].y); glEnd(); } else { VertexList aList; D3DTLVERTEX vertex0 = {(GLfloat)u1,(GLfloat)v1, rgba, (GLfloat)tp[0].x, (GLfloat)tp[0].y}; D3DTLVERTEX vertex1 = {(GLfloat)u1,(GLfloat)v2, rgba, (GLfloat)tp[1].x, (GLfloat)tp[1].y}; D3DTLVERTEX vertex2 = {(GLfloat)u2,(GLfloat)v1, rgba, (GLfloat)tp[2].x, (GLfloat)tp[2].y}; D3DTLVERTEX vertex3 = {(GLfloat)u2,(GLfloat)v2, rgba, (GLfloat)tp[3].x, (GLfloat)tp[3].y}; aList.push_back(vertex0); aList.push_back(vertex1); aList.push_back(vertex3); aList.push_back(vertex2); DrawPolyClipped(theClipRect, aList); } srcX += aWidth; dstX += aWidth; } srcY += aHeight; dstY += aHeight; } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// #define GetColorFromTriVertex(theVertex, theColor) (theVertex.color?theVertex.color:theColor) /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void TextureData::BltTriangles(const TriVertex theVertices[][3], int theNumTriangles, Uint32 theColor, float tx, float ty) { glEnable(GL_TEXTURE_2D); //FIXME only set this at start of drawing all if ((mMaxTotalU <= 1.0) && (mMaxTotalV <= 1.0)) { glBindTexture(GL_TEXTURE_2D, mTextures[0].mTexture); D3DTLVERTEX aVertexCache[300]; int aVertexCacheNum = 0; glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); glTexCoordPointer(2, GL_FLOAT, 5 * sizeof(GLfloat) + 4 * sizeof(GLubyte), aVertexCache); glColorPointer(4, GL_UNSIGNED_BYTE, 5 * sizeof(GLfloat) + 4 * sizeof(GLubyte), ((GLubyte*)aVertexCache) + 2 * sizeof(GLfloat)); glVertexPointer(3, GL_FLOAT, 5 * sizeof(GLfloat) + 4 * sizeof(GLubyte), ((GLubyte*)aVertexCache) + 2 * sizeof(GLfloat) + 4 * sizeof(GLubyte)); for (int aTriangleNum = 0; aTriangleNum < theNumTriangles; aTriangleNum++) { Color col; TriVertex* aTriVerts = (TriVertex*) theVertices[aTriangleNum]; D3DTLVERTEX* aD3DVertex = &aVertexCache[aVertexCacheNum]; aVertexCacheNum += 3; aD3DVertex[0].sx = aTriVerts[0].x + tx; aD3DVertex[0].sy = aTriVerts[0].y + ty; aD3DVertex[0].sz = 0; // aD3DVertex[0].rhw = 1; col = GetColorFromTriVertex(aTriVerts[0],theColor); aD3DVertex[0].color = col.ToRGBA(); //aD3DVertex[0].specular = 0; aD3DVertex[0].tu = aTriVerts[0].u * mMaxTotalU; aD3DVertex[0].tv = aTriVerts[0].v * mMaxTotalV; aD3DVertex[1].sx = aTriVerts[1].x + tx; aD3DVertex[1].sy = aTriVerts[1].y + ty; aD3DVertex[1].sz = 0; //aD3DVertex[1].rhw = 1; col = GetColorFromTriVertex(aTriVerts[0],theColor); aD3DVertex[1].color = col.ToRGBA(); //aD3DVertex[1].specular = 0; aD3DVertex[1].tu = aTriVerts[1].u * mMaxTotalU; aD3DVertex[1].tv = aTriVerts[1].v * mMaxTotalV; aD3DVertex[2].sx = aTriVerts[2].x + tx; aD3DVertex[2].sy = aTriVerts[2].y + ty; aD3DVertex[2].sz = 0; //aD3DVertex[2].rhw = 1; col = GetColorFromTriVertex(aTriVerts[0],theColor); aD3DVertex[2].color = col.ToRGBA(); //aD3DVertex[2].specular = 0; aD3DVertex[2].tu = aTriVerts[2].u * mMaxTotalU; aD3DVertex[2].tv = aTriVerts[2].v * mMaxTotalV; if ((aVertexCacheNum == 300) || (aTriangleNum == theNumTriangles - 1)) { glDrawArrays(GL_TRIANGLES, 0, 300); if (aTriangleNum == theNumTriangles - 1) { glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); } aVertexCacheNum = 0; } } } else { for (int aTriangleNum = 0; aTriangleNum < theNumTriangles; aTriangleNum++) { TriVertex* aTriVerts = (TriVertex*) theVertices[aTriangleNum]; D3DTLVERTEX aVertex[3]; Color col = GetColorFromTriVertex(aTriVerts[0],theColor); D3DTLVERTEX vertex1 = {(GLfloat)(aTriVerts[0].u * mMaxTotalU), (GLfloat)(aTriVerts[0].v * mMaxTotalV), col.ToRGBA(), aTriVerts[0].x + tx, aTriVerts[0].u + ty, 0.0f}; col = GetColorFromTriVertex(aTriVerts[1],theColor); D3DTLVERTEX vertex2 = {(GLfloat)(aTriVerts[1].u * mMaxTotalU), (GLfloat)(aTriVerts[1].v * mMaxTotalV), col.ToRGBA(), aTriVerts[1].x + tx, aTriVerts[1].u + ty, 0.0f}; col = GetColorFromTriVertex(aTriVerts[2],theColor); D3DTLVERTEX vertex3 = {(GLfloat)(aTriVerts[2].u * mMaxTotalU), (GLfloat)(aTriVerts[2].v * mMaxTotalV), col.ToRGBA(), aTriVerts[2].x + tx, aTriVerts[2].u + ty, 0.0f}; aVertex[0] = vertex1; aVertex[1] = vertex2; aVertex[2] = vertex3; float aMinU = mMaxTotalU, aMinV = mMaxTotalV; float aMaxU = 0, aMaxV = 0; int i,j,k; for (i=0; i<3; i++) { if(aVertex[i].tu < aMinU) aMinU = aVertex[i].tu; if(aVertex[i].tv < aMinV) aMinV = aVertex[i].tv; if(aVertex[i].tu > aMaxU) aMaxU = aVertex[i].tu; if(aVertex[i].tv > aMaxV) aMaxV = aVertex[i].tv; } VertexList aMasterList; aMasterList.push_back(aVertex[0]); aMasterList.push_back(aVertex[1]); aMasterList.push_back(aVertex[2]); VertexList aList; int aLeft = (int)floorf(aMinU); int aTop = (int)floorf(aMinV); int aRight = (int)ceilf(aMaxU); int aBottom = (int)ceilf(aMaxV); if (aLeft < 0) aLeft = 0; if (aTop < 0) aTop = 0; if (aRight > mTexVecWidth) aRight = mTexVecWidth; if (aBottom > mTexVecHeight) aBottom = mTexVecHeight; TextureDataPiece &aStandardPiece = mTextures[0]; for (i=aTop; i= 3) { glBindTexture(GL_TEXTURE_2D, aPiece.mTexture); glBegin(GL_TRIANGLE_FAN); for (int i = 0; i < aList.size(); ++i) {//FIXME optimize glTexCoord2f(aList[i].tu, aList[i].tv); glColor4ub(aList[i].color.r, aList[i].color.g, aList[i].color.b, aList[i].color.a); glVertex3f(aList[i].sx, aList[i].sy, aList[i].sz); } glEnd(); } } } } } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool D3DInterface::CreateImageTexture(MemoryImage *theImage) { bool wantPurge = false; if(theImage->mD3DData==NULL) { theImage->mD3DData = new TextureData(); // The actual purging was deferred wantPurge = theImage->mPurgeBits; #if 0 AutoCrit aCrit(gSexyAppBase->mDDInterface->mCritSect); // Make images thread safe #endif mImageSet.insert(theImage); } TextureData *aData = (TextureData*)theImage->mD3DData; aData->CheckCreateTextures(theImage); if (wantPurge) theImage->PurgeBits(); //FIXME return true;//aData->mPixelFormat != PixelFormat_Unknown; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// bool D3DInterface::RecoverBits(MemoryImage* theImage) { #if 0 if (theImage->mD3DData == NULL) return false; TextureData* aData = (TextureData*) theImage->mD3DData; if (aData->mBitsChangedCount != theImage->mBitsChangedCount) // bits have changed since texture was created return false; for (int aPieceRow = 0; aPieceRow < aData->mTexVecHeight; aPieceRow++) { for (int aPieceCol = 0; aPieceCol < aData->mTexVecWidth; aPieceCol++) { TextureDataPiece* aPiece = &aData->mTextures[aPieceRow*aData->mTexVecWidth + aPieceCol]; int offx = aPieceCol*aData->mTexPieceWidth; int offy = aPieceRow*aData->mTexPieceHeight; int aWidth = std::min(theImage->mWidth-offx, aPiece->mWidth); int aHeight = std::min(theImage->mHeight-offy, aPiece->mHeight); CopySurface8888ToImage(aPiece->mTexture, aDesc.lPitch, theImage, offx, offy, aWidth, aHeight); break; case PixelFormat_A4R4G4B4: CopyTexture4444ToImage(aDesc.lpSurface, aDesc.lPitch, theImage, offx, offy, aWidth, aHeight); break; case PixelFormat_R5G6B5: CopyTexture565ToImage(aDesc.lpSurface, aDesc.lPitch, theImage, offx, offy, aWidth, aHeight); break; case PixelFormat_Palette8: CopyTexturePalette8ToImage(aDesc.lpSurface, aDesc.lPitch, theImage, offx, offy, aWidth, aHeight, aData->mPalette); break; } } } #endif return true; } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::SetCurTexture(MemoryImage *theImage) { if (theImage==NULL) { glBindTexture(GL_TEXTURE_2D, 0); return; } if (!CreateImageTexture(theImage)) return; TextureData *aData = (TextureData*)theImage->mD3DData; glBindTexture(GL_TEXTURE_2D, aData->mTextures[0].mTexture); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::PushTransform(const SexyMatrix3 &theTransform, bool concatenate) { if (mTransformStack.empty() || !concatenate) mTransformStack.push_back(theTransform); else { SexyMatrix3 &aTrans = mTransformStack.back(); mTransformStack.push_back(theTransform*aTrans); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::PopTransform() { if (!mTransformStack.empty()) mTransformStack.pop_back(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::RemoveMemoryImage(MemoryImage *theImage) { if (theImage->mD3DData != NULL) { delete (TextureData*)theImage->mD3DData; theImage->mD3DData = NULL; #if 0 AutoCrit aCrit(gSexyAppBase->mDDInterface->mCritSect); // Make images thread safe #endif mImageSet.erase(theImage); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::Cleanup() { Flush(); ImageSet::iterator anItr; for(anItr = mImageSet.begin(); anItr != mImageSet.end(); ++anItr) { MemoryImage *anImage = *anItr; delete (TextureData*)anImage->mD3DData; anImage->mD3DData = NULL; } mImageSet.clear(); #if 0 if (mD3DDevice != NULL) { mD3DDevice->Release(); mD3DDevice = NULL; } if (mD3D != NULL) { mD3D->Release(); mD3D = NULL; } #endif if (mDDSDrawSurface != NULL) { SDL_FreeSurface(mDDSDrawSurface); mDDSDrawSurface = NULL; } if (mZBuffer != NULL) { SDL_FreeSurface(mZBuffer); mZBuffer = NULL; } // if (glIsTexture(custom_cursor_texture) == GL_TRUE) // glDeleteTextures(1, &custom_cursor_texture); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::SetupDrawMode(int theDrawMode, const Color &theColor, Image *theImage) { if (theDrawMode == Graphics::DRAWMODE_NORMAL) { glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } else // Additive { glBlendFunc(GL_SRC_ALPHA, GL_ONE); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::Blt(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode, bool linearFilter) { if (!mTransformStack.empty()) { BltClipF(theImage,theX,theY,theSrcRect,NULL,theColor,theDrawMode); return; } if (!PreDraw()) return; MemoryImage* aSrcMemoryImage = (MemoryImage*) theImage; if (!CreateImageTexture(aSrcMemoryImage)) return; SetupDrawMode(theDrawMode, theColor, theImage); TextureData *aData = (TextureData*)aSrcMemoryImage->mD3DData; SetLinearFilter(true); aData->Blt(theX,theY,theSrcRect,theColor); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::BltMirror(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Color& theColor, int theDrawMode, bool linearFilter) { SexyTransform2D aTransform; aTransform.Translate(-theSrcRect.mWidth,0); aTransform.Scale(-1, 1); aTransform.Translate(theX, theY); BltTransformed(theImage,NULL,theColor,theDrawMode,theSrcRect,aTransform,linearFilter); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::BltClipF(Image* theImage, float theX, float theY, const Rect& theSrcRect, const Rect *theClipRect, const Color& theColor, int theDrawMode) { SexyTransform2D aTransform; aTransform.Translate(theX, theY); BltTransformed(theImage,theClipRect,theColor,theDrawMode,theSrcRect,aTransform,true); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::StretchBlt(Image* theImage, const Rect& theDestRect, const Rect& theSrcRect, const Rect* theClipRect, const Color &theColor, int theDrawMode, bool fastStretch, bool mirror) { float xScale = (float)theDestRect.mWidth / theSrcRect.mWidth; float yScale = (float)theDestRect.mHeight / theSrcRect.mHeight; SexyTransform2D aTransform; if (mirror) { aTransform.Translate(-theSrcRect.mWidth,0); aTransform.Scale(-xScale, yScale); } else aTransform.Scale(xScale, yScale); aTransform.Translate(theDestRect.mX, theDestRect.mY); BltTransformed(theImage,theClipRect,theColor,theDrawMode,theSrcRect,aTransform,!fastStretch); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::BltRotated(Image* theImage, float theX, float theY, const Rect* theClipRect, const Color& theColor, int theDrawMode, double theRot, float theRotCenterX, float theRotCenterY, const Rect &theSrcRect) { SexyTransform2D aTransform; aTransform.Translate(-theRotCenterX, -theRotCenterY); aTransform.RotateRad(theRot); aTransform.Translate(theX+theRotCenterX,theY+theRotCenterY); BltTransformed(theImage,theClipRect,theColor,theDrawMode,theSrcRect,aTransform,true); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::BltTransformed(Image* theImage, const Rect* theClipRect, const Color& theColor, int theDrawMode, const Rect &theSrcRect, const SexyMatrix3 &theTransform, bool linearFilter, float theX, float theY, bool center) { if (!PreDraw()) return; MemoryImage* aSrcMemoryImage = (MemoryImage*) theImage; if (!CreateImageTexture(aSrcMemoryImage)) return; SetupDrawMode(theDrawMode, theColor, theImage); TextureData *aData = (TextureData*)aSrcMemoryImage->mD3DData; if (!mTransformStack.empty()) { SetLinearFilter(true); // force linear filtering in the case of a global transform if (theX!=0 || theY!=0) { SexyTransform2D aTransform; if (center) aTransform.Translate(-theSrcRect.mWidth/2.0f,-theSrcRect.mHeight/2.0f); aTransform = theTransform * aTransform; aTransform.Translate(theX,theY); aTransform = mTransformStack.back() * aTransform; aData->BltTransformed(aTransform, theSrcRect, theColor, theClipRect); } else { SexyTransform2D aTransform = mTransformStack.back()*theTransform; aData->BltTransformed(aTransform, theSrcRect, theColor, theClipRect, theX, theY, center); } } else { SetLinearFilter(true); aData->BltTransformed(theTransform, theSrcRect, theColor, theClipRect, theX, theY, center); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::DrawLine(double theStartX, double theStartY, double theEndX, double theEndY, const Color& theColor, int theDrawMode) { if (!PreDraw()) return; glDisable(GL_TEXTURE_2D); SetupDrawMode(theDrawMode, theColor, NULL); float x1, y1, x2, y2; SexyRGBA aColor = theColor.ToRGBA(); if (!mTransformStack.empty()) { SexyVector2 p1(theStartX,theStartY); SexyVector2 p2(theEndX,theEndY); p1 = mTransformStack.back()*p1; p2 = mTransformStack.back()*p2; x1 = p1.x; y1 = p1.y; x2 = p2.x; y2 = p2.y; } else { x1 = theStartX; y1 = theStartY; x2 = theEndX; y2 = theEndY; } glColor4ub(aColor.r, aColor.g, aColor.b, aColor.a); glBegin(GL_LINE_STRIP); glVertex2f(x1, y1); glVertex2f(x2, y2); // glVertex2f(x2+0.5f, y2+0.5f); glEnd(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::FillRect(const Rect& theRect, const Color& theColor, int theDrawMode) { if (!PreDraw()) return; glDisable(GL_TEXTURE_2D); SetupDrawMode(theDrawMode, theColor, NULL); SexyRGBA aColor = theColor.ToRGBA(); float x = theRect.mX;// - 0.5f; float y = theRect.mY;// - 0.5f; float aWidth = theRect.mWidth; float aHeight = theRect.mHeight; D3DTLVERTEX aVertex[4] = { { 0,0,aColor,x, y,0}, { 0,0,aColor,x, y + aHeight,0}, { 0,0,aColor,x + aWidth, y,0}, { 0,0,aColor,x + aWidth, y + aHeight,0} }; if (!mTransformStack.empty()) { SexyVector2 p[4] = { SexyVector2(x, y), SexyVector2(x,y+aHeight), SexyVector2(x+aWidth, y) , SexyVector2(x+aWidth, y+aHeight) }; int i; for (i=0; i<4; i++) { p[i] = mTransformStack.back()*p[i]; // p[i].x -= 0.5f; //p[i].y -= 0.5f; aVertex[i].sx = p[i].x; aVertex[i].sy = p[i].y; } } glColor4ub(aColor.r, aColor.g, aColor.b, aColor.a); glBegin(GL_TRIANGLE_STRIP); glVertex2f(aVertex[0].sx, aVertex[0].sy); glVertex2f(aVertex[1].sx, aVertex[1].sy); glVertex2f(aVertex[2].sx, aVertex[2].sy); glVertex2f(aVertex[3].sx, aVertex[3].sy); glEnd(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::DrawTriangle(const TriVertex &p1, const TriVertex &p2, const TriVertex &p3, const Color &theColor, int theDrawMode) { if (!PreDraw()) return; SetupDrawMode(theDrawMode, theColor, NULL); Color aColor1 = GetColorFromTriVertex(p1, theColor); Color aColor2 = GetColorFromTriVertex(p2, theColor); Color aColor3 = GetColorFromTriVertex(p3, theColor); SexyRGBA aRGBA1 = aColor1.ToRGBA(); SexyRGBA aRGBA2 = aColor2.ToRGBA(); SexyRGBA aRGBA3 = aColor3.ToRGBA(); D3DTLVERTEX aVertex[3] = { { 0,0,aRGBA1, p1.x, p1.y, 0}, { 0,0,aRGBA2, p2.x, p2.y, 0}, { 0,0,aRGBA3, p3.x, p3.y, 0} }; glDisable(GL_TEXTURE_2D); glBegin(GL_TRIANGLE_STRIP); glColor4ub(aRGBA1.r, aRGBA1.g, aRGBA1.b, aRGBA1.a); glVertex2f(aVertex[0].sx, aVertex[0].sy); glColor4ub(aRGBA2.r, aRGBA2.g, aRGBA2.b, aRGBA2.a); glVertex2f(aVertex[1].sx, aVertex[1].sy); glColor4ub(aRGBA3.r, aRGBA3.g, aRGBA3.b, aRGBA3.a); glVertex2f(aVertex[2].sx, aVertex[2].sy); glEnd(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::FillPoly(const Point theVertices[], int theNumVertices, const Rect *theClipRect, const Color &theColor, int theDrawMode, int tx, int ty) { if (theNumVertices<3) return; if (!PreDraw()) return; SetupDrawMode(theDrawMode, theColor, NULL); SexyRGBA aColor = theColor.ToRGBA(); VertexList aList; for (int i=0; imD3DData; SetLinearFilter(blend); aData->BltTriangles(theVertices, theNumTriangles, (Uint32)theColor.ToInt(), tx, ty); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// void D3DInterface::DrawTrianglesTexStrip(const TriVertex theVertices[], int theNumTriangles, const Color &theColor, int theDrawMode, Image *theTexture, float tx, float ty, bool blend) { TriVertex aList[100][3]; int aTriNum = 0; while (aTriNum < theNumTriangles) { int aMaxTriangles = std::min(100,theNumTriangles - aTriNum); for (int i=0; iEndScene(); #endif mSceneBegun = false; mErrorString.erase(); } } libtuxcap-1.4.0/tuxcap/lib/Slider.cpp0000644000175000017500000000772510641010432017371 0ustar inniyahinniyah#include "Slider.h" #include "Graphics.h" #include "Image.h" #include "SliderListener.h" #include "WidgetManager.h" #include "SexyAppBase.h" using namespace Sexy; Slider::Slider(Image* theTrackImage, Image* theThumbImage, int theId, SliderListener* theListener) : mTrackImage(theTrackImage), mThumbImage(theThumbImage), mId(theId), mListener(theListener), mVal(0.0) { mDragging = false; mHorizontal = true; mRelX = mRelY = 0; } void Slider::SetValue(double theValue) { mVal = theValue; if (mVal < 0.0) mVal = 0.0; else if (mVal > 1.0) mVal = 1.0; MarkDirtyFull(); } bool Slider::HasTransparencies() { return true; } void Slider::Draw(Graphics* g) { if (mTrackImage != NULL) { int cw = mHorizontal ? mTrackImage->GetWidth()/3 : mTrackImage->GetWidth(); int ch = mHorizontal ? mTrackImage->GetHeight() : mTrackImage->GetHeight()/3; if (mHorizontal) { int ty = (mHeight - ch) / 2; g->DrawImage(mTrackImage, 0, ty, Rect(0, 0, cw, ch)); Graphics aClipG(*g); aClipG.ClipRect(cw, ty, mWidth - cw*2, ch); for (int i = 0; i < (mWidth-cw*2+cw-1)/cw; i++) aClipG.DrawImage(mTrackImage, cw + i*cw, ty, Rect(cw, 0, cw, ch)); g->DrawImage(mTrackImage, mWidth-cw, ty, Rect(cw*2, 0, cw, ch)); } else { g->DrawImage(mTrackImage, 0, 0, Rect(0, 0, cw, ch)); Graphics aClipG(*g); aClipG.ClipRect(0, ch, cw, mHeight - ch * 2); for (int i = 0; i < (mHeight-ch*2+ch-1)/ch; i++) aClipG.DrawImage(mTrackImage, 0, ch + i*ch, Rect(0, ch, cw, ch)); g->DrawImage(mTrackImage, 0, mHeight-ch, Rect(0, ch*2, cw, ch)); } } if (mHorizontal && (mThumbImage != NULL)) g->DrawImage(mThumbImage, (int) (mVal * (mWidth - mThumbImage->GetWidth())), (mHeight - mThumbImage->GetHeight()) / 2); else if (!mHorizontal && (mThumbImage != NULL)) g->DrawImage(mThumbImage, (mWidth - mThumbImage->GetWidth()) / 2, (int) (mVal * (mHeight - mThumbImage->GetHeight()))); //g->SetColor(Color(255, 255, 0)); //g->FillRect(0, 0, mWidth, mHeight); } void Slider::MouseDown(int x, int y, int theClickCount) { if (mHorizontal) { int aThumbX = (int) (mVal * (mWidth - mThumbImage->GetWidth())); if ((x >= aThumbX) && (x < aThumbX + mThumbImage->GetWidth())) { mWidgetManager->mApp->SetCursor(CURSOR_DRAGGING); mDragging = true; mRelX = x - aThumbX; } else { // clicked on the bar, set position to mouse click double pos = (double)x / mWidth; SetValue(pos); } } else { int aThumbY = (int) (mVal * (mHeight - mThumbImage->GetHeight())); if ((y >= aThumbY) && (y < aThumbY + mThumbImage->GetHeight())) { mWidgetManager->mApp->SetCursor(CURSOR_DRAGGING); mDragging = true; mRelY = y - aThumbY; } else { // clicked on the bar, set position to mouse click double pos = (double)y / mHeight; SetValue(pos); } } } void Slider::MouseMove(int x, int y) { if (mHorizontal) { int aThumbX = (int) (mVal * (mWidth - mThumbImage->GetWidth())); if ((x >= aThumbX) && (x < aThumbX + mThumbImage->GetWidth())) mWidgetManager->mApp->SetCursor(CURSOR_DRAGGING); else mWidgetManager->mApp->SetCursor(CURSOR_POINTER); } else { int aThumbY = (int) (mVal * (mHeight - mThumbImage->GetHeight())); if ((y >= aThumbY) && (y < aThumbY + mThumbImage->GetHeight())) mWidgetManager->mApp->SetCursor(CURSOR_DRAGGING); else mWidgetManager->mApp->SetCursor(CURSOR_POINTER); } } void Slider::MouseDrag(int x, int y) { if (mDragging) { double anOldVal = mVal; if (mHorizontal) mVal = (x - mRelX) / (double) (mWidth - mThumbImage->GetWidth()); else mVal = (y - mRelY) / (double) (mHeight - mThumbImage->GetHeight()); if (mVal < 0.0) mVal = 0.0; if (mVal > 1.0) mVal = 1.0; if (mVal != anOldVal) { mListener->SliderVal(mId, mVal); MarkDirtyFull(); } } } void Slider::MouseUp(int x, int y) { mDragging = false; mWidgetManager->mApp->SetCursor(CURSOR_POINTER); mListener->SliderVal(mId, mVal); } void Slider::MouseLeave() { if (!mDragging) mWidgetManager->mApp->SetCursor(CURSOR_POINTER); } libtuxcap-1.4.0/tuxcap/lib/SWTri_Pixel555.cpp0000644000175000017500000000324210641010433020546 0ustar inniyahinniyah// This file is included by SWTri.cpp and should not be built directly by the project. #if defined(TEXTURED) { #include "SWTri_GetTexel.cpp" if (alpha > 0x08) { #include "SWTri_TexelARGB.cpp" #if defined(GLOBAL_ARGB) || defined (TEX_ALPHA) || defined(MOD_ARGB) { if (alpha < 0xf0) { unsigned int trb, tg; #if !defined(LINEAR_BLEND) { trb = (((tex&0xff00ff) * alpha) >> 8) & 0xff00ff; tg = (((tex&0x00ff00) * alpha) >> 8) & 0x00ff00; } #else { trb = tex&0xff00ff; tg = tex&0x00ff00; } #endif trb = ((trb>>9)&0x7c00)|((trb>>3)&0x001f); tg = ((tg>>6)&0x03e0); tex = *pix; alpha = (0xff - alpha)>>3; unsigned int prb = (((tex&0x7c1f) * alpha) >> 5) & 0x7c1f; unsigned int pg = (((tex&0x03e0) * alpha) >> 5) & 0x03e0; *pix = (trb|tg) + (prb|pg); } else { *pix = ((tex>>9)&0x7c00)|((tex>>6)&0x03e0)|((tex>>3)&0x001f); } } #else { *pix = ((tex>>9)&0x7c00)|((tex>>6)&0x03e0)|((tex>>3)&0x001f); } #endif } } #elif defined(MOD_ARGB) { if (a > 0xf00000) { *pix = ((r>>9)&0x7c00)|((g>>14)&0x03e0)|((b>>19)&0x001f); } else if (a > 0x080000) { unsigned int alpha = a >> 16; unsigned int _rb = ((((r&0xff0000) | (b>>16)) * alpha)>> 8)&0xff00ff; unsigned int _g = (((g&0xff0000) * alpha)>>16)&0x00ff00; _rb = ((_rb>>9)&0x7c00)|((_rb>>3)&0x001f); _g = ((_g>>6)&0x03e0); unsigned int p = *pix; alpha = (0xff - alpha)>>3; unsigned int prb = (((p&0x7c1f) * alpha) >> 5) & 0x7c1f; unsigned int pg = (((p&0x03e0) * alpha) >> 5) & 0x03e0; *pix = (_rb|_g)+(prb|pg); } } #endif libtuxcap-1.4.0/tuxcap/lib/SDLMixerSoundInstance.cpp0000644000175000017500000000776710675772656022340 0ustar inniyahinniyah/* Copyright (c) 2007 W.P. van Paassen * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "SDLMixerMusicInterface.h" #include "SDLMixerSoundInstance.h" #include "SDLMixerSoundManager.h" using namespace Sexy; SDLMixerSoundInstance::SDLMixerSoundInstance(SDLMixerSoundManager* theSoundManager, int channel, Mix_Chunk* theSourceSound) { mSDLMixerSoundManagerP = theSoundManager; mSample = theSourceSound; mChannel = channel; mReleased = false; mAutoRelease = false; mHasPlayed = false; mBaseVolume = 1.0; mBasePan = 0.0; mVolume = 1.0; mPan = 0.0; mPitch = 1.0; mHasPlayed = false; RehupVolume(); } SDLMixerSoundInstance::~SDLMixerSoundInstance() { Release(); mSample = NULL; mChannel = -1; } void SDLMixerSoundInstance::RehupVolume() { if (mSample) Mix_VolumeChunk(mSample, (int)(mBaseVolume * mVolume * mSDLMixerSoundManagerP->mMasterVolume * (float)MIX_MAX_VOLUME)); } void SDLMixerSoundInstance::RehupPan() { if (mSample) { float aPan = /*mBasePan/100.0f * */mPan/100.0f; if (aPan > 1.0f) aPan = 1.0f; else if (aPan < -1.0f) aPan =-1.0f; int mLeft, mRight; if (aPan < 0.0f) { mRight = 128 - (int)(128.0f * aPan); mLeft = 255 - mRight; } else { mLeft = 128 - (int)(128.0f * aPan); mRight = 255 - mLeft; } Mix_SetPanning(mChannel, mLeft, mRight); } } void SDLMixerSoundInstance::RehupPitch() { } void SDLMixerSoundInstance::Release() { Stop(); mSample = NULL; mReleased = true; } void SDLMixerSoundInstance::SetVolume(double theVolume) // 0.0 to 1.0 { mVolume = (float)theVolume; RehupVolume(); } void SDLMixerSoundInstance::SetPan(int thePosition) //-100 to +100 = left to right { mPan = float(thePosition/100); RehupPan(); } void SDLMixerSoundInstance::AdjustPitch(double theNumSteps) //+0.5 to +2.0 = lower to higher { mPitch = (float)theNumSteps; RehupPitch(); } void SDLMixerSoundInstance::SetBaseVolume(double theBaseVolume) { mBaseVolume = (float)theBaseVolume; RehupVolume(); } void SDLMixerSoundInstance::SetBasePan(int theBasePan) { mBasePan = float(theBasePan/100); RehupPan(); } void SDLMixerSoundInstance::AdjustBasePitch(float thePitch) { mBasePitch = thePitch; RehupPitch(); } bool SDLMixerSoundInstance::Play(bool looping, bool autoRelease) { Stop(); mAutoRelease = autoRelease; if (!mSample) return false; Mix_PlayChannel(mChannel, mSample, looping ? -1 : 0); mHasPlayed = true; return true; } void SDLMixerSoundInstance::Stop() { if (mSample) { Mix_HaltChannel(mChannel); mAutoRelease = false; } } bool SDLMixerSoundInstance::IsPlaying() { return Mix_Playing(mChannel); } bool SDLMixerSoundInstance::IsReleased() { if ((!mReleased) && (mAutoRelease) && (mHasPlayed) && (!IsPlaying())) Release(); return mReleased; } double SDLMixerSoundInstance::GetVolume() { return mVolume; } libtuxcap-1.4.0/tuxcap/lib/SWTri.cpp0000644000175000017500000007263010646110006017157 0ustar inniyahinniyah#include "SWTri.h" #if 0 #include "Debug.h" #endif #include using namespace Sexy; static SWHelper::XYZStruct vertexReservoir[64]; static unsigned int vertexReservoirUsed = 0; /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static int FixedFloor(int x) { if (x>0) return x&0xFFFF0000; else return (x&0xFFFF0000)-0x10000; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ********************* BEGIN CLIPPING STUFF ********************************************************************* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// static inline void lClip(SWHelper::XYZStruct & dst, const SWHelper::XYZStruct & on, const SWHelper::XYZStruct & off, const float edge) { float delta = (edge - off.mX) / (on.mX - off.mX); dst.mX = off.mX + (on.mX - off.mX) * delta; dst.mY = off.mY + (on.mY - off.mY) * delta; dst.mU = off.mU + (on.mU - off.mU) * delta; dst.mV = off.mV + (on.mV - off.mV) * delta; dst.mDiffuse = ((int) ((((off.mDiffuse >> 24)&0xff) + (((on.mDiffuse >> 24)&0xff) - ((off.mDiffuse >> 24)&0xff)) * delta))<<24) | ((int) ((((off.mDiffuse >> 16)&0xff) + (((on.mDiffuse >> 16)&0xff) - ((off.mDiffuse >> 16)&0xff)) * delta))<<16) | ((int) ((((off.mDiffuse >> 8)&0xff) + (((on.mDiffuse >> 8)&0xff) - ((off.mDiffuse >> 8)&0xff)) * delta))<<8 ) | ((int) ((((off.mDiffuse >> 0)&0xff) + (((on.mDiffuse >> 0)&0xff) - ((off.mDiffuse >> 0)&0xff)) * delta)) ); } // -------------------------------------------------------------------------------------------------------------------------------- static inline void rClip(SWHelper::XYZStruct & dst, const SWHelper::XYZStruct & on, const SWHelper::XYZStruct & off, const float edge) { float delta = (edge - off.mX) / (on.mX - off.mX); dst.mX = off.mX + (on.mX - off.mX) * delta; dst.mY = off.mY + (on.mY - off.mY) * delta; dst.mU = off.mU + (on.mU - off.mU) * delta; dst.mV = off.mV + (on.mV - off.mV) * delta; dst.mDiffuse = ((int) ((((off.mDiffuse >> 24)&0xff) + (((on.mDiffuse >> 24)&0xff) - ((off.mDiffuse >> 24)&0xff)) * delta))<<24) | ((int) ((((off.mDiffuse >> 16)&0xff) + (((on.mDiffuse >> 16)&0xff) - ((off.mDiffuse >> 16)&0xff)) * delta))<<16) | ((int) ((((off.mDiffuse >> 8)&0xff) + (((on.mDiffuse >> 8)&0xff) - ((off.mDiffuse >> 8)&0xff)) * delta))<<8 ) | ((int) ((((off.mDiffuse >> 0)&0xff) + (((on.mDiffuse >> 0)&0xff) - ((off.mDiffuse >> 0)&0xff)) * delta)) ); } // -------------------------------------------------------------------------------------------------------------------------------- static inline void tClip(SWHelper::XYZStruct & dst, const SWHelper::XYZStruct & on, const SWHelper::XYZStruct & off, const float edge) { float delta = (edge - off.mY) / (on.mY - off.mY); dst.mX = off.mX + (on.mX - off.mX) * delta; dst.mY = off.mY + (on.mY - off.mY) * delta; dst.mU = off.mU + (on.mU - off.mU) * delta; dst.mV = off.mV + (on.mV - off.mV) * delta; dst.mDiffuse = ((int) ((((off.mDiffuse >> 24)&0xff) + (((on.mDiffuse >> 24)&0xff) - ((off.mDiffuse >> 24)&0xff)) * delta))<<24) | ((int) ((((off.mDiffuse >> 16)&0xff) + (((on.mDiffuse >> 16)&0xff) - ((off.mDiffuse >> 16)&0xff)) * delta))<<16) | ((int) ((((off.mDiffuse >> 8)&0xff) + (((on.mDiffuse >> 8)&0xff) - ((off.mDiffuse >> 8)&0xff)) * delta))<<8 ) | ((int) ((((off.mDiffuse >> 0)&0xff) + (((on.mDiffuse >> 0)&0xff) - ((off.mDiffuse >> 0)&0xff)) * delta)) ); } // -------------------------------------------------------------------------------------------------------------------------------- static inline void bClip(SWHelper::XYZStruct & dst, const SWHelper::XYZStruct & on, const SWHelper::XYZStruct & off, const float edge) { float delta = (edge - off.mY) / (on.mY - off.mY); dst.mX = off.mX + (on.mX - off.mX) * delta; dst.mY = off.mY + (on.mY - off.mY) * delta; dst.mU = off.mU + (on.mU - off.mU) * delta; dst.mV = off.mV + (on.mV - off.mV) * delta; dst.mDiffuse = ((int) ((((off.mDiffuse >> 24)&0xff) + (((on.mDiffuse >> 24)&0xff) - ((off.mDiffuse >> 24)&0xff)) * delta))<<24) | ((int) ((((off.mDiffuse >> 16)&0xff) + (((on.mDiffuse >> 16)&0xff) - ((off.mDiffuse >> 16)&0xff)) * delta))<<16) | ((int) ((((off.mDiffuse >> 8)&0xff) + (((on.mDiffuse >> 8)&0xff) - ((off.mDiffuse >> 8)&0xff)) * delta))<<8 ) | ((int) ((((off.mDiffuse >> 0)&0xff) + (((on.mDiffuse >> 0)&0xff) - ((off.mDiffuse >> 0)&0xff)) * delta)) ); } // -------------------------------------------------------------------------------------------------------------------------------- static inline unsigned int leClip(SWHelper::XYZStruct ** src, SWHelper::XYZStruct ** dst, const float edge) { SWHelper::XYZStruct ** _dst = dst; for (SWHelper::XYZStruct ** v = src; *v; ++v) { SWHelper::XYZStruct * cur = *v; SWHelper::XYZStruct * nex = *(v+1) ? *(v+1):*src; switch((cur->mX < edge ? 1:0)|(nex->mX < edge ? 2:0)) { case 0: *dst = *v; ++dst; break; case 1: { SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; lClip(tmp, *nex, *cur, edge); *dst = &tmp; ++dst; break; } case 2: { *dst = *v; ++dst; SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; lClip(tmp, *cur, *nex, edge); *dst = &tmp; ++dst; break; } } } *dst = 0; return static_cast(dst - _dst); } // -------------------------------------------------------------------------------------------------------------------------------- static inline unsigned int reClip(SWHelper::XYZStruct ** src, SWHelper::XYZStruct ** dst, const float edge) { SWHelper::XYZStruct ** _dst = dst; for (SWHelper::XYZStruct ** v = src; *v; ++v) { SWHelper::XYZStruct * cur = *v; SWHelper::XYZStruct * nex = *(v+1) ? *(v+1):*src; switch((cur->mX > edge ? 1:0)|(nex->mX > edge ? 2:0)) { case 0: *dst = *v; ++dst; break; case 1: { SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; rClip(tmp, *nex, *cur, edge); *dst = &tmp; ++dst; break; } case 2: { *dst = *v; ++dst; SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; rClip(tmp, *cur, *nex, edge); *dst = &tmp; ++dst; break; } } } *dst = 0; return static_cast(dst - _dst); } // -------------------------------------------------------------------------------------------------------------------------------- static inline unsigned int teClip(SWHelper::XYZStruct ** src, SWHelper::XYZStruct ** dst, const float edge) { SWHelper::XYZStruct ** _dst = dst; for (SWHelper::XYZStruct ** v = src; *v; ++v) { SWHelper::XYZStruct * cur = *v; SWHelper::XYZStruct * nex = *(v+1) ? *(v+1):*src; switch((cur->mY < edge ? 1:0)|(nex->mY < edge ? 2:0)) { case 0: *dst = *v; ++dst; break; case 1: { SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; tClip(tmp, *nex, *cur, edge); *dst = &tmp; ++dst; break; } case 2: { *dst = *v; ++dst; SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; tClip(tmp, *cur, *nex, edge); *dst = &tmp; ++dst; break; } } } *dst = 0; return static_cast(dst - _dst); } // -------------------------------------------------------------------------------------------------------------------------------- static inline unsigned int beClip(SWHelper::XYZStruct ** src, SWHelper::XYZStruct ** dst, const float edge) { SWHelper::XYZStruct ** _dst = dst; for (SWHelper::XYZStruct ** v = src; *v; ++v) { SWHelper::XYZStruct * cur = *v; SWHelper::XYZStruct * nex = *(v+1) ? *(v+1):*src; switch((cur->mY > edge ? 1:0)|(nex->mY > edge ? 2:0)) { case 0: *dst = *v; ++dst; break; case 1: { SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; bClip(tmp, *nex, *cur, edge); *dst = &tmp; ++dst; break; } case 2: { *dst = *v; ++dst; SWHelper::XYZStruct & tmp = vertexReservoir[vertexReservoirUsed++]; bClip(tmp, *cur, *nex, edge); *dst = &tmp; ++dst; break; } } } *dst = 0; return static_cast(dst - _dst); } // -------------------------------------------------------------------------------------------------------------------------------- static inline int clipShape(SWHelper::XYZStruct ** dst, SWHelper::XYZStruct ** src, const float left, const float right, const float top, const float bottom) { vertexReservoirUsed = 0; SWHelper::XYZStruct * buf[64]; SWHelper::XYZStruct * ptr[4]; ptr[0] = src[0]; ptr[1] = src[1]; ptr[2] = src[2]; ptr[3] = 0; if (leClip(ptr, buf, left) < 3) return 0; if (reClip(buf, dst, right) < 3) return 0; if (teClip(dst, buf, top) < 3) return 0; return beClip(buf, dst, bottom); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ********************* END CLIPPING STUFF *********************************************************************** /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// void SWHelper::SWDrawShape(XYZStruct *theVerts, int theNumVerts, MemoryImage *theImage, const Color &theColor, int theDrawMode, const Rect &theClipRect, void *theSurface, int thePitch, int thePixelFormat, bool blend, bool vertexColor) { float tclx0 = theClipRect.mX; float tcly0 = theClipRect.mY; float tclx1 = theClipRect.mX + theClipRect.mWidth - 1; float tcly1 = theClipRect.mY + theClipRect.mHeight - 1; // // Okay, now we're gonna render. We have the vertex list. // mSWRenderPtr is a char* pointer to the upper left // bit of the of render array. // struct XYZStruct *aTVertPtr=theVerts; // // Some notes: // // If mSWTexture==NULL, no texture is selected and pure white can be substituted (clipped to // the current material color). // // If mAlphaMode!=mAlphaModeOn, then there's no need to do any alpha rendering, period. // All alpha, even in textures with it, should be ignored. Otherwise, Alpha basically // boils down to: texture pixel alpha * mClippedMaterial.diffuse.a // // The current material is stored in mClippedMaterial. You only need to ref the // diffuse color: // mClippedMaterial.diffuse.a // mClippedMaterial.diffuse.r // mClippedMaterial.diffuse.g // mClippedMaterial.diffuse.b // // The triangle cull can one one of three things: // mCullMode=mCullModeNone (cull no triangles) // mCullMode=mCullModeCW (cull CW triangles) // mCullMode=mCullModeCCW (cull CCW triangles) // // Texture clamping // For this implementation, all uv coordinates will be between 0-1. However, in DirectX, it // is sometimes necessary to clamp textures in order to prevent pixel bleed. So, though you // won't need to implement any texture clamping, please put a few notes in for us so that we // can later flesh it out if we decide the software renderer is fast enough to handle something // like Hamsterball. // // Clipping // There is a RECT structure defined called mClipArea. Rect is x,y,width,height -- it's NOT in // x1,y1,x2,y2 format. Anything outside of that rect should just not be clipped. If you decide // it's easier to clip against clip planes using a transform, then please scroll up to look at // the Clip() functions-- they translate the coordinates into clip planes. // SPECIAL NOTE: The clipping is in "absolute" coordinates. It is not in a 640x480 capable // format. Our framework allows us to specify a 'real' resolution to use, and conforms everything // down to whatever the screen is displaying. So, we usually use 800x600 for absolute resolution in // game. // // So, to turn the clip rectangle into the "screen resolution" from "page resolution" (page is what // we work in, screen is what displays), multiply the rectangle member variables by mPageWidthAdjust // and mPageHeightAdjust. // // "Game" coordinates to "Screen" coordinates: // int aLeft=mClipArea.mX*mPageWidthAdjust; // int aTop=mClipArea.mY*mPageHeightAdjust; // int aRight=(mClipArea.mX+mClipArea.mSWTexture->mTextureInfo.dwWidth)*mPageWidthAdjust; // int aBottom=(mClipArea.mY+mClipArea.mSWTexture->mTextureInfo.dwHeight)*mPageHeightAdjust; // // Another note: it *is* possible for the clip area to be bigger than the screen (for various // reasons). So, a final clip to 0,0-mSWTexture->mTextureInfo.dwWidth,mSWTexture->mTextureInfo.dwHeight is necessary when translating vertices. // // // Render the actual triangle strip. // int aTriCounter=0; bool aOddTriangle=false; // Our global diffuse value SWDiffuse globalDiffuse; { globalDiffuse.a = theColor.mAlpha; globalDiffuse.r = theColor.mRed; globalDiffuse.g = theColor.mGreen; globalDiffuse.b = theColor.mBlue; } // rendering flags bool globalargb = theColor!=Color::White; if (theImage) theImage->CommitBits(); bool textured = theImage!=NULL; bool talpha = (textured && (theImage->mHasAlpha || theImage->mHasTrans || blend)); for (;;) { // // Triangle strips... vertices go: // 1-2-3 2-4-3 3-4-5 4-6-5 ... every other triangle // swaps #2 & #3 vertices for draw to maintain clockwise order. // if (aTriCounter+3>theNumVerts) break; // // Picking triangle direction for culling... // struct XYZStruct *aTriRef[64]; if (!aOddTriangle) { aTriRef[0]=aTVertPtr; aTriRef[1]=aTVertPtr+1; aTriRef[2]=aTVertPtr+2; } else { aTriRef[0]=aTVertPtr; aTriRef[1]=aTVertPtr+2; aTriRef[2]=aTVertPtr+1; } aTriRef[3] = 0; // Clip XYZStruct * clipped[64]; float clipX0 = tclx0; float clipY0 = tcly0; float clipX1 = tclx1; float clipY1 = tcly1; unsigned int vCount = clipShape(clipped, aTriRef, clipX0, clipX1, clipY0, clipY1); if (vCount) { unsigned int * pFrameBuffer = reinterpret_cast(theSurface); SWVertex pVerts[64]; SWTextureInfo textureInfo; for (unsigned int i = 0; i < vCount; ++i) { pVerts[i].x = static_cast(clipped[i]->mX * 65536.0f); pVerts[i].y = static_cast(clipped[i]->mY * 65536.0f); } if (textured) { for (unsigned int i = 0; i < vCount; ++i) { pVerts[i].u = static_cast(clipped[i]->mU * (float) theImage->mWidth * 65536.0f); pVerts[i].v = static_cast(clipped[i]->mV * (float) theImage->mHeight * 65536.0f); } textureInfo.pTexture = reinterpret_cast(theImage->GetBits()); textureInfo.pitch = theImage->mWidth; textureInfo.height = theImage->mHeight; textureInfo.endpos = theImage->mWidth*theImage->mHeight; // unsigned int temp = static_cast(mSWTexture->mTextureInfo.lPitch) / (mSWTexture->mTextureInfo.ddpfPixelFormat.dwRGBBitCount / 8); unsigned int temp = theImage->mWidth; temp >>= 1; textureInfo.vShift = 0; while(temp) {textureInfo.vShift += 1; temp >>= 1;} textureInfo.vShift = 16 - textureInfo.vShift; textureInfo.uMask = static_cast(theImage->mWidth - 1) << 16; textureInfo.vMask = static_cast(theImage->mHeight - 1) << 16; } if (vertexColor) { for (unsigned int i = 0; i < vCount; ++i) { pVerts[i].a = (clipped[i]->mDiffuse >> 8) & 0xff0000; pVerts[i].r = (clipped[i]->mDiffuse >> 0) & 0xff0000; pVerts[i].g = (clipped[i]->mDiffuse << 8) & 0xff0000; pVerts[i].b = (clipped[i]->mDiffuse << 16) & 0xff0000; } } SWDrawTriangle(textured, talpha, vertexColor, globalargb, pVerts, pFrameBuffer, thePitch, &textureInfo, globalDiffuse, thePixelFormat, blend); if (vCount > 3) { for (unsigned int extraVert = 2; extraVert < vCount-1; ++extraVert) { pVerts[1] = pVerts[extraVert]; pVerts[2] = pVerts[extraVert+1]; SWDrawTriangle(textured, talpha, vertexColor, globalargb, pVerts, pFrameBuffer, thePitch, &textureInfo, globalDiffuse, thePixelFormat, blend); } } } aTVertPtr++; aTriCounter++; aOddTriangle=!aOddTriangle; } } static DrawTriFunc gDrawTriFunc[128] = {0}; void Sexy::SWTri_AddDrawTriFunc(bool textured, bool talpha, bool mod_argb, bool global_argb, int thePixelFormat, bool blend, DrawTriFunc theFunc) { int aType = (blend?1:0) | (global_argb?2:0) | (mod_argb?4:0) | (talpha?8:0) | (textured?16:0); switch (thePixelFormat) { case 0x8888: aType |= 0<<5; break; case 0x888: aType |= 1<<5; break; case 0x565: aType |= 2<<5; break; case 0x555: aType |= 3<<5; break; } gDrawTriFunc[aType] = theFunc; } void Sexy::SWTri_AddAllDrawTriFuncs() { gDrawTriFunc[0] = DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[1] = DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[2] = DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[3] = DrawTriangle_8888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[4] = DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[5] = DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[6] = DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[7] = DrawTriangle_8888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[8] = DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[9] = DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[10] = DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[11] = DrawTriangle_8888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[12] = DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[13] = DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[14] = DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[15] = DrawTriangle_8888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[16] = DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[17] = DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[18] = DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[19] = DrawTriangle_8888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[20] = DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[21] = DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[22] = DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[23] = DrawTriangle_8888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[24] = DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[25] = DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[26] = DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[27] = DrawTriangle_8888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[28] = DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[29] = DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[30] = DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[31] = DrawTriangle_8888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[32] = DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[33] = DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[34] = DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[35] = DrawTriangle_0888_TEX0_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[36] = DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[37] = DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[38] = DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[39] = DrawTriangle_0888_TEX0_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[40] = DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[41] = DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[42] = DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[43] = DrawTriangle_0888_TEX0_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[44] = DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[45] = DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[46] = DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[47] = DrawTriangle_0888_TEX0_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[48] = DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[49] = DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[50] = DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[51] = DrawTriangle_0888_TEX1_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[52] = DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[53] = DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[54] = DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[55] = DrawTriangle_0888_TEX1_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[56] = DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[57] = DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[58] = DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[59] = DrawTriangle_0888_TEX1_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[60] = DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[61] = DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[62] = DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[63] = DrawTriangle_0888_TEX1_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[64] = DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[65] = DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[66] = DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[67] = DrawTriangle_0565_TEX0_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[68] = DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[69] = DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[70] = DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[71] = DrawTriangle_0565_TEX0_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[72] = DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[73] = DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[74] = DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[75] = DrawTriangle_0565_TEX0_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[76] = DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[77] = DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[78] = DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[79] = DrawTriangle_0565_TEX0_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[80] = DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[81] = DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[82] = DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[83] = DrawTriangle_0565_TEX1_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[84] = DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[85] = DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[86] = DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[87] = DrawTriangle_0565_TEX1_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[88] = DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[89] = DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[90] = DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[91] = DrawTriangle_0565_TEX1_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[92] = DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[93] = DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[94] = DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[95] = DrawTriangle_0565_TEX1_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[96] = DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[97] = DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[98] = DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[99] = DrawTriangle_0555_TEX0_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[100] = DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[101] = DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[102] = DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[103] = DrawTriangle_0555_TEX0_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[104] = DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[105] = DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[106] = DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[107] = DrawTriangle_0555_TEX0_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[108] = DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[109] = DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[110] = DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[111] = DrawTriangle_0555_TEX0_TALPHA1_MOD1_GLOB1_BLEND1; gDrawTriFunc[112] = DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND0; gDrawTriFunc[113] = DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB0_BLEND1; gDrawTriFunc[114] = DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND0; gDrawTriFunc[115] = DrawTriangle_0555_TEX1_TALPHA0_MOD0_GLOB1_BLEND1; gDrawTriFunc[116] = DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND0; gDrawTriFunc[117] = DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB0_BLEND1; gDrawTriFunc[118] = DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND0; gDrawTriFunc[119] = DrawTriangle_0555_TEX1_TALPHA0_MOD1_GLOB1_BLEND1; gDrawTriFunc[120] = DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND0; gDrawTriFunc[121] = DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB0_BLEND1; gDrawTriFunc[122] = DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND0; gDrawTriFunc[123] = DrawTriangle_0555_TEX1_TALPHA1_MOD0_GLOB1_BLEND1; gDrawTriFunc[124] = DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND0; gDrawTriFunc[125] = DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB0_BLEND1; gDrawTriFunc[126] = DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND0; gDrawTriFunc[127] = DrawTriangle_0555_TEX1_TALPHA1_MOD1_GLOB1_BLEND1; } #include "SWTri_DrawTriangleInc1.cpp" void SWHelper::SWDrawTriangle(bool textured, bool talpha, bool mod_argb, bool global_argb, SWVertex * pVerts, unsigned int * pFrameBuffer, const unsigned int bytepitch, const SWTextureInfo * textureInfo, SWDiffuse & globalDiffuse, int thePixelFormat, bool blend) { int aType = (blend?1:0) | (global_argb?2:0) | (mod_argb?4:0) | (talpha?8:0) | (textured?16:0); switch (thePixelFormat) { case 0x8888: aType |= 0<<5; break; case 0x888: aType |= 1<<5; break; case 0x565: aType |= 2<<5; break; case 0x555: aType |= 3<<5; break; } DrawTriFunc aFunc = gDrawTriFunc[aType]; if (aFunc==NULL) { assert("You need to call SWTri_AddDrawTriFunc or SWTri_AddAllDrawTriFuncs"==NULL); } else aFunc(pVerts, pFrameBuffer, bytepitch, textureInfo, globalDiffuse); // #include "SWTri_DrawTriangleInc2.cpp" } libtuxcap-1.4.0/tuxcap/lib/KeyCodes.cpp0000644000175000017500000000703710775711737017701 0ustar inniyahinniyah#include "KeyCodes.h" using namespace Sexy; #define MAX_KEYNAME_LEN 12 typedef struct { char mKeyName[MAX_KEYNAME_LEN]; KeyCode mKeyCode; } KeyNameEntry; KeyNameEntry aKeyCodeArray[] = { {"UNKNOWN", SDLK_UNKNOWN}, {"TAB", SDLK_TAB}, {"SPACE", SDLK_SPACE}, {"BACKSPACE", SDLK_BACKSPACE}, {"INSERT", SDLK_INSERT}, {"DELETE", SDLK_DELETE}, {"RETURN", SDLK_RETURN}, {"PAUSE", SDLK_PAUSE}, {"LEFT", SDLK_LEFT}, {"UP", SDLK_UP}, {"RIGHT", SDLK_RIGHT}, {"DOWN", SDLK_DOWN}, {"ESCAPE", SDLK_ESCAPE}, {"LSHIFT", SDLK_LSHIFT}, {"RSHIFT", SDLK_RSHIFT}, {"LCONTROL", SDLK_LCTRL}, {"RCONTROL", SDLK_RCTRL}, {"LALT", SDLK_LALT}, {"RALT", SDLK_RALT}, {"F1", SDLK_F1}, {"F2", SDLK_F2}, {"F3", SDLK_F3}, {"F4", SDLK_F4}, {"F5", SDLK_F5}, {"F6", SDLK_F6}, {"F7", SDLK_F7}, {"F8", SDLK_F8}, {"F9", SDLK_F9}, {"F10", SDLK_F10}, {"F11", SDLK_F11}, {"F12", SDLK_F12}, {"F13", SDLK_F13}, {"F14", SDLK_F14}, {"F15", SDLK_F15} #if 0 {"LBUTTON", SDLK_LBUTTON}, {"RBUTTON", SDLK_RBUTTON}, {"CANCEL", SDLK_CANCEL}, {"MBUTTON", SDLK_MBUTTON}, {"BACK", SDLK_BACK}, {"CLEAR", SDLK_CLEAR}, {"MENU", SDLK_MENU}, {"CAPITAL", SDLK_CAPITAL}, {"KANA", SDLK_KANA}, {"HANGEUL", SDLK_HANGEUL}, {"HANGUL", SDLK_HANGUL}, {"JUNJA", SDLK_JUNJA}, {"FINAL", SDLK_FINAL}, {"HANJA", SDLK_HANJA}, {"KANJI", SDLK_KANJI}, {"CONVERT", SDLK_CONVERT}, {"NONCONVERT", SDLK_NONCONVERT}, {"ACCEPT", SDLK_ACCEPT}, {"MODECHANGE", SDLK_MODECHANGE}, {"PRIOR", SDLK_PRIOR}, {"NEXT", SDLK_NEXT}, {"END", SDLK_END}, {"HOME", SDLK_HOME}, {"SELECT", SDLK_SELECT}, {"PRINT", SDLK_PRINT}, {"EXECUTE", SDLK_EXECUTE}, {"SNAPSHOT", SDLK_SNAPSHOT}, {"HELP", SDLK_HELP}, {"LWIN", SDLK_LWIN}, {"RWIN", SDLK_RWIN}, {"APPS", SDLK_APPS}, {"NUMPAD0", SDLK_NUMPAD0}, {"NUMPAD1", SDLK_NUMPAD1}, {"NUMPAD2", SDLK_NUMPAD2}, {"NUMPAD3", SDLK_NUMPAD3}, {"NUMPAD4", SDLK_NUMPAD4}, {"NUMPAD5", SDLK_NUMPAD5}, {"NUMPAD6", SDLK_NUMPAD6}, {"NUMPAD7", SDLK_NUMPAD7}, {"NUMPAD8", SDLK_NUMPAD8}, {"NUMPAD9", SDLK_NUMPAD9}, {"MULTIPLY", SDLK_MULTIPLY}, {"ADD", SDLK_ADD}, {"SEPARATOR", SDLK_SEPARATOR}, {"SUBTRACT", SDLK_SUBTRACT}, {"DECIMAL", SDLK_DECIMAL}, {"DIVIDE", SDLK_DIVIDE}, {"F16", SDLK_F16}, {"F17", SDLK_F17}, {"F18", SDLK_F18}, {"F19", SDLK_F19}, {"F20", SDLK_F20}, {"F21", SDLK_F21}, {"F22", SDLK_F22}, {"F23", SDLK_F23}, {"F24", SDLK_F24}, {"NUMLOCK", SDLK_NUMLOCK}, {"SCROLL", SDLK_SCROLL} #endif }; KeyCode Sexy::GetKeyCodeFromName(const std::string& theKeyName) { if (theKeyName.length() >= MAX_KEYNAME_LEN-1) return SDLK_UNKNOWN; std::string copy = theKeyName; if (theKeyName.length() == 1) { std::transform(copy.begin(), copy.end(), copy.begin(), tolower); unsigned char aKeyNameChar = copy[0]; if (((aKeyNameChar >= 0x5B) && (aKeyNameChar <= 0x7F)) || ((aKeyNameChar >= 0x21) && (aKeyNameChar <= 0x40))) return (KeyCode) aKeyNameChar; } std::transform(copy.begin(), copy.end(), copy.begin(), toupper); for (int i = 0; i < sizeof(aKeyCodeArray)/sizeof(aKeyCodeArray[0]); i++) if (strcmp(copy.c_str(), aKeyCodeArray[i].mKeyName) == 0) return aKeyCodeArray[i].mKeyCode; return SDLK_UNKNOWN; } const std::string Sexy::GetKeyNameFromCode(const KeyCode& theKeyCode) { if (((theKeyCode >= 0x5B) && (theKeyCode <= 0x7F)) || ((theKeyCode >= 0x21) && (theKeyCode <= 0x40))) { char aStr[2] = {(char) theKeyCode, 0}; return aStr; } for (int i = 0; i < sizeof(aKeyCodeArray)/sizeof(aKeyCodeArray[0]); i++) if (theKeyCode == aKeyCodeArray[i].mKeyCode) return aKeyCodeArray[i].mKeyName; return "UNKNOWN"; } libtuxcap-1.4.0/tuxcap/lib/WidgetManager.cpp0000644000175000017500000004201011202747630020662 0ustar inniyahinniyah#include "WidgetManager.h" #include "Widget.h" #include "Graphics.h" #include "Image.h" #include "SexyAppBase.h" #include "MemoryImage.h" #include "DDImage.h" #if 0 #include "PerfTimer.h" #include "Debug.h" #endif using namespace Sexy; using namespace std; WidgetManager::WidgetManager(SexyAppBase* theApp) { mApp = theApp; mMinDeferredOverlayPriority = 0x7FFFFFFF; mWidgetManager = this; mMouseIn = false; mDefaultTab = NULL; mImage = NULL; mLastHadTransients = false; mPopupCommandWidget = NULL; mFocusWidget = NULL; mLastDownWidget = NULL; mOverWidget = NULL; mBaseModalWidget = NULL; mDefaultBelowModalFlagsMod.mRemoveFlags = WIDGETFLAGS_ALLOW_MOUSE | WIDGETFLAGS_ALLOW_FOCUS; mWidth = 0; mHeight = 0; mHasFocus = true; mUpdateCnt = 0; mLastDownButtonId = 0; mDownButtons = 0; mActualDownButtons = 0; mWidgetFlags = WIDGETFLAGS_UPDATE | WIDGETFLAGS_DRAW | WIDGETFLAGS_CLIP | WIDGETFLAGS_ALLOW_MOUSE | WIDGETFLAGS_ALLOW_FOCUS; for (int i = 0; i < SDLK_LAST; i++) mKeyDown[i] = false; } WidgetManager::~WidgetManager() { FreeResources(); } void WidgetManager::FreeResources() { } void WidgetManager::DisableWidget(Widget* theWidget) { if (mOverWidget == theWidget) { Widget* aOverWidget = mOverWidget; mOverWidget = NULL; MouseLeave(aOverWidget); } if (mLastDownWidget == theWidget) { Widget* aLastDownWidget = mLastDownWidget; mLastDownWidget = NULL; DoMouseUps(aLastDownWidget, mDownButtons); mDownButtons = 0; } if (mFocusWidget == theWidget) { Widget* aFocusWidget = mFocusWidget; mFocusWidget = NULL; aFocusWidget->LostFocus(); } if (mBaseModalWidget == theWidget) mBaseModalWidget = NULL; } int WidgetManager::GetWidgetFlags() { return mHasFocus ? mWidgetFlags : GetModFlags(mWidgetFlags, mLostFocusFlagsMod); } Widget* WidgetManager::GetAnyWidgetAt(int x, int y, int* theWidgetX, int* theWidgetY) { bool found; return GetWidgetAtHelper(x, y, GetWidgetFlags(), &found, theWidgetX, theWidgetY); } Widget* WidgetManager::GetWidgetAt(int x, int y, int* theWidgetX, int* theWidgetY) { Widget* aWidget = GetAnyWidgetAt(x, y, theWidgetX, theWidgetY); if ((aWidget != NULL) && (aWidget->mDisabled)) aWidget = NULL; return aWidget; } bool WidgetManager::IsLeftButtonDown() { return (mActualDownButtons&1)?true:false; } bool WidgetManager::IsMiddleButtonDown() { return (mActualDownButtons&4)?true:false; } bool WidgetManager::IsRightButtonDown() { return (mActualDownButtons&2)?true:false; } void WidgetManager::DoMouseUps() { if (mLastDownWidget!=NULL && mDownButtons!=0) { DoMouseUps(mLastDownWidget, mDownButtons); mDownButtons = 0; mLastDownWidget = NULL; } } void WidgetManager::DeferOverlay(Widget* theWidget, int thePriority) { mDeferredOverlayWidgets.push_back(std::pair(theWidget, thePriority)); if (thePriority < mMinDeferredOverlayPriority) mMinDeferredOverlayPriority = thePriority; } void WidgetManager::FlushDeferredOverlayWidgets(int theMaxPriority) { for (;;) { int aNextMinPriority = 0x7FFFFFFF; for (int i = 0; i < (int) mDeferredOverlayWidgets.size(); i++) { Widget* aWidget = mDeferredOverlayWidgets[i].first; if (aWidget != NULL) { int aPriority = mDeferredOverlayWidgets[i].second; if (aPriority == mMinDeferredOverlayPriority) { // Overlays don't get clipped Graphics g(*mCurG); g.Translate(-mMouseDestRect.mX, -mMouseDestRect.mY); g.Translate(aWidget->mX, aWidget->mY); g.SetFastStretch(!g.Is3D()); g.SetLinearBlend(g.Is3D()); aWidget->DrawOverlay(&g, aPriority); mDeferredOverlayWidgets[i].first = NULL; } else { if (aPriority < aNextMinPriority) aNextMinPriority = aPriority; } } } mMinDeferredOverlayPriority = aNextMinPriority; if (aNextMinPriority == 0x7FFFFFFF) { // No more widgets lined up for overlays, clear our vector mDeferredOverlayWidgets.resize(0); break; } // Lowest overlay priority is higher or equal to our current widget, // so continue deferring if (aNextMinPriority >= theMaxPriority) break; } } void WidgetManager::DoMouseUps(Widget* theWidget, uint32_t theDownCode) { int aClickCountTable[3] = { 1,-1, 3 }; for (int i = 0; i < 3; i++) { if ((theDownCode & (1 << i)) != 0) { theWidget->mIsDown = false; theWidget->MouseUp(mLastMouseX - theWidget->mX, mLastMouseY - theWidget->mY, aClickCountTable[i]); } } } void WidgetManager::RemapMouse(int& theX, int& theY) { theX = ( theX - mMouseSourceRect.mX ) * mMouseDestRect.mWidth / mMouseSourceRect.mWidth + mMouseDestRect.mX; theY = ( theY - mMouseSourceRect.mY ) * mMouseDestRect.mHeight / mMouseSourceRect.mHeight + mMouseDestRect.mY; } void WidgetManager::MouseEnter(Widget* theWidget) { theWidget->mIsOver = true; theWidget->MouseEnter(); if (theWidget->mDoFinger) theWidget->ShowFinger(true); } void WidgetManager::MouseLeave(Widget* theWidget) { theWidget->mIsOver = false; theWidget->MouseLeave(); if (theWidget->mDoFinger) theWidget->ShowFinger(false); } void WidgetManager::SetBaseModal(Widget* theWidget, const FlagsMod& theBelowFlagsMod) { mBaseModalWidget = theWidget; mBelowModalFlagsMod = theBelowFlagsMod; if ((mOverWidget != NULL) && (mBelowModalFlagsMod.mRemoveFlags & WIDGETFLAGS_ALLOW_MOUSE) && (IsBelow(mOverWidget, mBaseModalWidget))) { Widget* aWidget = mOverWidget; mOverWidget = NULL; MouseLeave(aWidget); } if ((mLastDownWidget != NULL) && (mBelowModalFlagsMod.mRemoveFlags & WIDGETFLAGS_ALLOW_MOUSE) && (IsBelow(mLastDownWidget, mBaseModalWidget))) { Widget* aWidget = mLastDownWidget; int aDownButtons = mDownButtons; mDownButtons = 0; mLastDownWidget = NULL; DoMouseUps(aWidget, aDownButtons); } if ((mFocusWidget != NULL) && (mBelowModalFlagsMod.mRemoveFlags & WIDGETFLAGS_ALLOW_FOCUS) && (IsBelow(mFocusWidget, mBaseModalWidget))) { Widget* aWidget = mFocusWidget; mFocusWidget = NULL; aWidget->LostFocus(); } } void WidgetManager::AddBaseModal(Widget* theWidget, const FlagsMod& theBelowFlagsMod) { PreModalInfo aPreModalInfo; aPreModalInfo.mBaseModalWidget = theWidget; aPreModalInfo.mPrevBaseModalWidget = mBaseModalWidget; aPreModalInfo.mPrevFocusWidget = mFocusWidget; aPreModalInfo.mPrevBelowModalFlagsMod = mBelowModalFlagsMod; mPreModalInfoList.push_back(aPreModalInfo); SetBaseModal(theWidget, theBelowFlagsMod); } void WidgetManager::AddBaseModal(Widget* theWidget) { AddBaseModal(theWidget, mDefaultBelowModalFlagsMod); } void WidgetManager::RemoveBaseModal(Widget* theWidget) { assert(mPreModalInfoList.size() > 0); bool first = true; while (mPreModalInfoList.size() > 0) { PreModalInfo* aPreModalInfo = &mPreModalInfoList.back(); if ((first) && (aPreModalInfo->mBaseModalWidget != theWidget)) { // We don't remove it yet, because we want to restore // its keyboard focused widget and crap later return; } // If we removed a widget's self from pre-modal info before // then that means the dialog got removed out-of-order but we // deferred setting the state back until now bool done = (aPreModalInfo->mPrevBaseModalWidget != NULL) || (mPreModalInfoList.size() == 1); SetBaseModal(aPreModalInfo->mPrevBaseModalWidget, aPreModalInfo->mPrevBelowModalFlagsMod); if (mFocusWidget == NULL) { mFocusWidget = aPreModalInfo->mPrevFocusWidget; if (mFocusWidget != NULL) mFocusWidget->GotFocus(); } mPreModalInfoList.pop_back(); if (done) break; first = false; } } void WidgetManager::Resize(const Rect& theMouseDestRect, const Rect& theMouseSourceRect) { mWidth = theMouseDestRect.mWidth + 2 * theMouseDestRect.mX; mHeight = theMouseDestRect.mHeight + 2 * theMouseDestRect.mY; mMouseDestRect = theMouseDestRect; mMouseSourceRect = theMouseSourceRect; } void WidgetManager::SetFocus(Widget* aWidget) { if (aWidget==mFocusWidget) return; if (mFocusWidget != NULL) mFocusWidget->LostFocus(); if ((aWidget != NULL) && (aWidget->mWidgetManager == this)) { mFocusWidget = aWidget; if ((mHasFocus) && (mFocusWidget != NULL)) mFocusWidget->GotFocus(); } else mFocusWidget = NULL; } void WidgetManager::GotFocus() { if (!mHasFocus) { mHasFocus = true; if (mFocusWidget != NULL) mFocusWidget->GotFocus(); } } void WidgetManager::LostFocus() { if (mHasFocus) { mActualDownButtons = 0; for (int aKeyNum = 0; aKeyNum < SDLK_LAST; aKeyNum++) { if (mKeyDown[aKeyNum]) KeyUp((SDLKey)aKeyNum); } mHasFocus = false; if (mFocusWidget != NULL) mFocusWidget->LostFocus(); } } void WidgetManager::InitModalFlags(ModalFlags* theModalFlags) { theModalFlags->mIsOver = mBaseModalWidget == NULL; theModalFlags->mOverFlags = GetWidgetFlags(); theModalFlags->mUnderFlags = GetModFlags(theModalFlags->mOverFlags, mBelowModalFlagsMod); } void WidgetManager::DrawWidgetsTo(Graphics* g) { mCurG = g; ModalFlags aModalFlags; InitModalFlags(&aModalFlags); WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget->mVisible) { Graphics aClipG(*g); aClipG.SetFastStretch(true); aClipG.Translate(aWidget->mX, aWidget->mY); aWidget->DrawAll(&aModalFlags, &aClipG); } ++anItr; } mCurG = NULL; } bool WidgetManager::DrawScreen() { #if 0 SEXY_AUTO_PERF("WidgetManager::DrawScreen"); #endif ModalFlags aModalFlags; InitModalFlags(&aModalFlags); bool drewStuff = false; int aDirtyCount = 0; bool hasTransients = false; bool hasDirtyTransients = false; // Survey WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget->mDirty) aDirtyCount++; ++anItr; } mMinDeferredOverlayPriority = 0x7FFFFFFF; mDeferredOverlayWidgets.resize(0); Graphics aScrG(mImage); mCurG = &aScrG; DDImage* aDDImage = dynamic_cast(mImage); bool surfaceLocked = false; if (aDDImage != NULL) surfaceLocked = aDDImage->LockSurface(); if (aDirtyCount > 0) { Graphics g(aScrG); g.Translate(-mMouseDestRect.mX, -mMouseDestRect.mY); bool is3D = mApp->Is3DAccelerated(); WidgetList::iterator anItr = mWidgets.begin(); while (anItr != mWidgets.end()) { Widget* aWidget = *anItr; if (aWidget == mWidgetManager->mBaseModalWidget) aModalFlags.mIsOver = true; if ((aWidget->mDirty) && (aWidget->mVisible)) { Graphics aClipG(g); aClipG.SetFastStretch(!is3D); aClipG.SetLinearBlend(is3D); aClipG.Translate(aWidget->mX, aWidget->mY); aWidget->DrawAll(&aModalFlags, &aClipG); aDirtyCount++; drewStuff = true; aWidget->mDirty = false; } ++anItr; } } FlushDeferredOverlayWidgets(0x7FFFFFFF); if (aDDImage != NULL && surfaceLocked) aDDImage->UnlockSurface(); mCurG = NULL; return drewStuff; } bool WidgetManager::UpdateFrame() { #if 0 SEXY_AUTO_PERF("WidgetManager::UpdateFrame"); #endif ModalFlags aModalFlags; InitModalFlags(&aModalFlags); // Keep us from having mLastWMUpdateCount interfere with our own updating mUpdateCnt++; mLastWMUpdateCount = mUpdateCnt; UpdateAll(&aModalFlags); return mDirty; } bool WidgetManager::UpdateFrameF(float theFrac) { #if 0 SEXY_AUTO_PERF("WidgetManager::UpdateFrame"); #endif ModalFlags aModalFlags; InitModalFlags(&aModalFlags); UpdateFAll(&aModalFlags, theFrac); return mDirty; } void WidgetManager::SetPopupCommandWidget(Widget* theList) { mPopupCommandWidget = theList; AddWidget(mPopupCommandWidget); } void WidgetManager::RemovePopupCommandWidget() { if (mPopupCommandWidget != NULL) { Widget *aWidget = mPopupCommandWidget; mPopupCommandWidget = NULL; RemoveWidget(aWidget); } } void WidgetManager::MousePosition(int x, int y) { int aLastMouseX = mLastMouseX; int aLastMouseY = mLastMouseY; mLastMouseX = x; mLastMouseY = y; int aWidgetX; int aWidgetY; Widget* aWidget = GetWidgetAt(x, y, &aWidgetX, &aWidgetY); if (aWidget != mOverWidget) { Widget* aLastOverWidget = mOverWidget; mOverWidget = NULL; if (aLastOverWidget != NULL) MouseLeave(aLastOverWidget); mOverWidget = aWidget; if (aWidget != NULL) { MouseEnter(aWidget); aWidget->MouseMove(aWidgetX, aWidgetY); } } else if ((aLastMouseX != x) || (aLastMouseY != y)) { if (aWidget != NULL) { aWidget->MouseMove(aWidgetX, aWidgetY); } } } void WidgetManager::RehupMouse() { if (mLastDownWidget != NULL) { if (mOverWidget != NULL) { Widget* aWidgetOver = GetWidgetAt(mLastMouseX, mLastMouseY, NULL, NULL); if (aWidgetOver != mLastDownWidget) { Widget* anOverWidget = mOverWidget; mOverWidget = NULL; MouseLeave(anOverWidget); } } } else if (mMouseIn) MousePosition(mLastMouseX, mLastMouseY); } bool WidgetManager::MouseUp(int x, int y, int theClickCount) { mLastInputUpdateCnt = mUpdateCnt; int aMask; if (theClickCount < 0) aMask = 0x02; else if (theClickCount == 3) aMask = 0x04; else aMask = 0x01; // Make sure that we thought this button was down anyway - possibly not, if we // disabled the widget already or something mActualDownButtons &= ~aMask; if ((mLastDownWidget != NULL) && ((mDownButtons & aMask) != 0)) { Widget* aLastDownWidget = mLastDownWidget; mDownButtons &= ~aMask; if (mDownButtons == 0) mLastDownWidget = NULL; aLastDownWidget->mIsDown = false; aLastDownWidget->MouseUp(x - aLastDownWidget->mX, y - aLastDownWidget->mY, theClickCount); } else mDownButtons &= ~aMask; MousePosition(x, y); return true; } bool WidgetManager::MouseDown(int x, int y, int theClickCount) { mLastInputUpdateCnt = mUpdateCnt; if (theClickCount < 0) mActualDownButtons |= 0x02; else if (theClickCount == 3) mActualDownButtons |= 0x04; else mActualDownButtons |= 0x01; MousePosition(x, y); if ((mPopupCommandWidget != NULL) && (!mPopupCommandWidget->Contains(x, y))) RemovePopupCommandWidget(); int aWidgetX; int aWidgetY; Widget* aWidget = GetWidgetAt(x, y, &aWidgetX, &aWidgetY); // Begin mouse down options /* // Option 1 //This code sets a new widget as the mouse drag focus widget and lets the old //mousedownwidget think the buttons popped up. if ((mLastDownWidget != NULL) && (mLastDownWidget != aWidget)) { DoMouseUps(mLastDownWidget, mDownButtons); mDownButtons = 0; } */ // Option 2 // This code passes all button downs to the mLastDownWidget if (mLastDownWidget != NULL) aWidget = mLastDownWidget; // End mouse down options if (theClickCount < 0) { mLastDownButtonId = -1; mDownButtons |= 0x02; } else if (theClickCount == 3) { mLastDownButtonId = 2; mDownButtons |= 0x04; } else { mLastDownButtonId = 1; mDownButtons |= 0x01; } mLastDownWidget = aWidget; if (aWidget != NULL) { if (aWidget->WantsFocus()) SetFocus(aWidget); aWidget->mIsDown = true; aWidget->MouseDown(aWidgetX, aWidgetY, theClickCount); } return true; } bool WidgetManager::MouseMove(int x, int y) { mLastInputUpdateCnt = mUpdateCnt; if (mDownButtons) return MouseDrag(x,y); mMouseIn = true; MousePosition(x, y); return true; } bool WidgetManager::MouseDrag(int x, int y) { mLastInputUpdateCnt = mUpdateCnt; mMouseIn = true; mLastMouseX = x; mLastMouseY = y; if ((mOverWidget != NULL) && (mOverWidget != mLastDownWidget)) { Widget* anOverWidget = mOverWidget; mOverWidget = NULL; MouseLeave(anOverWidget); } if (mLastDownWidget != NULL) { Point anAbsPos = mLastDownWidget->GetAbsPos(); int aWidgetX = x - anAbsPos.mX; int aWidgetY = y - anAbsPos.mY; mLastDownWidget->MouseDrag(aWidgetX, aWidgetY); Widget* aWidgetOver = GetWidgetAt(x, y, NULL, NULL); if ((aWidgetOver == mLastDownWidget) && (aWidgetOver != NULL)) { if (mOverWidget == NULL) { mOverWidget = mLastDownWidget; MouseEnter(mOverWidget); } } else { if (mOverWidget != NULL) { Widget* anOverWidget = mOverWidget; mOverWidget = NULL; MouseLeave(anOverWidget); } } } return true; } bool WidgetManager::MouseExit(int x, int y) { mLastInputUpdateCnt = mUpdateCnt; mMouseIn = false; if (mOverWidget != NULL) { MouseLeave(mOverWidget); mOverWidget = NULL; } return true; } void WidgetManager::MouseWheel(int theDelta) { mLastInputUpdateCnt = mUpdateCnt; if (mFocusWidget != NULL) mFocusWidget->MouseWheel(theDelta); } bool WidgetManager::KeyChar(SexyChar theChar) { mLastInputUpdateCnt = mUpdateCnt; if (theChar == SDLK_TAB) { //TODO: Check thing if (mKeyDown[SDLK_LCTRL] || mKeyDown[SDLK_RCTRL]) { if (mDefaultTab != NULL) mDefaultTab->KeyChar(theChar); return true; } } if (mFocusWidget != NULL) mFocusWidget->KeyChar(theChar); return true; } bool WidgetManager::KeyDown(SDLKey key) { mLastInputUpdateCnt = mUpdateCnt; if ((key >= 0) && (key < SDLK_LAST)) mKeyDown[key] = true; if (mFocusWidget != NULL) mFocusWidget->KeyDown(key); return true; } bool WidgetManager::KeyUp(SDLKey key) { mLastInputUpdateCnt = mUpdateCnt; if ((key >= 0) && (key < SDLK_LAST)) mKeyDown[key] = false; if ((key == SDLK_TAB) && (mKeyDown[SDLK_RCTRL] || mKeyDown[SDLK_LCTRL])) return true; if (mFocusWidget != NULL) mFocusWidget->KeyUp(key); return true; } libtuxcap-1.4.0/tuxcap/lib/SexyAppBase.cpp0000644000175000017500000053703711202747630020352 0ustar inniyahinniyah//#define SEXY_TRACING_ENABLED //#define SEXY_PERF_ENABLED //#define SEXY_MEMTRACE #include "SexyAppBase.h" #include #include #include #include #include #include #include #include #include #include #include "MTRand.h" #include "Rect.h" #include "WidgetManager.h" #include "Widget.h" #include "SDL_keysym.h" #include "MemoryImage.h" #include "ImageLib.h" #include "SoundManager.h" #include "SoundInstance.h" #include "MusicInterface.h" #ifdef USE_AUDIERE #include "AudiereMusicInterface.h" #include "AudiereSoundManager.h" #else #include "SDL_mixer.h" #include "SDLMixerMusicInterface.h" #include "SDLMixerSoundManager.h" #endif #include "DDInterface.h" #include "DDImage.h" #include "ResourceManager.h" #include "Dialog.h" #include "D3DInterface.h" #include "XMLWriter.h" #include "XMLParser.h" #include "PropertiesParser.h" #include "SWTri.h" #include "ImageFont.h" #if 0 #include "ModVal.h" #include "DSoundManager.h" #include "DSoundInstance.h" #include "SEHCatcher.h" #include "Debug.h" #include "D3DTester.h" #include "HTTPTransfer.h" #include "PerfTimer.h" #include #include #include #include #include "SysFont.h" #include "AutoCrit.h" #include "Debug.h" #include "../PakLib/PakInterface.h" #include "memmgr.h" #endif using namespace Sexy; const int DEMO_FILE_ID = 0x42BEEF78; const int DEMO_VERSION = 2; SexyAppBase* Sexy::gSexyAppBase = NULL; #if 0 SEHCatcher Sexy::gSEHCatcher; HMODULE gDDrawDLL = NULL; HMODULE gDSoundDLL = NULL; HMODULE gVersionDLL = NULL; //typedef struct { UINT cbSize; DWORD dwTime; } LASTINPUTINFO; typedef BOOL (WINAPI*GetLastInputInfoFunc)(LASTINPUTINFO *plii); GetLastInputInfoFunc gGetLastInputInfoFunc = NULL; #endif static bool gScreenSaverActive = false; #ifndef SPI_GETSCREENSAVERRUNNING #define SPI_GETSCREENSAVERRUNNING 114 #endif //HotSpot: 11 4 //Size: 32 32 unsigned char gFingerCursorData[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc3,0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xc0, 0x1f, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xfc, 0x40, 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x1b, 0x60, 0x00, 0x00, 0x1b, 0x68, 0x00, 0x00, 0x1b, 0x6c, 0x00, 0x01, 0x9f, 0xec, 0x00, 0x01, 0xdf, 0xfc, 0x00, 0x00, 0xdf, 0xfc, 0x00, 0x00, 0x5f, 0xfc, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //HotSpot: 15 10 //Size: 32 32 unsigned char gDraggingCursorData[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xff, 0xe0, 0x00, 0xff, 0xfe, 0x60, 0x00, 0xff, 0xfc, 0x20, 0x00, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xf0, 0x03, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x01, 0xb0, 0x00, 0x00, 0x0d, 0xb0, 0x00, 0x00, 0x0d, 0xb6, 0x00, 0x00, 0x0d, 0xb6, 0x00, 0x00, 0x0d, 0xb6, 0x00, 0x00, 0x0d, 0xb6, 0x00, 0x00, 0x0d, 0xb6, 0x00, 0x01, 0x8d, 0xb6, 0x00, 0x01, 0xcf, 0xfe, 0x00, 0x00, 0xef, 0xfe, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static DDImage* gFPSImage = NULL; static ImageFont* aFont = NULL; #if 0 ////////////////////////////////////////////////////////////////////////// typedef HRESULT (WINAPI *SHGetFolderPathFunc)(HWND, int, HANDLE, DWORD, LPTSTR); void* GetSHGetFolderPath(const char* theDLL, HMODULE* theMod) { HMODULE aMod = LoadLibrary(theDLL); SHGetFolderPathFunc aFunc = NULL; if (aMod != NULL) { *((void**)&aFunc) = (void*)GetProcAddress(aMod, "SHGetFolderPathA"); if (aFunc == NULL) { FreeLibrary(aMod); aMod = NULL; } } *theMod = aMod; return aFunc; } #endif ////////////////////////////////////////////////////////////////////////// SexyAppBase::SexyAppBase() { gSexyAppBase = this; if( SDL_Init( SDL_INIT_VIDEO) < 0 ) { /* Failed, exit. */ fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) ); } if (SDL_InitSubSystem(SDL_INIT_TIMER) == -1) { fprintf( stderr, "Timer initialization failed: %s\n", SDL_GetError( ) ); } #ifndef USE_AUDIERE if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { fprintf( stderr, "Audio initialization failed: %s\n", SDL_GetError( ) ); } #endif const char* path = getenv("HOME"); SetAppDataFolder(path); mMutex = NULL; mNotifyGameMessage = 0; #ifdef _DEBUG mOnlyAllowOneCopyToRun = false; #else mOnlyAllowOneCopyToRun = true; #endif #if 0 // Extract product version char aPath[_MAX_PATH]; GetModuleFileNameA(NULL, aPath, 256); mProductVersion = GetProductVersion(aPath); mChangeDirTo = GetFileDir(aPath); #endif mTimeLoaded = SDL_GetTicks(); mNoDefer = false; mFullScreenPageFlip = true; // should we page flip in fullscreen? mSEHOccured = false; mProdName = "Product"; mTitle = _S("SexyApp"); mShutdown = false; mExitToTop = false; mWidth = 640; mHeight = 480; mFullscreenBits = 32; //FIXME mIsWindowed = true; mIsPhysWindowed = true; mFullScreenWindow = false; mPreferredX = -1; mPreferredY = -1; mIsScreenSaver = false; mAllowMonitorPowersave = true; mMusicInterface = NULL; mWindowIconBMP = ""; #if 0 mHWnd = NULL; mInvisHWnd = NULL; #endif mFrameTime = 10; mNonDrawCount = 0; mDrawCount = 0; mSleepCount = 0; mUpdateCount = 0; mUpdateAppState = 0; mUpdateAppDepth = 0; mPendingUpdatesAcc = 0.0; mUpdateFTimeAcc = 0.0; mHasPendingDraw = true; mIsDrawing = false; mLastDrawWasEmpty = false; mUpdateMultiplier = 1; mPaused = false; mFastForwardToUpdateNum = 0; mFastForwardToMarker = false; mFastForwardStep = false; mLastTimeCheck = 0; mLastDrawTick = SDL_GetTicks(); mNextDrawTick = SDL_GetTicks(); mFPSStartTick = SDL_GetTicks(); mVSyncBrokenCount = 0; mVSyncBrokenTestStartTick = 0; mVSyncBrokenTestUpdates = 0; mRelaxUpdateBacklogCount = 0; mSoundManager = NULL; mDDInterface = NULL; #if 0 mOverrideCursor = NULL; mOldWndProc = 0; mMinVidMemory3D = 6; mRecommendedVidMemory3D = 14; mWindowAspect.Set(4, 3); #endif mCursorNum = CURSOR_POINTER; mMouseIn = false; mRunning = false; mActive = true; mProcessInTimer = false; mMinimized = false; mPhysMinimized = false; mIsDisabled = false; mLoaded = false; mYieldMainThread = false; mLoadingFailed = false; mLoadingThreadStarted = false; mLoadingThreadCompleted = false; mAutoStartLoadingThread = true; mNumLoadingThreadTasks = 0; mCompletedLoadingThreadTasks = 0; mSysCursor = true; mForceFullscreen = false; mForceWindowed = false; mHasFocus = true; mCustomCursorsEnabled = false; mCustomCursorDirty = false; mIsOpeningURL = false; mInitialized = false; mLastShutdownWasGraceful = true; mReadFromRegistry = false; mCmdLineParsed = false; mSkipSignatureChecks = false; mCtrlDown = false; mAltDown = false; mStepMode = 0; mCleanupSharedImages = false; mStandardWordWrap = true; mbAllowExtendedChars = true; mEnableMaximizeButton = false; mMusicVolume = 0.85; mSfxVolume = 0.85; mDemoMusicVolume = mDemoSfxVolume = 0.0; mMuteCount = 0; mAutoMuteCount = 0; mDemoMute = false; mMuteOnLostFocus = true; mCurHandleNum = 0; mFPSTime = 0; mFPSFlipCount = 0; mFPSCount = 0; mFPSDirtyCount = 0; mShowFPS = false; mShowFPSMode = FPS_ShowFPS; mDrawTime = 0; mScreenBltTime = 0; mAlphaDisabled = false; mDebugKeysEnabled = false; mNoSoundNeeded = false; mWantFMod = false; mSyncRefreshRate = 100; mVSyncUpdates = false; mVSyncBroken = false; mWaitForVSync = false; mSoftVSyncWait = true; mUserChanged3DSetting = false; mAutoEnable3D = false; mTest3D = true; mWidescreenAware = false; mEnableWindowAspect = false; mIsWideWindow = false; int i; for (i = 0; i < NUM_CURSORS; i++) mCursorImages[i] = NULL; for (i = 0; i < 256; i++) mAdd8BitMaxTable[i] = i; for (i = 256; i < 512; i++) mAdd8BitMaxTable[i] = 255; #if 0 // Set default strings. Init could read in overrides from partner.xml SetString("DIALOG_BUTTON_OK", L"OK"); SetString("DIALOG_BUTTON_CANCEL", L"CANCEL"); SetString("UPDATE_CHECK_TITLE", L"Update Check"); SetString("UPDATE_CHECK_BODY", L"Checking if there are any updates available for this product ..."); SetString("UP_TO_DATE_TITLE", L"Up to Date"); SetString("UP_TO_DATE_BODY", L"There are no updates available for this product at this time."); SetString("NEW_VERSION_TITLE", L"New Version"); SetString("NEW_VERSION_BODY", L"There is an update available for this product. Would you like to visit the web site to download it?"); mRecordingDemoBuffer = false; mDemoPrefix = "sexyapp"; mDemoFileName = mDemoPrefix + ".dmo"; mPlayingDemoBuffer = false; mManualShutdown = false; #endif mLastDemoMouseX = 0; mLastDemoMouseY = 0; mLastDemoUpdateCnt = 0; mDemoNeedsCommand = true; mDemoLoadingComplete = false; mDemoLength = 0; mDemoCmdNum = 0; mDemoCmdOrder = -1; // Means we haven't processed any demo commands yet mDemoCmdBitPos = 0; mPrimaryThreadId = 0; mWidgetManager = new WidgetManager(this); mResourceManager = new ResourceManager(this); #if 0 if (GetSystemMetrics(86)) // check for tablet pc { mTabletPC = true; mFullScreenPageFlip = false; // so that tablet keyboard can show up } else mTabletPC = false; gSEHCatcher.mApp = this; #endif } SexyAppBase::~SexyAppBase() { if (!mShutdown) Shutdown(); // Check if we should write the current 3d setting bool showedMsgBox = false; if (mUserChanged3DSetting) { bool writeToRegistry = true; #if 0 if(!is3DOptionSet) // should we write the option? { if(!Is3DAccelerationRecommended()) // may need to prompt user if he wants to keep 3d acceleration on { if (Is3DAccelerated()) { showedMsgBox = true; int aResult = MessageBox(NULL, GetString("HARDWARE_ACCEL_SWITCHED_ON", _S("Hardware Acceleration was switched on during this session.\r\n") _S("If this resulted in slower performance, it should be switched off.\r\n") _S("Would you like to keep Hardware Acceleration switched on?")).c_str(), (StringToSexyString(mCompanyName) + _S(" ") + GetString("HARDWARE_ACCEL_CONFIRMATION", _S("Hardware Acceleration Confirmation"))).c_str(), MB_YESNO | MB_ICONQUESTION); mDDInterface->mIs3D = aResult == IDYES ? true : false; if (aResult!=IDYES) writeToRegistry = false; } else writeToRegistry = false; } } #endif RegistryWriteBoolean("Is3D", mDDInterface->mIs3D); } #if 0 extern bool gD3DInterfacePreDrawError; if (!showedMsgBox && gD3DInterfacePreDrawError && !IsScreenSaver()) { int aResult = MessageBox(NULL, GetString("HARDWARE_ACCEL_NOT_WORKING", _S("Hardware Acceleration may not have been working correctly during this session.\r\n") _S("If you noticed graphics problems, you may want to turn off Hardware Acceleration.\r\n") _S("Would you like to keep Hardware Acceleration switched on?")).c_str(), (StringToSexyString(mCompanyName) + _S(" ") + GetString("HARDWARE_ACCEL_CONFIRMATION", _S("Hardware Acceleration Confirmation"))).c_str(), MB_YESNO | MB_ICONQUESTION); if (aResult==IDNO) RegistryWriteBoolean("Is3D", false); } if (mInvisHWnd != NULL) { HWND aWindow = mInvisHWnd; mInvisHWnd = NULL; SetWindowLong(aWindow, GWL_USERDATA, NULL); DestroyWindow(aWindow); } if (mHWnd != NULL) { HWND aWindow = mHWnd; mHWnd = NULL; SetWindowLong(aWindow, GWL_USERDATA, NULL); /*char aStr[256]; sprintf(aStr, "HWND: %d\r\n", aWindow); OutputDebugString(aStr);*/ DestroyWindow(aWindow); } WriteDemoBuffer(); FreeLibrary(gDDrawDLL); FreeLibrary(gDSoundDLL); FreeLibrary(gVersionDLL); #endif delete gFPSImage; gFPSImage = NULL; delete aFont; aFont = NULL; WaitForLoadingThread(); DialogMap::iterator aDialogItr = mDialogMap.begin(); while (aDialogItr != mDialogMap.end()) { mWidgetManager->RemoveWidget(aDialogItr->second); delete aDialogItr->second; ++aDialogItr; } mDialogMap.clear(); mDialogList.clear(); delete mWidgetManager; delete mResourceManager; SharedImageMap::iterator aSharedImageItr = mSharedImageMap.begin(); while (aSharedImageItr != mSharedImageMap.end()) { SharedImage* aSharedImage = &aSharedImageItr->second; assert(aSharedImage->mRefCount == 0); delete aSharedImage->mImage; mSharedImageMap.erase(aSharedImageItr++); } delete mDDInterface; delete mSoundManager; delete mMusicInterface; SDL_FreeCursor(mHandCursor); SDL_FreeCursor(mDraggingCursor); SDL_FreeCursor(mArrowCursor); if (mMutex != NULL) SDL_DestroyMutex(mMutex); if (mReadFromRegistry) { WriteToRegistry(); WriteRegistryToIni(BuildIniName(mRegKey, ".") + ".ini"); } gSexyAppBase = NULL; SDL_Quit(); } #if 0 static BOOL CALLBACK ChangeDisplayWindowEnumProc(HWND hwnd, LPARAM lParam) { typedef std::map WindowMap; static WindowMap aMap; if (lParam==0 && aMap.find(hwnd)==aMap.end()) // record { RECT aRect; if (!IsIconic(hwnd) && IsWindowVisible(hwnd)) { if (GetWindowRect(hwnd,&aRect)) { // char aBuf[4096]; // GetWindowText(hwnd,aBuf,4000); // DWORD aProcessId = 0; // GetWindowThreadProcessId(hwnd,&aProcessId); // SEXY_TRACE(StrFormat("%s %d - %d %d %d %d",aBuf,aProcessId,aRect.left,aRect.top,aRect.right,aRect.bottom).c_str()); aMap[hwnd] = aRect; } } } else { WindowMap::iterator anItr = aMap.find(hwnd); if (anItr != aMap.end()) { RECT &r = anItr->second; MoveWindow(hwnd,r.left,r.top,abs(r.right-r.left),abs(r.bottom-r.top),TRUE); } } return TRUE; } bool SexyAppBase::IsScreenSaver() { return mIsScreenSaver; } bool SexyAppBase::AppCanRestore() { return !mIsDisabled; } bool SexyAppBase::ReadDemoBuffer(std::string &theError) { FILE* aFP = fopen(mDemoFileName.c_str(), "rb"); if (aFP == NULL) { theError = "Demo file not found: " + mDemoFileName; return false; } struct AutoFile { FILE *f; AutoFile(FILE *file) : f(file) {} ~AutoFile() { fclose(f); } }; AutoFile aCloseFile(aFP); uint32_t aFileID; fread(&aFileID, 4, 1, aFP); DBG_ASSERTE(aFileID == DEMO_FILE_ID); if (aFileID != DEMO_FILE_ID) { theError = "Invalid demo file."; return false; } uint32_t aVersion; fread(&aVersion, 4, 1, aFP); fread(&mRandSeed, 4, 1, aFP); SRand(mRandSeed); ushort aStrLen = 4; fread(&aStrLen, 2, 1, aFP); if (aStrLen > 255) aStrLen = 255; char aStr[256]; fread(aStr, 1, aStrLen, aFP); aStr[aStrLen] = '\0'; DBG_ASSERTE(mProductVersion == aStr); if (mProductVersion != aStr) { theError = "This demo file appears to be for '" + std::string(aStr) + "'"; return false; } int aFilePos = ftell(aFP); fseek(aFP, 0, SEEK_END); int aBytesLeft = ftell(aFP) - aFilePos; fseek(aFP, aFilePos, SEEK_SET); uchar* aBuffer; // read marker list if (aVersion >= 2) { int aSize; fread(&aSize, 4, 1, aFP); aBytesLeft -= 4; if (aSize >= aBytesLeft) { theError = "Invalid demo file."; return false; } Buffer aMarkerBuffer; aBuffer = new uchar[aSize]; fread(aBuffer, 1, aSize, aFP); aMarkerBuffer.WriteBytes(aBuffer, aSize); aMarkerBuffer.SeekFront(); int aNumItems = aMarkerBuffer.ReadLong(); int i; for (i=0; ifirst); aMarkerBuffer.WriteLong(aMarkerItr->second); } int aMarkerBufferSize = aMarkerBuffer.GetDataLen(); fwrite(&aMarkerBufferSize, 4, 1, aFP); fwrite(aMarkerBuffer.GetDataPtr(), aMarkerBufferSize, 1, aFP); uint32_t aDemoLength = mUpdateCount; fwrite(&aDemoLength, 4, 1, aFP); fwrite(mDemoBuffer.GetDataPtr(), 1, mDemoBuffer.GetDataLen(), aFP); fclose(aFP); } } } void SexyAppBase::DemoSyncBuffer(Buffer* theBuffer) { if (mPlayingDemoBuffer) { if (mManualShutdown) return; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_SYNC); uint32_t aLen = mDemoBuffer.ReadLong(); theBuffer->Clear(); for (int i = 0; i < (int) aLen; i++) theBuffer->WriteByte(mDemoBuffer.ReadByte()); } else if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_SYNC, 5); mDemoBuffer.WriteLong(theBuffer->GetDataLen()); mDemoBuffer.WriteBytes((uchar*) theBuffer->GetDataPtr(), theBuffer->GetDataLen()); } } void SexyAppBase::DemoSyncString(std::string* theString) { Buffer aBuffer; aBuffer.WriteString(*theString); DemoSyncBuffer(&aBuffer); *theString = aBuffer.ReadString(); } void SexyAppBase::DemoSyncInt(int* theInt) { Buffer aBuffer; aBuffer.WriteLong(*theInt); DemoSyncBuffer(&aBuffer); *theInt = aBuffer.ReadLong(); } void SexyAppBase::DemoSyncBool(bool* theBool) { Buffer aBuffer; aBuffer.WriteBoolean(*theBool); DemoSyncBuffer(&aBuffer); *theBool = aBuffer.ReadBoolean(); } void SexyAppBase::DemoAssertStringEqual(const std::string& theString) { if (mPlayingDemoBuffer) { if (mManualShutdown) return; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_ASSERT_STRING_EQUAL); std::string aString = mDemoBuffer.ReadString(); DBG_ASSERTE(aString == theString); } else if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_ASSERT_STRING_EQUAL, 5); mDemoBuffer.WriteString(theString); } } void SexyAppBase::DemoAddMarker(const std::string& theString) { if (mPlayingDemoBuffer) { mFastForwardToMarker = false; } else if (mRecordingDemoBuffer) { mDemoMarkerList.push_back(DemoMarker(theString,mUpdateCount)); } } void SexyAppBase::DemoRegisterHandle(HANDLE theHandle) { if ((mRecordingDemoBuffer) || (mPlayingDemoBuffer)) { // Insert the handle into a map with an auto-incrementing number so // we can match up the auto-incrementing numbers with the handle // later on, as handles may not be the same between executions std::pair aPair = mHandleToIntMap.insert(HandleToIntMap::value_type(theHandle, mCurHandleNum)); DBG_ASSERT(aPair.second); mCurHandleNum++; } } void SexyAppBase::DemoWaitForHandle(HANDLE theHandle) { WaitForSingleObject(theHandle, INFINITE); if ((mRecordingDemoBuffer) || (mPlayingDemoBuffer)) { // Remove the handle from our waiting map HandleToIntMap::iterator anItr = mHandleToIntMap.find(theHandle); DBG_ASSERT(anItr != mHandleToIntMap.end()); mHandleToIntMap.erase(anItr); } } bool SexyAppBase::DemoCheckHandle(HANDLE theHandle) { if (mPlayingDemoBuffer) { // We only need to try to get the result if we think we are waiting for one if (gSexyAppBase->PrepareDemoCommand(false)) { if ((!gSexyAppBase->mDemoIsShortCmd) && (gSexyAppBase->mDemoCmdNum == DEMO_HANDLE_COMPLETE)) { // Find auto-incrementing handle num from handle HandleToIntMap::iterator anItr = mHandleToIntMap.find(theHandle); DBG_ASSERT(anItr != mHandleToIntMap.end()); int anOldBufferPos = gSexyAppBase->mDemoBuffer.mReadBitPos; // Since we don't require a demo result entry to be here, we must verify // that this is referring to us int aDemoHandleNum = gSexyAppBase->mDemoBuffer.ReadLong(); if (aDemoHandleNum == anItr->second) { // Alright, this was the handle we were waiting for! gSexyAppBase->mDemoNeedsCommand = true; // Actually wait for our local buddy to complete WaitForSingleObject(theHandle, INFINITE); mHandleToIntMap.erase(anItr); return true; } else { // Not us, go back gSexyAppBase->mDemoBuffer.mReadBitPos = anOldBufferPos; } } } return false; } else { if (WaitForSingleObject(theHandle, 0) == WAIT_OBJECT_0) { if (mRecordingDemoBuffer) { // Find auto-incrementing handle num from handle HandleToIntMap::iterator anItr = mHandleToIntMap.find(theHandle); DBG_ASSERT(anItr != mHandleToIntMap.end()); gSexyAppBase->WriteDemoTimingBlock(); gSexyAppBase->mDemoBuffer.WriteNumBits(0, 1); gSexyAppBase->mDemoBuffer.WriteNumBits(DEMO_HANDLE_COMPLETE, 5); gSexyAppBase->mDemoBuffer.WriteLong(anItr->second); mHandleToIntMap.erase(anItr); } return true; } return false; } } void SexyAppBase::DemoAssertIntEqual(int theInt) { if (mPlayingDemoBuffer) { if (mManualShutdown) return; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_ASSERT_INT_EQUAL); int anInt = mDemoBuffer.ReadLong(); DBG_ASSERTE(anInt == theInt); } else if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_ASSERT_INT_EQUAL, 5); mDemoBuffer.WriteLong(theInt); } } void SexyAppBase::URLOpenFailed(const std::string& theURL) { mIsOpeningURL = false; } void SexyAppBase::URLOpenSucceeded(const std::string& theURL) { mIsOpeningURL = false; if (mShutdownOnURLOpen) Shutdown(); } bool SexyAppBase::OpenURL(const std::string& theURL, bool shutdownOnOpen) { if ((!mIsOpeningURL) || (theURL != mOpeningURL)) { mShutdownOnURLOpen = shutdownOnOpen; mIsOpeningURL = true; mOpeningURL = theURL; mOpeningURLTime = GetTickCount(); if ((int) ShellExecuteA(NULL, "open", theURL.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32) { return true; } else { URLOpenFailed(theURL); return false; } } return true; } std::string SexyAppBase::GetProductVersion(const std::string& thePath) { // Dynamically Load Version.dll typedef DWORD (APIENTRY *GetFileVersionInfoSizeFunc)(LPSTR lptstrFilename, LPDWORD lpdwHandle); typedef BOOL (APIENTRY *GetFileVersionInfoFunc)(LPSTR lptstrFilename, DWORD dwHandle, DWORD dwLen, LPVOID lpData); typedef BOOL (APIENTRY *VerQueryValueFunc)(const LPVOID pBlock, LPSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen); static GetFileVersionInfoSizeFunc aGetFileVersionInfoSizeFunc = NULL; static GetFileVersionInfoFunc aGetFileVersionInfoFunc = NULL; static VerQueryValueFunc aVerQueryValueFunc = NULL; if (aGetFileVersionInfoSizeFunc==NULL) { aGetFileVersionInfoSizeFunc = (GetFileVersionInfoSizeFunc)GetProcAddress(gVersionDLL,"GetFileVersionInfoSizeA"); aGetFileVersionInfoFunc = (GetFileVersionInfoFunc)GetProcAddress(gVersionDLL,"GetFileVersionInfoA"); aVerQueryValueFunc = (VerQueryValueFunc)GetProcAddress(gVersionDLL,"VerQueryValueA"); } // Get Product Version std::string aProductVersion; uint aSize = aGetFileVersionInfoSizeFunc((char*) thePath.c_str(), 0); if (aSize > 0) { uchar* aVersionBuffer = new uchar[aSize]; aGetFileVersionInfoFunc((char*) thePath.c_str(), 0, aSize, aVersionBuffer); char* aBuffer; if (aVerQueryValueFunc(aVersionBuffer, "\\StringFileInfo\\040904B0\\ProductVersion", (void**) &aBuffer, &aSize)) { aProductVersion = aBuffer; } else if (aVerQueryValueFunc(aVersionBuffer, "\\StringFileInfo\\040904E4\\ProductVersion", (void**) &aBuffer, &aSize)) { aProductVersion = aBuffer; } delete aVersionBuffer; } return aProductVersion; } #endif #if 0 void SexyAppBase::TakeScreenshot() { if (mDDInterface==NULL || mDDInterface->mDrawSurface==NULL) return; // Get free image name std::string anImageDir = GetAppDataFolder() + "_screenshots"; MkDir(anImageDir); anImageDir += "/"; WIN32_FIND_DATAA aData; int aMaxId = 0; std::string anImagePrefix = "image"; HANDLE aHandle = FindFirstFileA((anImageDir + "*.png").c_str(), &aData); if (aHandle!=INVALID_HANDLE_VALUE) { do { int aNum = 0; if (sscanf(aData.cFileName,(anImagePrefix + "%d.png").c_str(), &aNum)==1) { if (aNum>aMaxId) aMaxId = aNum; } } while(FindNextFileA(aHandle,&aData)); FindClose(aHandle); } std::string anImageName = anImageDir + anImagePrefix + StrFormat("%d.png",aMaxId+1); // Capture screen LPDIRECTDRAWSURFACE aSurface = mDDInterface->mDrawSurface; // Temporarily set the mDrawSurface to NULL so DDImage::Check3D // returns false so we can lock the surface. mDDInterface->mDrawSurface = NULL; DDImage anImage(mDDInterface); anImage.SetSurface(aSurface); anImage.GetBits(); anImage.DeleteDDSurface(); mDDInterface->mDrawSurface = aSurface; if (anImage.mBits==NULL) return; // Write image ImageLib::Image aSaveImage; aSaveImage.mBits = anImage.mBits; aSaveImage.mWidth = anImage.mWidth; aSaveImage.mHeight = anImage.mHeight; ImageLib::WritePNGImage(anImageName, &aSaveImage); aSaveImage.mBits = NULL; /* keybd_event(VK_MENU,0,0,0); keybd_event(VK_SNAPSHOT,0,0,0); keybd_event(VK_MENU,0,KEYEVENTF_KEYUP,0); if (OpenClipboard(mHWnd)) { HBITMAP aBitmap = (HBITMAP)GetClipboardData(CF_BITMAP); if (aBitmap!=NULL) { BITMAP anObject; ZeroMemory(&anObject,sizeof(anObject)); GetObject(aBitmap,sizeof(anObject),&anObject); BITMAPINFO anInfo; ZeroMemory(&anInfo,sizeof(anInfo)); BITMAPINFOHEADER &aHeader = anInfo.bmiHeader; aHeader.biBitCount = 32; aHeader.biPlanes = 1; aHeader.biHeight = -abs(anObject.bmHeight); aHeader.biWidth = abs(anObject.bmWidth); aHeader.biSize = sizeof(aHeader); aHeader.biSizeImage = aHeader.biHeight*aHeader.biWidth*4; ImageLib::Image aSaveImage; aSaveImage.mBits = new DWORD[abs(anObject.bmWidth*anObject.bmHeight)]; aSaveImage.mWidth = abs(anObject.bmWidth); aSaveImage.mHeight = abs(anObject.bmHeight); HDC aDC = GetDC(NULL); if (GetDIBits(aDC,aBitmap,0,aSaveImage.mHeight,aSaveImage.mBits,&anInfo,DIB_RGB_COLORS)) ImageLib::WritePNGImage(anImageName, &aSaveImage); ReleaseDC(NULL,aDC); } CloseClipboard(); }*/ ClearUpdateBacklog(); } void SexyAppBase::DumpProgramInfo() { Deltree(GetAppDataFolder() + "_dump"); for (;;) { if (mkdir((GetAppDataFolder() + "_dump").c_str())) break; Sleep(100); } std::fstream aDumpStream((GetAppDataFolder() + "_dump\\imagelist.html").c_str(), std::ios::out); time_t aTime; time(&aTime); tm* aTM = localtime(&aTime); aDumpStream << "

" << asctime(aTM) << "
" << std::endl; int anImgNum = 0; int aThumbWidth = 64; int aThumbHeight = 64; ImageLib::Image anImageLibImage; anImageLibImage.mWidth = aThumbWidth; anImageLibImage.mHeight = aThumbHeight; anImageLibImage.mBits = new uint32_t[aThumbWidth*aThumbHeight]; typedef std::multimap > SortedImageMap; int aTotalMemory = 0; SortedImageMap aSortedImageMap; MemoryImageSet::iterator anItr = mMemoryImageSet.begin(); while (anItr != mMemoryImageSet.end()) { MemoryImage* aMemoryImage = *anItr; int aNumPixels = aMemoryImage->mWidth*aMemoryImage->mHeight; DDImage* aDDImage = dynamic_cast(aMemoryImage); int aBitsMemory = 0; int aSurfaceMemory = 0; int aPalletizedMemory = 0; int aNativeAlphaMemory = 0; int aRLAlphaMemory = 0; int aRLAdditiveMemory = 0; int aTextureMemory = 0; int aMemorySize = 0; if (aMemoryImage->mBits != NULL) aBitsMemory = aNumPixels * 4; if ((aDDImage != NULL) && (aDDImage->mSurface != NULL)) aSurfaceMemory = aNumPixels * 4; // Assume 32bit screen... if (aMemoryImage->mColorTable != NULL) aPalletizedMemory = aNumPixels + 256*4; if (aMemoryImage->mNativeAlphaData != NULL) { if (aMemoryImage->mColorTable != NULL) aNativeAlphaMemory = 256*4; else aNativeAlphaMemory = aNumPixels * 4; } if (aMemoryImage->mRLAlphaData != NULL) aRLAlphaMemory = aNumPixels; if (aMemoryImage->mRLAdditiveData != NULL) aRLAdditiveMemory = aNumPixels; if (aMemoryImage->mD3DData != NULL) aTextureMemory += ((TextureData*)aMemoryImage->mD3DData)->mTexMemSize; aMemorySize = aBitsMemory + aSurfaceMemory + aPalletizedMemory + aNativeAlphaMemory + aRLAlphaMemory + aRLAdditiveMemory + aTextureMemory; aTotalMemory += aMemorySize; aSortedImageMap.insert(SortedImageMap::value_type(aMemorySize, aMemoryImage)); ++anItr; } aDumpStream << "Total Image Allocation: " << CommaSeperate(aTotalMemory).c_str() << " bytes
"; aDumpStream << ""; int aTotalMemorySize = 0; int aTotalBitsMemory = 0; int aTotalSurfaceMemory = 0; int aTotalPalletizedMemory = 0; int aTotalNativeAlphaMemory = 0; int aTotalRLAlphaMemory = 0; int aTotalRLAdditiveMemory = 0; int aTotalTextureMemory = 0; SortedImageMap::iterator aSortedItr = aSortedImageMap.begin(); while (aSortedItr != aSortedImageMap.end()) { MemoryImage* aMemoryImage = aSortedItr->second; char anImageName[256]; sprintf(anImageName, "img%04d.png", anImgNum); char aThumbName[256]; sprintf(aThumbName, "thumb%04d.jpg", anImgNum); aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; int aNumPixels = aMemoryImage->mWidth*aMemoryImage->mHeight; DDImage* aDDImage = dynamic_cast(aMemoryImage); int aMemorySize = aSortedItr->first; int aBitsMemory = 0; int aSurfaceMemory = 0; int aPalletizedMemory = 0; int aNativeAlphaMemory = 0; int aRLAlphaMemory = 0; int aRLAdditiveMemory = 0; int aTextureMemory = 0; std::string aTextureFormatName; if (aMemoryImage->mBits != NULL) aBitsMemory = aNumPixels * 4; if ((aDDImage != NULL) && (aDDImage->mSurface != NULL)) aSurfaceMemory = aNumPixels * 4; // Assume 32bit screen... if (aMemoryImage->mColorTable != NULL) aPalletizedMemory = aNumPixels + 256*4; if (aMemoryImage->mNativeAlphaData != NULL) { if (aMemoryImage->mColorTable != NULL) aNativeAlphaMemory = 256*4; else aNativeAlphaMemory = aNumPixels * 4; } if (aMemoryImage->mRLAlphaData != NULL) aRLAlphaMemory = aNumPixels; if (aMemoryImage->mRLAdditiveData != NULL) aRLAdditiveMemory = aNumPixels; if (aMemoryImage->mD3DData != NULL) { aTextureMemory += ((TextureData*)aMemoryImage->mD3DData)->mTexMemSize; switch (((TextureData*)aMemoryImage->mD3DData)->mPixelFormat) { case PixelFormat_A8R8G8B8: aTextureFormatName = "A8R8G8B8"; break; case PixelFormat_A4R4G4B4: aTextureFormatName = "A4R4G4B4"; break; case PixelFormat_R5G6B5: aTextureFormatName = "R5G6B5"; break; case PixelFormat_Palette8: aTextureFormatName = "Palette8"; break; } } aTotalMemorySize += aMemorySize; aTotalBitsMemory += aBitsMemory; aTotalTextureMemory += aTextureMemory; aTotalSurfaceMemory += aSurfaceMemory; aTotalPalletizedMemory += aPalletizedMemory; aTotalNativeAlphaMemory += aNativeAlphaMemory; aTotalRLAlphaMemory += aRLAlphaMemory; aTotalRLAdditiveMemory += aRLAdditiveMemory; char aStr[256]; sprintf(aStr, "%d x %d
%s bytes", aMemoryImage->mWidth, aMemoryImage->mHeight, CommaSeperate(aMemorySize).c_str()); aDumpStream << "
" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; // Write thumb MemoryImage aCopiedImage(*aMemoryImage); uint32_t* aBits = aCopiedImage.GetBits(); uint32_t* aThumbBitsPtr = anImageLibImage.mBits; for (int aThumbY = 0; aThumbY < aThumbHeight; aThumbY++) for (int aThumbX = 0; aThumbX < aThumbWidth; aThumbX++) { int aSrcX = (int) (aCopiedImage.mWidth * (aThumbX + 0.5)) / aThumbWidth; int aSrcY = (int) (aCopiedImage.mHeight * (aThumbY + 0.5)) / aThumbHeight; *(aThumbBitsPtr++) = aBits[aSrcX + (aSrcY*aCopiedImage.mWidth)]; } ImageLib::WriteJPEGImage((GetAppDataFolder() + std::string("_dump\\") + aThumbName).c_str(), &anImageLibImage); // Write high resolution image ImageLib::Image anFullImage; anFullImage.mBits = aCopiedImage.GetBits(); anFullImage.mWidth = aCopiedImage.GetWidth(); anFullImage.mHeight = aCopiedImage.GetHeight(); ImageLib::WritePNGImage((GetAppDataFolder() + std::string("_dump\\") + anImageName).c_str(), &anFullImage); anFullImage.mBits = NULL; anImgNum++; aSortedItr++; } aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "" << std::endl; aDumpStream << "
" << aStr << "" << SexyStringToString(((aBitsMemory != 0) ? _S("mBits
") + CommaSeperate(aBitsMemory) : _S(" "))) << "
" << SexyStringToString(((aPalletizedMemory != 0) ? _S("Palletized
") + CommaSeperate(aPalletizedMemory) : _S(" "))) << "
" << SexyStringToString(((aSurfaceMemory != 0) ? _S("DDSurface
") + CommaSeperate(aSurfaceMemory) : _S(" "))) << "
" << SexyStringToString(((aMemoryImage->mD3DData!=NULL) ? _S("Texture
") + StringToSexyString(aTextureFormatName) + _S("
") + CommaSeperate(aTextureMemory) : _S(" "))) << "
" << SexyStringToString(((aMemoryImage->mIsVolatile) ? _S("Volatile") : _S(" "))) << "" << SexyStringToString(((aMemoryImage->mForcedMode) ? _S("Forced") : _S(" "))) << "" << SexyStringToString(((aMemoryImage->mHasAlpha) ? _S("HasAlpha") : _S(" "))) << "" << SexyStringToString(((aMemoryImage->mHasTrans) ? _S("HasTrans") : _S(" "))) << "" << SexyStringToString(((aNativeAlphaMemory != 0) ? _S("NativeAlpha
") + CommaSeperate(aNativeAlphaMemory) : _S(" "))) << "
" << SexyStringToString(((aRLAlphaMemory != 0) ? _S("RLAlpha
") + CommaSeperate(aRLAlphaMemory) : _S(" "))) << "
" << SexyStringToString(((aRLAdditiveMemory != 0) ? _S("RLAdditive
") + CommaSeperate(aRLAdditiveMemory) : _S(" "))) << "
" << (aMemoryImage->mFilePath.empty()? " ":aMemoryImage->mFilePath) << "
Totals" << SexyStringToString(CommaSeperate(aTotalMemorySize)) << "" << SexyStringToString(CommaSeperate(aTotalBitsMemory)) << "" << SexyStringToString(CommaSeperate(aTotalPalletizedMemory)) << "" << SexyStringToString(CommaSeperate(aTotalSurfaceMemory)) << "" << SexyStringToString(CommaSeperate(aTotalTextureMemory)) << "    " << SexyStringToString(CommaSeperate(aTotalNativeAlphaMemory)) << "" << SexyStringToString(CommaSeperate(aTotalRLAlphaMemory)) << "" << SexyStringToString(CommaSeperate(aTotalRLAdditiveMemory)) << " 
" << std::endl; } #endif bool SexyAppBase::RegistryWrite(const std::string& theValueName, uint32_t theType, const uchar* theValue, uint32_t theLength) { if (mRegKey.length() == 0) return false; #if 0 if (mPlayingDemoBuffer) { if (mManualShutdown) return true; PrepareDemoCommand(true); mDemoNeedsCommand = true; assert(!mDemoIsShortCmd); assert(mDemoCmdNum == DEMO_REGISTRY_WRITE); return mDemoBuffer.ReadNumBits(1, false) != 0; } #endif if (!mReadFromRegistry) { ReadRegistryFromIni(BuildIniName(mRegKey, ".") + ".ini"); mReadFromRegistry = true; } std::string aValueName; int aSlashPos = (int) theValueName.rfind('\\'); if (aSlashPos != std::string::npos) { aValueName = theValueName.substr(aSlashPos + 1); } else { aValueName = theValueName; } std::ostringstream stream; if (theType == REG_DWORD) { int i ; memcpy(&i, theValue, sizeof(int));; stream << i; } else if (theType == REG_SZ) { stream << theValue; } else if (theType == REG_BINARY) { uchar* buf = new uchar[theLength+1]; memcpy(buf, theValue, theLength); buf[theLength] = '\0'; stream << buf; } mRegistry[StringToSexyString(aValueName)] = StringToSexyString(stream.str()); #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_REGISTRY_WRITE, 5); mDemoBuffer.WriteNumBits(1, 1); // success } #endif return true; } bool SexyAppBase::WriteRegistryToIni(const std::string& IniFile) { if (mRegKey.length() == 0) return false; XMLWriter writer; std::string absolute_path = GetAppDataFolder(); struct stat dir_stat; stat(absolute_path.c_str(), &dir_stat); if (!S_ISDIR(dir_stat.st_mode)) { MkDir(absolute_path); } absolute_path += IniFile; if (!writer.OpenFile(absolute_path)) return false; writer.StartElement("Registry"); std::map::const_iterator it = mRegistry.begin(); while (it != mRegistry.end()) { writer.StartElement("Key"); writer.WriteAttribute("ID", it->first); writer.StartElement("Value"); writer.WriteAttribute("value", it->second); writer.StopElement(); writer.StopElement(); ++it; } writer.StopElement(); return true; } bool SexyAppBase::ReadRegistryFromIni(const std::string& IniFile) { XMLParser parser; std::string absolute_path = GetAppDataFolder(); absolute_path += IniFile; if (parser.OpenFile(absolute_path)) { XMLElement e; std::string key; std::string value; mRegistry.clear(); while (parser.NextElement(&e)) { if (e.mType == XMLElement::TYPE_START) { if (e.mSection == "Registry") { if (e.mValue == "Key") { key = e.mAttributes["ID"]; } } else if (e.mSection == "Registry/Key") { if (e.mValue == "Value") { value= e.mAttributes["value"]; } } } else if (e.mType == XMLElement::TYPE_END) { if (e.mSection == "Registry/Key") { mRegistry[key] = value; } } } } return true; } bool SexyAppBase::RegistryWriteString(const std::string& theValueName, const std::string& theString) { return RegistryWrite(theValueName, REG_SZ, (uchar*) theString.c_str(), theString.length()); } bool SexyAppBase::RegistryWriteInteger(const std::string& theValueName, int theValue) { return RegistryWrite(theValueName, REG_DWORD, (uchar*) &theValue, sizeof(int)); } bool SexyAppBase::RegistryWriteBoolean(const std::string& theValueName, bool theValue) { int aValue = theValue ? 1 : 0; return RegistryWrite(theValueName, REG_DWORD, (uchar*) &aValue, sizeof(int)); } bool SexyAppBase::RegistryWriteData(const std::string& theValueName, const uchar* theValue, uint32_t theLength) { return RegistryWrite(theValueName, REG_BINARY, (uchar*) theValue, theLength); } void SexyAppBase::WriteToRegistry() { RegistryWriteInteger("MusicVolume", (int) (mMusicVolume * 100)); RegistryWriteInteger("SfxVolume", (int) (mSfxVolume * 100)); RegistryWriteInteger("Muted", (mMuteCount - mAutoMuteCount > 0) ? 1 : 0); RegistryWriteInteger("ScreenMode", mIsWindowed ? 0 : 1); RegistryWriteInteger("PreferredX", mPreferredX); RegistryWriteInteger("PreferredY", mPreferredY); RegistryWriteInteger("CustomCursors", mCustomCursorsEnabled ? 1 : 0); RegistryWriteInteger("InProgress", 0); RegistryWriteBoolean("WaitForVSync", mWaitForVSync); RegistryWriteBoolean("VSyncUpdates", mVSyncUpdates); RegistryWriteBoolean("Is3D", Is3DAccelerated()); } bool SexyAppBase::RegistryEraseKey(const SexyString& _theKeyName) { if (mRegKey.length() == 0) return false; #if 0 if (mPlayingDemoBuffer) { if (mManualShutdown) return true; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_REGISTRY_ERASE); return mDemoBuffer.ReadNumBits(1, false) != 0; } #endif mRegistry.erase(_theKeyName); #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_REGISTRY_ERASE, 5); mDemoBuffer.WriteNumBits(1, 1); // success } #endif return true; } void SexyAppBase::RegistryEraseValue(const SexyString& _theValueName) { if (mRegKey.length() == 0) return; std::map::iterator it = mRegistry.begin(); while (it != mRegistry.end()) { if (it->second == _theValueName) it->second = ""; ++it; } } bool SexyAppBase::RegistryGetSubKeys(const std::string& theKeyName, StringVector* theSubKeys) { //FIXME TODO #if 0 theSubKeys->clear(); if (mRegKey.length() == 0) return false; if (mPlayingDemoBuffer) { #if 0 if (mManualShutdown) return true; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_REGISTRY_GETSUBKEYS); bool success = mDemoBuffer.ReadNumBits(1, false) != 0; if (!success) return false; int aNumKeys = mDemoBuffer.ReadLong(); for (int i = 0; i < aNumKeys; i++) theSubKeys->push_back(mDemoBuffer.ReadString()); return true; #endif } else { #if 0 HKEY aKey; std::string aKeyName = RemoveTrailingSlash(RemoveTrailingSlash("SOFTWARE\\" + mRegKey) + "\\" + theKeyName); int aResult = RegOpenKeyExA(HKEY_CURRENT_USER, aKeyName.c_str(), 0, KEY_READ, &aKey); if (aResult == ERROR_SUCCESS) { for (int anIdx = 0; ; anIdx++) { char aStr[1024]; aResult = RegEnumKeyA(aKey, anIdx, aStr, 1024); if (aResult != ERROR_SUCCESS) break; theSubKeys->push_back(aStr); } RegCloseKey(aKey); #endif #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_REGISTRY_GETSUBKEYS, 5); mDemoBuffer.WriteNumBits(1, 1); // success mDemoBuffer.WriteLong(theSubKeys->size()); for (int i = 0; i < (int) theSubKeys->size(); i++) mDemoBuffer.WriteString((*theSubKeys)[i]); } #endif return true; } else { #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_REGISTRY_GETSUBKEYS, 5); mDemoBuffer.WriteNumBits(0, 1); // failure } #endif return false; } } #else return false; #endif } bool SexyAppBase::RegistryRead(const std::string& theValueName, uint32_t* theType, uchar* theValue, uint32_t* theLength) { return RegistryReadKey(theValueName, theType, theValue, theLength, HKEY_CURRENT_USER); } bool SexyAppBase::RegistryReadKey(const std::string& theValueName, uint32_t* theType, uchar* theValue, uint32_t* theLength, HKEY theKey) { if (mRegKey.length() == 0) return false; #if 0 if (mPlayingDemoBuffer) { if (mManualShutdown) return false; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_REGISTRY_READ); bool success = mDemoBuffer.ReadNumBits(1, false) != 0; if (!success) return false; *theType = mDemoBuffer.ReadLong(); uint32_t aLen = mDemoBuffer.ReadLong(); *theLength = aLen; if (*theLength >= aLen) { mDemoBuffer.ReadBytes(theValue, aLen); return true; } else { for (int i = 0; i < (int) aLen; i++) mDemoBuffer.ReadByte(); return false; } } else #endif { if (!mReadFromRegistry) { ReadRegistryFromIni(BuildIniName(mRegKey, ".") + ".ini"); mReadFromRegistry = true; } std::string aValueName; int aSlashPos = (int) theValueName.rfind('\\'); if (aSlashPos != -1) { aValueName = theValueName.substr(aSlashPos + 1); } else { aValueName = theValueName; } SexyString s = mRegistry[aValueName]; if (s == "") return false; uchar* c_str = (uchar*)(SexyStringToString(s)).c_str(); if (*theType == REG_SZ) { memcpy(theValue, c_str, 1023); } else if (*theType == REG_DWORD) { int i = atoi((const char*)c_str); memcpy(theValue, &i, sizeof(int)); } else if (*theType == REG_BINARY) { memcpy(theValue, c_str, *theLength); } #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_REGISTRY_READ, 5); mDemoBuffer.WriteNumBits(1, 1); // success mDemoBuffer.WriteLong(*theType); mDemoBuffer.WriteLong(*theLength); mDemoBuffer.WriteBytes(theValue, *theLength); } #endif } return true; } bool SexyAppBase::RegistryReadString(const std::string& theKey, std::string* theString) { char aStr[1024]; uint32_t aType = REG_SZ; uint32_t aLen = sizeof(aStr) - 1; if (!RegistryRead(theKey, &aType, (uchar*) aStr, &aLen)) return false; aStr[aLen] = 0; *theString = aStr; return true; } bool SexyAppBase::RegistryReadInteger(const std::string& theKey, int* theValue) { uint32_t aType = REG_DWORD; uint32_t aLong; uint32_t aLen = 4; if (!RegistryRead(theKey, &aType, (uchar*) &aLong, &aLen)) return false; *theValue = aLong; return true; } bool SexyAppBase::RegistryReadBoolean(const std::string& theKey, bool* theValue) { int aValue; if (!RegistryReadInteger(theKey, &aValue)) return false; *theValue = aValue != 0; return true; } bool SexyAppBase::RegistryReadData(const std::string& theKey, uchar* theValue, uint32_t* theLength) { uint32_t aType = REG_BINARY; uint32_t aLen = *theLength; if (!RegistryRead(theKey, &aType, (uchar*) theValue, theLength)) return false; return true; } void SexyAppBase::ReadFromRegistry() { mRegKey = SexyStringToString(GetString("RegistryKey", StringToSexyString(mRegKey))); if (mRegKey.length() == 0) return; int anInt = 0; if (RegistryReadInteger("MusicVolume", &anInt)) mMusicVolume = anInt / 100.0; if (RegistryReadInteger("SfxVolume", &anInt)) mSfxVolume = anInt / 100.0; if (RegistryReadInteger("Muted", &anInt)) mMuteCount = anInt; if (RegistryReadInteger("ScreenMode", &anInt)) mIsWindowed = anInt == 0; RegistryReadInteger("PreferredX", &mPreferredX); RegistryReadInteger("PreferredY", &mPreferredY); if (RegistryReadInteger("CustomCursors", &anInt)) EnableCustomCursors(anInt != 0); RegistryWriteBoolean("WaitForVSync", mWaitForVSync); RegistryWriteBoolean("VSyncUpdates", mVSyncUpdates); if (RegistryReadInteger("InProgress", &anInt)) mLastShutdownWasGraceful = anInt == 0; #if 0 if (!IsScreenSaver()) RegistryWriteInteger("InProgress", 1); #endif } #if 0 ///////////////////////////// FPS Stuff static PerfTimer gFPSTimer; #endif static Uint32 fps_oldtime = SDL_GetTicks(); static int gFrameCount = 0; static int gFPSDisplay = 0; static bool gForceDisplay = true; static void CalculateFPS() { gFrameCount++; //workaround to force texture reloading if (gSexyAppBase->Is3DAccelerated()) { delete gFPSImage; gFPSImage = NULL; } if (gFPSImage == NULL) { gFPSImage = new DDImage(gSexyAppBase->mDDInterface); gFPSImage->Create(80,aFont->GetHeight()+4); gFPSImage->SetImageMode(false,false); gFPSImage->SetVolatile(true); gFPSImage->mPurgeBits = false; gFPSImage->mWantDDSurface = true; gFPSImage->PurgeBits(); } Uint32 fps_newtime = SDL_GetTicks(); if (fps_newtime - fps_oldtime >= 1000 || gForceDisplay) { if (!gForceDisplay) gFPSDisplay = (int)((gFrameCount*1000/(fps_newtime - fps_oldtime)) + 0.5f); else { gForceDisplay = false; gFPSDisplay = 0; } gFrameCount = 0; fps_oldtime = SDL_GetTicks(); Graphics aDrawG(gFPSImage); aDrawG.SetFont(aFont); SexyString aFPS = StrFormat(_S("FPS: %d"), gFPSDisplay); aDrawG.SetColor(0x000000); aDrawG.FillRect(0,0,gFPSImage->GetWidth(),gFPSImage->GetHeight()); aDrawG.SetColor(0xFFFFFF); aDrawG.DrawString(aFPS,2,aFont->GetAscent()); gFPSImage->mBitsChangedCount++; } } ///////////////////////////// FPS Stuff to draw mouse coords static void FPSDrawCoords(int theX, int theY) { //workaround to force texture reloading if (gSexyAppBase->Is3DAccelerated()) { delete gFPSImage; gFPSImage = NULL; } if (gFPSImage == NULL) { gFPSImage = new DDImage(gSexyAppBase->mDDInterface); gFPSImage->Create(80,aFont->GetHeight()+4); gFPSImage->SetImageMode(false,false); gFPSImage->SetVolatile(true); gFPSImage->mPurgeBits = false; gFPSImage->mWantDDSurface = true; gFPSImage->PurgeBits(); } Graphics aDrawG(gFPSImage); aDrawG.SetFont(aFont); SexyString aFPS = StrFormat(_S("%d,%d"),theX,theY); aDrawG.SetColor(0x000000); aDrawG.FillRect(0,0,gFPSImage->GetWidth(),gFPSImage->GetHeight()); aDrawG.SetColor(0xFFFFFF); aDrawG.DrawString(aFPS,2,aFont->GetAscent()); gFPSImage->mBitsChangedCount++; } #if 0 bool SexyAppBase::EraseFile(const std::string& theFileName) { if (mPlayingDemoBuffer) return true; return DeleteFileA(theFileName.c_str()) != 0; } void SexyAppBase::SEHOccured() { SetMusicVolume(0); ::ShowWindow(mHWnd, SW_HIDE); mSEHOccured = true; EnforceCursor(); } std::string SexyAppBase::GetGameSEHInfo() { int aSecLoaded = (GetTickCount() - mTimeLoaded) / 1000; char aTimeStr[16]; sprintf(aTimeStr, "%02d:%02d:%02d", (aSecLoaded/60/60), (aSecLoaded/60)%60, aSecLoaded%60); char aThreadIdStr[16]; sprintf(aThreadIdStr, "%X", mPrimaryThreadId); std::string anInfoString = "Product: " + mProdName + "\r\n" + "Version: " + mProductVersion + "\r\n"; anInfoString += "Time Loaded: " + std::string(aTimeStr) + "\r\n" "Fullscreen: " + (mIsWindowed ? std::string("No") : std::string("Yes")) + "\r\n" "Primary ThreadId: " + aThreadIdStr + "\r\n"; return anInfoString; } void SexyAppBase::GetSEHWebParams(DefinesMap* theDefinesMap) { } ///////////////////////////// Demo TimeLeft Stuff static DDImage* gDemoTimeLeftImage = NULL; static void CalculateDemoTimeLeft() { static SysFont aFont(gSexyAppBase,"Tahoma",8); static DWORD aLastTick = 0; if (gDemoTimeLeftImage==NULL) { gDemoTimeLeftImage = new DDImage(gSexyAppBase->mDDInterface); gDemoTimeLeftImage->Create(50,aFont.GetHeight()+4); gDemoTimeLeftImage->SetImageMode(false,false); gDemoTimeLeftImage->SetVolatile(true); gDemoTimeLeftImage->mPurgeBits = false; gDemoTimeLeftImage->mWantDDSurface = true; gDemoTimeLeftImage->PurgeBits(); } DWORD aTick = GetTickCount(); if (aTick - aLastTick < 1000/gSexyAppBase->mUpdateMultiplier) return; aLastTick = aTick; int aNumUpdatesLeft = gSexyAppBase->mDemoLength - gSexyAppBase->mUpdateCount; Graphics aDrawG(gDemoTimeLeftImage); aDrawG.SetFont(&aFont); int aTotalSeconds = aNumUpdatesLeft*gSexyAppBase->mFrameTime/1000; int aSeconds = aTotalSeconds%60; int aMinutes = (aTotalSeconds/60)%60; int anHours = (aTotalSeconds/3600); SexyString aFPS = StrFormat(_S("%02d:%02d:%02d"), anHours,aMinutes,aSeconds); aDrawG.SetColor(0x000000); aDrawG.FillRect(0,0,gDemoTimeLeftImage->GetWidth(),gDemoTimeLeftImage->GetHeight()); aDrawG.SetColor(0xFFFFFF); aDrawG.DrawString(aFPS,2,aFont.GetAscent()); gDemoTimeLeftImage->mBitsChangedCount++; } static void UpdateScreenSaverInfo(DWORD theTick) { if (gSexyAppBase->IsScreenSaver() || !gSexyAppBase->mIsPhysWindowed) return; // Get screen saver timeout static DWORD aPeriodicTick = 0; static DWORD aScreenSaverTimeout = 60000; static BOOL aScreenSaverEnabled = TRUE; if (theTick-aPeriodicTick > 10000) { aPeriodicTick = theTick; int aTimeout = 0; SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT,0,&aTimeout,0); SystemParametersInfo(SPI_GETSCREENSAVEACTIVE,0,&aScreenSaverEnabled,0); aTimeout-=2; if (aTimeout < 1) aTimeout = 1; aScreenSaverTimeout = aTimeout*1000; if (!aScreenSaverEnabled) gScreenSaverActive = false; } // Get more accurate last user input time if (gGetLastInputInfoFunc) { LASTINPUTINFO anInfo; anInfo.cbSize = sizeof(anInfo); if (gGetLastInputInfoFunc(&anInfo)) { if (anInfo.dwTime > theTick) anInfo.dwTime = theTick; gSexyAppBase->mLastUserInputTick = anInfo.dwTime; } } if (!aScreenSaverEnabled) return; DWORD anIdleTime = theTick - gSexyAppBase->mLastUserInputTick; if (gScreenSaverActive) { BOOL aBool = FALSE; if (SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, &aBool, 0)) { if (aBool) // screen saver not off yet return; } if (anIdleTime < aScreenSaverTimeout) { gScreenSaverActive = false; gSexyAppBase->mWidgetManager->MarkAllDirty(); } } else if (anIdleTime > aScreenSaverTimeout) gScreenSaverActive = true; } void SexyAppBase::LogScreenSaverError(const std::string &theError) { static bool firstTime = true; char aBuf[512]; const char *aFlag = firstTime?"w":"a+"; firstTime = false; FILE *aFile = fopen("ScrError.txt",aFlag); if (aFile != NULL) { fprintf(aFile,"%s %s %u\n",theError.c_str(),_strtime(aBuf),GetTickCount()); fclose(aFile); } } void SexyAppBase::BeginPopup() { if (!mIsPhysWindowed) { if (mDDInterface && mDDInterface->mDD) { mDDInterface->mDD->FlipToGDISurface(); mNoDefer = true; } } } void SexyAppBase::EndPopup() { if (!mIsPhysWindowed) mNoDefer = false; ClearUpdateBacklog(); ClearKeysDown(); if (mWidgetManager->mDownButtons) { mWidgetManager->DoMouseUps(); ReleaseCapture(); } } int SexyAppBase::MsgBox(const std::string& theText, const std::string& theTitle, int theFlags) { // if (mDDInterface && mDDInterface->mDD) // mDDInterface->mDD->FlipToGDISurface(); if (IsScreenSaver()) { LogScreenSaverError(theText); return IDOK; } BeginPopup(); int aResult = MessageBoxA(mHWnd, theText.c_str(), theTitle.c_str(), theFlags); EndPopup(); return aResult; } int SexyAppBase::MsgBox(const std::wstring& theText, const std::wstring& theTitle, int theFlags) { // if (mDDInterface && mDDInterface->mDD) // mDDInterface->mDD->FlipToGDISurface(); if (IsScreenSaver()) { LogScreenSaverError(WStringToString(theText)); return IDOK; } BeginPopup(); int aResult = MessageBoxW(mHWnd, theText.c_str(), theTitle.c_str(), theFlags); EndPopup(); return aResult; } void SexyAppBase::Popup(const std::string& theString) { if (IsScreenSaver()) { LogScreenSaverError(theString); return; } BeginPopup(); if (!mShutdown) ::MessageBoxA(mHWnd, theString.c_str(), SexyStringToString(GetString("FATAL_ERROR", _S("FATAL ERROR"))).c_str(), MB_APPLMODAL | MB_ICONSTOP); EndPopup(); } void SexyAppBase::Popup(const std::wstring& theString) { if (IsScreenSaver()) { LogScreenSaverError(WStringToString(theString)); return; } BeginPopup(); if (!mShutdown) ::MessageBoxW(mHWnd, theString.c_str(), SexyStringToWString(GetString("FATAL_ERROR", _S("FATAL ERROR"))).c_str(), MB_APPLMODAL | MB_ICONSTOP); EndPopup(); } BOOL CALLBACK EnumCloseThing2(HWND hwnd, LPARAM lParam) { //CloseWindow(hwnd); char aClassName[256]; if (GetClassNameA(hwnd, aClassName, 256) != 0) { if (strcmp(aClassName, "Internet Explorer_Server") == 0) { DestroyWindow(hwnd); } else { EnumChildWindows(hwnd, EnumCloseThing2, lParam); } } return TRUE; } BOOL CALLBACK EnumCloseThing(HWND hwnd, LPARAM lParam) { //CloseWindow(hwnd); char aClassName[256]; if (GetClassNameA(hwnd, aClassName, 256) != 0) { if (strcmp(aClassName, "AmWBC_WClass") == 0) { EnumChildWindows(hwnd, EnumCloseThing2, lParam); } } return TRUE; } static INT_PTR CALLBACK MarkerListDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { HWND aListBox = GetDlgItem(hwnd,100); DWORD dwExtent = 0; HDC hDCListBox; HFONT hFontOld, hFontNew; TEXTMETRIC tm; RECT aRect; SIZE aSize; hDCListBox = GetDC(aListBox); hFontNew = (HFONT)SendMessage(aListBox, WM_GETFONT, NULL, NULL); hFontOld = (HFONT)SelectObject(hDCListBox, hFontNew); GetTextMetrics(hDCListBox, (LPTEXTMETRIC)&tm); GetClientRect(hwnd, &aRect); MoveWindow(aListBox,10,10,aRect.right-aRect.left-20,aRect.bottom-aRect.top-20,FALSE); for (SexyAppBase::DemoMarkerList::iterator anItr = gSexyAppBase->mDemoMarkerList.begin(); anItr != gSexyAppBase->mDemoMarkerList.end(); ++anItr) { if (anItr->second <= gSexyAppBase->mUpdateCount) continue; int aTotalSeconds = (gSexyAppBase->mDemoLength - anItr->second)*gSexyAppBase->mFrameTime/1000; int aSeconds = aTotalSeconds%60; int aMinutes = (aTotalSeconds/60)%60; int anHours = (aTotalSeconds/3600); SexyString aStr = StrFormat(_S("%s (%02d:%02d:%02d)"), anItr->first.c_str(),anHours,aMinutes,aSeconds); GetTextExtentPoint32(hDCListBox, aStr.c_str(), aStr.length(), &aSize); dwExtent = max (aSize.cx + tm.tmAveCharWidth, (int)dwExtent); SendMessage(aListBox, LB_SETHORIZONTALEXTENT, dwExtent, 0); LRESULT anIndex = SendMessage(aListBox, LB_ADDSTRING, 0, (LPARAM)aStr.c_str()); SendMessage(aListBox, LB_SETITEMDATA, anIndex, anItr->second); } SelectObject(hDCListBox, hFontOld); ReleaseDC(aListBox, hDCListBox); return TRUE; } case WM_CLOSE: EndDialog(hwnd,0); return TRUE; case WM_COMMAND: if (HIWORD(wParam)==LBN_DBLCLK) { HWND aListBox = GetDlgItem(hwnd,100); int anIndex = SendMessage(aListBox,LB_GETCURSEL,0,0); if (anIndex >= 0) { int anUpdateTime = SendMessage(aListBox,LB_GETITEMDATA,anIndex,0); if (anUpdateTime > gSexyAppBase->mUpdateCount) { gSexyAppBase->mFastForwardToUpdateNum = anUpdateTime; EndDialog(hwnd,0); } } return TRUE; } break; } return FALSE; } static LPWORD lpdwAlign ( LPWORD lpIn) { ULONG ul; ul = (ULONG) lpIn; ul +=3; ul >>=2; ul <<=2; return (LPWORD) ul; } static int ListDemoMarkers() { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar; hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; lpdt->cdit = 1; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 200; lpdt->cy = 200; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Marker List", -1, lpwsz, 50); lpw += nchar; *lpw++ = 8; lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Tahoma", -1, lpwsz, 50); lpw += nchar; // Define Listbox lpw = lpdwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 5; lpdit->y = 5; lpdit->cx = 190; lpdit->cy = 195; lpdit->id = 100; lpdit->style = WS_VISIBLE | WS_CHILD | WS_VSCROLL | WS_HSCROLL | LBS_NOTIFY; lpdit->dwExtendedStyle = WS_EX_CLIENTEDGE; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0083; // listbox class *lpw++ = 0; // no window text *lpw++ = 0; // no creation data GlobalUnlock(hgbl); ret = DialogBoxIndirect(gHInstance, (LPDLGTEMPLATE) hgbl, gSexyAppBase->mHWnd, (DLGPROC) MarkerListDialogProc); GlobalFree(hgbl); gSexyAppBase->mLastTime = timeGetTime(); return ret; } static INT_PTR CALLBACK JumpToTimeDialogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { HWND anEdit = GetDlgItem(hwnd,100); HKEY aGameKey; std::string aKeyName = RemoveTrailingSlash("SOFTWARE\\" + gSexyAppBase->mRegKey); if (RegOpenKeyExA(HKEY_CURRENT_USER, aKeyName.c_str(), 0, KEY_READ | KEY_WRITE, &aGameKey) == ERROR_SUCCESS) { char aBuf[1024]; DWORD aLength = 1000; DWORD aType = REG_SZ; if (RegQueryValueExA(aGameKey, "DemoJumpTime", 0, &aType, (uchar*) aBuf, &aLength) == ERROR_SUCCESS) { aBuf[aLength] = 0; SetWindowTextA(anEdit,aBuf); SendMessage(anEdit,EM_SETSEL,0,-1); } RegCloseKey(aGameKey); } return TRUE; } break; case WM_CLOSE: EndDialog(hwnd,0); return TRUE; case WM_COMMAND: if (HIWORD(wParam)==BN_CLICKED) { if (LOWORD(wParam)==IDOK) { char aBuf[512]; HWND anEdit = GetDlgItem(hwnd,100); GetWindowTextA(anEdit,aBuf,500); HKEY aGameKey; std::string aKeyName = RemoveTrailingSlash("SOFTWARE\\" + gSexyAppBase->mRegKey); if (RegOpenKeyExA(HKEY_CURRENT_USER, aKeyName.c_str(), 0, KEY_READ | KEY_WRITE, &aGameKey) == ERROR_SUCCESS) { RegSetValueExA(aGameKey, "DemoJumpTime", 0, REG_SZ, (const BYTE*)aBuf, strlen(aBuf)+1); RegCloseKey(aGameKey); } int aTime = 0; char *aPtr = strtok(aBuf,":"); while (aPtr != NULL) { aTime *= 60; aTime += atoi(aPtr); aPtr = strtok(NULL,":"); } aTime++; int aNumFrames = aTime*1000/gSexyAppBase->mFrameTime; gSexyAppBase->mFastForwardToUpdateNum = gSexyAppBase->mDemoLength - aNumFrames; } EndDialog(hwnd,0); return TRUE; } break; } return FALSE; } static int DemoJumpToTime() { HGLOBAL hgbl; LPDLGTEMPLATE lpdt; LPDLGITEMTEMPLATE lpdit; LPWORD lpw; LPWSTR lpwsz; LRESULT ret; int nchar; hgbl = GlobalAlloc(GMEM_ZEROINIT, 1024); if (!hgbl) return -1; lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl); // Define a dialog box. lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION | DS_SETFONT; lpdt->cdit = 3; // number of controls lpdt->x = 10; lpdt->y = 10; lpdt->cx = 200; lpdt->cy = 50; lpw = (LPWORD) (lpdt + 1); *lpw++ = 0; // no menu *lpw++ = 0; // predefined dialog box class (by default) lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Jump To Time", -1, lpwsz, 50); lpw += nchar; *lpw++ = 8; lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Tahoma", -1, lpwsz, 50); lpw += nchar; // Define Edit lpw = lpdwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 5; lpdit->y = 5; lpdit->cx = 190; lpdit->cy = 15; lpdit->id = 100; lpdit->style = WS_VISIBLE | WS_CHILD; lpdit->dwExtendedStyle = WS_EX_CLIENTEDGE; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0081; // edit class *lpw++ = 0; // no window text *lpw++ = 0; // no creation data // Define Button lpw = lpdwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 30; lpdit->y = 25; lpdit->cx = 60; lpdit->cy = 15; lpdit->id = IDOK; lpdit->style = WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON; // lpdit->dwExtendedStyle = WS_EX_CLIENTEDGE; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Ok", -1, lpwsz, 50); lpw += nchar; lpw = lpdwAlign (lpw); // align creation data on DWORD boundary *lpw++ = 0; // no creation data // Define Button lpw = lpdwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary lpdit = (LPDLGITEMTEMPLATE) lpw; lpdit->x = 100; lpdit->y = 25; lpdit->cx = 60; lpdit->cy = 15; lpdit->id = IDCANCEL; lpdit->style = WS_VISIBLE | WS_CHILD; // lpdit->dwExtendedStyle = WS_EX_CLIENTEDGE; lpw = (LPWORD) (lpdit + 1); *lpw++ = 0xFFFF; *lpw++ = 0x0080; // button class lpwsz = (LPWSTR) lpw; nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50); lpw += nchar; lpw = lpdwAlign (lpw); // align creation data on DWORD boundary *lpw++ = 0; // no creation data GlobalUnlock(hgbl); ret = DialogBoxIndirect(gHInstance, (LPDLGTEMPLATE) hgbl, gSexyAppBase->mHWnd, (DLGPROC) JumpToTimeDialogProc); GlobalFree(hgbl); gSexyAppBase->mLastTime = timeGetTime(); return ret; } static void ToggleDemoSoundVolume() { if (gSexyAppBase->GetMusicVolume() == 0.0) gSexyAppBase->SetMusicVolume(gSexyAppBase->mDemoMusicVolume); else { gSexyAppBase->mDemoMusicVolume = gSexyAppBase->mMusicVolume; gSexyAppBase->SetMusicVolume(0.0); } if (gSexyAppBase->GetSfxVolume() == 0.0) gSexyAppBase->SetSfxVolume(gSexyAppBase->mDemoSfxVolume); else { gSexyAppBase->mDemoSfxVolume = gSexyAppBase->mSfxVolume; gSexyAppBase->SetSfxVolume(0.0); } } static DWORD gPowerSaveTick = 0; static bool ScreenSaverWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &theResult) { static bool gCreated = false; static int gMouseMoveCount = 0; static int gLastMouseX = 0, gLastMouseY = 0; static bool gClosed = false; typedef BOOL (WINAPI *VERIFYPWDPROC)(HWND); static VERIFYPWDPROC aPasswordFunc = NULL; HMODULE aPasswordLib = NULL; if (gClosed) return false; switch (uMsg) { case WM_CREATE: { if (gCreated) return false; gCreated = true; POINT aMousePoint; GetCursorPos(&aMousePoint); gLastMouseX = aMousePoint.x; gLastMouseY = aMousePoint.y; // Password checking stuff for 95/98/ME OSVERSIONINFO aVersion; aVersion.dwOSVersionInfoSize = sizeof(aVersion); GetVersionEx(&aVersion); if (aVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { HKEY hKey; if (RegOpenKey(HKEY_CURRENT_USER, REGSTR_PATH_SCREENSAVE ,&hKey) == ERROR_SUCCESS) { DWORD aCheckPwd = 0; DWORD aSize = sizeof(DWORD); DWORD aType; LONG aResult = RegQueryValueEx(hKey, REGSTR_VALUE_USESCRPASSWORD, NULL, &aType, (PBYTE) &aCheckPwd, &aSize); if (aResult==ERROR_SUCCESS && aCheckPwd) { aPasswordLib = LoadLibrary(TEXT("PASSWORD.CPL")); if (aPasswordLib) { aPasswordFunc = (VERIFYPWDPROC)GetProcAddress(aPasswordLib, "VerifyScreenSavePwd"); // prevents user from ctrl-alt-deleting the screensaver etc to avoid typing in a password int aPrev; SystemParametersInfo(SPI_SCREENSAVERRUNNING, TRUE, &aPrev, 0); } } RegCloseKey(hKey); } } return false; } break; case WM_SYSCOMMAND: { switch (wParam) { case SC_CLOSE: case SC_SCREENSAVE: case SC_NEXTWINDOW: case SC_PREVWINDOW: theResult = FALSE; return true; default: return false; } } break; case WM_MOUSEMOVE: { int aMouseX = LOWORD(lParam); int aMouseY = HIWORD(lParam); // SEXY_TRACE(StrFormat("SCR MouseMove: %d %d",aMouseX,aMouseY).c_str()); if (aMouseX!=gLastMouseX || aMouseY!=gLastMouseY) { gLastMouseX = aMouseX; gLastMouseY = aMouseY; gMouseMoveCount++; } if (gMouseMoveCount < 4) { theResult = 0; return true; } } break; case WM_NCACTIVATE: case WM_ACTIVATE: case WM_ACTIVATEAPP: { if (wParam != FALSE) return false; } break; case WM_CLOSE: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_KEYDOWN: case WM_SYSKEYDOWN: break; default: return false; } if (gSexyAppBase!=NULL && gSexyAppBase->mHWnd!=hWnd) // wrong window return false; if (GetTickCount()-gPowerSaveTick < 1000) // powersave just went on so ignore certain messages that seem to come on certain os's at that time { switch (uMsg) { case WM_MOUSEMOVE: case WM_NCACTIVATE: case WM_ACTIVATE: case WM_ACTIVATEAPP: case WM_CLOSE: return false; } } if (aPasswordFunc && gSexyAppBase!=NULL && gSexyAppBase->mInitialized) // need to verify password before closing { if (gSexyAppBase!=NULL && gSexyAppBase->mDDInterface!=NULL && gSexyAppBase->mDDInterface->mDD!=NULL) { gSexyAppBase->mDDInterface->mDD->FlipToGDISurface(); // so we can see the password dialog gSexyAppBase->mNoDefer = true; // so the app doesn't draw over the password dialog } gClosed = true; // prevent this function from doing anything while in the password dialog BOOL aPasswordResult = aPasswordFunc(hWnd); gClosed = false; // let this functino work again if (gSexyAppBase!=NULL) { gSexyAppBase->mNoDefer = false; gSexyAppBase->ClearUpdateBacklog(); } if (!aPasswordResult) // bad password { // Get new mouse coordinate POINT aMousePoint; GetCursorPos(&aMousePoint); gLastMouseX = aMousePoint.x; gLastMouseY = aMousePoint.y; gMouseMoveCount = 0; return false; } // can turn this SPI_SCREENSAVERRUNNING off now since screensaver is about to stop int aPrev; SystemParametersInfo(SPI_SCREENSAVERRUNNING, FALSE, &aPrev, 0); // good password -> close and unload dll FreeLibrary(aPasswordLib); aPasswordLib = NULL; aPasswordFunc = NULL; } // Screen saver should shutdown gClosed = true; PostMessage(hWnd, WM_CLOSE, 0, 0); /* const char *str = ""; switch (uMsg) { case WM_CREATE: str="WM_CREATE"; break; case WM_SYSCOMMAND: str="WM_SYSCOMMAND"; break; case WM_MOUSEMOVE: str="WM_MOUSEMOVE"; break; case WM_NCACTIVATE: str="WM_NCACTIVATE"; break; case WM_ACTIVATE: str="WM_ACTIVATE"; break; case WM_ACTIVATEAPP: str="WM_ACTIVATEAPP"; break; case WM_CLOSE: str="WM_CLOSE"; break; case WM_LBUTTONDOWN: str="WM_LBUTTONDOWN"; break; case WM_RBUTTONDOWN: str="WM_RBUTTONDOWN"; break; case WM_MBUTTONDOWN: str="WM_MBUTTONDOWN"; break; case WM_KEYDOWN: str="WM_KEYDOWN"; break; case WM_SYSKEYDOWN: str="WM_SYSKEYDOWN"; break; } SEXY_TRACE(StrFormat("Scr shutdown: %s",str).c_str());*/ return false; } LRESULT CALLBACK SexyAppBase::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (gSexyAppBase!=NULL && gSexyAppBase->IsScreenSaver()) { LRESULT aResult; if (ScreenSaverWindowProc(hWnd,uMsg,wParam,lParam,aResult)) return aResult; } SexyAppBase* aSexyApp = (SexyAppBase*) GetWindowLong(hWnd, GWL_USERDATA); switch (uMsg) { // TODO: switch to killfocus/setfocus? // case WM_KILLFOCUS: // case WM_SETFOCUS: // if ((aSexyApp != NULL) && (!aSexyApp->mPlayingDemoBuffer)) // { // if (hWnd == aSexyApp->mHWnd) // aSexyApp->mActive = uMsg==WM_SETFOCUS; // } // //Fallthrough case WM_ACTIVATEAPP: if ((aSexyApp != NULL) && (!aSexyApp->mPlayingDemoBuffer)) { if (hWnd == aSexyApp->mHWnd) { aSexyApp->mActive = wParam != 0; } } //Fallthrough case WM_SIZE: case WM_MOVE: case WM_TIMER: case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_MOUSEMOVE: case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: case WM_CHAR: case WM_CLOSE: case WM_MOUSEWHEEL: case WM_DISPLAYCHANGE: case WM_SYSCOLORCHANGE: { /* if (aSexyApp!=NULL && aSexyApp->mProcessInTimer && !aSexyApp->mShutdown && aSexyApp->mRunning) { if (uMsg==WM_TIMER && wParam==101) { for (int i=0; i<5; i++) { if (GetQueueStatus(QS_INPUT | QS_PAINT)) break; if (!aSexyApp->Process(false)) break; } } break; }*/ /*if ((aSexyApp != NULL) && (aSexyApp->mNoDefer)) { // Check to see if we should be windowed WINDOWPLACEMENT aWindowPlacement; aWindowPlacement.length = sizeof(aWindowPlacement); if (GetWindowPlacement(aSexyApp->mHWnd, &aWindowPlacement)) { if (aWindowPlacement.showCmd == SW_SHOWMINIMIZED) { aSexyApp->Redraw(NULL); } } }*/ if ((aSexyApp != NULL) && (!aSexyApp->mNoDefer)) { bool keyDown = (uMsg==WM_KEYDOWN) || (uMsg==WM_SYSKEYDOWN); if ((keyDown) || (uMsg==WM_KEYUP) || (uMsg == WM_SYSKEYUP)) { if (wParam == VK_CONTROL) aSexyApp->mCtrlDown = keyDown; if (wParam == VK_MENU) aSexyApp->mAltDown = keyDown; } if ((keyDown) && (aSexyApp->DebugKeyDownAsync(wParam, aSexyApp->mCtrlDown, aSexyApp->mAltDown))) return 0; if (aSexyApp->mPlayingDemoBuffer) { if (uMsg==WM_CHAR) { switch (wParam) { case '+': aSexyApp->mUpdateMultiplier *= 1.5; break; case '-': aSexyApp->mUpdateMultiplier /= 1.5; break; case '=': aSexyApp->mUpdateMultiplier = 1; break; case 'p': case 'P': aSexyApp->mPaused = !aSexyApp->mPaused; aSexyApp->mLastTimeCheck = timeGetTime(); aSexyApp->mUpdateFTimeAcc = 0.0; break; case 'n': case 'N': aSexyApp->mFastForwardToUpdateNum = aSexyApp->mUpdateCount+1; aSexyApp->mFastForwardStep = true; break; case 'm': case 'M': aSexyApp->mFastForwardToMarker = true; break; case 'l': case 'L': ListDemoMarkers(); break; case 'j': case 'J': DemoJumpToTime(); break; case 's': case 'S': ToggleDemoSoundVolume(); break; case '4': // Fast foward to 120 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (120000 / aSexyApp->mFrameTime); break; case '5': // Fast foward to 90 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (90000 / aSexyApp->mFrameTime); break; case '6': // Fast foward to 60 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (60000 / aSexyApp->mFrameTime); break; case '7': // Fast foward to 30 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (30000 / aSexyApp->mFrameTime); break; case '8': // Fast foward to 10 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (10000 / aSexyApp->mFrameTime); break; case '9': // Fast foward to 5 seconds before it ends aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength - (5000 / aSexyApp->mFrameTime); break; case '0': // Fast forward to the end aSexyApp->mFastForwardToUpdateNum = aSexyApp->mDemoLength; break; } } else if (uMsg==WM_KEYDOWN) aSexyApp->DebugKeyDown(wParam); } bool pushMessage = true; if (aSexyApp->mDeferredMessages.size() > 0) { // Don't add any more messages after WM_CLOSE MSG* aMsg = &aSexyApp->mDeferredMessages.back(); if (aMsg->message == WM_CLOSE) pushMessage = false; if ((uMsg == WM_TIMER) && (uMsg == aMsg->message)) pushMessage = false; // Don't need more timer messages if (pushMessage && (uMsg==WM_SYSCOLORCHANGE || uMsg==WM_DISPLAYCHANGE)) // kill duplicate SysColorChange() events. { WindowsMessageList::iterator aMsgListItr = aSexyApp->mDeferredMessages.begin(); while (pushMessage && aMsgListItr != aSexyApp->mDeferredMessages.end()) { MSG& aMsg = *aMsgListItr; if (aMsg.message == WM_SYSCOLORCHANGE || aMsg.message == WM_DISPLAYCHANGE) pushMessage = false; ++aMsgListItr; } } } if (pushMessage) { MSG msg; msg.hwnd = hWnd; msg.message = uMsg; msg.lParam = lParam; msg.wParam = wParam; aSexyApp->mDeferredMessages.push_back(msg); } if (uMsg == WM_SIZE) { aSexyApp->mPhysMinimized = wParam == SIZE_MINIMIZED; } else if (uMsg == WM_SYSKEYDOWN) { if (wParam != VK_F4) return 0; } else if (uMsg == WM_CLOSE) { /*char aStr[256]; sprintf(aStr, "CLOSED HWND: %d\r\n", hWnd); OutputDebugString(aStr);*/ aSexyApp->CloseRequestAsync(); return 0; } } } break; case WM_ENABLE: if (aSexyApp != NULL) { aSexyApp->mIsDisabled = wParam == 0; } break; case WM_QUERYOPEN: if ((aSexyApp != NULL) && (!aSexyApp->AppCanRestore())) return 0; break; case WM_SYSCHAR: if ((aSexyApp != NULL) && (aSexyApp->IsAltKeyUsed(wParam))) return 0; break; case WM_NCLBUTTONDOWN: if (aSexyApp!=NULL) { // aSexyApp->mProcessInTimer = true; LRESULT aResult = DefWindowProc(hWnd, uMsg, wParam, lParam); // aSexyApp->mProcessInTimer = false; aSexyApp->ClearUpdateBacklog(); return aResult; } break; case WM_SYSCOMMAND: if (wParam==SC_MONITORPOWER) { gPowerSaveTick = GetTickCount(); if (aSexyApp!=NULL && (!aSexyApp->mAllowMonitorPowersave || !aSexyApp->mLoaded)) return FALSE; } if (wParam==SC_SCREENSAVE && aSexyApp!=NULL && (!aSexyApp->mLoaded || !aSexyApp->mIsPhysWindowed)) return FALSE; break; case WM_DESTROY: { char aStr[256]; sprintf(aStr, "DESTROYED HWND: %d\r\n", hWnd); OutputDebugStringA(aStr); } break; case WM_SETCURSOR: if (!aSexyApp->mSEHOccured) aSexyApp->EnforceCursor(); return TRUE; case WM_ERASEBKGND: return TRUE; case WM_ENDSESSION: aSexyApp->Shutdown(); break; case WM_PAINT: if ((aSexyApp->mInitialized) && (!gInAssert) && (!aSexyApp->mSEHOccured)) { RECT aClientRect; GetClientRect(hWnd, &aClientRect); PAINTSTRUCT ps; BeginPaint(hWnd, &ps); if (aSexyApp->mRunning) aSexyApp->Redraw(NULL); EndPaint(hWnd, &ps); return 0; } break; } if ((aSexyApp != NULL) && (uMsg == aSexyApp->mNotifyGameMessage) && (hWnd == aSexyApp->mHWnd)) { // Oh, we are trying to open another instance of ourselves. // Bring up the original window instead aSexyApp->HandleNotifyGameMessage(wParam,lParam); return 0; } if (gSexyAppBase->mIsWideWindow) return DefWindowProcW(hWnd, uMsg, wParam, lParam); else return DefWindowProcA(hWnd, uMsg, wParam, lParam); } void SexyAppBase::HandleNotifyGameMessage(int theType, int theParam) { if (theType==0) // bring to front message { WINDOWPLACEMENT aWindowPlacement; aWindowPlacement.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(mHWnd, &aWindowPlacement); if (aWindowPlacement.showCmd == SW_SHOWMINIMIZED) ShowWindow(mHWnd, SW_RESTORE); ::SetForegroundWindow(mHWnd); } } void SexyAppBase::RehupFocus() { bool wantHasFocus = mActive && !mMinimized; if (wantHasFocus != mHasFocus) { mHasFocus = wantHasFocus; if (mHasFocus) { if (mMuteOnLostFocus) Unmute(true); mWidgetManager->GotFocus(); GotFocus(); } else { if (mMuteOnLostFocus) Mute(true); mWidgetManager->LostFocus(); LostFocus(); ReleaseCapture(); mWidgetManager->DoMouseUps(); } } } void SexyAppBase::ClearKeysDown() { if (mWidgetManager != NULL) // fix stuck alt-key problem { for (int aKeyNum = 0; aKeyNum < 0xFF; aKeyNum++) mWidgetManager->mKeyDown[aKeyNum] = false; } mCtrlDown = false; mAltDown = false; } void SexyAppBase::WriteDemoTimingBlock() { // Demo writing functions can only be called from the main thread and after SexyAppBase::Init DBG_ASSERTE(GetCurrentThreadId() == mPrimaryThreadId); while (mUpdateCount - mLastDemoUpdateCnt > 15) { mDemoBuffer.WriteNumBits(15, 4); mLastDemoUpdateCnt += 15; mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_IDLE, 5); mDemoCmdOrder++; } mDemoBuffer.WriteNumBits(mUpdateCount - mLastDemoUpdateCnt, 4); mLastDemoUpdateCnt = mUpdateCount; mDemoCmdOrder++; } int aNumBigMoveMessages = 0; int aNumSmallMoveMessages = 0; int aNumTimerMessages = 0; bool SexyAppBase::PrepareDemoCommand(bool required) { if (mDemoNeedsCommand) { mDemoCmdBitPos = mDemoBuffer.mReadBitPos; mLastDemoUpdateCnt += mDemoBuffer.ReadNumBits(4, false); mDemoIsShortCmd = mDemoBuffer.ReadNumBits(1, false) == 1; if (mDemoIsShortCmd) mDemoCmdNum = mDemoBuffer.ReadNumBits(1, false); else mDemoCmdNum = mDemoBuffer.ReadNumBits(5, false); mDemoNeedsCommand = false; mDemoCmdOrder++; } DBG_ASSERTE((mUpdateCount == mLastDemoUpdateCnt) || (!required)); return mUpdateCount == mLastDemoUpdateCnt; } void SexyAppBase::ProcessDemo() { if (mPlayingDemoBuffer) { // At end of demo buffer? How dare you! DBG_ASSERTE(!mDemoBuffer.AtEnd()); while ((!mShutdown) && (mUpdateCount == mLastDemoUpdateCnt) && (!mDemoBuffer.AtEnd())) { if (PrepareDemoCommand(false)) { mDemoNeedsCommand = true; if (mDemoIsShortCmd) { switch (mDemoCmdNum) { case 0: { int aDeltaX = mDemoBuffer.ReadNumBits(6, true); int aDeltaY = mDemoBuffer.ReadNumBits(6, true); mLastDemoMouseX += aDeltaX; mLastDemoMouseY += aDeltaY; mWidgetManager->MouseMove(mLastDemoMouseX, mLastDemoMouseY); } break; case 1: { bool down = mDemoBuffer.ReadNumBits(1, false) != 0; int aBtnCount = mDemoBuffer.ReadNumBits(3, true); if (down) mWidgetManager->MouseDown(mLastDemoMouseX, mLastDemoMouseY, aBtnCount); else mWidgetManager->MouseUp(mLastDemoMouseX, mLastDemoMouseY, aBtnCount); } break; } } else { switch (mDemoCmdNum) { case DEMO_MOUSE_POSITION: { mLastDemoMouseX = mDemoBuffer.ReadNumBits(12, false); mLastDemoMouseY = mDemoBuffer.ReadNumBits(12, false); mWidgetManager->MouseMove(mLastDemoMouseX, mLastDemoMouseY); } break; case DEMO_ACTIVATE_APP: { mActive = mDemoBuffer.ReadNumBits(1, false) != 0; RehupFocus(); if ((mActive) && (!mIsWindowed)) mWidgetManager->MarkAllDirty(); if ((mIsOpeningURL) && (!mActive)) URLOpenSucceeded(mOpeningURL); } break; case DEMO_SIZE: { bool isMinimized = mDemoBuffer.ReadBoolean(); if ((!mShutdown) && (isMinimized != mMinimized)) { mMinimized = isMinimized; // We don't want any sounds (or music) playing while its minimized if (mMinimized) Mute(true); else { Unmute(true); mWidgetManager->MarkAllDirty(); } } RehupFocus(); } break; case DEMO_MOUSE_WHEEL: { int aScroll = mDemoBuffer.ReadNumBits(8, true); mWidgetManager->MouseWheel(aScroll); } break; case DEMO_KEY_DOWN: { KeyCode aKeyCode = (KeyCode) mDemoBuffer.ReadNumBits(8, false); mWidgetManager->KeyDown(aKeyCode); } break; case DEMO_KEY_UP: { KeyCode aKeyCode = (KeyCode) mDemoBuffer.ReadNumBits(8, false); mWidgetManager->KeyUp(aKeyCode); } break; case DEMO_KEY_CHAR: { int sizeMult = (int)mDemoBuffer.ReadNumBits(1, false) + 1; // will be 1 for single, 2 for double SexyChar aChar = (SexyChar) mDemoBuffer.ReadNumBits(8*sizeMult, false); mWidgetManager->KeyChar(aChar); } break; case DEMO_CLOSE: Shutdown(); break; case DEMO_MOUSE_ENTER: mMouseIn = true; EnforceCursor(); break; case DEMO_MOUSE_EXIT: mWidgetManager->MouseExit(mLastDemoMouseX, mLastDemoMouseY); mMouseIn = false; EnforceCursor(); break; case DEMO_LOADING_COMPLETE: mDemoLoadingComplete = true; break; case DEMO_VIDEO_DATA: mIsWindowed = mDemoBuffer.ReadBoolean(); mSyncRefreshRate = mDemoBuffer.ReadByte(); break; case DEMO_IDLE: break; default: DBG_ASSERTE("Invalid Demo Command" == 0); break; } } } } } } void SexyAppBase::ShowMemoryUsage() { DWORD aTotal = 0; DWORD aFree = 0; if (mDDInterface->mDD7 != NULL) { DDSCAPS2 aCaps; ZeroMemory(&aCaps,sizeof(aCaps)); aCaps.dwCaps = DDSCAPS_VIDEOMEMORY; mDDInterface->mDD7->GetAvailableVidMem(&aCaps,&aTotal,&aFree); } MemoryImageSet::iterator anItr = mMemoryImageSet.begin(); typedef std::pair FormatUsage; typedef std::map FormatMap; FormatMap aFormatMap; int aTextureMemory = 0; while (anItr != mMemoryImageSet.end()) { MemoryImage* aMemoryImage = *anItr; if (aMemoryImage->mD3DData != NULL) { TextureData *aData = (TextureData*)aMemoryImage->mD3DData; aTextureMemory += aData->mTexMemSize; FormatUsage &aUsage = aFormatMap[aData->mPixelFormat]; aUsage.first++; aUsage.second += aData->mTexMemSize; } ++anItr; } std::string aStr; const char *aDesc; if (Is3DAccelerationRecommended()) aDesc = "Recommended"; else if (Is3DAccelerationSupported()) aDesc = "Supported"; else aDesc = "Unsupported"; aStr += StrFormat("3D-Mode is %s (3D is %s on this system)\r\n\r\n",Is3DAccelerated()?"On":"Off",aDesc); aStr += StrFormat("Num Images: %d\r\n",(int)mMemoryImageSet.size()); aStr += StrFormat("Num Sounds: %d\r\n",mSoundManager->GetNumSounds()); aStr += StrFormat("Video Memory: %s/%s KB\r\n", SexyStringToString(CommaSeperate((aTotal-aFree)/1024)).c_str(), SexyStringToString(CommaSeperate(aTotal/1024)).c_str()); aStr += StrFormat("Texture Memory: %s KB\r\n",CommaSeperate(aTextureMemory/1024).c_str()); FormatUsage aUsage = aFormatMap[PixelFormat_A8R8G8B8]; aStr += StrFormat("A8R8G8B8: %d - %s KB\r\n",aUsage.first,SexyStringToString(CommaSeperate(aUsage.second/1024)).c_str()); aUsage = aFormatMap[PixelFormat_A4R4G4B4]; aStr += StrFormat("A4R4G4B4: %d - %s KB\r\n",aUsage.first,SexyStringToString(CommaSeperate(aUsage.second/1024)).c_str()); aUsage = aFormatMap[PixelFormat_R5G6B5]; aStr += StrFormat("R5G6B5: %d - %s KB\r\n",aUsage.first,SexyStringToString(CommaSeperate(aUsage.second/1024)).c_str()); aUsage = aFormatMap[PixelFormat_Palette8]; aStr += StrFormat("Palette8: %d - %s KB\r\n",aUsage.first,SexyStringToString(CommaSeperate(aUsage.second/1024)).c_str()); MsgBox(aStr,"Video Stats",MB_OK); mLastTime = timeGetTime(); } bool SexyAppBase::IsAltKeyUsed(WPARAM wParam) { int aChar = tolower(wParam); switch (aChar) { case 13: // alt-enter case 'r': return true; default: return false; } } bool SexyAppBase::DebugKeyDown(int theKey) { if ((theKey == 'R') && (mWidgetManager->mKeyDown[KEYCODE_MENU])) { #ifndef RELEASEFINAL if (ReparseModValues()) PlaySoundA("c:\\windows\\media\\Windows XP Menu Command.wav", NULL, SND_ASYNC); else { for (int aKeyNum = 0; aKeyNum < 0xFF; aKeyNum++) // prevent alt from getting stuck mWidgetManager->mKeyDown[aKeyNum] = false; } #endif } else if (theKey == VK_F3) { if(mWidgetManager->mKeyDown[KEYCODE_SHIFT]) { mShowFPS = true; if (++mShowFPSMode >= Num_FPS_Types) mShowFPSMode = 0; } else mShowFPS = !mShowFPS; mWidgetManager->MarkAllDirty(); if (mShowFPS) { gFPSTimer.Start(); gFrameCount = 0; gFPSDisplay = 0; gForceDisplay = true; } } else if (theKey == VK_F8) { if(mWidgetManager->mKeyDown[KEYCODE_SHIFT]) { Set3DAcclerated(!Is3DAccelerated()); char aBuf[512]; sprintf(aBuf,"3D-Mode: %s",Is3DAccelerated()?"ON":"OFF"); MsgBox(aBuf,"Mode Switch",MB_OK); mLastTime = timeGetTime(); } else ShowMemoryUsage(); return true; } else if (theKey == VK_F10) { #ifndef RELEASEFINAL if (mWidgetManager->mKeyDown[KEYCODE_CONTROL]) { if (mUpdateMultiplier==0.25) mUpdateMultiplier = 1.0; else mUpdateMultiplier = 0.25; } else if(mWidgetManager->mKeyDown[KEYCODE_SHIFT]) { mStepMode = 0; ClearUpdateBacklog(); } else mStepMode = 1; #endif return true; } else if (theKey == VK_F11) { if (mWidgetManager->mKeyDown[KEYCODE_SHIFT]) DumpProgramInfo(); else TakeScreenshot(); return true; } else if (theKey == VK_F2) { bool isPerfOn = !SexyPerf::IsPerfOn(); if (isPerfOn) { // MsgBox("Perf Monitoring: ON", "Perf Monitoring", MB_OK); ClearUpdateBacklog(); SexyPerf::BeginPerf(); } else { SexyPerf::EndPerf(); MsgBox(SexyPerf::GetResults().c_str(), "Perf Results", MB_OK); ClearUpdateBacklog(); } } else return false; return false; } bool SexyAppBase::DebugKeyDownAsync(int theKey, bool ctrlDown, bool altDown) { return false; } void SexyAppBase::CloseRequestAsync() { } // Why did I defer messages? Oh, incase a dialog comes up such as a crash // it won't keep crashing and stuff bool SexyAppBase::ProcessDeferredMessages(bool singleMessage) { while (mDeferredMessages.size() > 0) { MSG aMsg = mDeferredMessages.front(); mDeferredMessages.pop_front(); UINT uMsg = aMsg.message; LPARAM lParam = aMsg.lParam; WPARAM wParam = aMsg.wParam; HWND hWnd = aMsg.hwnd; if ((mRecordingDemoBuffer) && (!mShutdown)) { switch (uMsg) { // TODO: switch to killfocus/setfocus? // case WM_SETFOCUS: // case WM_KILLFOCUS: // if (hWnd == mHWnd) // { // WriteDemoTimingBlock(); // mDemoBuffer.WriteNumBits(0, 1); // mDemoBuffer.WriteNumBits(DEMO_ACTIVATE_APP, 5); // mDemoBuffer.WriteNumBits(uMsg==WM_SETFOCUS ? 1 : 0, 1); // } // break; case WM_ACTIVATEAPP: if (hWnd == mHWnd) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_ACTIVATE_APP, 5); mDemoBuffer.WriteNumBits((wParam != 0) ? 1 : 0, 1); } break; case WM_SIZE: { bool isMinimized = wParam == SIZE_MINIMIZED; WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_SIZE, 5); mDemoBuffer.WriteBoolean(isMinimized); } break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_MOUSEMOVE: { int aCurX = (short) LOWORD(lParam); int aCurY = (short) HIWORD(lParam); int aDiffX = aCurX - mLastDemoMouseX; int aDiffY = aCurY - mLastDemoMouseY; if ((abs(aCurX - mLastDemoMouseX) < 32) && (abs(aCurY - mLastDemoMouseY) < 32)) { if ((aDiffX != 0) || (aDiffY != 0)) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(1, 1); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(aDiffX, 6); mDemoBuffer.WriteNumBits(aDiffY, 6); } } else { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_MOUSE_POSITION, 5); mDemoBuffer.WriteNumBits(aCurX, 12); mDemoBuffer.WriteNumBits(aCurY, 12); } bool down = true; int aBtnNum = 0; switch (uMsg) { case WM_LBUTTONDOWN: aBtnNum = 1; break; case WM_RBUTTONDOWN: aBtnNum = -1; break; case WM_MBUTTONDOWN: aBtnNum = 3; break; case WM_LBUTTONDBLCLK: aBtnNum = 2; break; case WM_RBUTTONDBLCLK: aBtnNum = -2; break; case WM_LBUTTONUP: aBtnNum = 1; down = false; break; case WM_RBUTTONUP: aBtnNum = -1; down = false; break; case WM_MBUTTONUP: aBtnNum = 3; down = false; break; } if (aBtnNum != 0) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(1, 1); mDemoBuffer.WriteNumBits(1, 1); mDemoBuffer.WriteNumBits(down ? 1 : 0, 1); mDemoBuffer.WriteNumBits(aBtnNum, 3); } mLastDemoMouseX = aCurX; mLastDemoMouseY = aCurY; } break; case WM_MOUSEWHEEL: { int aZDelta = ((short)HIWORD(wParam)) / 120; WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_MOUSE_WHEEL, 5); mDemoBuffer.WriteNumBits(aZDelta, 8); } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: { KeyCode aKeyCode = (KeyCode) wParam; WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_KEY_DOWN, 5); mDemoBuffer.WriteNumBits(aKeyCode, 8); } break; case WM_KEYUP: case WM_SYSKEYUP: { KeyCode aKeyCode = (KeyCode) wParam; WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_KEY_UP, 5); mDemoBuffer.WriteNumBits((int) aKeyCode, 8); } break; case WM_CHAR: { SexyChar aChar = (SexyChar) wParam; WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_KEY_CHAR, 5); mDemoBuffer.WriteNumBits(sizeof(SexyChar) == 2, 1); mDemoBuffer.WriteNumBits(aChar, sizeof(SexyChar)*8); } break; case WM_CLOSE: if ((hWnd == mHWnd) || (hWnd == mInvisHWnd)) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_CLOSE, 5); } break; } int aBufferSize = mDemoBuffer.GetDataLen(); } if (!mPlayingDemoBuffer) { switch (uMsg) { // TODO: switch to killfocus/setfocus? // case WM_KILLFOCUS: // case WM_SETFOCUS: case WM_ACTIVATEAPP: if ((hWnd == mHWnd) && (!gInAssert) && (!mSEHOccured) && (!mShutdown)) { // mActive = uMsg==WM_SETFOCUS; RehupFocus(); if ((mActive) && (!mIsWindowed)) mWidgetManager->MarkAllDirty(); if ((mIsOpeningURL) && (!mActive)) URLOpenSucceeded(mOpeningURL); } break; case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_MBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: case WM_LBUTTONUP: case WM_RBUTTONUP: case WM_MBUTTONUP: case WM_MOUSEMOVE: if ((!gInAssert) && (!mSEHOccured)) { int x = (short) LOWORD(lParam); int y = (short) HIWORD(lParam); mWidgetManager->RemapMouse(x, y); mLastUserInputTick = mLastTimerTime; mWidgetManager->MouseMove(x, y); if (!mMouseIn) { if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_MOUSE_ENTER, 5); } mMouseIn = true; EnforceCursor(); } switch (uMsg) { case WM_LBUTTONDOWN: SetCapture(hWnd); mWidgetManager->MouseDown(x, y, 1); break; case WM_RBUTTONDOWN: SetCapture(hWnd); mWidgetManager->MouseDown(x, y, -1); break; case WM_MBUTTONDOWN: SetCapture(hWnd); mWidgetManager->MouseDown(x, y, 3); break; case WM_LBUTTONDBLCLK: SetCapture(hWnd); mWidgetManager->MouseDown(x, y, 2); break; case WM_RBUTTONDBLCLK: SetCapture(hWnd); mWidgetManager->MouseDown(x, y, -2); break; case WM_LBUTTONUP: if ((mWidgetManager->mDownButtons & ~1) == 0) ReleaseCapture(); mWidgetManager->MouseUp(x, y, 1); break; case WM_RBUTTONUP: if ((mWidgetManager->mDownButtons & ~2) == 0) ReleaseCapture(); mWidgetManager->MouseUp(x, y, -1); break; case WM_MBUTTONUP: if ((mWidgetManager->mDownButtons & ~4) == 0) ReleaseCapture(); mWidgetManager->MouseUp(x, y, 3); break; } } break; case WM_MOUSEWHEEL: { char aZDelta = ((short)HIWORD(wParam)) / 120; mWidgetManager->MouseWheel(aZDelta); } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: mLastUserInputTick = mLastTimerTime; if (wParam==VK_RETURN && uMsg==WM_SYSKEYDOWN && !mForceFullscreen && !mForceWindowed) { SwitchScreenMode(!mIsWindowed); ClearKeysDown(); break; } else if ((wParam == 'D') && (mWidgetManager != NULL) && (mWidgetManager->mKeyDown[KEYCODE_CONTROL]) && (mWidgetManager->mKeyDown[KEYCODE_MENU])) { PlaySoundA("c:\\windows\\media\\Windows XP Menu Command.wav", NULL, SND_ASYNC); mDebugKeysEnabled = !mDebugKeysEnabled; } if (mDebugKeysEnabled) { if (DebugKeyDown(wParam)) break; } mWidgetManager->KeyDown((KeyCode) wParam); break; case WM_KEYUP: case WM_SYSKEYUP: mLastUserInputTick = mLastTimerTime; mWidgetManager->KeyUp((KeyCode) wParam); break; case WM_CHAR: mLastUserInputTick = mLastTimerTime; mWidgetManager->KeyChar((SexyChar) wParam); break; case WM_MOVE: { if ((hWnd == mHWnd) && (mIsWindowed)) { WINDOWPLACEMENT aWindowPlacment; aWindowPlacment.length = sizeof(aWindowPlacment); GetWindowPlacement(hWnd, &aWindowPlacment); if ((aWindowPlacment.showCmd == SW_SHOW) || (aWindowPlacment.showCmd == SW_SHOWNORMAL)) { mPreferredX = aWindowPlacment.rcNormalPosition.left; mPreferredY = aWindowPlacment.rcNormalPosition.top; } } } break; case WM_SIZE: { bool isMinimized = wParam == SIZE_MINIMIZED; if ((hWnd == mHWnd) && (!mShutdown) && (isMinimized != mMinimized)) { mMinimized = isMinimized; // We don't want any sounds (or music) playing while its minimized if (mMinimized) { if (mMuteOnLostFocus) Mute(true); } else { if (mMuteOnLostFocus) Unmute(true); mWidgetManager->MarkAllDirty(); } } RehupFocus(); if (wParam==SIZE_MAXIMIZED) SwitchScreenMode(false); } break; case WM_TIMER: if ((!gInAssert) && (!mSEHOccured) && (mRunning)) { DWORD aTimeNow = GetTickCount(); if (aTimeNow - mLastTimerTime > 500) mLastBigDelayTime = aTimeNow; mLastTimerTime = aTimeNow; if ((mIsOpeningURL) && (aTimeNow - mLastBigDelayTime > 5000)) { if ((aTimeNow - mOpeningURLTime > 8000) && (!mActive)) { //TODO: Have some demo message thing URLOpenSucceeded(mOpeningURL); } else if ((aTimeNow - mOpeningURLTime > 12000) && (mActive)) { URLOpenFailed(mOpeningURL); } } POINT aULCorner = {0, 0}; ::ClientToScreen(hWnd, &aULCorner); POINT aBRCorner = {mDDInterface->mDisplayWidth, mDDInterface->mDisplayHeight}; ::ClientToScreen(hWnd, &aBRCorner); POINT aPoint; ::GetCursorPos(&aPoint); HWND aWindow = ::WindowFromPoint(aPoint); bool isMouseIn = (aWindow == hWnd) && (aPoint.x >= aULCorner.x) && (aPoint.y >= aULCorner.y) && (aPoint.x < aBRCorner.x) && (aPoint.y < aBRCorner.y); if (mMouseIn != isMouseIn) { if ((mRecordingDemoBuffer) && (!mShutdown)) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); if (isMouseIn) mDemoBuffer.WriteNumBits(DEMO_MOUSE_ENTER, 5); else mDemoBuffer.WriteNumBits(DEMO_MOUSE_EXIT, 5); } if (!isMouseIn) { int x = aPoint.x - aULCorner.x; int y = aPoint.y - aULCorner.y; mWidgetManager->RemapMouse(x, y); mWidgetManager->MouseExit(x, y); } mMouseIn = isMouseIn; EnforceCursor(); } } break; case WM_SYSCOLORCHANGE: case WM_DISPLAYCHANGE: mWidgetManager->SysColorChangedAll(); mWidgetManager->MarkAllDirty(); break; } } switch (uMsg) { case WM_CLOSE: if ((hWnd == mHWnd) || (hWnd == mInvisHWnd)) { // This should short-circuit all demo calls, otherwise we will get // all sorts of weird asserts because we are changing // program flow mManualShutdown = true; Shutdown(); } break; } if (singleMessage) break; } return (mDeferredMessages.size() > 0); } void SexyAppBase::DoParseCmdLine() { char* aCmdLine = GetCommandLineA(); char* aCmdLinePtr = aCmdLine; if (aCmdLinePtr[0] == '"') { aCmdLinePtr = strchr(aCmdLinePtr + 1, '"'); if (aCmdLinePtr != NULL) aCmdLinePtr++; } if (aCmdLinePtr != NULL) { aCmdLinePtr = strchr(aCmdLinePtr, ' '); if (aCmdLinePtr != NULL) ParseCmdLine(aCmdLinePtr+1); } mCmdLineParsed = true; } void SexyAppBase::ParseCmdLine(const std::string& theCmdLine) { // Command line example: -play -demofile="game demo.dmo" // Results in HandleCmdLineParam("-play", ""); HandleCmdLineParam("-demofile", "game demo.dmo"); std::string aCurParamName; std::string aCurParamValue; int aSpacePos = 0; bool inQuote = false; bool onValue = false; for (int i = 0; i < (int) theCmdLine.length(); i++) { char c = theCmdLine[i]; bool atEnd = false; if (c == '"') { inQuote = !inQuote; if (!inQuote) atEnd = true; } else if ((c == ' ') && (!inQuote)) atEnd = true; else if (c == '=') onValue = true; else if (onValue) aCurParamValue += c; else aCurParamName += c; if (i == theCmdLine.length() - 1) atEnd = true; if (atEnd && !aCurParamName.empty()) { HandleCmdLineParam(aCurParamName, aCurParamValue); aCurParamName = ""; aCurParamValue = ""; onValue = false; } } } static int GetMaxDemoFileNum(const std::string& theDemoPrefix, int theMaxToKeep, bool doErase) { WIN32_FIND_DATAA aData; HANDLE aHandle = FindFirstFileA((theDemoPrefix + "*.dmo").c_str(), &aData); if (aHandle==INVALID_HANDLE_VALUE) return 0; typedef std::set IntSet; IntSet aSet; do { int aNum = 0; if (sscanf(aData.cFileName,(theDemoPrefix + "%d.dmo").c_str(), &aNum)==1) aSet.insert(aNum); } while(FindNextFileA(aHandle,&aData)); FindClose(aHandle); IntSet::iterator anItr = aSet.begin(); if ((int)aSet.size()>theMaxToKeep-1 && doErase) DeleteFile(StrFormat((theDemoPrefix + "%d.dmo").c_str(),*anItr).c_str()); if (aSet.empty()) return 0; anItr = aSet.end(); --anItr; return (*anItr); } void SexyAppBase::HandleCmdLineParam(const std::string& theParamName, const std::string& theParamValue) { if (theParamName == "-play") { mPlayingDemoBuffer = true; mRecordingDemoBuffer = false; } else if (theParamName == "-recnum") { int aNum = atoi(theParamValue.c_str()); if (aNum<=0) aNum=5; int aDemoFileNum = GetMaxDemoFileNum(mDemoPrefix, aNum, true) + 1; mDemoFileName = SexyStringToString(StrFormat(StringToSexyString(mDemoPrefix + "%d.dmo").c_str(),aDemoFileNum)); if (mDemoFileName.length() < 2 || (mDemoFileName[1] != ':' && mDemoFileName[2] != '\\')) { mDemoFileName = GetAppDataFolder() + mDemoFileName; } mRecordingDemoBuffer = true; mPlayingDemoBuffer = false; } else if (theParamName == "-playnum") { int aNum = atoi(theParamValue.c_str())-1; if (aNum<0) aNum=0; int aDemoFileNum = GetMaxDemoFileNum(mDemoPrefix, aNum, false)-aNum; mDemoFileName = SexyStringToString(StrFormat(StringToSexyString(mDemoPrefix + "%d.dmo").c_str(),aDemoFileNum)); mRecordingDemoBuffer = false; mPlayingDemoBuffer = true; } else if (theParamName == "-record") { mRecordingDemoBuffer = true; mPlayingDemoBuffer = false; } else if (theParamName == "-demofile") { mDemoFileName = theParamValue; if (mDemoFileName.length() < 2 || (mDemoFileName[1] != ':' && mDemoFileName[2] != '\\')) { mDemoFileName = GetAppDataFolder() + mDemoFileName; } } else if (theParamName == "-crash") { // Try to access NULL char* a = 0; *a = '!'; } else if (theParamName == "-screensaver") { mIsScreenSaver = true; } else if (theParamName == "-changedir") { mChangeDirTo = theParamValue; } else { Popup(GetString("INVALID_COMMANDLINE_PARAM", _S("Invalid command line parameter: ")) + StringToSexyString(theParamName)); DoExit(0); } } void SexyAppBase::CopyToClipboard(const std::string& theString) { if (mPlayingDemoBuffer) return; HGLOBAL aGlobalHandle; char* theData; WCHAR* theWData; if (OpenClipboard(mHWnd)) { EmptyClipboard(); aGlobalHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, theString.length()+1); theData = (char*) GlobalLock(aGlobalHandle); strcpy(theData, theString.c_str()); GlobalUnlock(aGlobalHandle); SetClipboardData(CF_TEXT, aGlobalHandle); SetClipboardData(CF_OEMTEXT, aGlobalHandle); SetClipboardData(CF_LOCALE, aGlobalHandle); int aSize = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, theString.c_str(), theString.length(), NULL, 0); aGlobalHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, (aSize + 1) * sizeof(WCHAR)); theWData = (WCHAR*) GlobalLock(aGlobalHandle); MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, theString.c_str(), theString.length(), theWData, aSize); theWData[aSize] = '\0'; GlobalUnlock(aGlobalHandle); SetClipboardData(CF_UNICODETEXT, aGlobalHandle); CloseClipboard(); } } std::string SexyAppBase::GetClipboard() { HGLOBAL aGlobalHandle; std::string aString; if (!mPlayingDemoBuffer) { if (OpenClipboard(mHWnd)) { aGlobalHandle = GetClipboardData(CF_TEXT); if (aGlobalHandle != NULL) { char* theData = (char*) GlobalLock(aGlobalHandle); if (theData != NULL) { aString = theData; GlobalUnlock(aGlobalHandle); } } CloseClipboard(); } } DemoSyncString(&aString); return aString; } void SexyAppBase::DemoSyncRefreshRate() { mSyncRefreshRate = mDDInterface->mRefreshRate; if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_VIDEO_DATA, 5); mDemoBuffer.WriteBoolean(mIsWindowed); uchar aByte = (uchar) mSyncRefreshRate; mDemoBuffer.WriteByte(aByte); } } #endif void SexyAppBase::Set3DAcclerated(bool is3D, bool reinit) { if (mDDInterface->mIs3D == is3D) return; mUserChanged3DSetting = true; mDDInterface->mIs3D = is3D; if (reinit) { int aResult = InitDDInterface(); if (is3D && aResult != DDInterface::RESULT_OK) { Set3DAcclerated(false, reinit); return; } else if (aResult != DDInterface::RESULT_OK) { #if 0 Popup(GetString("FAILED_INIT_DIRECTDRAW", _S("Failed to initialize DirectDraw: ")) + StringToSexyString(DDInterface::ResultToString(aResult) + " " + mDDInterface->mErrorString)); #endif DoExit(1); } ReInitImages(); mWidgetManager->mImage = mDDInterface->GetScreenImage(); mWidgetManager->MarkAllDirty(); } } //convert from win32 cursors to sdl cursor static void ConvertCursorToSDL(unsigned char* data) { unsigned char temp_cursor[256]; for (int i = 0; i < 128; ++i) { unsigned char and_mask = data[i]; unsigned char xor_mask = data[i + 128]; unsigned char new_and_mask = 0; unsigned char new_xor_mask = 0; for (int j = 0; j < 8; ++j) { if ((and_mask & (1 << j)) && (xor_mask & (1 << j))) { new_and_mask |= 1 << j; } else if (!(and_mask & (1 << j)) && (xor_mask & (1 << j))) { new_xor_mask |= 1 << j; } else if (!(and_mask & (1 << j)) && !(xor_mask & (1 << j))) { new_and_mask |= 1 << j; new_xor_mask |= 1 << j; } } temp_cursor[i] = new_and_mask; temp_cursor[i + 128] = new_xor_mask; } memcpy(data, temp_cursor, 256); } void SexyAppBase::Init() { mPrimaryThreadId = SDL_ThreadID(); if (mShutdown) return; SetAppDataFolder(GetAppDataFolder() + "." + mRegKey + "/"); InitPropertiesHook(); surface = NULL; ReadFromRegistry(); #if 0 if (!mCmdLineParsed) DoParseCmdLine(); if (IsScreenSaver()) mOnlyAllowOneCopyToRun = false; // Change directory if (!ChangeDirHook(mChangeDirTo.c_str())) chdir(mChangeDirTo.c_str()); gPakInterface->AddPakFile("main.pak"); // Create a message we can use to talk to ourselves inter-process mNotifyGameMessage = RegisterWindowMessage((_S("Notify") + StringToSexyString(mProdName)).c_str()); // Create a globally unique mutex #endif if (mMutex != NULL) HandleGameAlreadyRunning(); mMutex = SDL_CreateMutex(); mRandSeed = SDL_GetTicks(); SRand(mRandSeed); #if 0 // Set up demo recording stuff if (mPlayingDemoBuffer) { std::string anError; if (!ReadDemoBuffer(anError)) { mPlayingDemoBuffer = false; Popup(anError); DoExit(0); } } #endif srand(SDL_GetTicks()); mArrowCursor = SDL_GetCursor(); ConvertCursorToSDL(gFingerCursorData); ConvertCursorToSDL(gDraggingCursorData); mHandCursor = SDL_CreateCursor(gFingerCursorData, gFingerCursorData+sizeof(gFingerCursorData)/2, 32, 32, 11, 4); mDraggingCursor = SDL_CreateCursor(gDraggingCursorData, gDraggingCursorData+sizeof(gDraggingCursorData)/2, 32, 32, 15,10); // Let app do something before showing window, or switching to fullscreen mode // NOTE: Moved call to PreDisplayHook above mIsWindowed and GetSystemsMetrics // checks because the checks below use values that could change in PreDisplayHook. // PreDisplayHook must call mWidgetManager->Resize if it changes mWidth or mHeight. PreDisplayHook(); mWidgetManager->Resize(Rect(0, 0, mWidth, mHeight), Rect(0, 0, mWidth, mHeight)); // Check to see if we CAN run windowed or not... if (mIsWindowed && !mFullScreenWindow) { //FIXME check opengl SDL_Rect **modes; modes=SDL_ListModes(NULL, SDL_DOUBLEBUF); /* Check is there are any modes available */ if(modes == (SDL_Rect **)0){ printf("No modes available!\n"); exit(-1); } /* Check if our resolution is restricted */ if(modes == (SDL_Rect **)-1){ ; // printf("All resolutions available.\n"); } else{ // How can we be windowed if our screen isn't even big enough? // if ((mWidth >= modes[0]->w) || (mHeight >= modes[0]->h)) { mIsWindowed = false; mForceFullscreen = true; } } } else if (mFullScreenWindow) { SDL_Rect **modes; modes=SDL_ListModes(NULL, SDL_DOUBLEBUF | SDL_FULLSCREEN); /* Check is there are any modes available */ if(modes == (SDL_Rect **)0){ mFullScreenWindow = false; mIsWindowed = false; } } MakeWindow(); if (mShowFPS) aFont = new ImageFont(gSexyAppBase,"fonts/Kiloton9.txt"); #if 0 if (mPlayingDemoBuffer) { // Get video data PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_VIDEO_DATA); mIsWindowed = mDemoBuffer.ReadBoolean(); mSyncRefreshRate = mDemoBuffer.ReadByte(); } #endif if (mSoundManager == NULL) #ifdef USE_AUDIERE mSoundManager = new AudiereSoundManager(); #else mSoundManager = new SDLMixerSoundManager(); #endif SetSfxVolume(mSfxVolume); mMusicInterface = CreateMusicInterface(); SetMusicVolume(mMusicVolume); #if 0 if (IsScreenSaver()) { SetCursor(CURSOR_NONE); } InitHook(); #endif SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); //SWTri_AddAllDrawTriFuncs(); mInitialized = true; } void SexyAppBase::DeleteExtraImageData() { #if 0 AutoCrit anAutoCrit(mDDInterface->mCritSect); #endif MemoryImageSet::iterator anItr = mMemoryImageSet.begin(); while (anItr != mMemoryImageSet.end()) { MemoryImage* aMemoryImage = *anItr; aMemoryImage->DeleteExtraBuffers(); ++anItr; } } void SexyAppBase::ReInitImages() { MemoryImageSet::iterator anItr = mMemoryImageSet.begin(); while (anItr != mMemoryImageSet.end()) { MemoryImage* aMemoryImage = *anItr; aMemoryImage->ReInit(); ++anItr; } } void SexyAppBase::Shutdown() { if ((mPrimaryThreadId != 0) && (SDL_ThreadID() != mPrimaryThreadId)) { mLoadingFailed = true; } else if (!mShutdown) { mExitToTop = true; mShutdown = true; ShutdownHook(); #if 0 if (mPlayingDemoBuffer) { //if the music/sfx volume is 0, then it means that in playback //someone pressed the "S" key to mute sounds (or that the //sound volume was set to 0 in the first place). Out of politeness, //return the system sound volume to what it last was in the game. SetMusicVolume(mDemoMusicVolume); SetSfxVolume(mDemoSfxVolume); } if ((!mIsPhysWindowed) && (mDDInterface != NULL) && (mDDInterface->mDD != NULL)) { mDDInterface->mDD->RestoreDisplayMode(); } if (mHWnd != NULL) { ShowWindow(mHWnd, SW_HIDE); } RestoreScreenResolution(); ImageLib::CloseJPEG2000(); #endif } } void SexyAppBase::Start() { if (mShutdown) return; if (mAutoStartLoadingThread) StartLoadingThread(); #if 0 ::ShowWindow(mHWnd, SW_SHOW); ::SetFocus(mHWnd); timeBeginPeriod(1); #endif int aCount = 0; int aSleepCount = 0; Uint32 aStartTime = SDL_GetTicks(); mRunning = true; mLastTime = aStartTime; mLastUserInputTick = aStartTime; mLastTimerTime = aStartTime; DoMainLoop(); ProcessSafeDeleteList(); mRunning = false; WaitForLoadingThread(); char aString[256]; #if 0 sprintf(aString, "Seconds = %g\r\n", (timeGetTime() - aStartTime) / 1000.0); OutputDebugStringA(aString); //sprintf(aString, "Count = %d\r\n", aCount); //OutputDebugString(aString); sprintf(aString, "Sleep Count = %d\r\n", mSleepCount); OutputDebugStringA(aString); sprintf(aString, "Update Count = %d\r\n", mUpdateCount); OutputDebugStringA(aString); sprintf(aString, "Draw Count = %d\r\n", mDrawCount); OutputDebugStringA(aString); sprintf(aString, "Draw Time = %d\r\n", mDrawTime); OutputDebugStringA(aString); sprintf(aString, "Screen Blt = %d\r\n", mScreenBltTime); OutputDebugStringA(aString); if (mDrawTime+mScreenBltTime > 0) { sprintf(aString, "Avg FPS = %d\r\n", (mDrawCount*1000)/(mDrawTime+mScreenBltTime)); OutputDebugStringA(aString); } timeEndPeriod(1); #endif // PreTerminate(); WriteToRegistry(); WriteRegistryToIni(BuildIniName(mRegKey, ".") + ".ini"); } void SexyAppBase::DoMainLoop() { while (!mShutdown) { if (mExitToTop) mExitToTop = false; UpdateApp(); } } bool SexyAppBase::UpdateApp() { bool updated; for (;;) { if (!UpdateAppStep(&updated)) return false; if (updated) return true; } } bool SexyAppBase::UpdateAppStep(bool* updated) { if (updated != NULL) *updated = false; if (mExitToTop) return false; if (mUpdateAppState == UPDATESTATE_PROCESS_DONE) mUpdateAppState = UPDATESTATE_MESSAGES; mUpdateAppDepth++; // We update in two stages to avoid doing a Process if our loop termination // condition has already been met by processing windows messages if (mUpdateAppState == UPDATESTATE_MESSAGES) { SDL_Event test_event; // static int counti = 0; if (SDL_PollEvent(&test_event)) { switch(test_event.type) { case SDL_MOUSEMOTION: //FIXME if (/*(!gInAssert) &&*/ (!mSEHOccured)) { mDDInterface->mCursorX = test_event.motion.x; mDDInterface->mCursorY = test_event.motion.y; mWidgetManager->RemapMouse(mDDInterface->mCursorX, mDDInterface->mCursorY); mLastUserInputTick = mLastTimerTime; mWidgetManager->MouseMove(mDDInterface->mCursorX,mDDInterface->mCursorY); if (!mMouseIn) { #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_MOUSE_ENTER, 5); } #endif mMouseIn = true; EnforceCursor(); } } break; case SDL_MOUSEBUTTONUP: if (test_event.button.button == SDL_BUTTON_LEFT && test_event.button.state == SDL_RELEASED) mWidgetManager->MouseUp(test_event.button.x, test_event.button.y, 1); else if (test_event.button.button == SDL_BUTTON_RIGHT && test_event.button.state == SDL_RELEASED) mWidgetManager->MouseUp(test_event.button.x, test_event.button.y, -1); else if (test_event.button.button == SDL_BUTTON_MIDDLE && test_event.button.state == SDL_RELEASED) mWidgetManager->MouseUp(test_event.button.x, test_event.button.y, 3); break; case SDL_MOUSEBUTTONDOWN: if (test_event.button.button == SDL_BUTTON_LEFT && test_event.button.state == SDL_PRESSED) mWidgetManager->MouseDown(test_event.button.x, test_event.button.y, 1); else if (test_event.button.button == SDL_BUTTON_RIGHT && test_event.button.state == SDL_PRESSED) mWidgetManager->MouseDown(test_event.button.x, test_event.button.y, -1); else if (test_event.button.button == SDL_BUTTON_MIDDLE && test_event.button.state == SDL_PRESSED) mWidgetManager->MouseDown(test_event.button.x, test_event.button.y, 3); break; case SDL_KEYDOWN: mLastUserInputTick = mLastTimerTime; if (test_event.key.type == SDL_KEYDOWN) { SDLKey k = test_event.key.keysym.sym; mWidgetManager->KeyDown(k); if (k >= SDLK_a && k <= SDLK_z) mWidgetManager->KeyChar((SexyChar)*SDL_GetKeyName(k)); } break; case SDL_KEYUP: mLastUserInputTick = mLastTimerTime; if (test_event.key.type == SDL_KEYUP) { SDLKey k = test_event.key.keysym.sym; mWidgetManager->KeyUp(k); } break; case SDL_ACTIVEEVENT: if (test_event.active.gain == 1) { mHasFocus = true; GotFocus(); if (mMuteOnLostFocus) Unmute(true); mWidgetManager->MouseMove(mDDInterface->mCursorX, mDDInterface->mCursorY); } else { mHasFocus = false; LostFocus(); mWidgetManager->MouseExit(mDDInterface->mCursorX, mDDInterface->mCursorY); if (mMuteOnLostFocus) Mute(true); } break; case SDL_QUIT: Shutdown(); break; } if (SDL_PeepEvents(&test_event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS) == 0) mUpdateAppState = UPDATESTATE_PROCESS_1; } else mUpdateAppState = UPDATESTATE_PROCESS_1; } else { // Process changes state by itself if (mStepMode) { if (mStepMode==2) { struct timespec timeOut,remains; timeOut.tv_sec = 0; timeOut.tv_nsec = mFrameTime * 1000000; nanosleep(&timeOut, &remains); mUpdateAppState = UPDATESTATE_PROCESS_DONE; // skip actual update until next step } else { mStepMode = 2; DoUpdateFrames(); DoUpdateFramesF(1.0f); DrawDirtyStuff(); } } else { int anOldUpdateCnt = mUpdateCount; Process(); if (updated != NULL) *updated = mUpdateCount != anOldUpdateCnt; } } mUpdateAppDepth--; return true; } void SexyAppBase::DoUpdateFramesF(float theFrac) { if ((mVSyncUpdates) && (!mMinimized)) mWidgetManager->UpdateFrameF(theFrac); } bool SexyAppBase::DoUpdateFrames() { if (mLoadingThreadCompleted && !mLoaded) { mLoaded = true; mYieldMainThread = false; LoadingThreadCompleted(); } UpdateFrames(); return true; } void SexyAppBase::UpdateFrames() { mUpdateCount++; if (!mMinimized) { if (mWidgetManager->UpdateFrame()) ++mFPSDirtyCount; } mMusicInterface->Update(); CleanSharedImages(); } bool gIsFailing = false; bool SexyAppBase::DrawDirtyStuff() { MTAutoDisallowRand aDisallowRand; if (gIsFailing) // just try to reinit { Redraw(NULL); mHasPendingDraw = false; mLastDrawWasEmpty = true; return false; } if (mShowFPS) { switch(mShowFPSMode) { case FPS_ShowFPS : CalculateFPS(); break; case FPS_ShowCoords: if (mWidgetManager!=NULL) FPSDrawCoords(mWidgetManager->mLastMouseX, mWidgetManager->mLastMouseY); break; } #if 0 if (mPlayingDemoBuffer) CalculateDemoTimeLeft(); #endif } Uint32 aStartTime = SDL_GetTicks(); // Update user input and screen saver info static Uint32 aPeriodicTick = 0; if (aStartTime-aPeriodicTick > 1000) { aPeriodicTick = aStartTime; //UpdateScreenSaverInfo(aStartTime); } #if 0 if (gScreenSaverActive) { mHasPendingDraw = false; mLastDrawWasEmpty = true; return false; } #endif mIsDrawing = true; bool drewScreen = mWidgetManager->DrawScreen(); mIsDrawing = false; //custom mouse pointers need page flipping if ((drewScreen || mCustomCursorsEnabled || (aStartTime - mLastDrawTick >= 1000) || (mCustomCursorDirty)) && ((int) (aStartTime - mNextDrawTick) >= 0)) { mLastDrawWasEmpty = false; mDrawCount++; Uint32 aMidTime = SDL_GetTicks(); mFPSCount++; mFPSTime += aMidTime - aStartTime; mDrawTime += aMidTime - aStartTime; if (mShowFPS) { Graphics g(mDDInterface->GetScreenImage()); g.DrawImage(gFPSImage,mWidth-gFPSImage->GetWidth()-10,mHeight-gFPSImage->GetHeight()-10); #if 0 if (mPlayingDemoBuffer) g.DrawImage(gDemoTimeLeftImage,mWidth-gDemoTimeLeftImage->GetWidth()-10,mHeight-gFPSImage->GetHeight()-gDemoTimeLeftImage->GetHeight()-15); #endif } if (mWaitForVSync && mIsPhysWindowed && mSoftVSyncWait) { Uint32 aTick = SDL_GetTicks(); if (aTick-mLastDrawTick < mDDInterface->mMillisecondsPerFrame) { struct timespec timeOut,remains; timeOut.tv_sec = 0; timeOut.tv_nsec =(mDDInterface->mMillisecondsPerFrame - (aTick-mLastDrawTick)) * 1000000; nanosleep(&timeOut, &remains); } } Uint32 aPreScreenBltTime = SDL_GetTicks(); mLastDrawTick = aPreScreenBltTime; Redraw(NULL); // This is our one UpdateFTimeAcc if we are vsynched UpdateFTimeAcc(); Uint32 aEndTime = SDL_GetTicks(); mScreenBltTime = aEndTime - aPreScreenBltTime; if ((mLoadingThreadStarted) && (!mLoadingThreadCompleted)) { int aTotalTime = aEndTime - aStartTime; mNextDrawTick += 35 + std::max(aTotalTime, 15); if ((int) (aEndTime - mNextDrawTick) >= 0) mNextDrawTick = aEndTime; } else mNextDrawTick = aEndTime; mHasPendingDraw = false; mCustomCursorDirty = false; return true; } else { mHasPendingDraw = false; mLastDrawWasEmpty = true; return false; } return false; } void SexyAppBase::LoadingThreadCompleted() { } void SexyAppBase::UpdateFTimeAcc() { Uint32 aCurTime = SDL_GetTicks(); if (mLastTimeCheck != 0) { int aDeltaTime = aCurTime - mLastTimeCheck; mUpdateFTimeAcc = std::min(mUpdateFTimeAcc + aDeltaTime, 200.0); if (mRelaxUpdateBacklogCount > 0) mRelaxUpdateBacklogCount = std::max(mRelaxUpdateBacklogCount - aDeltaTime, 0); } mLastTimeCheck = aCurTime; } //FIXME why use doubles?? bool SexyAppBase::Process(bool allowSleep) { if (mLoadingFailed) Shutdown(); bool isVSynched = #if 0 (!mPlayingDemoBuffer) && #endif (mVSyncUpdates) && (!mLastDrawWasEmpty) && (!mVSyncBroken) && ((!mIsPhysWindowed) || (mIsPhysWindowed && mWaitForVSync && !mSoftVSyncWait)); double aFrameFTime; double anUpdatesPerUpdateF; if (mVSyncUpdates) { aFrameFTime = (1000.0 / mSyncRefreshRate) / mUpdateMultiplier; anUpdatesPerUpdateF = (float) (1000.0 / (mFrameTime * mSyncRefreshRate)); } else { aFrameFTime = mFrameTime / mUpdateMultiplier; anUpdatesPerUpdateF = 1.0; } #if 0 // Do we need to fast forward? if (mPlayingDemoBuffer) { if (mUpdateCount < mFastForwardToUpdateNum || mFastForwardToMarker) { if (!mDemoMute && !mFastForwardStep) { mDemoMute = true; Mute(true); } static Uint32 aTick = SDL_GetTicks(); while (mUpdateCount < mFastForwardToUpdateNum || mFastForwardToMarker) { ClearUpdateBacklog(); int aLastUpdateCount = mUpdateCount; // Actual updating code below ////////////////////////////////////////////////////////////////////////// bool Hadrealupdate = Doupdateframes(); If (hadRealUpdate) { mPendingUpdatesAcc += anUpdatesPerUpdateF; mPendingUpdatesAcc -= 1.0; ProcessSafeDeleteList(); // Process any extra updates while (mPendingUpdatesAcc >= 1.0) { // These should just be IDLE commands we have to clear out ProcessDemo(); bool hasRealUpdate = DoUpdateFrames(); assert(hasRealUpdate); if (!hasRealUpdate) break; ProcessSafeDeleteList(); mPendingUpdatesAcc -= 1.0; } DoUpdateFramesF((float) anUpdatesPerUpdateF); ProcessSafeDeleteList(); } ////////////////////////////////////////////////////////////////////////// // If the update count doesn't change, its because we are // playing back a demo and need to read more if (aLastUpdateCount == mUpdateCount) return true; Uint32 aNewTick = SDL_GetTicks(); if (aNewTick - aTick >= 1000 || mFastForwardStep) // let the app draw some { mFastForwardStep = false; aTick = SDL_GetTicks(); DrawDirtyStuff(); return true; } } } if (mDemoMute) { mDemoMute = false; mSoundManager->StopAllSounds(); Unmute(true); } } #endif // Make sure we're not paused if ((!mPaused) && (mUpdateMultiplier > 0)) { Uint32 aStartTime = SDL_GetTicks(); Uint32 aCurTime = aStartTime; int aCumSleepTime = 0; // When we are VSynching, only calculate this FTimeAcc right after drawing if (!isVSynched) UpdateFTimeAcc(); // mNonDrawCount is used to make sure we draw the screen at least // 10 times per second, even if it means we have to slow down // the updates to make it draw 10 times per second in "game time" bool didUpdate = false; if (mUpdateAppState == UPDATESTATE_PROCESS_1) { if ((++mNonDrawCount < (int) ceil(10*mUpdateMultiplier)) || (!mLoaded)) { bool doUpdate = false; if (isVSynched) { // Synch'ed to vertical refresh, so update as soon as possible after draw doUpdate = (!mHasPendingDraw) || (mUpdateFTimeAcc >= (int) (aFrameFTime * 0.75)); } else if (mUpdateFTimeAcc >= aFrameFTime) { doUpdate = true; } if (doUpdate) { // Do VSyncBroken test. This test fails if we're in fullscreen and // "don't vsync" has been forced in Advanced settings up Display Properties if ( #if 0 (!mPlayingDemoBuffer) && #endif (mUpdateMultiplier == 1.0)) { mVSyncBrokenTestUpdates++; if (mVSyncBrokenTestUpdates >= (Uint32) ((1000+mFrameTime-1)/mFrameTime)) { // It has to be running 33% fast to be "broken" (25% = 1/0.800) if (aStartTime - mVSyncBrokenTestStartTick <= 800) { // The test has to fail 3 times in a row before we decide that // vsync is broken overall mVSyncBrokenCount++; if (mVSyncBrokenCount >= 3) mVSyncBroken = true; } else mVSyncBrokenCount = 0; mVSyncBrokenTestStartTick = aStartTime; mVSyncBrokenTestUpdates = 0; } } bool hadRealUpdate = DoUpdateFrames(); if (hadRealUpdate) mUpdateAppState = UPDATESTATE_PROCESS_2; mHasPendingDraw = true; didUpdate = true; } } } else if (mUpdateAppState == UPDATESTATE_PROCESS_2) { mUpdateAppState = UPDATESTATE_PROCESS_DONE; mPendingUpdatesAcc += anUpdatesPerUpdateF; mPendingUpdatesAcc -= 1.0; ProcessSafeDeleteList(); // Process any extra updates while (mPendingUpdatesAcc >= 1.0) { // These should just be IDLE commands we have to clear out #if 0 ProcessDemo(); #endif ++mNonDrawCount; bool hasRealUpdate = DoUpdateFrames(); assert(hasRealUpdate); if (!hasRealUpdate) break; ProcessSafeDeleteList(); mPendingUpdatesAcc -= 1.0; } //aNumCalls++; DoUpdateFramesF((float) anUpdatesPerUpdateF); ProcessSafeDeleteList(); // Don't let mUpdateFTimeAcc dip below 0 // Subtract an extra 0.2ms, because sometimes refresh rates have some // fractional component that gets truncated, and it's better to take off // too much to keep our timing tending toward occuring right after // redraws if (isVSynched) mUpdateFTimeAcc = std::max(mUpdateFTimeAcc - aFrameFTime - 0.2f, 0.0); else mUpdateFTimeAcc -= aFrameFTime; if (mRelaxUpdateBacklogCount > 0) mUpdateFTimeAcc = 0; didUpdate = true; } if (!didUpdate) { mUpdateAppState = UPDATESTATE_PROCESS_DONE; mNonDrawCount = 0; if (mHasPendingDraw) { DrawDirtyStuff(); } else { // Let us take into account the time it took to draw dirty stuff int aTimeToNextFrame = (int) (aFrameFTime - mUpdateFTimeAcc); if (aTimeToNextFrame > 0) { if (!allowSleep) return false; // Wait till next processing cycle ++mSleepCount; struct timespec timeOut,remains; timeOut.tv_sec = 0; timeOut.tv_nsec = aTimeToNextFrame * 1000000; nanosleep(&timeOut, &remains); aCumSleepTime += aTimeToNextFrame; } } } if (mYieldMainThread) { // This is to make sure that the title screen doesn't take up any more than // 1/3 of the processor time #if 0 Uint32 anEndTime = SDL_GetTicks(); int anElapsedTime = anEndTime - aStartTime - aCumSleepTime; int aLoadingYieldSleepTime = std::min(250, anElapsedTime * 2 - aCumSleepTime); if (aLoadingYieldSleepTime >= 0) { if (!allowSleep) return false; SDL_Delay(aLoadingYieldSleepTime); } #endif } } ProcessSafeDeleteList(); return true; } void SexyAppBase::ClearUpdateBacklog(bool relaxForASecond) { mLastTimeCheck = SDL_GetTicks(); mUpdateFTimeAcc = 0.0; if (relaxForASecond) mRelaxUpdateBacklogCount = 1000; } void SexyAppBase::ProcessSafeDeleteList() { MTAutoDisallowRand aDisallowRand; WidgetSafeDeleteList::iterator anItr = mSafeDeleteList.begin(); while (anItr != mSafeDeleteList.end()) { WidgetSafeDeleteInfo* aWidgetSafeDeleteInfo = &(*anItr); if (mUpdateAppDepth <= aWidgetSafeDeleteInfo->mUpdateAppDepth) { delete aWidgetSafeDeleteInfo->mWidget; anItr = mSafeDeleteList.erase(anItr); } else ++anItr; } } void SexyAppBase::Redraw(Rect* theClipRect) { #if 0 SEXY_AUTO_PERF("SexyAppBase::Redraw"); #endif // Do mIsDrawing check because we could enter here at a bad time if any windows messages // are processed during WidgetManager->Draw if ((mIsDrawing) || (mShutdown)) return; if (gScreenSaverActive) return; static Uint32 aRetryTick = 0; if (!mDDInterface->Redraw(theClipRect)) { #if 0 extern bool gD3DInterfacePreDrawError; gD3DInterfacePreDrawError = false; // this predraw error happens naturally when ddraw is failing if (!gIsFailing) { //gDebugStream << GetTickCount() << " Redraw failed!" << std::endl; gIsFailing = true; } WINDOWPLACEMENT aWindowPlacement; ZeroMemory(&aWindowPlacement, sizeof(aWindowPlacement)); aWindowPlacement.length = sizeof(aWindowPlacement); ::GetWindowPlacement(mHWnd, &aWindowPlacement); DWORD aTick = GetTickCount(); if ((mActive || (aTick-aRetryTick>1000 && mIsPhysWindowed)) && (aWindowPlacement.showCmd != SW_SHOWMINIMIZED) && (!mMinimized)) { aRetryTick = aTick; mWidgetManager->mImage = NULL; // Re-check resolution at this point, because we hit here when you change your resolution. if (((mWidth >= GetSystemMetrics(SM_CXFULLSCREEN)) || (mHeight >= GetSystemMetrics(SM_CYFULLSCREEN))) && (mIsWindowed)) { if (mForceWindowed) { Popup(GetString("PLEASE_SET_COLOR_DEPTH", _S("Please set your desktop color depth to 16 bit."))); Shutdown(); return; } mForceFullscreen = true; SwitchScreenMode(false); return; } int aResult = InitDDInterface(); //gDebugStream << GetTickCount() << " ReInit..." << std::endl; if ((mIsWindowed) && (aResult == DDInterface::RESULT_INVALID_COLORDEPTH)) { //gDebugStream << GetTickCount() << "ReInit Invalid Colordepth" << std::endl; if (!mActive) // don't switch to full screen if not active app return; SwitchScreenMode(false); mForceFullscreen = true; return; } else if (aResult == DDInterface::RESULT_3D_FAIL) { Set3DAcclerated(false); return; } else if (aResult != DDInterface::RESULT_OK) { return; } ReInitImages(); mWidgetManager->mImage = mDDInterface->GetScreenImage(); mWidgetManager->MarkAllDirty(); mLastTime = timeGetTime(); } #endif } else { if (gIsFailing) { gIsFailing = false; aRetryTick = 0; } } mFPSFlipCount++; } void SexyAppBase::ShutdownHook() { } void SexyAppBase::SetCursor(int theCursorNum) { mCursorNum = theCursorNum; EnforceCursor(); } void SexyAppBase::SafeDeleteWidget(Widget* theWidget) { WidgetSafeDeleteInfo aWidgetSafeDeleteInfo; aWidgetSafeDeleteInfo.mUpdateAppDepth = mUpdateAppDepth; aWidgetSafeDeleteInfo.mWidget = theWidget; mSafeDeleteList.push_back(aWidgetSafeDeleteInfo); } void SexyAppBase::AddMemoryImage(MemoryImage* theMemoryImage) { #if 0 AutoCrit anAutoCrit(mDDInterface->mCritSect); #endif mMemoryImageSet.insert(theMemoryImage); } void SexyAppBase::RemoveMemoryImage(MemoryImage* theMemoryImage) { #if 0 AutoCrit anAutoCrit(mDDInterface->mCritSect); #endif MemoryImageSet::iterator anItr = mMemoryImageSet.find(theMemoryImage); if (anItr != mMemoryImageSet.end()) mMemoryImageSet.erase(anItr); Remove3DData(theMemoryImage); } void SexyAppBase::WaitForLoadingThread() { while ((mLoadingThreadStarted) && (!mLoadingThreadCompleted)) { SDL_Delay(20); } } SharedImageRef SexyAppBase::GetSharedImage(const std::string& theFileName, const std::string& theVariant, bool* isNew) { std::string anUpperFileName = StringToUpper(theFileName); std::string anUpperVariant = StringToUpper(theVariant); std::pair aResultPair; SharedImageRef aSharedImageRef; { #if 0 AutoCrit anAutoCrit(mDDInterface->mCritSect); #endif aResultPair = mSharedImageMap.insert(SharedImageMap::value_type(SharedImageMap::key_type(anUpperFileName, anUpperVariant), SharedImage())); aSharedImageRef = &aResultPair.first->second; } if (isNew != NULL) *isNew = aResultPair.second; if (aResultPair.second) { // Pass in a '!' as the first char of the file name to create a new image if ((theFileName.length() > 0) && (theFileName[0] == '!')) aSharedImageRef.mSharedImage->mImage = new DDImage(mDDInterface); else aSharedImageRef.mSharedImage->mImage = GetImage(theFileName,false); } return aSharedImageRef; } double SexyAppBase::GetLoadingThreadProgress() { if (mLoaded) return 1.0; if (!mLoadingThreadStarted) return 0.0; if (mNumLoadingThreadTasks == 0) return 0.0; return std::min(mCompletedLoadingThreadTasks / (double) mNumLoadingThreadTasks, 1.0); } void SexyAppBase::LoadingThreadProc() { } int SexyAppBase::LoadingThreadProcStub(void *theArg) { SexyAppBase* aSexyApp = (SexyAppBase*) theArg; aSexyApp->LoadingThreadProc(); #if 0 char aStr[256]; sprintf(aStr, "Resource Loading Time: %d\r\n", (SDL_GetTicks() - aSexyApp->mTimeLoaded)); OutputDebugStringA(aStr); #endif aSexyApp->mLoadingThreadCompleted = true; return 0; } void SexyAppBase::StartLoadingThread() { if (!mLoadingThreadStarted) { mYieldMainThread = true; mLoadingThreadStarted = true; SDL_CreateThread(&LoadingThreadProcStub, this); } } void SexyAppBase::PlaySample(int theSoundNum) { if (!mSoundManager) return; SoundInstance* aSoundInstance = mSoundManager->GetSoundInstance(theSoundNum); if (aSoundInstance != NULL) { aSoundInstance->Play(false, true); } } void SexyAppBase::PlaySample(int theSoundNum, int thePan) { if (!mSoundManager) return; SoundInstance* aSoundInstance = mSoundManager->GetSoundInstance(theSoundNum); if (aSoundInstance != NULL) { aSoundInstance->SetPan(thePan); aSoundInstance->Play(false, true); } } bool SexyAppBase::IsMuted() { return mMuteCount > 0; } void SexyAppBase::Mute(bool autoMute) { mMuteCount++; if (autoMute) mAutoMuteCount++; SetMusicVolume(mMusicVolume); SetSfxVolume(mSfxVolume); } void SexyAppBase::Unmute(bool autoMute) { if (mMuteCount > 0) { mMuteCount--; if (autoMute) mAutoMuteCount--; } SetMusicVolume(mMusicVolume); SetSfxVolume(mSfxVolume); } double SexyAppBase::GetMusicVolume() { return mMusicVolume; } void SexyAppBase::SetMusicVolume(double theVolume) { mMusicVolume = theVolume; if (mMusicInterface != NULL) mMusicInterface->SetVolume((mMuteCount > 0) ? 0.0 : mMusicVolume); } double SexyAppBase::GetSfxVolume() { return mSfxVolume; } void SexyAppBase::SetSfxVolume(double theVolume) { mSfxVolume = theVolume; if (mSoundManager != NULL) mSoundManager->SetVolume((mMuteCount > 0) ? 0.0 : mSfxVolume); } double SexyAppBase::GetMasterVolume() { return mSoundManager->GetMasterVolume(); } void SexyAppBase::SetMasterVolume(double theMasterVolume) { mSfxVolume = theMasterVolume; mSoundManager->SetMasterVolume(mSfxVolume); } MusicInterface* SexyAppBase::CreateMusicInterface() { if (mNoSoundNeeded) return new MusicInterface; #ifdef USE_AUDIERE return new AudiereMusicInterface(mInvisHWnd); #else return new SDLMixerMusicInterface(mInvisHWnd); #endif } DDImage* SexyAppBase::CopyImage(Image* theImage, const Rect& theRect) { DDImage* anImage = new DDImage(mDDInterface); anImage->Create(theRect.mWidth, theRect.mHeight); Graphics g(anImage); g.DrawImage(theImage, -theRect.mX, -theRect.mY); anImage->CopyAttributes(theImage); return anImage; } DDImage* SexyAppBase::CopyImage(Image* theImage) { return CopyImage(theImage, Rect(0, 0, theImage->GetWidth(), theImage->GetHeight())); } Sexy::DDImage* SexyAppBase::GetImage(const std::string& theFileName, bool commitBits) { ImageLib::Image* aLoadedImage; std::string resourcepath = GetAppResourceFolder(); if (!resourcepath.empty()) { if (theFileName.substr(0, resourcepath.size()) == resourcepath) aLoadedImage = ImageLib::GetImage(theFileName, true); else aLoadedImage = ImageLib::GetImage(resourcepath + theFileName, true); } else aLoadedImage = ImageLib::GetImage(theFileName, true); if (aLoadedImage == NULL) return NULL; DDImage* anImage = new DDImage(mDDInterface); anImage->SetBits(aLoadedImage->GetBits(), aLoadedImage->GetWidth(), aLoadedImage->GetHeight(), commitBits); anImage->mFilePath = theFileName; delete aLoadedImage; return anImage; } Sexy::DDImage* SexyAppBase::CreateCrossfadeImage(Sexy::Image* theImage1, const Rect& theRect1, Sexy::Image* theImage2, const Rect& theRect2, double theFadeFactor) { MemoryImage* aMemoryImage1 = dynamic_cast(theImage1); MemoryImage* aMemoryImage2 = dynamic_cast(theImage2); if ((aMemoryImage1 == NULL) || (aMemoryImage2 == NULL)) return NULL; if ((theRect1.mX < 0) || (theRect1.mY < 0) || (theRect1.mX + theRect1.mWidth > theImage1->GetWidth()) || (theRect1.mY + theRect1.mHeight > theImage1->GetHeight())) { assert("Crossfade Rect1 out of bounds"); return NULL; } if ((theRect2.mX < 0) || (theRect2.mY < 0) || (theRect2.mX + theRect2.mWidth > theImage2->GetWidth()) || (theRect2.mY + theRect2.mHeight > theImage2->GetHeight())) { assert("Crossfade Rect2 out of bounds"); return NULL; } int aWidth = theRect1.mWidth; int aHeight = theRect1.mHeight; DDImage* anImage = new DDImage(mDDInterface); anImage->Create(aWidth, aHeight); uint32_t* aDestBits = anImage->GetBits(); uint32_t* aSrcBits1 = aMemoryImage1->GetBits(); uint32_t* aSrcBits2 = aMemoryImage2->GetBits(); int aSrc1Width = aMemoryImage1->GetWidth(); int aSrc2Width = aMemoryImage2->GetWidth(); uint32_t aMult = (int) (theFadeFactor*256); uint32_t aOMM = (256 - aMult); for (int y = 0; y < aHeight; y++) { uint32_t* s1 = &aSrcBits1[(y+theRect1.mY)*aSrc1Width+theRect1.mX]; uint32_t* s2 = &aSrcBits2[(y+theRect2.mY)*aSrc2Width+theRect2.mX]; uint32_t* d = &aDestBits[y*aWidth]; for (int x = 0; x < aWidth; x++) { uint32_t p1 = *s1++; uint32_t p2 = *s2++; //p1 = 0; //p2 = 0xFFFFFFFF; *d++ = ((((p1 & 0x000000FF)*aOMM + (p2 & 0x000000FF)*aMult)>>8) & 0x000000FF) | ((((p1 & 0x0000FF00)*aOMM + (p2 & 0x0000FF00)*aMult)>>8) & 0x0000FF00) | ((((p1 & 0x00FF0000)*aOMM + (p2 & 0x00FF0000)*aMult)>>8) & 0x00FF0000) | ((((p1 >> 24)*aOMM + (p2 >> 24)*aMult)<<16) & 0xFF000000); } } anImage->BitsChanged(); return anImage; } void SexyAppBase::ColorizeImage(Image* theImage, const Color& theColor) { MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); if (aSrcMemoryImage == NULL) return; uint32_t* aBits; int aNumColors; if (aSrcMemoryImage->mColorTable == NULL) { aBits = aSrcMemoryImage->GetBits(); aNumColors = theImage->GetWidth()*theImage->GetHeight(); } else { aBits = aSrcMemoryImage->mColorTable; aNumColors = 256; } if ((theColor.mAlpha <= 255) && (theColor.mRed <= 255) && (theColor.mGreen <= 255) && (theColor.mBlue <= 255)) { for (int i = 0; i < aNumColors; i++) { uint32_t aColor = aBits[i]; aBits[i] = ((((aColor & 0xFF000000) >> 8) * theColor.mAlpha) & 0xFF000000) | ((((aColor & 0x00FF0000) * theColor.mRed) >> 8) & 0x00FF0000) | ((((aColor & 0x0000FF00) * theColor.mGreen) >> 8) & 0x0000FF00)| ((((aColor & 0x000000FF) * theColor.mBlue) >> 8) & 0x000000FF); } } else { for (int i = 0; i < aNumColors; i++) { uint32_t aColor = aBits[i]; int aAlpha = ((aColor >> 24) * theColor.mAlpha) / 255; int aRed = (((aColor >> 16) & 0xFF) * theColor.mRed) / 255; int aGreen = (((aColor >> 8) & 0xFF) * theColor.mGreen) / 255; int aBlue = ((aColor & 0xFF) * theColor.mBlue) / 255; if (aAlpha > 255) aAlpha = 255; if (aRed > 255) aRed = 255; if (aGreen > 255) aGreen = 255; if (aBlue > 255) aBlue = 255; aBits[i] = (aAlpha << 24) | (aRed << 16) | (aGreen << 8) | (aBlue); } } aSrcMemoryImage->BitsChanged(); } DDImage* SexyAppBase::CreateColorizedImage(Image* theImage, const Color& theColor) { MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); if (aSrcMemoryImage == NULL) return NULL; DDImage* anImage = new DDImage(mDDInterface); anImage->Create(theImage->GetWidth(), theImage->GetHeight()); uint32_t* aSrcBits; uint32_t* aDestBits; int aNumColors; if (aSrcMemoryImage->mColorTable == NULL) { aSrcBits = aSrcMemoryImage->GetBits(); aDestBits = anImage->GetBits(); aNumColors = theImage->GetWidth()*theImage->GetHeight(); } else { aSrcBits = aSrcMemoryImage->mColorTable; aDestBits = anImage->mColorTable = new uint32_t[256]; aNumColors = 256; anImage->mColorIndices = new uchar[anImage->mWidth*theImage->mHeight]; memcpy(anImage->mColorIndices, aSrcMemoryImage->mColorIndices, anImage->mWidth*theImage->mHeight); } if ((theColor.mAlpha <= 255) && (theColor.mRed <= 255) && (theColor.mGreen <= 255) && (theColor.mBlue <= 255)) { for (int i = 0; i < aNumColors; i++) { uint32_t aColor = aSrcBits[i]; aDestBits[i] = ((((aColor & 0xFF000000) >> 8) * theColor.mAlpha) & 0xFF000000) | ((((aColor & 0x00FF0000) * theColor.mRed) >> 8) & 0x00FF0000) | ((((aColor & 0x0000FF00) * theColor.mGreen) >> 8) & 0x0000FF00)| ((((aColor & 0x000000FF) * theColor.mBlue) >> 8) & 0x000000FF); } } else { for (int i = 0; i < aNumColors; i++) { uint32_t aColor = aSrcBits[i]; int aAlpha = ((aColor >> 24) * theColor.mAlpha) / 255; int aRed = (((aColor >> 16) & 0xFF) * theColor.mRed) / 255; int aGreen = (((aColor >> 8) & 0xFF) * theColor.mGreen) / 255; int aBlue = ((aColor & 0xFF) * theColor.mBlue) / 255; if (aAlpha > 255) aAlpha = 255; if (aRed > 255) aRed = 255; if (aGreen > 255) aGreen = 255; if (aBlue > 255) aBlue = 255; aDestBits[i] = (aAlpha << 24) | (aRed << 16) | (aGreen << 8) | (aBlue); } } anImage->BitsChanged(); return anImage; } void SexyAppBase::MirrorImage(Image* theImage) { MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); uint32_t* aSrcBits = aSrcMemoryImage->GetBits(); int aPhysSrcWidth = aSrcMemoryImage->mWidth; for (int y = 0; y < aSrcMemoryImage->mHeight; y++) { uint32_t* aLeftBits = aSrcBits + (y * aPhysSrcWidth); uint32_t* aRightBits = aLeftBits + (aPhysSrcWidth - 1); for (int x = 0; x < (aPhysSrcWidth >> 1); x++) { uint32_t aSwap = *aLeftBits; *(aLeftBits++) = *aRightBits; *(aRightBits--) = aSwap; } } aSrcMemoryImage->BitsChanged(); } void SexyAppBase::FlipImage(Image* theImage) { MemoryImage* aSrcMemoryImage = dynamic_cast(theImage); uint32_t* aSrcBits = aSrcMemoryImage->GetBits(); int aPhysSrcHeight = aSrcMemoryImage->mHeight; int aPhysSrcWidth = aSrcMemoryImage->mWidth; for (int x = 0; x < aPhysSrcWidth; x++) { uint32_t* aTopBits = aSrcBits + x; uint32_t* aBottomBits = aTopBits + (aPhysSrcWidth * (aPhysSrcHeight - 1)); for (int y = 0; y < (aPhysSrcHeight >> 1); y++) { uint32_t aSwap = *aTopBits; *aTopBits = *aBottomBits; aTopBits += aPhysSrcWidth; *aBottomBits = aSwap; aBottomBits -= aPhysSrcWidth; } } aSrcMemoryImage->BitsChanged(); } void SexyAppBase::RotateImageHue(Sexy::MemoryImage *theImage, int theDelta) { while (theDelta < 0) theDelta += 256; int aSize = theImage->mWidth * theImage->mHeight; uint32_t *aPtr = theImage->GetBits(); for (int i=0; i>16)&0xff; int g = (aPixel>>8) &0xff; int b = aPixel&0xff; int maxval = std::max(r, std::max(g, b)); int minval = std::min(r, std::min(g, b)); int h = 0; int s = 0; int l = (minval+maxval)/2; int delta = maxval - minval; if (delta != 0) { s = (delta * 256) / ((l <= 128) ? (minval + maxval) : (512 - maxval - minval)); if (r == maxval) h = (g == minval ? 1280 + (((maxval-b) * 256) / delta) : 256 - (((maxval - g) * 256) / delta)); else if (g == maxval) h = (b == minval ? 256 + (((maxval-r) * 256) / delta) : 768 - (((maxval - b) * 256) / delta)); else h = (r == minval ? 768 + (((maxval-g) * 256) / delta) : 1280 - (((maxval - r) * 256) / delta)); h /= 6; } h += theDelta; if (h >= 256) h -= 256; double v= (l < 128) ? (l * (255+s))/255 : (l+s-l*s/255); int y = (int) (2*l-v); int aColorDiv = (6 * h) / 256; int x = (int)(y+(v-y)*((h - (aColorDiv * 256 / 6)) * 6)/255); if (x > 255) x = 255; int z = (int) (v-(v-y)*((h - (aColorDiv * 256 / 6)) * 6)/255); if (z < 0) z = 0; switch (aColorDiv) { case 0: r = (int) v; g = x; b = y; break; case 1: r = z; g= (int) v; b = y; break; case 2: r = y; g= (int) v; b = x; break; case 3: r = y; g = z; b = (int) v; break; case 4: r = x; g = y; b = (int) v; break; case 5: r = (int) v; g = y; b = z; break; default: r = (int) v; g = x; b = y; break; } *aPtr++ = alpha | (r<<16) | (g << 8) | (b); } theImage->BitsChanged(); } uint32_t SexyAppBase::HSLToRGB(int h, int s, int l) { int r; int g; int b; double v= (l < 128) ? (l * (255+s))/255 : (l+s-l*s/255); int y = (int) (2*l-v); int aColorDiv = (6 * h) / 256; int x = (int)(y+(v-y)*((h - (aColorDiv * 256 / 6)) * 6)/255); if (x > 255) x = 255; int z = (int) (v-(v-y)*((h - (aColorDiv * 256 / 6)) * 6)/255); if (z < 0) z = 0; switch (aColorDiv) { case 0: r = (int) v; g = x; b = y; break; case 1: r = z; g= (int) v; b = y; break; case 2: r = y; g= (int) v; b = x; break; case 3: r = y; g = z; b = (int) v; break; case 4: r = x; g = y; b = (int) v; break; case 5: r = (int) v; g = y; b = z; break; default: r = (int) v; g = x; b = y; break; } return 0xFF000000 | (r << 16) | (g << 8) | (b); } uint32_t SexyAppBase::RGBToHSL(int r, int g, int b) { int maxval = std::max(r, std::max(g, b)); int minval = std::min(r, std::min(g, b)); int hue = 0; int saturation = 0; int luminosity = (minval+maxval)/2; int delta = maxval - minval; if (delta != 0) { saturation = (delta * 256) / ((luminosity <= 128) ? (minval + maxval) : (512 - maxval - minval)); if (r == maxval) hue = (g == minval ? 1280 + (((maxval-b) * 256) / delta) : 256 - (((maxval - g) * 256) / delta)); else if (g == maxval) hue = (b == minval ? 256 + (((maxval-r) * 256) / delta) : 768 - (((maxval - b) * 256) / delta)); else hue = (r == minval ? 768 + (((maxval-g) * 256) / delta) : 1280 - (((maxval - r) * 256) / delta)); hue /= 6; } return 0xFF000000 | (hue) | (saturation << 8) | (luminosity << 16); } void SexyAppBase::HSLToRGB(const uint32_t* theSource, uint32_t* theDest, int theSize) { for (int i = 0; i < theSize; i++) { uint32_t src = theSource[i]; theDest[i] = (src & 0xFF000000) | (HSLToRGB((src & 0xFF), (src >> 8) & 0xFF, (src >> 16) & 0xFF) & 0x00FFFFFF); } } void SexyAppBase::RGBToHSL(const uint32_t* theSource, uint32_t* theDest, int theSize) { for (int i = 0; i < theSize; i++) { uint32_t src = theSource[i]; theDest[i] = (src & 0xFF000000) | (RGBToHSL(((src >> 16) & 0xFF), (src >> 8) & 0xFF, (src & 0xFF)) & 0x00FFFFFF); } } void SexyAppBase::PrecacheAdditive(MemoryImage* theImage) { theImage->GetRLAdditiveData(mDDInterface); } void SexyAppBase::PrecacheAlpha(MemoryImage* theImage) { theImage->GetRLAlphaData(); } void SexyAppBase::PrecacheNative(MemoryImage* theImage) { theImage->GetNativeAlphaData(mDDInterface); } void SexyAppBase::MakeWindow() { if (mDDInterface == NULL) { mDDInterface = new DDInterface(this); // Enable 3d setting bool is3D = mAutoEnable3D; bool tested3D = false; if (mAutoEnable3D) { tested3D = true; } else { RegistryReadBoolean("Is3D", &is3D); RegistryReadBoolean("Tested3D", &tested3D); } #ifndef APPLE if (mTest3D && !tested3D) { //run glxinfo to get direct rendering info from driver FILE* info = popen("glxinfo | grep rendering", "r"); std::string s; if (info != NULL) { int c; while ((c = fgetc(info)) != EOF) s += (unsigned char)c; } pclose(info); if (s.find("Yes", 0) != std::string::npos) { is3D = true; } else { is3D = false; } RegistryWriteBoolean("Tested3D", true); } #else is3D = true; #endif mDDInterface->mIs3D = is3D; } if (!mWindowIconBMP.empty()) { SDL_WM_SetIcon(SDL_LoadBMP((GetAppResourceFolder() + mWindowIconBMP).c_str()), NULL); } if (mDDInterface->mIs3D) { //FIXME hardcoded values SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 8 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); if (surface != NULL) { SDL_FreeSurface(surface); } surface = SDL_SetVideoMode(mWidth,mHeight,32, SDL_OPENGL); } else { if (surface != NULL) { SDL_FreeSurface(surface); } surface = SDL_SetVideoMode(mWidth,mHeight,32, SDL_DOUBLEBUF | SDL_HWSURFACE); } if (surface == NULL) exit(1); if (!mIsWindowed) { if ((surface->flags & SDL_FULLSCREEN) != SDL_FULLSCREEN) { if (SDL_WM_ToggleFullScreen(surface) == -1) { mShutdown = true; } } } else { if ((surface->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) { if (SDL_WM_ToggleFullScreen(surface) == -1) { mShutdown = true; } } } SDL_WM_SetCaption(mTitle.c_str(), NULL); int aResult = InitDDInterface(); #if 0 if (mDDInterface->mD3DTester!=NULL && mDDInterface->mD3DTester->ResultsChanged()) RegistryEraseValue(_S("Is3D")); if ((mIsWindowed) && (aResult == DDInterface::RESULT_INVALID_COLORDEPTH)) { if (mForceWindowed) { Popup(GetString("PLEASE_SET_COLOR_DEPTH", _S("Please set your desktop color depth to 16 bit."))); DoExit(1); } else { mForceFullscreen = true; SwitchScreenMode(false); } return; } else if ((!mIsWindowed) && ((aResult == DDInterface::RESULT_EXCLUSIVE_FAIL) || (aResult == DDInterface::RESULT_DISPCHANGE_FAIL))) { mForceWindowed = true; SwitchScreenMode(true); } else if (aResult == DDInterface::RESULT_3D_FAIL) { Set3DAcclerated(false); return; } else if (aResult != DDInterface::RESULT_OK) { if (Is3DAccelerated()) { Set3DAcclerated(false); return; } else { Popup(GetString("FAILED_INIT_DIRECTDRAW", _S("Failed to initialize DirectDraw: ")) + StringToSexyString(DDInterface::ResultToString(aResult) + " " + mDDInterface->mErrorString)); DoExit(1); } } bool isActive = mActive; mActive = GetActiveWindow() == mHWnd; mPhysMinimized = false; if (mMinimized) { if (mMuteOnLostFocus) Unmute(true); mMinimized = false; isActive = mActive; // set this here so we don't call RehupFocus again. RehupFocus(); } if (isActive != mActive) RehupFocus(); #endif ReInitImages(); mWidgetManager->mImage = mDDInterface->GetScreenImage(); mWidgetManager->MarkAllDirty(); #if 0 SetTimer(mHWnd, 100, mFrameTime, NULL); #endif } int SexyAppBase::InitDDInterface() { PreDDInterfaceInitHook(); DeleteNativeImageData(); int aResult = mDDInterface->Init(NULL, mIsPhysWindowed); #if 0 DemoSyncRefreshRate(); #endif if ( DDInterface::RESULT_OK == aResult ) { mScreenBounds.mX = ( mWidth - mDDInterface->mWidth ) / 2; mScreenBounds.mY = ( mHeight - mDDInterface->mHeight ) / 2; mScreenBounds.mWidth = mDDInterface->mWidth; mScreenBounds.mHeight = mDDInterface->mHeight; mWidgetManager->Resize(mScreenBounds, mDDInterface->mPresentationRect); PostDDInterfaceInitHook(); } return aResult; } void SexyAppBase::PreDisplayHook() { } void SexyAppBase::DeleteNativeImageData() { MemoryImageSet::iterator anItr = mMemoryImageSet.begin(); while (anItr != mMemoryImageSet.end()) { MemoryImage* aMemoryImage = *anItr; aMemoryImage->DeleteNativeData(); ++anItr; } } void SexyAppBase::PostDDInterfaceInitHook() { } void SexyAppBase::PreDDInterfaceInitHook() { } bool SexyAppBase::Is3DAccelerated() { return mDDInterface->mIs3D; } bool SexyAppBase::FileExists(const std::string& theFileName) { #if 0 if (mPlayingDemoBuffer) { if (mManualShutdown) return true; PrepareDemoCommand(true); mDemoNeedsCommand = true; assert(!mDemoIsShortCmd); assert(mDemoCmdNum == DEMO_FILE_EXISTS); bool success = mDemoBuffer.ReadNumBits(1, false) != 0; return success; } else #endif { FILE* aFP = fopen(theFileName.c_str(), "rb"); #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_FILE_EXISTS, 5); mDemoBuffer.WriteNumBits((aFP != NULL) ? 1 : 0, 1); } #endif if (aFP == NULL) return false; fclose(aFP); return true; } } bool SexyAppBase::ReadBufferFromFile(const std::string& theFileName, Buffer* theBuffer, bool dontWriteToDemo) { #if 0 if ((mPlayingDemoBuffer) && (!dontWriteToDemo)) { if (mManualShutdown) return false; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_FILE_READ); bool success = mDemoBuffer.ReadNumBits(1, false) != 0; if (!success) return false; uint32_t aLen = mDemoBuffer.ReadLong(); theBuffer->Clear(); for (int i = 0; i < (int) aLen; i++) theBuffer->WriteByte(mDemoBuffer.ReadByte()); return true; } else #endif { FILE* aFP = fopen(theFileName.c_str(), "rb"); if (aFP == NULL) { #if 0 if ((mRecordingDemoBuffer) && (!dontWriteToDemo)) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_FILE_READ, 5); mDemoBuffer.WriteNumBits(0, 1); // failure } #endif return false; } fseek(aFP, 0, SEEK_END); int aFileSize = ftell(aFP); fseek(aFP, 0, SEEK_SET); uchar* aData = new uchar[aFileSize]; size_t read_bytes = fread(aData, sizeof(unsigned char), aFileSize, aFP); fclose(aFP); if (read_bytes != aFileSize * sizeof(unsigned char)) { delete[] aData; return false; } theBuffer->Clear(); theBuffer->SetData(aData, aFileSize); #if 0 if ((mRecordingDemoBuffer) && (!dontWriteToDemo)) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_FILE_READ, 5); mDemoBuffer.WriteNumBits(1, 1); // success mDemoBuffer.WriteLong(aFileSize); mDemoBuffer.WriteBytes(aData, aFileSize); } #endif delete[] aData; return true; } } bool SexyAppBase::WriteBufferToFile(const std::string& theFileName, const Buffer* theBuffer) { return WriteBytesToFile(theFileName,theBuffer->GetDataPtr(),theBuffer->GetDataLen()); } bool SexyAppBase::WriteBytesToFile(const std::string& theFileName, const void *theData, uint32_t theDataLen) { #if 0 if (mPlayingDemoBuffer) { if (mManualShutdown) return true; PrepareDemoCommand(true); mDemoNeedsCommand = true; DBG_ASSERTE(!mDemoIsShortCmd); DBG_ASSERTE(mDemoCmdNum == DEMO_FILE_WRITE); bool success = mDemoBuffer.ReadNumBits(1, false) != 0; if (!success) return false; return true; } #endif MkDir(GetFileDir(theFileName)); FILE* aFP = fopen(theFileName.c_str(), "w+b"); if (aFP == NULL) { #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_FILE_WRITE, 5); mDemoBuffer.WriteNumBits(0, 1); // failure } #endif return false; } size_t written_bytes = fwrite(theData, sizeof(unsigned char), theDataLen, aFP); fclose(aFP); if (written_bytes != theDataLen * sizeof(unsigned char)) return false; #if 0 if (mRecordingDemoBuffer) { WriteDemoTimingBlock(); mDemoBuffer.WriteNumBits(0, 1); mDemoBuffer.WriteNumBits(DEMO_FILE_WRITE, 5); mDemoBuffer.WriteNumBits(1, 1); // success } #endif return true; } void SexyAppBase::LoadResourceManifest() { if (!mResourceManager->ParseResourcesFile("properties//resources.xml")) ShowResourceError(true); } void SexyAppBase::ShowResourceError(bool doExit) { #if 0 Popup(mResourceManager->GetErrorText()); #endif if (doExit) DoExit(0); } void SexyAppBase::RestoreScreenResolution() { if (mFullScreenWindow) { #if 0 EnumWindows(ChangeDisplayWindowEnumProc,0); // get any windows that appeared while we were running ChangeDisplaySettings(NULL,0); EnumWindows(ChangeDisplayWindowEnumProc,1); // restore window pos #endif mFullScreenWindow = false; } } void SexyAppBase::DoExit(int theCode) { RestoreScreenResolution(); exit(theCode); } Dialog* SexyAppBase::NewDialog(int theDialogId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode) { Dialog* aDialog = new Dialog(NULL, NULL, theDialogId, isModal, theDialogHeader, theDialogLines, theDialogFooter, theButtonMode); return aDialog; } Dialog* SexyAppBase::DoDialog(int theDialogId, bool isModal, const SexyString& theDialogHeader, const SexyString& theDialogLines, const SexyString& theDialogFooter, int theButtonMode) { KillDialog(theDialogId); Dialog* aDialog = NewDialog(theDialogId, isModal, theDialogHeader, theDialogLines, theDialogFooter, theButtonMode); AddDialog(theDialogId, aDialog); return aDialog; } Dialog* SexyAppBase::GetDialog(int theDialogId) { DialogMap::iterator anItr = mDialogMap.find(theDialogId); if (anItr != mDialogMap.end()) return anItr->second; return NULL; } bool SexyAppBase::KillDialog(int theDialogId, bool removeWidget, bool deleteWidget) { DialogMap::iterator anItr = mDialogMap.find(theDialogId); if (anItr != mDialogMap.end()) { Dialog* aDialog = anItr->second; // set the result to something else so DoMainLoop knows that the dialog is gone // in case nobody else sets mResult if (aDialog->mResult == -1) aDialog->mResult = 0; DialogList::iterator aListItr = std::find(mDialogList.begin(),mDialogList.end(),aDialog); if (aListItr != mDialogList.end()) mDialogList.erase(aListItr); mDialogMap.erase(anItr); if (removeWidget || deleteWidget) mWidgetManager->RemoveWidget(aDialog); if (aDialog->IsModal()) { ModalClose(); mWidgetManager->RemoveBaseModal(aDialog); } if (deleteWidget) SafeDeleteWidget(aDialog); return true; } return false; } bool SexyAppBase::KillDialog(int theDialogId) { return KillDialog(theDialogId,true,true); } bool SexyAppBase::KillDialog(Dialog* theDialog) { return KillDialog(theDialog->mId); } int SexyAppBase::GetDialogCount() { return mDialogMap.size(); } void SexyAppBase::AddDialog(int theDialogId, Dialog* theDialog) { KillDialog(theDialogId); if (theDialog->mWidth == 0) { // Set the dialog position ourselves int aWidth = mWidth/2; theDialog->Resize((mWidth - aWidth)/2, mHeight / 5, aWidth, theDialog->GetPreferredHeight(aWidth)); } mDialogMap.insert(DialogMap::value_type(theDialogId, theDialog)); mDialogList.push_back(theDialog); mWidgetManager->AddWidget(theDialog); if (theDialog->IsModal()) { mWidgetManager->AddBaseModal(theDialog); ModalOpen(); } } void SexyAppBase::AddDialog(Dialog* theDialog) { AddDialog(theDialog->mId, theDialog); } void SexyAppBase::ModalOpen() { } void SexyAppBase::ModalClose() { } void SexyAppBase::DialogButtonPress(int theDialogId, int theButtonId) { if (theButtonId == Dialog::ID_YES) ButtonPress(2000 + theDialogId); else if (theButtonId == Dialog::ID_NO) ButtonPress(3000 + theDialogId); } void SexyAppBase::DialogButtonDepress(int theDialogId, int theButtonId) { if (theButtonId == Dialog::ID_YES) ButtonDepress(2000 + theDialogId); else if (theButtonId == Dialog::ID_NO) ButtonDepress(3000 + theDialogId); } void SexyAppBase::GotFocus() { } void SexyAppBase::LostFocus() { } void SexyAppBase::CleanSharedImages() { #if 0 AutoCrit anAutoCrit(mDDInterface->mCritSect); #endif if (mCleanupSharedImages) { // Delete shared images with reference counts of 0 // This doesn't occur in ~SharedImageRef because sometimes we can not only access the image // through the SharedImageRef returned by GetSharedImage, but also by calling GetSharedImage // again with the same params -- so we can have instances where we do the 'final' deref on // an image but immediately re-request it via GetSharedImage SharedImageMap::iterator aSharedImageItr = mSharedImageMap.begin(); while (aSharedImageItr != mSharedImageMap.end()) { SharedImage* aSharedImage = &aSharedImageItr->second; if (aSharedImage->mRefCount == 0) { delete aSharedImage->mImage; mSharedImageMap.erase(aSharedImageItr++); } else ++aSharedImageItr; } mCleanupSharedImages = false; } } bool SexyAppBase::ChangeDirHook(const char *theIntendedPath) { return false; } void SexyAppBase::InitPropertiesHook() { } void SexyAppBase::InitHook() { } void SexyAppBase::SetAlphaDisabled(bool isDisabled) { if (mAlphaDisabled != isDisabled) { mAlphaDisabled = isDisabled; mDDInterface->SetVideoOnlyDraw(mAlphaDisabled); mWidgetManager->mImage = mDDInterface->GetScreenImage(); mWidgetManager->MarkAllDirty(); } } void SexyAppBase::HandleGameAlreadyRunning() { if(mOnlyAllowOneCopyToRun) { #if 0 // Notify the other window and then shut ourselves down if (mNotifyGameMessage != 0) PostMessage(HWND_BROADCAST, mNotifyGameMessage, 0, 0); #endif DoExit(0); } } void SexyAppBase::SwitchScreenMode(bool wantWindowed, bool is3d, bool force) { if (mForceFullscreen) wantWindowed = false; #if 0 //SDL needs a new video surface so don't do this if (mIsWindowed == wantWindowed && !force) { Set3DAcclerated(is3d); return; } #endif //FIXME TODO should be enabled #if 0 if (!wantWindowed) { // full screen = smooth scrolling and vsyncing mVSyncUpdates = true; mWaitForVSync = true; } else { // windowed doesn't vsync and do smooth motion mVSyncUpdates = false; mWaitForVSync = false; } #endif // Set 3d acceleration preference Set3DAcclerated(is3d,false); // Always make the app windowed when playing demos, in order to // make it easier to track down bugs. We place this after the // sanity check just so things get re-initialized and stuff //if (mPlayingDemoBuffer) // wantWindowed = true; mIsWindowed = wantWindowed; MakeWindow(); #if 0 // We need to do this check to allow IE to get focus instead of // stealing it away for ourselves if (!mIsOpeningURL) { ::ShowWindow(mHWnd, SW_NORMAL); ::SetForegroundWindow(mHWnd); } else { // Show it but don't activate it ::ShowWindow(mHWnd, SW_SHOWNOACTIVATE); } #endif if (mSoundManager!=NULL) { mSoundManager->SetCooperativeWindow(mHWnd,mIsWindowed); } mLastTime = SDL_GetTicks(); } void SexyAppBase::SwitchScreenMode(bool wantWindowed) { SwitchScreenMode(wantWindowed, Is3DAccelerated()); } void SexyAppBase::SwitchScreenMode() { SwitchScreenMode(mIsWindowed, Is3DAccelerated(), true); } bool SexyAppBase::Is3DAccelerationSupported() { #if 0 if (mDDInterface->mD3DTester) return mDDInterface->mD3DTester->Is3DSupported(); else return false; #else return true; #endif } bool SexyAppBase::Is3DAccelerationRecommended() { #if 0 if (mDDInterface->mD3DTester) return mDDInterface->mD3DTester->Is3DRecommended(); else return false; #else return true; #endif } void SexyAppBase::Remove3DData(MemoryImage* theMemoryImage) { if (mDDInterface) mDDInterface->Remove3DData(theMemoryImage); } void SexyAppBase::EnforceCursor() { bool wantSysCursor = true; if (mDDInterface == NULL) return; if ((mSEHOccured) || (!mMouseIn)) { SDL_SetCursor(mArrowCursor); SDL_ShowCursor(SDL_ENABLE); if (mDDInterface->SetCursorImage(NULL)) mCustomCursorDirty = true; } else { if ((mCursorImages[mCursorNum] == NULL) || ( #if 0 (!mPlayingDemoBuffer) && #endif (!mCustomCursorsEnabled) && (mCursorNum != CURSOR_CUSTOM))) { switch(mCursorNum) { case CURSOR_POINTER: SDL_SetCursor(mArrowCursor); SDL_ShowCursor(SDL_ENABLE); break; case CURSOR_HAND: SDL_SetCursor(mHandCursor); SDL_ShowCursor(SDL_ENABLE); break; case CURSOR_DRAGGING: SDL_SetCursor(mDraggingCursor); SDL_ShowCursor(SDL_ENABLE); break; case CURSOR_NONE: SDL_ShowCursor(SDL_DISABLE); break; } if (mDDInterface->SetCursorImage(NULL)) mCustomCursorDirty = true; } else { if (mDDInterface->SetCursorImage(mCursorImages[mCursorNum])) mCustomCursorDirty = true; #if 0 if (!mPlayingDemoBuffer) { #endif SDL_ShowCursor(SDL_DISABLE); #if 0 } else { SDL_ShowCursor(SDL_ENABLE); } #endif wantSysCursor = false; } } if (wantSysCursor != mSysCursor) { mSysCursor = wantSysCursor; } } void SexyAppBase::SetCursorImage(int theCursorNum, Image* theImage) { if ((theCursorNum >= 0) && (theCursorNum < NUM_CURSORS)) { mCursorImages[theCursorNum] = theImage; EnforceCursor(); } } int SexyAppBase::GetCursor() { return mCursorNum; } void SexyAppBase::EnableCustomCursors(bool enabled) { mCustomCursorsEnabled = enabled; if (!mCustomCursorsEnabled) { SDL_ShowCursor(SDL_ENABLE); } EnforceCursor(); } SexyString SexyAppBase::GetString(const std::string& theId) { StringWStringMap::iterator anItr = mStringProperties.find(theId); assert(anItr != mStringProperties.end()); if (anItr != mStringProperties.end()) return WStringToSexyString(anItr->second); else return _S(""); } SexyString SexyAppBase::GetString(const std::string& theId, const SexyString& theDefault) { StringWStringMap::iterator anItr = mStringProperties.find(theId); if (anItr != mStringProperties.end()) return WStringToSexyString(anItr->second); else return theDefault; } void SexyAppBase::Done3dTesting() { } // return file name that you want to upload std::string SexyAppBase::NotifyCrashHook() { return ""; } void SexyAppBase::PreTerminate() { } bool SexyAppBase::CheckSignature(const Buffer& theBuffer, const std::string& theFileName) { // Add your own signature checking code here return false; } bool SexyAppBase::LoadProperties(const std::string& theFileName, bool required, bool checkSig) { Buffer aBuffer; if (!ReadBufferFromFile(GetAppResourceFolder() + theFileName, &aBuffer)) { if (!required) return true; else { #if 0 Popup(GetString("UNABLE_OPEN_PROPERTIES", _S("Unable to open properties file ")) + StringToSexyString(theFileName)); #endif return false; } } if (checkSig) { if (!CheckSignature(aBuffer, theFileName)) { #if 0 Popup(GetString("PROPERTIES_SIG_FAILED", _S("Signature check failed on ")) + StringToSexyString(theFileName + "'")); #endif return false; } } PropertiesParser aPropertiesParser(this); // Load required language-file properties if (!aPropertiesParser.ParsePropertiesBuffer(aBuffer)) { #if 0 Popup(aPropertiesParser.GetErrorText()); return false; #endif } else return true; } bool SexyAppBase::LoadProperties() { // Load required language-file properties return LoadProperties("properties\\default.xml", true, false); } bool SexyAppBase::GetBoolean(const std::string& theId) { StringBoolMap::iterator anItr = mBoolProperties.find(theId); assert(anItr != mBoolProperties.end()); if (anItr != mBoolProperties.end()) return anItr->second; else return false; } bool SexyAppBase::GetBoolean(const std::string& theId, bool theDefault) { StringBoolMap::iterator anItr = mBoolProperties.find(theId); if (anItr != mBoolProperties.end()) return anItr->second; else return theDefault; } int SexyAppBase::GetInteger(const std::string& theId) { StringIntMap::iterator anItr = mIntProperties.find(theId); assert(anItr != mIntProperties.end()); if (anItr != mIntProperties.end()) return anItr->second; else return false; } int SexyAppBase::GetInteger(const std::string& theId, int theDefault) { StringIntMap::iterator anItr = mIntProperties.find(theId); if (anItr != mIntProperties.end()) return anItr->second; else return theDefault; } double SexyAppBase::GetDouble(const std::string& theId) { StringDoubleMap::iterator anItr = mDoubleProperties.find(theId); assert(anItr != mDoubleProperties.end()); if (anItr != mDoubleProperties.end()) return anItr->second; else return false; } double SexyAppBase::GetDouble(const std::string& theId, double theDefault) { StringDoubleMap::iterator anItr = mDoubleProperties.find(theId); if (anItr != mDoubleProperties.end()) return anItr->second; else return theDefault; } StringVector SexyAppBase::GetStringVector(const std::string& theId) { StringStringVectorMap::iterator anItr = mStringVectorProperties.find(theId); assert(anItr != mStringVectorProperties.end()); if (anItr != mStringVectorProperties.end()) return anItr->second; else return StringVector(); } void SexyAppBase::SetString(const std::string& theId, const std::wstring& theValue) { std::pair aPair = mStringProperties.insert(StringWStringMap::value_type(theId, theValue)); if (!aPair.second) // Found it, change value aPair.first->second = theValue; } void SexyAppBase::SetBoolean(const std::string& theId, bool theValue) { std::pair aPair = mBoolProperties.insert(StringBoolMap::value_type(theId, theValue)); if (!aPair.second) // Found it, change value aPair.first->second = theValue; } void SexyAppBase::SetInteger(const std::string& theId, int theValue) { std::pair aPair = mIntProperties.insert(StringIntMap::value_type(theId, theValue)); if (!aPair.second) // Found it, change value aPair.first->second = theValue; } void SexyAppBase::SetDouble(const std::string& theId, double theValue) { std::pair aPair = mDoubleProperties.insert(StringDoubleMap::value_type(theId, theValue)); if (!aPair.second) // Found it, change value aPair.first->second = theValue; } void SexyAppBase::SetWindowIconBMP(const std::string& icon) { mWindowIconBMP = ReplaceBackSlashes(icon); } libtuxcap-1.4.0/tuxcap/CMakeLists.txt0000644000175000017500000000613011212652465017437 0ustar inniyahinniyah#include some macros from another file... INCLUDE(${libtuxcap_SOURCE_DIR}/tuxcap/CMakeMacros/IJMacros.txt) SET(CMAKE_MODULE_PATH "${libtuxcap_SOURCE_DIR}/tuxcap/CMakeModules" ) SET(CMAKE_C_FLAGS_RELEASE "-DNDEBUG -O3") SET(CMAKE_C_FLAGS_DEBUG "-Wall -g -O0") SET(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -O3") SET(CMAKE_CXX_FLAGS_DEBUG "-Wall -g -O0") INCLUDE(FindImageMagick) INCLUDE(FindSDL) INCLUDE(FindOpenGL) INCLUDE(FindSDL_mixer) INCLUDE(FindPythonLibs) Find_Package ( SDL REQUIRED ) Find_Package ( SDL_mixer REQUIRED ) Find_Package ( ImageMagick REQUIRED ) Find_Package ( OpenGL REQUIRED ) FIND_PACKAGE(ImageMagickLib) FIND_PACKAGE(AudiereLib) IF(AUDIERELIB_FOUND) MESSAGE("DBG lib Audiere found. ${AUDIERELIB_INCLUDE_DIR} ${AUDIERELIB_LINK_DIRECTORIES} ${AUDIERELIB_LIBRARIES}") LINK_DIRECTORIES(${AUDIERELIB_LINK_DIRECTORIES}) ENDIF(AUDIERELIB_FOUND) SET(MY_LINK_LIBS ${SDL_LIBRARY} ${SDLMIXER_LIBRARY} ${OPENGL_LIBRARIES} ${IMAGEMAGICKLIB_LIBRARIES} ${IMAGEMAGICKLIB_CXX_LIBRARIES} ) IF (PYTHON_LIBRARIES) MESSAGE("Python development libraries found, building TuxCap Python bindings and examples") MESSAGE("Python libraries ${PYTHON_LIBRARIES} include path ${PYTHON_INCLUDE_PATH}") SET(MY_LINK_LIBS ${MY_LINK_LIBS} ${PYTHON_LIBRARIES}) SET(MY_DIRS ${MY_DIRS} pythondemo1 pythondemo2 pythondemo_template) ELSE (PYTHON_LIBRARIES) MESSAGE("No Python development libraries found, skipping building of TuxCap Python bindings") ENDIF (PYTHON_LIBRARIES) SET (MY_DIRS ${MY_DIRS} lib demo1 demo2 demo3 demo4 demo5 physicsdemo physicsdemo2 physicsdemo3 physicsdemo4 physicsdemo5 physicsdemo6 physicsdemo7 particledemo hungarr ) IF(AUDIERELIB_FOUND) SET(MY_LINK_LIBS ${MY_LINK_LIBS} audiere) ENDIF(AUDIERELIB_FOUND) link_libraries ( ${MY_LINK_LIBS} ) IF(SDL_FOUND) MESSAGE("libSDL found. ${SDL_INCLUDE_DIR} ${SDL_LIBRARY}") ELSE(SDL_FOUND) MESSAGE(FATAL_ERROR "libSDL requested but not found.") ENDIF(SDL_FOUND) IF(IMAGEMAGICKLIB_FOUND) MESSAGE("lib ImageMagick found. ${IMAGEMAGICKLIB_INCLUDE_DIR} ${IMAGEMAGICKLIB_LIBRARIES} ${IMAGEMAGICKLIB_CXX_LIBRARIES}") ELSE(IMAGEMAGICKLIB_FOUND) MESSAGE(FATAL_ERROR "lib ImageMagick requested but not found.") ENDIF(IMAGEMAGICKLIB_FOUND) IF(SDLMIXER_FOUND) MESSAGE("libSDL_mixer found. ${SDLMIXER_INCLUDE_DIR} ${SDLMIXER_LIBRARY}") ELSE(SDLMIXER_FOUND) MESSAGE(FATAL_ERROR "libSDL_mixer requested but not found.") ENDIF(SDLMIXER_FOUND) IF(OPENGL_FOUND) MESSAGE("OpenGL found. ${OPENGL_INCLUDE_DIR} ${OPENGL_LIBRARIES}") ELSE(OPENGL_FOUND) MESSAGE(FATAL_ERROR "OpenGL requested but not found.") ENDIF(OPENGL_FOUND) SET ( MY_INCLUDE_DIRS #/usr/include/swfdec-0.5 /usr/include/glib-2.0 /usr/lib/glib-2.0/include {SDL_INCLUDE_DIR} ${IMAGEMAGICKLIB_INCLUDE_DIR} ${SDLMIXER_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${PYTHON_INCLUDE_PATH} ) IF(AUDIERELIB_FOUND) SET ( MY_INCLUDE_DIRS ${MY_INCLUDE_DIRS} ${AUDIERELIB_INCLUDE_DIR} ) ENDIF(AUDIERELIB_FOUND) INCLUDE_DIRECTORIES ( ${MY_INCLUDE_DIRS} ) SUBDIRS( ${MY_DIRS} ) libtuxcap-1.4.0/tuxcap/physicsdemo3/0000755000175000017500000000000011212652053017302 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo3/GameApp.cpp0000644000175000017500000001207311062533667021337 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo3"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo3/CMakeLists.txt0000644000175000017500000000402210762446645022061 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo3") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo3/Board.h0000644000175000017500000001420010667046272020514 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; std::vector points; PhysicsObject* object1; PhysicsObject* object2; PhysicsObject* object3; PhysicsObject* object4; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); virtual void HandleCollision(CollisionObject* col); virtual void AfterPhysicsStep(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo3/GameApp.h0000644000175000017500000000612110667046272021002 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo3/main.cpp0000644000175000017500000000022710667046272020750 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo3/Board.cpp0000644000175000017500000002230410675254242021050 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetSteps(3); physics->ResizeStaticHash(200.0f, 99); physics->ResizeActiveHash(30.0f, 999); physics->SetGravity(SexyVector2(0,400)); int num = 4; SexyVector2 verts[] = { SexyVector2(-30,-15), SexyVector2(-30, 15), SexyVector2( 30, 15), SexyVector2( 30,-15) }; SexyVector2 a = SexyVector2(-200,-200); SexyVector2 b = SexyVector2(-200,200); SexyVector2 c = SexyVector2(200, 200); SexyVector2 d = SexyVector2(200, -200); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(a, b, 0.0f,1.0f,1.0f); obj->SetAngularVelocity(-0.4f); object1 = obj; obj = physics->CreateStaticObject(); obj->AddSegmentShape(b, c, 0.0f,1.0f,1.0f); obj->SetAngularVelocity(-0.4f); object2 = obj; obj = physics->CreateStaticObject(); obj->AddSegmentShape(c, d, 0.0f,1.0f,1.0f); obj->SetAngularVelocity(-0.4f); object3 = obj; obj = physics->CreateStaticObject(); obj->AddSegmentShape(d, a, 0.0f,1.0f,1.0f); obj->SetAngularVelocity(-0.4f); object4 = obj; int i,j; for(i=0; i<3; i++){ for(j=0; j<7; j++){ PhysicsObject* obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,0.7f); obj->SetPosition(SexyVector2(i*60 -150, j*30 -150)); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) physics->Draw(g); //draw saved collision points g->SetColor(Color(255,0,0)); std::vector::const_iterator it = points.begin(); while (it != points.end()) { SexyVector2 pos = (*it) + SexyVector2(320,240); g->DrawLine((int)pos.x - 2, (int)pos.y, (int)pos.x + 2, (int)pos.y); g->DrawLine((int)pos.x, (int)pos.y - 2, (int)pos.x, (int)pos.y + 2); ++it; } points.clear(); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin() + SexyVector2(320,240); SexyVector2 endpos = object->GetSegmentShapeEnd() + SexyVector2(320,240); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i) + SexyVector2(320,240); SexyVector2 endpos = object->GetVertex(i + 1) + SexyVector2(320,240); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1) + SexyVector2(320,240); SexyVector2 endpos = object->GetVertex(0) + SexyVector2(320,240); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } /* watch it!, this is being called for every step in which a collision occurres, so in case of physics->SetSteps(3) it might get called 3 times by every Board->Update(). */ void Board::HandleCollision(CollisionObject* col) { /* Watch it! col->points and col are invalid when this function exits, so if you want to store its data, copy it! col->object1 and col->object2 are not invalidated upon return */ for (int i = 0; i < col->num_points; ++i) { points.push_back(SexyVector2(col->points[i].point.x, col->points[i].point.y)); } } void Board::AfterPhysicsStep(){ object1->UpdatePosition(); object2->UpdatePosition(); object3->UpdatePosition(); object4->UpdatePosition(); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { points.clear(); physics->Clear(); physics->Init(); InitDemo(); } } libtuxcap-1.4.0/tuxcap/physicsdemo6/0000755000175000017500000000000011212652053017305 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo6/GameApp.cpp0000644000175000017500000001207311062533667021342 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo6"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo6/CMakeLists.txt0000644000175000017500000000402210762446645022064 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo6") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo6/Board.h0000644000175000017500000001354510670535173020527 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); virtual void AfterPhysicsStep(); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo6/GameApp.h0000644000175000017500000000612110667046274021007 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo6/main.cpp0000644000175000017500000000022710667046274020755 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo6/Board.cpp0000644000175000017500000002010510670535173021050 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetIterations(5); physics->SetSteps(1); physics->ResizeStaticHash(40.0f,999); physics->ResizeActiveHash(30.0f,2999); int num = 5; SexyVector2 verts[5]; int i; for(i=0; iCreateStaticObject(); obj->AddPolyShape(3, tris, offset, 1.0f, 1.0f); } } for(i=0; i<300; i++){ PhysicsObject* obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); cpFloat x = rand()/(cpFloat)RAND_MAX*640; obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f), 0.0f,0.4f); obj->SetPosition(SexyVector2(x, -110)); } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); physics->Draw(g); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLineAA((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i); SexyVector2 endpos = object->GetVertex(i + 1); g->DrawLineAA((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1); SexyVector2 endpos = object->GetVertex(0); g->DrawLineAA((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); SexyVector2 pos = object->GetPosition(); g->DrawLineAA((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } void Board::AfterPhysicsStep(){ std::vector objects = physics->GetPhysicsObjects(); std::vector::iterator it = objects.begin(); while (it != objects.end()) { if((*it)->GetPosition().y > 520 || (*it)->GetPosition().x > 680 || (*it)->GetPosition().x < -40){ cpFloat x = rand()/(cpFloat)RAND_MAX*640; (*it)->SetPosition(SexyVector2(x, -110)); } ++it; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { physics->Clear(); physics->Init(); InitDemo(); } } libtuxcap-1.4.0/tuxcap/hgeparticle/0000755000175000017500000000000011212652053017157 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/hgeparticle/hgecolor.h0000644000175000017500000000370111202747625021144 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeColor helper class */ #ifndef HGECOLOR_H #define HGECOLOR_H namespace HGE { #define GETA(col) ((col)>>24) #define GETR(col) (((col)>>16) & 0xFF) #define GETG(col) (((col)>>8) & 0xFF) #define GETB(col) ((col) & 0xFF) #ifndef WIN32 typedef uint32_t DWORD; #else #define PATH_MAX MAX_PATH #endif inline void ColorClamp(float &x) { if(x<0.0f) x=0.0f; if(x>1.0f) x=1.0f; } class hgeColor { public: float r,g,b,a; hgeColor(float _r, float _g, float _b, float _a) { r=_r; g=_g; b=_b; a=_a; } hgeColor(DWORD col) { SetHWColor(col); } hgeColor() { r=g=b=a=0; } hgeColor operator- (const hgeColor &c) { return hgeColor(r-c.r, g-c.g, b-c.b, a-c.a); } hgeColor operator+ (const hgeColor &c) { return hgeColor(r+c.r, g+c.g, b+c.b, a+c.a); } hgeColor operator* (float scalar) { return hgeColor(r*scalar, g*scalar, b*scalar, a*scalar); } hgeColor& operator-= (const hgeColor &c) { r-=c.r; g-=c.g; b-=c.b; a-=c.a; return *this; } hgeColor& operator+= (const hgeColor &c) { r+=c.r; g+=c.g; b+=c.b; a+=c.a; return *this; } hgeColor& operator*= (float scalar) { r*=scalar; g*=scalar; b*=scalar; a*=scalar; return *this; } bool operator== (const hgeColor &c) { return (r==c.r && g==c.g && b==c.b && a==c.a); } bool operator!= (const hgeColor &c) { return (r!=c.r || g!=c.g || b!=c.b || a!=c.a); } void Clamp() { ColorClamp(r); ColorClamp(g); ColorClamp(b); ColorClamp(a); } void SetHWColor(DWORD col) { a=(col>>24)/255.0f; r=((col>>16) & 0xFF)/255.0f; g=((col>>8) & 0xFF)/255.0f; b=(col & 0xFF)/255.0f; } DWORD GetHWColor() const { return (DWORD(a*255.0f)<<24) + (DWORD(r*255.0f)<<16) + (DWORD(g*255.0f)<<8) + DWORD(b*255.0f); } }; inline hgeColor operator* (const hgeColor &c, float s) { return hgeColor(s*c.r, s*c.g, s*c.b, s*c.a); } inline hgeColor operator* (float s, const hgeColor &c) { return hgeColor(s*c.r, s*c.g, s*c.b, s*c.a); } } #endif libtuxcap-1.4.0/tuxcap/hgeparticle/hgerect.h0000644000175000017500000000142310736754547020776 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeRect helper class */ #ifndef HGERECT_H #define HGERECT_H namespace HGE { class hgeRect { public: float x1, y1, x2, y2; hgeRect(float _x1, float _y1, float _x2, float _y2) {x1=_x1; y1=_y1; x2=_x2; y2=_y2; bClean=false; } hgeRect() {bClean=true;} void Clear() {bClean=true;} bool IsClean() const {return bClean;} void Set(float _x1, float _y1, float _x2, float _y2) { x1=_x1; x2=_x2; y1=_y1; y2=_y2; bClean=false; } void SetRadius(float x, float y, float r) { x1=x-r; x2=x+r; y1=y-r; y2=y+r; bClean=false; } void Encapsulate(float x, float y); bool TestPoint(float x, float y) const; bool Intersect(const hgeRect *rect) const; private: bool bClean; }; } #endif libtuxcap-1.4.0/tuxcap/hgeparticle/hgerect.cpp0000644000175000017500000000133010736754547021326 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeRect helper class implementation */ #include #include "hgerect.h" using namespace HGE; void hgeRect::Encapsulate(float x, float y) { if(bClean) { x1=x2=x; y1=y2=y; bClean=false; } else { if(xx2) x2=x; if(yy2) y2=y; } } bool hgeRect::TestPoint(float x, float y) const { if(x>=x1 && x=y1 && yx1-rect->x2) < (x2-x1 + rect->x2-rect->x1)) { if(fabs(y1+y2 - rect->y1-rect->y2) < (y2-y1 + rect->y2-rect->y1)) return true; } return false; } libtuxcap-1.4.0/tuxcap/hgeparticle/hgevector.h0000644000175000017500000000324510736754547021347 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeVector helper class */ #ifndef HGEVECTOR_H #define HGEVECTOR_H #include namespace HGE { /* ** Fast 1.0/sqrtf(float) routine */ float InvSqrt(float x); class hgeVector { public: float x,y; hgeVector(float _x, float _y) { x=_x; y=_y; } hgeVector() { x=0; y=0; } hgeVector operator- (const hgeVector &v) { return hgeVector(x-v.x, y-v.y); } hgeVector operator+ (const hgeVector &v) { return hgeVector(x+v.x, y+v.y); } hgeVector operator* (float scalar) { return hgeVector(x*scalar, y*scalar); } hgeVector& operator-= (const hgeVector &v) { x-=v.x; y-=v.y; return *this; } hgeVector& operator+= (const hgeVector &v) { x+=v.x; y+=v.y; return *this; } hgeVector& operator*= (float scalar) { x*=scalar; y*=scalar; return *this; } hgeVector operator- () { return hgeVector(-x, -y); } bool operator== (const hgeVector &v) { return (x==v.x && y==v.y); } bool operator!= (const hgeVector &v) { return (x!=v.x || y!=v.y); } float Dot(const hgeVector *v) const { return x*v->x + y*v->y; } hgeVector* Normalize() { float rc=InvSqrt(Dot(this)); x*=rc; y*=rc; return this; } float Length() const { return sqrtf(Dot(this)); } float Angle(const hgeVector *v = 0) const; hgeVector* Rotate(float a); }; inline hgeVector operator* (const hgeVector &v, float s) { return hgeVector(s*v.x, s*v.y); } inline hgeVector operator* (float s, const hgeVector &v) { return hgeVector(s*v.x, s*v.y); } inline float operator^ (const hgeVector &v, const hgeVector &u) { return v.Angle(&u); } inline float operator% (const hgeVector &v, const hgeVector &u) { return v.Dot(&u); } } #endif libtuxcap-1.4.0/tuxcap/hgeparticle/hgevector.cpp0000644000175000017500000000177010736754547021703 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeVector helper class implementation */ #include "hgevector.h" namespace HGE { float InvSqrt(float x) { union { int intPart; float floatPart; } convertor; convertor.floatPart = x; convertor.intPart = 0x5f3759df - (convertor.intPart >> 1); return convertor.floatPart*(1.5f - 0.4999f*x*convertor.floatPart*convertor.floatPart); } }; using namespace HGE; /* hgeVector *hgeVector::Normalize() { float lenRcp; lenRcp=sqrtf(Dot(this)); if(lenRcp) { lenRcp=1.0f/lenRcp; x*=lenRcp; y*=lenRcp; } return this; } */ float hgeVector::Angle(const hgeVector *v) const { if(v) { hgeVector s=*this, t=*v; s.Normalize(); t.Normalize(); return acosf(s.Dot(&t)); } else return atan2f(y, x); } hgeVector *hgeVector::Rotate(float a) { hgeVector v; v.x=x*cosf(a) - y*sinf(a); v.y=x*sinf(a) + y*cosf(a); x=v.x; y=v.y; return this; } libtuxcap-1.4.0/tuxcap/hgeparticle/hgeRandom.h0000644000175000017500000000032310736754547021257 0ustar inniyahinniyah/* provide some functions to provide random float value */ #ifndef HGE_RANDOM_H #define HGE_RANDOM_H namespace HGE { void Random_Seed( int seed = 0 ); float Random_Float( float min, float max ); } #endif libtuxcap-1.4.0/tuxcap/hgeparticle/hgepmanager.cpp0000644000175000017500000000651010743475610022155 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeParticleManager helper class implementation ** Hacked on by ** ** Kevin Lynx ** James Poag ** W.P. van Paassen */ #include "hgeparticle.h" #include "ParticlePhysicsSystem.h" using namespace Sexy; using namespace HGE; hgeParticleManager::hgeParticleManager(float fps) { nPS=0; fFPS=fps; tX=tY=0.0f; } hgeParticleManager::~hgeParticleManager() { int i; for(i=0;iinfo.nEmission = theRate; } hgeParticleSystem* hgeParticleManager::SpawnPS(const char *filename, DDImage *sprite, float x, float y, bool parseMetaData, bool old_format, Physics* physics) { if(nPS==MAX_PSYSTEMS) return 0; hgeParticleSystem* system; if (physics == NULL) system = new hgeParticleSystem(filename, sprite, fFPS, parseMetaData, old_format); else system = new ParticlePhysicsSystem(filename, sprite, physics, fFPS, parseMetaData, old_format); if (!system->bInitOK) return 0; psList[nPS]=system; psList[nPS]->FireAt(x,y); psList[nPS]->Translate(tX,tY); nPS++; return psList[nPS-1]; } hgeParticleSystem* hgeParticleManager::SpawnPS(hgeParticleSystemInfo *psi, float x, float y, Physics* physics) { if(nPS==MAX_PSYSTEMS) return 0; hgeParticleSystem* system; if (physics != NULL) { system = new ParticlePhysicsSystem(psi, physics, fFPS); } else { system = new hgeParticleSystem(psi, fFPS); } if (!system->bInitOK) return 0; psList[nPS]=system; psList[nPS]->FireAt(x,y); psList[nPS]->Translate(tX,tY); nPS++; return psList[nPS-1]; } hgeParticleSystem* hgeParticleManager::SpawnPS(hgeParticleSystem *system, float x, float y, Physics* physics) { if(nPS==MAX_PSYSTEMS || !system->bInitOK) return 0; hgeParticleSystem* psystem; ParticlePhysicsSystem* s = dynamic_cast(system); if (s != NULL) psystem = new ParticlePhysicsSystem(*s); else if (physics != NULL) psystem = new ParticlePhysicsSystem(*system, physics); else psystem = new hgeParticleSystem(*system); psList[nPS]= psystem; psList[nPS]->FireAt(x,y); psList[nPS]->Translate(tX,tY); nPS++; return psList[nPS-1]; } void hgeParticleManager::Update(float dt) { int i; for(i=0;iUpdate(dt); if(psList[i]->GetAge()==-2.0f && psList[i]->GetParticlesAlive()==0) { delete psList[i]; psList[i]=psList[nPS-1]; nPS--; i--; } } } void hgeParticleManager::Render( Graphics *g ) { int i; for(i=0;iRender( g ); } bool hgeParticleManager::IsPSAlive(hgeParticleSystem *ps) const { int i; for(i=0;iTranslate(x,y); tX=x; tY=y; } void hgeParticleManager::KillPS(hgeParticleSystem *ps) { int i; for(i=0;i #include #include #include using namespace HGE; bool hgeParticleSystem::m_bInitRandom = false; hgeParticleSystem::hgeParticleSystem(const char *filename, DDImage *sprite, float fps /*= 0.0f*/, bool parseMetaData /*= true*/, bool old_format /*=true*/) // Change default behavior in header { // LOAD DEFAULTS mbAdditiveBlend = false; mPlayMode = PLAY_ONCE; mAnimPlaying = false; mPlayMarker = 0; mPlayTime = 0.0f; mPlayTimer = 0.0f; mPlayTimerStepSize = 0.0f; mPingPong = PING; bOldFormat = old_format; vecLocation.x=vecPrevLocation.x=0.0f; vecLocation.y=vecPrevLocation.y=0.0f; fTx=fTy=0; fScale = 1.0f; fParticleScale = 1.0f; fEmissionResidue=0.0f; nParticlesAlive=0; fAge=-2.0; if(fps!=0.0f) fUpdSpeed=1.0f/fps; else fUpdSpeed=0.0f; fResidue=0.0f; rectBoundingBox.Clear(); bUpdateBoundingBox=false; InitRandom(); bInitOK = false; // LOAD FROM FILE FILE *fp = fopen( filename, "rb" ); if( fp == NULL ) return ; char tmpInfo[128]; int bytes = fread(&tmpInfo, sizeof(unsigned char), 128, fp); int additiveBlendTmp; memcpy(&additiveBlendTmp, &tmpInfo[0], 4); memcpy(&info.nEmission, &tmpInfo[4], 4); memcpy(&info.fLifetime, &tmpInfo[8], 4); memcpy(&info.fParticleLifeMin, &tmpInfo[12], 4); memcpy(&info.fParticleLifeMax, &tmpInfo[16], 4); memcpy(&info.fDirection, &tmpInfo[20], 4); memcpy(&info.fSpread, &tmpInfo[24], 4); memcpy(&info.bRelative, &tmpInfo[28], 4); memcpy(&info.fSpeedMin, &tmpInfo[32], 4); memcpy(&info.fSpeedMax, &tmpInfo[36], 4); memcpy(&info.fGravityMin, &tmpInfo[40], 4); memcpy(&info.fGravityMax, &tmpInfo[44], 4); memcpy(&info.fRadialAccelMin, &tmpInfo[48], 4); memcpy(&info.fRadialAccelMax, &tmpInfo[52], 4); memcpy(&info.fTangentialAccelMin, &tmpInfo[56], 4); memcpy(&info.fTangentialAccelMax, &tmpInfo[60], 4); memcpy(&info.fSizeStart, &tmpInfo[64], 4); memcpy(&info.fSizeEnd, &tmpInfo[68], 4); memcpy(&info.fSizeVar, &tmpInfo[72], 4); memcpy(&info.fSpinStart, &tmpInfo[76], 4); memcpy(&info.fSpinEnd, &tmpInfo[80], 4); memcpy(&info.fSpinVar, &tmpInfo[84], 4); memcpy(&info.colColorStart.r, &tmpInfo[88], 4); memcpy(&info.colColorStart.g, &tmpInfo[92], 4); memcpy(&info.colColorStart.b, &tmpInfo[96], 4); memcpy(&info.colColorStart.a, &tmpInfo[100], 4); memcpy(&info.colColorEnd.r, &tmpInfo[104], 4); memcpy(&info.colColorEnd.g, &tmpInfo[108], 4); memcpy(&info.colColorEnd.b, &tmpInfo[112], 4); memcpy(&info.colColorEnd.a, &tmpInfo[116], 4); memcpy(&info.fColorVar, &tmpInfo[120], 4); memcpy(&info.fAlphaVar, &tmpInfo[124], 4); mbAdditiveBlend = (((additiveBlendTmp) >> 16) & 2) == 0; info.sprite = sprite; if(parseMetaData) ParseMetaData(fp); fclose(fp); bInitOK = true; } hgeParticleSystem::hgeParticleSystem(hgeParticleSystemInfo *psi, float fps) { memcpy(&info, psi, sizeof(hgeParticleSystemInfo)); vecLocation.x=vecPrevLocation.x=0.0f; vecLocation.y=vecPrevLocation.y=0.0f; fTx=fTy=0; fScale = 1.0f; fEmissionResidue=0.0f; nParticlesAlive=0; fAge=-2.0; if(fps!=0.0f) fUpdSpeed=1.0f/fps; else fUpdSpeed=0.0f; fResidue=0.0f; rectBoundingBox.Clear(); bUpdateBoundingBox=false; mbAdditiveBlend = false; InitRandom(); mPlayMode = STOPPED; mAnimPlaying = false; mPlayMarker = 0; bOldFormat = true; bInitOK = true; } hgeParticleSystem::hgeParticleSystem(const hgeParticleSystem &ps) { memcpy(this, &ps, sizeof(hgeParticleSystem)); InitRandom(); mPlayMode = STOPPED; mAnimPlaying = false; mPlayMarker = 0; } void hgeParticleSystem::ParseMetaData(FILE* aFile) { unsigned char aMetaTag = -1; // If you Change Size of MetaTag, change it in SaveMetaData char aBuffer[PATH_MAX] = {0}; memset(aBuffer, 0, PATH_MAX); //No Dirty Strings int aSize = 0; // Read Returns Zero when it doesn't read something while(fread(&aMetaTag, sizeof(unsigned char), 1, aFile)) { switch(aMetaTag) { case ADDITIVE: { size_t br = fread( &mbAdditiveBlend, sizeof(bool), 1, aFile ); break; // Never forget to Break! } case POSITION: { if(fread( &vecPrevLocation, sizeof(vecPrevLocation), 1, aFile)) { vecLocation.x=vecPrevLocation.x; vecLocation.y=vecPrevLocation.y; } break; // Never forget to Break! } case TEXTURE_PATH: { if(fread( &aSize, sizeof(int), 1, aFile) && fread(aBuffer, 1, aSize, aFile)) { // Attemp to Load Texture mTextureName = StrFormat("%s", aBuffer); if(mTextureName != "") { DDImage* aTempImage = gSexyAppBase->GetImage(mTextureName); if(aTempImage != NULL) { info.sprite = aTempImage; } } } break; // Never forget to Break! } case POLYGON_POINTS: { if(fread( &aSize, sizeof(int), 1, aFile)) { for(int i = 0; i < aSize; ++i) { Sexy::Point aPoint; if(fread(&aPoint, sizeof(Sexy::Point), 1, aFile)) mPolygonClipPoints.push_back(aPoint); } } break; // Never forget to Break! } case WAY_POINTS: { if(fread( &aSize, sizeof(int), 1, aFile)) { for(int i = 0; i < aSize; ++i) { Sexy::Point aPoint; if(fread(&aPoint, sizeof(Sexy::Point), 1, aFile)) mWayPoints.push_back(aPoint); } } break; // Never forget to Break! } case ANIMATION_DATA: { size_t br = fread(&mPlayTime, sizeof(mPlayTime), 1, aFile); br = fread(&mPlayMode, sizeof(mPlayMode), 1, aFile); break; } // TODO: Add your additional meta tags to this switch tree } } } void hgeParticleSystem::SaveFile(const char *filename) { FILE* aFile = fopen(filename, "w+b"); if(aFile != NULL) { // Standard Format size_t bw = fwrite(&(info), sizeof(hgeParticleSystemInfo), 1, aFile); // Extended Format SaveMetaData(aFile); fclose(aFile); } } void hgeParticleSystem::SaveMetaData(FILE* aFile) { unsigned char aMetaTag = 0; // If you change size of MetaTag, besure to change it in ParseMetaData int aSize = 0; // Step 1: Write Meta Tag // Step 2: Write Size Info (Optional) // Step 3: Write Meta Data aMetaTag = ADDITIVE; size_t bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); bw = fwrite(&mbAdditiveBlend, sizeof(bool), 1, aFile); aMetaTag = POSITION; bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); bw = fwrite(&vecLocation, sizeof(vecLocation), 1, aFile); aMetaTag = TEXTURE_PATH; bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); aSize = (int)mTextureName.size(); bw = fwrite(&aSize, sizeof(int), 1, aFile); bw = fwrite(mTextureName.c_str(),1, aSize, aFile); aMetaTag = POLYGON_POINTS; bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); aSize = (int)mPolygonClipPoints.size(); bw = fwrite(&aSize, sizeof(int), 1, aFile); for(unsigned int i = 0; i < mPolygonClipPoints.size(); ++i) { bw = fwrite(&mPolygonClipPoints[i], sizeof(Sexy::Point), 1, aFile); } aMetaTag = WAY_POINTS; bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); aSize = (int)mWayPoints.size(); bw = fwrite(&aSize, sizeof(int), 1, aFile); for(unsigned int i = 0; i < mWayPoints.size(); ++i) { bw = fwrite(&mWayPoints[i], sizeof(Sexy::Point), 1, aFile); } aMetaTag = ANIMATION_DATA; bw = fwrite(&aMetaTag, sizeof(aMetaTag), 1, aFile); bw = fwrite(&mPlayTime, sizeof(mPlayTime), 1, aFile); bw = fwrite(&mPlayMode, sizeof(mPlayMode), 1, aFile); } void hgeParticleSystem::Update(float fDeltaTime) { if(fUpdSpeed==0.0f) _update(fDeltaTime); else { fResidue+=fDeltaTime; if(fResidue>=fUpdSpeed) { _update(fUpdSpeed); while(fResidue>=fUpdSpeed) fResidue-=fUpdSpeed; } } } void hgeParticleSystem::_update(float fDeltaTime) { int i; float ang; hgeParticle *par; hgeVector vecAccel, vecAccel2; if(fAge >= 0) { fAge += fDeltaTime; if(fAge >= info.fLifetime) fAge = -2.0f; } // Play Animation if(mAnimPlaying) _updatePlay(fDeltaTime); // update all alive particles if(bUpdateBoundingBox) rectBoundingBox.Clear(); par=particles; for(i=0; ifAge += fDeltaTime; if(par->fAge >= par->fTerminalAge) { nParticlesAlive--; memcpy(par, &particles[nParticlesAlive], sizeof(hgeParticle)); i--; continue; } vecAccel = par->vecLocation-vecLocation; vecAccel.Normalize(); vecAccel2 = vecAccel; vecAccel *= par->fRadialAccel; // vecAccel2.Rotate(M_PI_2); // the following is faster ang = vecAccel2.x; vecAccel2.x = -vecAccel2.y; vecAccel2.y = ang; vecAccel2 *= par->fTangentialAccel; par->vecVelocity += (vecAccel+vecAccel2)*fDeltaTime; par->vecVelocity.y += par->fGravity*fDeltaTime; if (bOldFormat) par->vecLocation += par->vecVelocity; else par->vecLocation += par->vecVelocity * fDeltaTime; par->fSpin += par->fSpinDelta*fDeltaTime; par->fSize += par->fSizeDelta*fDeltaTime; par->colColor += par->colColorDelta*fDeltaTime; //-----use hgeColor if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y); par++; } // generate new particles if(fAge != -2.0f) { float fParticlesNeeded = info.nEmission*fDeltaTime + fEmissionResidue; int nParticlesCreated = (unsigned int)fParticlesNeeded; fEmissionResidue=fParticlesNeeded-nParticlesCreated; par=&particles[nParticlesAlive]; for(i=0; i=MAX_PARTICLES) break; par->fAge = 0.0f; //random par->fTerminalAge = Random_Float(info.fParticleLifeMin, info.fParticleLifeMax); par->vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*Random_Float(0.0f, 1.0f); par->vecLocation.x += Random_Float(-2.0f, 2.0f); par->vecLocation.y += Random_Float(-2.0f, 2.0f); ang=info.fDirection-M_PI_2+Random_Float(0,info.fSpread)-info.fSpread/2.0f; if(info.bRelative) ang += (vecPrevLocation-vecLocation).Angle()+M_PI_2; par->vecVelocity.x = cosf(ang); par->vecVelocity.y = sinf(ang); par->vecVelocity *= Random_Float(info.fSpeedMin, info.fSpeedMax); par->fGravity = Random_Float(info.fGravityMin, info.fGravityMax); par->fRadialAccel = Random_Float(info.fRadialAccelMin, info.fRadialAccelMax); par->fTangentialAccel = Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax); par->fSize = Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar); par->fSizeDelta = (info.fSizeEnd-par->fSize) / par->fTerminalAge; par->fSpin = Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar); par->fSpinDelta = (info.fSpinEnd-par->fSpin) / par->fTerminalAge; ////-----use hgeColor par->colColor.r = Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar); par->colColor.g = Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar); par->colColor.b = Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar); par->colColor.a = Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar); par->colColorDelta.r = (info.colColorEnd.r-par->colColor.r) / par->fTerminalAge; par->colColorDelta.g = (info.colColorEnd.g-par->colColor.g) / par->fTerminalAge; par->colColorDelta.b = (info.colColorEnd.b-par->colColor.b) / par->fTerminalAge; par->colColorDelta.a = (info.colColorEnd.a-par->colColor.a) / par->fTerminalAge; if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par->vecLocation.x, par->vecLocation.y); nParticlesAlive++; par++; } } vecPrevLocation=vecLocation; } void hgeParticleSystem::_updatePlay(float fDeltaTime) { // Play WayPoints if(mAnimPlaying) { hgeVector anAnimPosVec; mPlayTimer += fDeltaTime; while(mPlayTimer > mPlayTimerStepSize) //Fast Forward! { mPlayTimer -= mPlayTimerStepSize; switch(mPlayMode) { case PLAY_ONCE: { if(++mPlayMarker >= mWayPoints.size()-1) { mAnimPlaying = false; } break; } case PLAY_LOOPED: { mPlayMarker = (mWayPoints.size() > 1)? (++mPlayMarker)%(mWayPoints.size()-1) : 0; break; } case PLAY_PINGPONGED: { switch(mPingPong) { case PING: { if(++mPlayMarker >= mWayPoints.size()) { mPlayMarker = mWayPoints.size() - 1; mPingPong = PONG; } break; } case PONG: { if(--mPlayMarker < 0) { mPlayMarker = 0; mPingPong = PING; } break; } default: { mPingPong = PING; break; } } break; } default: { mAnimPlaying = false; break; } } } if(mAnimPlaying && mPlayMarker < mWayPoints.size() - 1) { anAnimPosVec = hgeVector(mWayPoints[mPlayMarker+1].mX - mWayPoints[mPlayMarker].mX,mWayPoints[mPlayMarker+1].mY - mWayPoints[mPlayMarker].mY); anAnimPosVec.Normalize(); if(mPlayTimerStepSize != 0.0f) anAnimPosVec *= mPlayTimer/mPlayTimerStepSize; Point aPosPoint((int)(mWayPoints[mPlayMarker].mX + anAnimPosVec.x) , (int)(mWayPoints[mPlayMarker].mY + anAnimPosVec.y)); MoveTo(aPosPoint.mX, aPosPoint.mY); } } } void hgeParticleSystem::MoveTo(float x, float y, bool bMoveParticles) { int i; float dx,dy; if(bMoveParticles) { dx=x-vecLocation.x; dy=y-vecLocation.y; for(i=0;i= 2) { FireAt(mWayPoints[0].mX, mWayPoints[0].mY); mAnimPlaying = true; mPlayMarker = 0; mPlayTimerStepSize = (mPlayTime/mWayPoints.size() > 0)? mPlayTime/mWayPoints.size() : 0.05f; mPlayTimer = 0.0f; } else mAnimPlaying = false; } void hgeParticleSystem::Fire() { if(info.fLifetime==-1.0f) fAge=-1.0f; else fAge=0.0f; fResidue=0.0; } void hgeParticleSystem::Stop(bool bKillParticles) { fAge=-2.0f; if(bKillParticles) { nParticlesAlive=0; rectBoundingBox.Clear(); } } void hgeParticleSystem::Render( Graphics *g ) { // Check to make sure the texture is valid if(info.sprite == NULL) return; int blendMode = g->GetDrawMode(); if( mbAdditiveBlend && blendMode == Graphics::DRAWMODE_NORMAL ) g->SetDrawMode( Graphics::DRAWMODE_ADDITIVE ); else if( !mbAdditiveBlend && blendMode == Graphics::DRAWMODE_ADDITIVE ) g->SetDrawMode( Graphics::DRAWMODE_NORMAL ); g->SetColorizeImages( true ); int i; //DWORD col; hgeParticle *par=particles; //col=info.sprite->GetColor(); Color col = g->GetColor(); /*****************************************************/ // This section sets up the poly points by wrapping // // the front around to the back. // /*****************************************************/ bool front_pushed = false; // Clip to Polygon 3 points is a triangle if(mPolygonClipPoints.size() > 2) { mPolygonClipPoints.push_back(mPolygonClipPoints.front()); front_pushed = true; } /*****************************************************/ /*****************************************************/ for(i=0; i 3) if(!wn_PnPoly(Point((int)(par->vecLocation.x+fTx), (int)(par->vecLocation.y+fTy)))) continue; /*****************************************************/ /*****************************************************/ //info.sprite->SetColor(par->colColor.GetHWColor()); //hgeColor col2( par->colColor.GetHWColor() ); DWORD col2 = par->colColor.GetHWColor(); //g->SetColor( Color( col2.r * 255, col2.g * 255, col2.b * 255, col2.a * 255 ) ); g->SetColor( Color( GETR( col2 ), GETG( col2 ), GETB( col2 ), GETA( col2 ) ) ); //info.sprite->RenderEx(par->vecLocation.x+fTx, par->vecLocation.y+fTy, par->fSpin*particles[i].fAge, par->fSize); Transform t; SexyVector2 v; t.RotateRad( par->fSpin*particles[i].fAge ); t.Scale( par->fSize*fParticleScale, par->fSize*fParticleScale); if (fScale == 1.0f) t.Translate(fTx, fTy); else { // grrrr, popcap should really improve their vector and point classes, this is ugly! //TODO use the stored location of the system in particle instead of vecLocation. This is to be used for scaling particlesystems which are moved around, currently this results in a funny effect v = SexyVector2(par->vecLocation.x - vecLocation.x, par->vecLocation.y - vecLocation.y); v *= fScale; v.x = vecLocation.x + v.x; v.y = vecLocation.y + v.y; t.Translate(fTx + v.x - par->vecLocation.x, fTy + v.y - par->vecLocation.y); } if( gSexyAppBase->Is3DAccelerated() ) { g->DrawImageTransformF( info.sprite, t, par->vecLocation.x, par->vecLocation.y ); } else { if(!mbAdditiveBlend) // Works fine g->DrawImageTransform( info.sprite, t, par->vecLocation.x, par->vecLocation.y ); // Ok, Several problems here. // 1. Software Rendering using a complex transform requires SWTri_AddAllDrawTriFuncs() // 2. Software SWTri rendering functions don't support Additive. // // The main cause of this problem boils down to three variables: Additive drawing, Rotation and // scaling. Rotation AND scaling make the transform complex and will not render additive. // So the solution is to remove one of the variables to simplify the situation. // // The two solutions are: ignore the rotation and use standard funtions (removes the rotation // variable) OR cache the scaling thusly eliminating that variable. // // I choose the former because it doesn't make the particles look like a step function and // most particles are round and you can't tell they are rotating. (and it's easier) else { if (fScale == 1.0f) { if (fParticleScale == 1.0f) { g->DrawImage( info.sprite, (int)(par->vecLocation.x+ fTx - (info.sprite->GetWidth()*par->fSize)/2.0f), //Centered (int)(par->vecLocation.y+ fTy - (info.sprite->GetHeight()*par->fSize)/2.0f), //Centered (int)(info.sprite->GetWidth()*par->fSize), (int)(info.sprite->GetHeight()*par->fSize)); } else { g->DrawImage( info.sprite, (int)(par->vecLocation.x+ fTx - (info.sprite->GetWidth()*fParticleScale*par->fSize)/2.0f), //Centered (int)(par->vecLocation.y+ fTy - (info.sprite->GetHeight()*fParticleScale*par->fSize)/2.0f), //Centered (int)(info.sprite->GetWidth()*fParticleScale*par->fSize), (int)(info.sprite->GetHeight()*fParticleScale*par->fSize)); } } else { if (fParticleScale == 1.0f) { g->DrawImage( info.sprite, (int)(v.x + fTx - (info.sprite->GetWidth()*par->fSize)/2.0f), //Centered (int)(v.y + fTy - (info.sprite->GetHeight()*par->fSize)/2.0f), //Centered (int)(info.sprite->GetWidth()*par->fSize), (int)(info.sprite->GetHeight()*par->fSize)); } else { g->DrawImage( info.sprite, (int)(v. x + fTx - (info.sprite->GetWidth()*fParticleScale*par->fSize)/2.0f), //Centered (int)(v. y + fTy - (info.sprite->GetHeight()*fParticleScale*par->fSize)/2.0f), //Centered (int)(info.sprite->GetWidth()*fParticleScale*par->fSize), (int)(info.sprite->GetHeight()*fParticleScale*par->fSize)); } } } } } if(front_pushed) mPolygonClipPoints.pop_back(); //info.sprite->SetColor(col); g->SetColor( col ); g->SetColorizeImages( false ); g->SetDrawMode( blendMode ); } hgeRect *hgeParticleSystem::GetBoundingBox(hgeRect *rect) const { *rect = rectBoundingBox; rect->x1 *= fScale; rect->y1 *= fScale; rect->x2 *= fScale; rect->y2 *= fScale; return rect; } void hgeParticleSystem::InitRandom() { if( !m_bInitRandom ) { Random_Seed( 0 ); m_bInitRandom = true; } } // isLeft(): tests if a point is Left|On|Right of an infinite line. // Input: three points P0, P1, and P2 // Return: >0 for P2 left of the line through P0 and P1 // =0 for P2 on the line // <0 for P2 right of the line // See: the January 2001 Algorithm "Area of 2D and 3D Triangles and Polygons" inline int isLeft( Point P0, Point P1, Point P2 ) { return ( (P1.mX - P0.mX) * (P2.mY - P0.mY) - (P2.mX - P0.mX) * (P1.mY - P0.mY) ); } //=================================================================== // wn_PnPoly(): winding number test for a point in a polygon // Input: P = a point, // V[] = vertex points of a polygon V[n+1] with V[n]=V[0] // Basically, the First vertex is duplicated after the last vertex // Return: wn = the winding number (=0 only if P is outside V[]) bool hgeParticleSystem::wn_PnPoly( Sexy::Point theTestPoint) { int wn = 0; // the winding number counter // loop through all edges of the polygon for (unsigned int i = 0; i < mPolygonClipPoints.size() - 1; i++) { // edge from mPolygonClipPoints[i] to mPolygonClipPoints[i+1] if (mPolygonClipPoints[i].mY <= theTestPoint.mY) { // start y <= theTestPoint.mY if (mPolygonClipPoints[i+1].mY > theTestPoint.mY) // an upward crossing if (isLeft( mPolygonClipPoints[i], mPolygonClipPoints[i+1], theTestPoint) > 0) // theTestPoint left of edge ++wn; // have a valid up intersect } else { // start y > theTestPoint.mY (no test needed) if (mPolygonClipPoints[i+1].mY <= theTestPoint.mY) // a downward crossing if (isLeft( mPolygonClipPoints[i], mPolygonClipPoints[i+1], theTestPoint) < 0) // theTestPoint right of edge --wn; // have a valid down intersect } } return (wn != 0); } //=================================================================== // cn_PnPoly(): crossing number test for a point in a polygon // Input: P = a point, // V[] = vertex points of a polygon V[n+1] with V[n]=V[0] // Return: 0 = outside, 1 = inside // This code is patterned after [Franklin, 2000] bool hgeParticleSystem::cn_PnPoly( Point theTestPoint) { int cn = 0; // the crossing number counter // loop through all edges of the polygon for (unsigned int i=0; i theTestPoint.mY)) // an upward crossing || ((mPolygonClipPoints[i].mY > theTestPoint.mY) && (mPolygonClipPoints[i+1].mY <= theTestPoint.mY))) { // a downward crossing // compute the actual edge-ray intersect x-coordinate float vt = (float)(theTestPoint.mY - mPolygonClipPoints[i].mY) / (mPolygonClipPoints[i+1].mY - mPolygonClipPoints[i].mY); if (theTestPoint.mX < mPolygonClipPoints[i].mX + vt * (mPolygonClipPoints[i+1].mX - mPolygonClipPoints[i].mX)) // theTestPoint.mX < intersect ++cn; // a valid crossing of y=theTestPoint.mY right of theTestPoint.mX } } return (cn&1) != 0; // 0 if even (out), and 1 if odd (in) } unsigned int hgeParticleSystem::GetCollisionType() const { assert(false); //only supported in child class ParticlePhysicsSystem return 0; } unsigned int hgeParticleSystem::GetCollisionGroup() const { assert(false); //only supported in child class ParticlePhysicsSystem return 0; } void hgeParticleSystem::SetCollisionType(unsigned int type) { assert(false); //only supported in child class ParticlePhysicsSystem } void hgeParticleSystem::SetCollisionGroup(unsigned int group) { assert(false); //only supported in child class ParticlePhysicsSystem } libtuxcap-1.4.0/tuxcap/hgeparticle/hgeRandom.cpp0000644000175000017500000000046210736754547021616 0ustar inniyahinniyah/* */ #include "hgeRandom.h" #include "Common.h" namespace HGE { unsigned int g_seed=0; void Random_Seed(int seed) { if(!seed) g_seed=Sexy::Rand(); else g_seed=seed; } float Random_Float(float min, float max) { g_seed=214013*g_seed+2531011; return min+(g_seed>>16)*(1.0f/65535.0f)*(max-min); } } libtuxcap-1.4.0/tuxcap/hgeparticle/hgeparticle.h0000644000175000017500000001537710743475610021646 0ustar inniyahinniyah/* ** Haaf's Game Engine 1.5 ** Copyright (C) 2003-2004, Relish Games ** hge.relishgames.com ** ** hgeParticleSystem helper class header ** ** Hacked on by ** ** Kevin Lynx ** James Poag ** W.P. van Paassen */ #ifndef HGEPARTICLE_H #define HGEPARTICLE_H #include "Graphics.h" #include "Physics.h" #include "Point.h" #include "DDImage.h" #include #include "hgevector.h" #include "hgecolor.h" #include "hgerect.h" using namespace Sexy; namespace HGE { #define MAX_PARTICLES 500 #define MAX_PSYSTEMS 100 #ifndef M_PI #define M_PI 3.14159265358979323846f #define M_PI_2 1.57079632679489661923f #define M_PI_4 0.785398163397448309616f #define M_1_PI 0.318309886183790671538f #define M_2_PI 0.636619772367581343076f #endif struct hgeParticle { hgeVector vecLocation; hgeVector vecVelocity; float fGravity; float fRadialAccel; float fTangentialAccel; float fSpin; float fSpinDelta; float fSize; float fSizeDelta; hgeColor colColor; // + alpha hgeColor colColorDelta; float fAge; float fTerminalAge; PhysicsObject* ph_object; //TODO store the location of the system on creation of the particle, to be used for scaling particlesystems which are moved around //hgeVector vecSpawnLocation; }; struct hgeParticleSystemInfo { //hgeSprite* sprite; // texture + blend mode DDImage *sprite; int nEmission; // particles per sec float fLifetime; float fParticleLifeMin; float fParticleLifeMax; float fDirection; float fSpread; bool bRelative; float fSpeedMin; float fSpeedMax; float fGravityMin; float fGravityMax; float fRadialAccelMin; float fRadialAccelMax; float fTangentialAccelMin; float fTangentialAccelMax; float fSizeStart; float fSizeEnd; float fSizeVar; float fSpinStart; float fSpinEnd; float fSpinVar; hgeColor colColorStart; // + alpha hgeColor colColorEnd; float fColorVar; float fAlphaVar; }; class hgeParticleSystem { public: hgeParticleSystemInfo info; hgeParticleSystem(const char *filename, DDImage *sprite, float fps=0.0f, bool parseMetaData = true, bool old_format=true); hgeParticleSystem(hgeParticleSystemInfo *psi, float fps=0.0f); hgeParticleSystem(const hgeParticleSystem &ps); virtual ~hgeParticleSystem() {} hgeParticleSystem& operator= (const hgeParticleSystem &ps); std::vector mPolygonClipPoints; std::vector mWayPoints; virtual void SaveFile(const char *filename); virtual void Play(int thePlayMode = MAX_PLAYMODES); // Plays the Particle along the waypoint's path virtual void Render( Graphics *g ); virtual void FireAt(float x, float y); virtual void Fire(); virtual void Stop(bool bKillParticles=false); virtual void Update(float fDeltaTime); virtual void MoveTo(float x, float y, bool bMoveParticles=false); virtual void Translate(float x, float y) { fTx=x; fTy=y; } virtual void TrackBoundingBox(bool bTrack) { bUpdateBoundingBox=bTrack; } virtual void SetParticleScale(float scale) { fParticleScale = scale; } virtual float GetParticleScale() const { return fParticleScale; } virtual void SetScale(float scale) { fScale = scale; } virtual float GetScale() const { return fScale; } virtual int GetParticlesAlive() const { return nParticlesAlive; } virtual float GetAge() const { return fAge; } virtual void GetPosition(float *x, float *y) const { *x=vecLocation.x; *y=vecLocation.y; } virtual void GetTranslation(float *x, float *y) const { *x=fTx; *y=fTy; } virtual hgeRect* GetBoundingBox(hgeRect *rect) const; virtual unsigned int GetCollisionType() const; virtual unsigned int GetCollisionGroup() const; virtual void SetCollisionType(unsigned int type); virtual void SetCollisionGroup(unsigned int group); /* whether addtive blend */ bool mbAdditiveBlend; // Texture file to load std::string mTextureName; // ANimation state variables int mPlayMode; float mPlayTime; float mPlayTimer; float mPlayTimerStepSize; bool mAnimPlaying; int mPlayMarker; int mPingPong; bool bInitOK; enum{PING, PONG}; enum{STOPPED = -1, PLAY_ONCE, PLAY_LOOPED, PLAY_PINGPONGED, MAX_PLAYMODES}; protected: hgeParticleSystem(); virtual void _update(float fDeltaTime); virtual void _updatePlay(float fDeltaTime); float fScale; //scales the particle system float fParticleScale; float fUpdSpeed; float fResidue; float fAge; float fEmissionResidue; hgeVector vecPrevLocation; hgeVector vecLocation; float fTx, fTy; int nParticlesAlive; hgeRect rectBoundingBox; bool bUpdateBoundingBox; hgeParticle particles[MAX_PARTICLES]; protected: static bool m_bInitRandom; bool bOldFormat; virtual void InitRandom(); virtual void ParseMetaData(FILE* aFile); virtual void SaveMetaData(FILE* aFile); virtual bool wn_PnPoly(Sexy::Point theTestPoint); virtual bool cn_PnPoly(Sexy::Point theTestPoint); public: // METADATA Tags Enumeration // When adding File attributes, add to the END of this list. enum{ADDITIVE = 0, POSITION = 1, TEXTURE_PATH = 2, POLYGON_POINTS = 3, WAY_POINTS = 4, ANIMATION_DATA= 5}; }; class hgeParticleManager { public: hgeParticleManager(float fps=0.0f); virtual ~hgeParticleManager(); virtual void Update(float dt); virtual void Render( Graphics *g ); hgeParticleSystem* SpawnPS(const char *filename, DDImage *sprite, float x, float y, bool parseMetaData = true, bool old_format=true, Physics* physics = NULL); hgeParticleSystem* SpawnPS(hgeParticleSystemInfo *psi, float x, float y, Physics* physics = NULL); hgeParticleSystem* SpawnPS(hgeParticleSystem *system, float x, float y, Physics* physics = NULL); virtual bool IsPSAlive(hgeParticleSystem *ps) const; virtual void Translate(float x, float y); virtual void GetTranslation(float *dx, float *dy) const {*dx=tX; *dy=tY;} virtual void KillPS(hgeParticleSystem *ps); virtual void KillAll(); virtual void SetEmissions(int theRate); virtual void SetFPS(float fps) { fFPS = fps; } virtual float GetFPS() { return fFPS; } protected: hgeParticleManager(const hgeParticleManager &); hgeParticleManager& operator= (const hgeParticleManager &); float fFPS; int nPS; float tX; float tY; hgeParticleSystem* psList[MAX_PSYSTEMS]; }; } #endif libtuxcap-1.4.0/tuxcap/CMakeMacros/0000755000175000017500000000000011212652053017015 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/CMakeMacros/IJMacros.txt0000644000175000017500000001137410641010445021231 0ustar inniyahinniyah#Macro to find a package and load it #(you shouldn't need to modify this code) MACRO(LOADPACKAGE Package) SET(Included FALSE) IF(EXISTS "/home/tester/XMLTestParser.py") #If we're in the test environment, check and see if we're being asked for #a specific version of some package. If so, we'll provide a direct path #instead of counting on CMake to choose the right version. IF(${Package} MATCHES "^ITK.*3[.]2[.]0$") SET(ITK_DIR "/home/tester/ITK3.2.0/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(${Package} MATCHES "^ITK.*3[.]2[.]0$") IF(${Package} MATCHES "^ITK.*2[.]8[.]1$") SET(ITK_DIR "/home/tester/ITK2.8.1/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(${Package} MATCHES "^ITK.*2[.]8[.]1$") IF(${Package} MATCHES "^ITK.*2[.]4[.]1$") SET(ITK_DIR "/home/tester/ITK-2-4-1/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(${Package} MATCHES "^ITK.*2[.]4[.]1$") IF(${Package} MATCHES "^ITK.*2[.]2[.]1$") SET(ITK_DIR "/home/tester/ITK2.2.1/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(${Package} MATCHES "^ITK.*2[.]2[.]1$") IF(NOT Included AND ${Package} MATCHES "^ITK.*1[.]8[.]1$") SET(ITK_DIR "/home/tester/ITK1.8.1/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "^ITK.*1[.]8[.]1$") IF(NOT Included AND ${Package} MATCHES "^VTK.*4[.]4$") SET(VTK_DIR "/home/tester/VTK4.4/bin") INCLUDE("/usr/local/share/CMake/Modules/FindVTK.cmake") INCLUDE(${VTK_USE_FILE}) SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "^VTK.*4[.]4$") IF(NOT Included AND ${Package} MATCHES "^VTK.*5[.]0$") SET(VTK_DIR "/home/tester/VTK5.0/bin") INCLUDE("/usr/local/share/CMake/Modules/FindVTK.cmake") INCLUDE(${VTK_USE_FILE}) SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "^VTK.*5[.]0$") IF(NOT Included AND ${Package} MATCHES "KWWidgets") SET(KWWidgets_DIR "/home/tester/KWWidgets/bin") SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "KWWidgets") #If we get this far and we still haven't found a match, set it up so the #tester will by default use the most current version of the toolkit IF(NOT Included AND ${Package} MATCHES "^VTK") SET(VTK_DIR "/home/tester/VTK5.0/bin") INCLUDE("/usr/local/share/CMake/Modules/FindVTK.cmake") INCLUDE(${VTK_USE_FILE}) SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "^VTK") IF(NOT Included AND ${Package} MATCHES "^ITK") SET(ITK_DIR "/home/tester/ITK2.8.1/bin") INCLUDE("/usr/local/share/CMake/Modules/FindITK.cmake") INCLUDE(${ITK_USE_FILE}) SET(Included TRUE) ENDIF(NOT Included AND ${Package} MATCHES "^ITK") #if we're not in the testing environment, and a specific version is being #specified, reset the variable to just be the name of the package ELSE(EXISTS "/home/tester/XMLTestParser.py") IF(${Package} MATCHES "^ITK[0-9]") SET(Package "ITK") ENDIF(${Package} MATCHES "^ITK[0-9]") IF(${Package} MATCHES "^VTK[0-9]") SET(Package "VTK") ENDIF(${Package} MATCHES "^VTK[0-9]") ENDIF(EXISTS "/home/tester/XMLTestParser.py") #no point in executing the code below if we already found the package we're #looking for. IF(NOT Included) FIND_PACKAGE(${Package}) IF(${Package}_FOUND) #most packages define a Package_INCLUDE_DIR variable, so we'll check for #that first IF(${Package}_INCLUDE_DIR) INCLUDE(${${Package}_INCLUDE_DIR}) SET(Included TRUE) ELSE(${Package}_INCLUDE_DIR) #VTK and ITK prefer to define a Package_USE_FILE, so we need to look for #that too IF(${Package}_USE_FILE) INCLUDE(${${Package}_USE_FILE}) SET(Included TRUE) ENDIF(${Package}_USE_FILE) ENDIF(${Package}_INCLUDE_DIR) #then there's some other pesky packages that don't like to define standard #variables at all. If you're trying to include one of those you might have #to do a little bit of investigating on your own. IF(NOT Included) MESSAGE(FATAL_ERROR "${Package} was found, but couldn't be included.\n Try including it manually out of the FOREACH in the CMakeLists file.\n Look at Find${Package}.cmake in the CMake module directory for clues on what you're supposed to include. Good luck.") ENDIF(NOT Included) ENDIF(${Package}_FOUND) ENDIF(NOT Included) ENDMACRO(LOADPACKAGE) libtuxcap-1.4.0/tuxcap/physicsdemo5/0000755000175000017500000000000011212652053017304 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo5/GameApp.cpp0000644000175000017500000001207311062533667021341 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo5"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo5/CMakeLists.txt0000644000175000017500000000402210762446645022063 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo5") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo5/Board.h0000644000175000017500000001346510667046273020533 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo5/GameApp.h0000644000175000017500000000612110667046273021005 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo5/main.cpp0000644000175000017500000000022710667046273020753 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo5/Board.cpp0000644000175000017500000002173510667046273021065 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); InitDemo(); } void Board::InitDemo() { physics->SetSteps(2); physics->SetIterations(20); physics->ResizeStaticHash(40.0f, 99); physics->ResizeActiveHash(40.0f, 2999); physics->SetGravity(SexyVector2(0,300)); int num = 4; SexyVector2 verts[] = { SexyVector2(-3,-20), SexyVector2(-3, 20), SexyVector2( 3, 20), SexyVector2( 3,-20) }; PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(-200,480), SexyVector2(840, 480), 0.0f,1.0f,1.0f); float u = 0.6; int n = 9; int i, j; for(i=1; i<=n; i++){ SexyVector2 offset = SexyVector2(320 + -i*60/2.0f, i*52); for(j=0; jCreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,u); obj->SetPosition(SexyVector2(j*60, -8) + offset); obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,u); obj->SetPosition(SexyVector2(j*60,15) + offset); obj->SetAngle(M_PI/2.0f); if(j == (i - 1)) continue; obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,u); obj->SetPosition(SexyVector2(j*60 + 30,21) + offset); obj->SetAngle(M_PI/2.0f); } obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,u); obj->SetPosition(SexyVector2(-17, 48) + offset); obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,u); obj->SetPosition(SexyVector2((i - 1) * 60 + 17, 48) + offset); } obj->SetAngularVelocity(-1); obj->SetVelocity(SexyVector2(20,0)); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete physics; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) physics->Draw(g); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i); SexyVector2 endpos = object->GetVertex(i + 1); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1); SexyVector2 endpos = object->GetVertex(0); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); SexyVector2 pos = object->GetPosition(); g->DrawLine((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { physics->Clear(); physics->Init(); InitDemo(); } } libtuxcap-1.4.0/tuxcap/particledemo/0000755000175000017500000000000011212652053017340 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/particledemo/GameApp.cpp0000644000175000017500000001136111062533667021374 0ustar inniyahinniyah/* W.P. van Paassen 2008 */ #include "GameApp.h" #include "Board.h" #include "WidgetManager.h" #include "Common.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "ParticleDemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\ParticleDemo"; // Set the application width/height in terms of pixels here. mWidth = 640; mHeight = 480; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // In later demos, you will see more done with this function. // For now, we have nothing else to initialize, so we are done. // Once complete, the LoadingThreadProc function will automatically // start and we will begin loading all our needed resources. //gSexyAppBase->SwitchScreenMode(true, true); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // In this particular demo, there are no resources that we // need to load. In every game and in all subsequent demos, however, // there will be things we need to load. Besides loading data, // this thread can also update the progress indicator for the loading // screen, which you will see in later demos. // Once complete, the LoadingThreadCompleted function will be called. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 640x480. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); //Setting focus to be able to receive mouse and keyboard events mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/particledemo/CMakeLists.txt0000644000175000017500000000371510762446645022127 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../particle_demo") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/particledemo/Board.h0000644000175000017500000001053510760515321020547 0ustar inniyahinniyah/* W.P. van Paassen 2008 */ #ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "ParticlePhysicsSystem.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; class Physics; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; hgeParticleManager* pmanager; hgeParticleSystem* explosion; public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); virtual void KeyDown(KeyCode theKey); //functions from PhysicsListener virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); virtual bool HandleTypedCollision(CollisionObject* col); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/particledemo/GameApp.h0000644000175000017500000000615510736754547021057 0ustar inniyahinniyah/* W.P. van Paassen 2008 */ #ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/particledemo/main.cpp0000644000175000017500000000022710736754550021010 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/particledemo/Board.cpp0000644000175000017500000002357510760515321021112 0ustar inniyahinniyah/* W.P. van Paassen 2008 */ #include "Board.h" #include "Graphics.h" #include "DDImage.h" #include "SexyAppBase.h" #include "Color.h" #include "Physics.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->Init(); physics->SetPhysicsListener(this); physics->SetSteps(2); physics->ResizeStaticHash(50.0f,100); physics->ResizeActiveHash(5.0f,2000); //left vulcano slope PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(300,240), SexyVector2(0,480 ), 0.6f,0.6f,1.0f); obj->SetCollisionType(2); //right vulcano slope obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(340,240), SexyVector2(640, 480), 0.6f,0.6f,1.0f); obj->SetCollisionType(2); //left wall obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(60,0), SexyVector2(60, 480), 0.9f,0.6f,1.0f); obj->SetCollisionType(2); //right wall obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(580,0), SexyVector2(580, 480), 0.9f,0.6f,1.0f); obj->SetCollisionType(2); //left platform obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(290,400), SexyVector2(300, 400), 0.0f,0.0f,1.0f); obj->SetCollisionType(3); //right platform obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(340,400), SexyVector2(350, 400), 0.0f,0.0f,1.0f); obj->SetCollisionType(3); DDImage* sprite = (DDImage*) gSexyAppBase->GetImage("images/particle.png"); pmanager = new hgeParticleManager(); //creating the lava particle system with physics enabled hgeParticleSystem* p = pmanager->SpawnPS("images/particle10.psi", sprite, 320,240, false, false, physics); p->SetCollisionType(4); //This id is used to set the type of the particlesystem which can be used to register collisions between objects of the physics engine, see the //example below in which collisions between the lava particles and the platforms are registered and handled in HandleTypedCollision //p->SetCollisionGroup(1); //this assigns all particles in this particle system to the same group, meaning they do not collide with each other and with other //particle systems with the same group id. To make the particles in a particlesystem collide with each other, set this to 0 //p->SetScale(2.0f); ///same particle system but no physics //gSexyAppBase->mParticleManager->SpawnPS("images/particle10.psi", sprite, 320,240, false, false); //alternatives to create a particle system, use this if you're gonna reuse the same particlesystem to avoid loading it. //the pro of declaring a hgeParticleSystem is that you can use the system to spawn both physics enabled and physics disabled particle systems from it //hgeParticleSystem* system = new hgeParticleSystem("images/particle10.psi",sprite, 0.0f, false, false); //creates a particle system without physics //gSexyAppBase->mParticleManager->SpawnPS(system, 320,400); //creates a particle system with physics //gSexyAppBase->mParticleManager->SpawnPS(system, 320,400, physics); //it is also possible to use the ParticlePhysicsSystem class directly but you can only spawn physics enabled particle systems from it //ParticlePhysicsSystem* p_system = new ParticlePhysicsSystem("images/particle10.psi",sprite, physics, 0.0f, false, false); //creates a particle system with physics //gSexyAppBase->mParticleManager->SpawnPS(p_system, 320,400); //creates a particle system with physics //gSexyAppBase->mParticleManager->SpawnPS(p_system, 320,400, physics); //explosion system which is used to spawn a new particle system from, this is done whenever the lava hits the platforms, see the HandleTypedCollision function. //this system does not have physics enabled explosion= new hgeParticleSystem("images/particle6.psi",sprite, 0.0f, false, false); explosion->SetParticleScale(2.0f);//scales the particles in the explosion particle system explosion->SetScale(2.0f);//scales the explosion particle system itself //register collisions between lava and platforms, to be handled inHandleTypedCollision physics->RegisterCollisionType(p->GetCollisionType(), 3); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { physics->UnregisterCollisionType(4,3); delete pmanager; delete physics; delete explosion; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); pmanager->Update(0.01f); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // And now for the good stuff! The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by drawing some geometric primitives. By // default, the drawing color is black. We will change it later // on. The first command clears the screen by drawing a // black rectangle (black due to the default color) that is // located at coordinate 0, 0 and is the same size as our // Board widget, which is the same size as the application and // thus is the same size of the game window. g->FillRect(0, 0, mWidth, mHeight); physics->Draw(g); pmanager->Render(g); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_ESCAPE) { gSexyAppBase->Shutdown(); } } //draws the lines of the slopes, walls and platforms void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); SexyVector2 pos = object->GetPosition(); if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } } /* watch it!, this is being called for every step in which a collision occurres, so in case of physics->SetSteps(3) it might get called 3 times in every Board->Update(). */ bool Board::HandleTypedCollision(CollisionObject* col){ /* Watch it! col->points and col are invalid when this function exits, so if you want to store its data, copy it! col->object1 and col->object2 are not invalidated upon return */ /* collision between platform and lava */ SexyVector2 p = col->points[0].point; pmanager->SpawnPS(explosion, p.x,p.y); /*return true to make the collision happen, return false to cancel the collision*/ return true; } libtuxcap-1.4.0/tuxcap/pythondemo_template/0000755000175000017500000000000011212652053020751 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/pythondemo_template/CMakeLists.txt0000644000175000017500000000411410762446645023532 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${PYTHON_INCLUDE_PATH} ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle ${libtuxcap_SOURCE_DIR}/tuxcap/pycap ) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../pythondemo_template/Pythondemo_template") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/pythondemo_template/main.cpp0000644000175000017500000000032411062277514022410 0ustar inniyahinniyah#include "PycapApp.h" using namespace Sexy; int main(int argc, char** argv) { PycapApp app; SetAppResourceFolder("../images"); app.Init(argc,argv, false); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/chipmunk/0000755000175000017500000000000011212652053016506 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/chipmunk/cpBB.c0000644000175000017500000000317610670737717017511 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include "chipmunk.h" cpVect cpBBClampVect(const cpBB bb, const cpVect v) { cpFloat x = cpfmin(cpfmax(bb.l, v.x), bb.r); cpFloat y = cpfmin(cpfmax(bb.b, v.y), bb.t); return cpv(x, y); } cpVect cpBBWrapVect(const cpBB bb, const cpVect v) { cpFloat ix = fabsf(bb.r - bb.l); cpFloat modx = fmodf(v.x - bb.l, ix); cpFloat x = (modx > 0.0f) ? modx : modx + ix; cpFloat iy = fabsf(bb.t - bb.b); cpFloat mody = fmodf(v.y - bb.b, iy); cpFloat y = (mody > 0.0f) ? mody : mody + iy; return cpv(x + bb.l, y + bb.b); } libtuxcap-1.4.0/tuxcap/chipmunk/cpJoint.h0000644000175000017500000000627410672744075020315 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // TODO: Comment me! extern cpFloat cp_joint_bias_coef; // Enumeration of joint types. typedef enum cpJointType{ CP_PIN_JOINT, CP_SLIDE_JOINT, CP_PIVOT_JOINT, CP_GROOVE_JOINT, CP_NUM_JOINTS } cpJointType; typedef struct cpJoint { cpJointType type; cpBody *a, *b; void (*preStep)(struct cpJoint *joint, cpFloat dt_inv); void (*applyImpulse)(struct cpJoint *joint); } cpJoint; void cpJointDestroy(cpJoint *joint); void cpJointFree(cpJoint *joint); typedef struct cpPinJoint { cpJoint joint; cpVect anchr1, anchr2; cpFloat dist; cpVect r1, r2; cpVect n; cpFloat nMass; cpFloat jnAcc, jBias; cpFloat bias; } cpPinJoint; cpPinJoint *cpPinJointAlloc(void); cpPinJoint *cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); cpJoint *cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2); typedef struct cpSlideJoint { cpJoint joint; cpVect anchr1, anchr2; cpFloat min, max; cpVect r1, r2; cpVect n; cpFloat nMass; cpFloat jnAcc, jBias; cpFloat bias; } cpSlideJoint; cpSlideJoint *cpSlideJointAlloc(void); cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); cpJoint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max); typedef struct cpPivotJoint { cpJoint joint; cpVect anchr1, anchr2; cpVect r1, r2; cpVect k1, k2; cpVect jAcc, jBias; cpVect bias; } cpPivotJoint; cpPivotJoint *cpPivotJointAlloc(void); cpPivotJoint *cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect pivot); cpJoint *cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot); typedef struct cpGrooveJoint { cpJoint joint; cpVect grv_n, grv_a, grv_b; cpVect anchr2; cpVect grv_tn; cpFloat clamp; cpVect r1, r2; cpVect k1, k2; cpVect jAcc, jBias; cpVect bias; } cpGrooveJoint; cpGrooveJoint *cpGrooveJointAlloc(void); cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); cpJoint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2); libtuxcap-1.4.0/tuxcap/chipmunk/cpVect.c0000644000175000017500000000315310673525350020111 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "stdio.h" #include "math.h" #include "chipmunk.h" cpFloat cpvlength(const cpVect v) { return sqrtf( cpvdot(v, v) ); } cpFloat cpvlengthsq(const cpVect v) { return cpvdot(v, v); } cpVect cpvnormalize(const cpVect v) { return cpvmult( v, 1.0f/cpvlength(v) ); } cpVect cpvforangle(const cpFloat a) { return cpv(cos(a), sin(a)); } cpFloat cpvtoangle(const cpVect v) { return atan2(v.y, v.x); } char* cpvstr(const cpVect v) { static char str[256]; sprintf(str, "(% .3f, % .3f)", v.x, v.y); return str; } libtuxcap-1.4.0/tuxcap/chipmunk/cpJoint.c0000644000175000017500000003377110672744075020312 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "chipmunk.h" // TODO: Comment me! cpFloat cp_joint_bias_coef = 0.1f; void cpJointDestroy(cpJoint *joint){} void cpJointFree(cpJoint *joint) { if(joint) cpJointDestroy(joint); free(joint); } static void pinJointPreStep(cpJoint *joint, cpFloat dt_inv) { cpBody *a = joint->a; cpBody *b = joint->b; cpPinJoint *jnt = (cpPinJoint *)joint; cpFloat mass_sum = a->m_inv + b->m_inv; jnt->r1 = cpvrotate(jnt->anchr1, a->rot); jnt->r2 = cpvrotate(jnt->anchr2, b->rot); cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1)); cpFloat dist = cpvlength(delta); jnt->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY)); // calculate mass normal cpFloat r1cn = cpvcross(jnt->r1, jnt->n); cpFloat r2cn = cpvcross(jnt->r2, jnt->n); cpFloat kn = mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn; jnt->nMass = 1.0f/kn; // calculate bias velocity jnt->bias = -cp_joint_bias_coef*dt_inv*(dist - jnt->dist); jnt->jBias = 0.0f; // apply accumulated impulse cpVect j = cpvmult(jnt->n, jnt->jnAcc); cpBodyApplyImpulse(a, cpvneg(j), jnt->r1); cpBodyApplyImpulse(b, j, jnt->r2); } static void pinJointApplyImpulse(cpJoint *joint) { cpBody *a = joint->a; cpBody *b = joint->b; cpPinJoint *jnt = (cpPinJoint *)joint; cpVect n = jnt->n; cpVect r1 = jnt->r1; cpVect r2 = jnt->r2; //calculate bias impulse cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n); cpFloat jbn = (jnt->bias - vbn)*jnt->nMass; jnt->jBias += jbn; cpVect jb = cpvmult(n, jbn); cpBodyApplyBiasImpulse(a, cpvneg(jb), r1); cpBodyApplyBiasImpulse(b, jb, r2); // compute relative velocity cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); cpFloat vrn = cpvdot(cpvsub(v2, v1), n); // compute normal impulse cpFloat jn = -vrn*jnt->nMass; jnt->jnAcc =+ jn; // apply impulse cpVect j = cpvmult(n, jn); cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } cpPinJoint * cpPinJointAlloc(void) { return (cpPinJoint *)malloc(sizeof(cpPinJoint)); } cpPinJoint * cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) { joint->joint.preStep = &pinJointPreStep; joint->joint.applyImpulse = &pinJointApplyImpulse; joint->joint.a = a; joint->joint.b = b; ((cpJoint*)joint)->type = CP_PIN_JOINT; joint->anchr1 = anchr1; joint->anchr2 = anchr2; cpVect p1 = cpvadd(a->p, cpvrotate(anchr1, a->rot)); cpVect p2 = cpvadd(b->p, cpvrotate(anchr2, b->rot)); joint->dist = cpvlength(cpvsub(p2, p1)); joint->jnAcc = 0.0; return joint; } cpJoint * cpPinJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2) { return (cpJoint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchr1, anchr2); } static void SlideJointPreStep(cpJoint *joint, cpFloat dt_inv) { cpBody *a = joint->a; cpBody *b = joint->b; cpSlideJoint *jnt = (cpSlideJoint *)joint; cpFloat mass_sum = a->m_inv + b->m_inv; jnt->r1 = cpvrotate(jnt->anchr1, a->rot); jnt->r2 = cpvrotate(jnt->anchr2, b->rot); cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1)); cpFloat dist = cpvlength(delta); cpFloat pdist = 0.0; if(dist > jnt->max) { pdist = dist - jnt->max; } else if(dist < jnt->min) { pdist = jnt->min - dist; dist = -dist; } jnt->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY)); // calculate mass normal cpFloat r1cn = cpvcross(jnt->r1, jnt->n); cpFloat r2cn = cpvcross(jnt->r2, jnt->n); cpFloat kn = mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn; jnt->nMass = 1.0f/kn; // calculate bias velocity jnt->bias = -cp_joint_bias_coef*dt_inv*(pdist); jnt->jBias = 0.0f; // apply accumulated impulse if(!jnt->bias) jnt->jnAcc = 0.0f; cpVect j = cpvmult(jnt->n, jnt->jnAcc); cpBodyApplyImpulse(a, cpvneg(j), jnt->r1); cpBodyApplyImpulse(b, j, jnt->r2); } static void SlideJointApplyImpulse(cpJoint *joint) { cpSlideJoint *jnt = (cpSlideJoint *)joint; if(!jnt->bias) return; cpBody *a = joint->a; cpBody *b = joint->b; cpVect n = jnt->n; cpVect r1 = jnt->r1; cpVect r2 = jnt->r2; //calculate bias impulse cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n); cpFloat jbn = (jnt->bias - vbn)*jnt->nMass; cpFloat jbnOld = jnt->jBias; jnt->jBias = cpfmin(jbnOld + jbn, 0.0f); jbn = jnt->jBias - jbnOld; cpVect jb = cpvmult(n, jbn); cpBodyApplyBiasImpulse(a, cpvneg(jb), r1); cpBodyApplyBiasImpulse(b, jb, r2); // compute relative velocity cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); cpFloat vrn = cpvdot(cpvsub(v2, v1), n); // compute normal impulse cpFloat jn = -vrn*jnt->nMass; cpFloat jnOld = jnt->jnAcc; jnt->jnAcc = cpfmin(jnOld + jn, 0.0f); jn = jnt->jnAcc - jnOld; // apply impulse cpVect j = cpvmult(n, jn); cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } cpSlideJoint * cpSlideJointAlloc(void) { return (cpSlideJoint *)malloc(sizeof(cpSlideJoint)); } cpSlideJoint * cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max) { joint->joint.preStep = &SlideJointPreStep; joint->joint.applyImpulse = &SlideJointApplyImpulse; joint->joint.a = a; joint->joint.b = b; ((cpJoint*)joint)->type = CP_SLIDE_JOINT; joint->anchr1 = anchr1; joint->anchr2 = anchr2; joint->min = min; joint->max = max; joint->jnAcc = 0.0; return joint; } cpJoint * cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max) { return (cpJoint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max); } static void pivotJointPreStep(cpJoint *joint, cpFloat dt_inv) { cpBody *a = joint->a; cpBody *b = joint->b; cpPivotJoint *jnt = (cpPivotJoint *)joint; jnt->r1 = cpvrotate(jnt->anchr1, a->rot); jnt->r2 = cpvrotate(jnt->anchr2, b->rot); // calculate mass matrix // If I wasn't lazy, this wouldn't be so gross... cpFloat k11, k12, k21, k22; cpFloat m_sum = a->m_inv + b->m_inv; k11 = m_sum; k12 = 0.0f; k21 = 0.0f; k22 = m_sum; cpFloat r1xsq = jnt->r1.x * jnt->r1.x * a->i_inv; cpFloat r1ysq = jnt->r1.y * jnt->r1.y * a->i_inv; cpFloat r1nxy = -jnt->r1.x * jnt->r1.y * a->i_inv; k11 += r1ysq; k12 += r1nxy; k21 += r1nxy; k22 += r1xsq; cpFloat r2xsq = jnt->r2.x * jnt->r2.x * b->i_inv; cpFloat r2ysq = jnt->r2.y * jnt->r2.y * b->i_inv; cpFloat r2nxy = -jnt->r2.x * jnt->r2.y * b->i_inv; k11 += r2ysq; k12 += r2nxy; k21 += r2nxy; k22 += r2xsq; cpFloat det_inv = 1.0f/(k11*k22 - k12*k21); jnt->k1 = cpv( k22*det_inv, -k12*det_inv); jnt->k2 = cpv(-k21*det_inv, k11*det_inv); // calculate bias velocity cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1)); jnt->bias = cpvmult(delta, -cp_joint_bias_coef*dt_inv); jnt->jBias = cpvzero; // apply accumulated impulse cpBodyApplyImpulse(a, cpvneg(jnt->jAcc), jnt->r1); cpBodyApplyImpulse(b, jnt->jAcc, jnt->r2); } static void pivotJointApplyImpulse(cpJoint *joint) { cpBody *a = joint->a; cpBody *b = joint->b; cpPivotJoint *jnt = (cpPivotJoint *)joint; cpVect r1 = jnt->r1; cpVect r2 = jnt->r2; cpVect k1 = jnt->k1; cpVect k2 = jnt->k2; //calculate bias impulse cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); cpVect vbr = cpvsub(jnt->bias, cpvsub(vb2, vb1)); cpVect jb = cpv(cpvdot(vbr, k1), cpvdot(vbr, k2)); jnt->jBias = cpvadd(jnt->jBias, jb); cpBodyApplyBiasImpulse(a, cpvneg(jb), r1); cpBodyApplyBiasImpulse(b, jb, r2); // compute relative velocity cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); cpVect vr = cpvsub(v2, v1); // compute normal impulse cpVect j = cpv(-cpvdot(vr, k1), -cpvdot(vr, k2)); jnt->jAcc = cpvadd(jnt->jAcc, j); // apply impulse cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } cpPivotJoint * cpPivotJointAlloc(void) { return (cpPivotJoint *)malloc(sizeof(cpPivotJoint)); } cpPivotJoint * cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect pivot) { joint->joint.preStep = &pivotJointPreStep; joint->joint.applyImpulse = &pivotJointApplyImpulse; joint->joint.a = a; joint->joint.b = b; ((cpJoint*)joint)->type = CP_PIVOT_JOINT; joint->anchr1 = cpvunrotate(cpvsub(pivot, a->p), a->rot); joint->anchr2 = cpvunrotate(cpvsub(pivot, b->p), b->rot); joint->jAcc = cpvzero; return joint; } cpJoint * cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot) { return (cpJoint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, pivot); } static void grooveJointPreStep(cpJoint *joint, cpFloat dt_inv) { cpBody *a = joint->a; cpBody *b = joint->b; cpGrooveJoint *jnt = (cpGrooveJoint *)joint; // calculate endpoints in worldspace cpVect ta = cpBodyLocal2World(a, jnt->grv_a); cpVect tb = cpBodyLocal2World(a, jnt->grv_b); // calculate axis cpVect n = cpvrotate(jnt->grv_n, a->rot); cpFloat d = cpvdot(ta, n); jnt->grv_tn = n; jnt->r2 = cpvrotate(jnt->anchr2, b->rot); // calculate tangential distance along the axis of r2 cpFloat td = cpvcross(cpvadd(b->p, jnt->r2), n); // calculate clamping factor and r2 if(td < cpvcross(ta, n)){ jnt->clamp = 1.0f; jnt->r1 = cpvsub(ta, a->p); } else if(td > cpvcross(tb, n)){ jnt->clamp = -1.0f; jnt->r1 = cpvsub(tb, a->p); } else { jnt->clamp = 0.0f; jnt->r1 = cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)); } // calculate mass matrix // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross... cpFloat k11, k12, k21, k22; cpFloat m_sum = a->m_inv + b->m_inv; // start with I*m_sum k11 = m_sum; k12 = 0.0f; k21 = 0.0f; k22 = m_sum; // add the influence from r1 cpFloat r1xsq = jnt->r1.x * jnt->r1.x * a->i_inv; cpFloat r1ysq = jnt->r1.y * jnt->r1.y * a->i_inv; cpFloat r1nxy = -jnt->r1.x * jnt->r1.y * a->i_inv; k11 += r1ysq; k12 += r1nxy; k21 += r1nxy; k22 += r1xsq; // add the influnce from r2 cpFloat r2xsq = jnt->r2.x * jnt->r2.x * b->i_inv; cpFloat r2ysq = jnt->r2.y * jnt->r2.y * b->i_inv; cpFloat r2nxy = -jnt->r2.x * jnt->r2.y * b->i_inv; k11 += r2ysq; k12 += r2nxy; k21 += r2nxy; k22 += r2xsq; // invert cpFloat det_inv = 1.0f/(k11*k22 - k12*k21); jnt->k1 = cpv( k22*det_inv, -k12*det_inv); jnt->k2 = cpv(-k21*det_inv, k11*det_inv); // calculate bias velocity cpVect delta = cpvsub(cpvadd(b->p, jnt->r2), cpvadd(a->p, jnt->r1)); jnt->bias = cpvmult(delta, -cp_joint_bias_coef*dt_inv); jnt->jBias = cpvzero; // apply accumulated impulse cpBodyApplyImpulse(a, cpvneg(jnt->jAcc), jnt->r1); cpBodyApplyImpulse(b, jnt->jAcc, jnt->r2); } static inline cpVect grooveConstrain(cpGrooveJoint *jnt, cpVect j){ cpVect n = jnt->grv_tn; cpVect jn = cpvmult(n, cpvdot(j, n)); cpVect t = cpvperp(n); cpFloat coef = (jnt->clamp*cpvcross(j, n) > 0.0f) ? 1.0f : 0.0f; cpVect jt = cpvmult(t, cpvdot(j, t)*coef); return cpvadd(jn, jt); } static void grooveJointApplyImpulse(cpJoint *joint) { cpBody *a = joint->a; cpBody *b = joint->b; cpGrooveJoint *jnt = (cpGrooveJoint *)joint; cpVect r1 = jnt->r1; cpVect r2 = jnt->r2; cpVect k1 = jnt->k1; cpVect k2 = jnt->k2; //calculate bias impulse cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); cpVect vbr = cpvsub(jnt->bias, cpvsub(vb2, vb1)); cpVect jb = cpv(cpvdot(vbr, k1), cpvdot(vbr, k2)); cpVect jbOld = jnt->jBias; jnt->jBias = grooveConstrain(jnt, cpvadd(jbOld, jb)); jb = cpvsub(jnt->jBias, jbOld); cpBodyApplyBiasImpulse(a, cpvneg(jb), r1); cpBodyApplyBiasImpulse(b, jb, r2); // compute relative velocity cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); cpVect vr = cpvsub(v2, v1); // compute impulse cpVect j = cpv(-cpvdot(vr, k1), -cpvdot(vr, k2)); cpVect jOld = jnt->jAcc; jnt->jAcc = grooveConstrain(jnt, cpvadd(jOld, j)); j = cpvsub(jnt->jAcc, jOld); // apply impulse cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } cpGrooveJoint * cpGrooveJointAlloc(void) { return (cpGrooveJoint *)malloc(sizeof(cpGrooveJoint)); } cpGrooveJoint * cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2) { joint->joint.preStep = &grooveJointPreStep; joint->joint.applyImpulse = &grooveJointApplyImpulse; joint->joint.a = a; joint->joint.b = b; ((cpJoint*)joint)->type = CP_GROOVE_JOINT; joint->grv_a = groove_a; joint->grv_b = groove_b; joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a))); joint->anchr2 = anchr2; joint->jAcc = cpvzero; return joint; } cpJoint * cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2) { return (cpJoint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2); } libtuxcap-1.4.0/tuxcap/chipmunk/cpHashSet.h0000644000175000017500000000645510670737717020575 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // cpHashSet uses a chained hashtable implementation. // Other than the transformation functions, there is nothing fancy going on. // cpHashSetBin's form the linked lists in the chained hash table. typedef struct cpHashSetBin { // Pointer to the element. void *elt; // Hash value of the element. unsigned int hash; // Next element in the chain. struct cpHashSetBin *next; } cpHashSetBin; // Equality function. Returns true if ptr is equal to elt. typedef int (*cpHashSetEqlFunc)(void *ptr, void *elt); // Used by cpHashSetInsert(). Called to transform the ptr into an element. typedef void *(*cpHashSetTransFunc)(void *ptr, void *data); // Iterator function for a hashset. typedef void (*cpHashSetIterFunc)(void *elt, void *data); // Reject function. Returns true if elt should be dropped. typedef int (*cpHashSetRejectFunc)(void *elt, void *data); typedef struct cpHashSet { // Number of elements stored in the table. int entries; // Number of cells in the table. int size; cpHashSetEqlFunc eql; cpHashSetTransFunc trans; // Default value returned by cpHashSetFind() when no element is found. // Defaults to NULL. void *default_value; cpHashSetBin **table; } cpHashSet; // Basic allocation/destruction functions. void cpHashSetDestroy(cpHashSet *set); void cpHashSetFree(cpHashSet *set); cpHashSet *cpHashSetAlloc(void); cpHashSet *cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans); cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans); // Insert an element into the set, returns the element. // If it doesn't already exist, the transformation function is applied. void *cpHashSetInsert(cpHashSet *set, unsigned int hash, void *ptr, void *data); // Remove and return an element from the set. void *cpHashSetRemove(cpHashSet *set, unsigned int hash, void *ptr); // Find an element in the set. Returns the default value if the element isn't found. void *cpHashSetFind(cpHashSet *set, unsigned int hash, void *ptr); // Iterate over a hashset. void cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data); // Iterate over a hashset while rejecting certain elements. void cpHashSetReject(cpHashSet *set, cpHashSetRejectFunc func, void *data); libtuxcap-1.4.0/tuxcap/chipmunk/chipmunk.h0000644000175000017500000000433011212031546020473 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #ifdef __cplusplus extern "C" { #endif typedef float cpFloat; static inline cpFloat cpfmax(cpFloat a, cpFloat b) { return (a > b) ? a : b; } static inline cpFloat cpfmin(cpFloat a, cpFloat b) { return (a < b) ? a : b; } #ifndef INFINITY #ifdef _WIN32 union MSVC_EVIL_FLOAT_HACK { unsigned __int8 Bytes[4]; float Value; }; static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; #define INFINITY (INFINITY_HACK.Value) #else #define INFINITY (1e1000) #endif #endif #include #include "cpVect.h" #include "cpBB.h" #include "cpBody.h" #include "cpArray.h" #include "cpHashSet.h" #include "cpSpaceHash.h" #include "cpShape.h" #include "cpPolyShape.h" #include "cpArbiter.h" #include "cpCollision.h" #include "cpJoint.h" #include "cpSpace.h" #define CP_HASH_COEF (3344921057ul) #define CP_HASH_PAIR(A, B) ((uintptr_t)(A)*CP_HASH_COEF ^ (uintptr_t)(B)*CP_HASH_COEF) void cpInitChipmunk(void); cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset); cpFloat cpMomentForPoly(cpFloat m, int numVerts, cpVect *verts, cpVect offset); #ifdef __cplusplus } #endif libtuxcap-1.4.0/tuxcap/chipmunk/cpPolyShape.c0000644000175000017500000000665010712171657021122 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include "chipmunk.h" cpPolyShape * cpPolyShapeAlloc(void) { return (cpPolyShape *)calloc(1, sizeof(cpPolyShape)); } static void cpPolyShapeTransformVerts(cpPolyShape *poly, cpVect p, cpVect rot) { cpVect *src = poly->verts; cpVect *dst = poly->tVerts; for(int i=0; inumVerts; i++) dst[i] = cpvadd(p, cpvrotate(src[i], rot)); } static void cpPolyShapeTransformAxes(cpPolyShape *poly, cpVect p, cpVect rot) { cpPolyShapeAxis *src = poly->axes; cpPolyShapeAxis *dst = poly->tAxes; for(int i=0; inumVerts; i++){ cpVect n = cpvrotate(src[i].n, rot); dst[i].n = n; dst[i].d = cpvdot(p, n) + src[i].d; } } static cpBB cpPolyShapeCacheData(cpShape *shape, cpVect p, cpVect rot) { cpPolyShape *poly = (cpPolyShape *)shape; cpFloat l, b, r, t; cpPolyShapeTransformAxes(poly, p, rot); cpPolyShapeTransformVerts(poly, p, rot); cpVect *verts = poly->tVerts; l = r = verts[0].x; b = t = verts[0].y; for(int i=1; inumVerts; i++){ cpVect v = verts[i]; l = cpfmin(l, v.x); r = cpfmax(r, v.x); b = cpfmin(b, v.y); t = cpfmax(t, v.y); } return cpBBNew(l, b, r, t); } static void cpPolyShapeDestroy(cpShape *shape) { cpPolyShape *poly = (cpPolyShape *)shape; free(poly->verts); free(poly->tVerts); free(poly->axes); free(poly->tAxes); } cpPolyShape * cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int numVerts, cpVect *verts, cpVect offset) { poly->numVerts = numVerts; poly->verts = (cpVect *)calloc(numVerts, sizeof(cpVect)); poly->tVerts = (cpVect *)calloc(numVerts, sizeof(cpVect)); poly->axes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis)); poly->tAxes = (cpPolyShapeAxis *)calloc(numVerts, sizeof(cpPolyShapeAxis)); for(int i=0; iverts[i] = a; poly->axes[i].n = n; poly->axes[i].d = cpvdot(n, a); } poly->shape.cacheData = &cpPolyShapeCacheData; poly->shape.destroy = &cpPolyShapeDestroy; cpShapeInit((cpShape *)poly, CP_POLY_SHAPE, body); return poly; } cpShape * cpPolyShapeNew(cpBody *body, int numVerts, cpVect *verts, cpVect offset) { return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, numVerts, verts, offset); } libtuxcap-1.4.0/tuxcap/chipmunk/cpBody.c0000644000175000017500000001037110712171657020106 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include "chipmunk.h" cpBody* cpBodyAlloc(void) { return (cpBody *)malloc(sizeof(cpBody)); } cpBody* cpBodyInit(cpBody *body, cpFloat m, cpFloat i) { cpBodySetMass(body, m); cpBodySetMoment(body, i); body->p = cpvzero; body->v = cpvzero; body->f = cpvzero; cpBodySetAngle(body, 0.0f); body->w = 0.0f; body->t = 0.0f; body->v_bias = cpvzero; body->w_bias = 0.0f; // body->active = 1; return body; } cpBody* cpBodyNew(cpFloat m, cpFloat i) { return cpBodyInit(cpBodyAlloc(), m, i); } void cpBodyDestroy(cpBody *body){} void cpBodyFree(cpBody *body) { if(body) cpBodyDestroy(body); free(body); } void cpBodySetMass(cpBody *body, cpFloat m) { body->m = m; body->m_inv = 1.0f/m; } void cpBodySetMoment(cpBody *body, cpFloat i) { body->i = i; body->i_inv = 1.0f/i; } void cpBodySetAngle(cpBody *body, cpFloat a) { body->a = fmod(a, (cpFloat)M_PI*2.0f); body->rot = cpvforangle(a); } void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt) { cpVect delta = cpvsub(body->p, pos); body->v = cpvmult(delta, 1.0/dt); } void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) { body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)); body->w = body->w*damping + body->t*body->i_inv*dt; } void cpBodyUpdatePosition(cpBody *body, cpFloat dt) { body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt)); cpBodySetAngle(body, body->a + (body->w + body->w_bias)*dt); body->v_bias = cpvzero; body->w_bias = 0.0f; } void cpBodyResetForces(cpBody *body) { body->f = cpvzero; body->t = 0.0f; } void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r) { body->f = cpvadd(body->f, f); body->t += cpvcross(r, f); } void cpDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt) { // Calculate the world space anchor coordinates. cpVect r1 = cpvrotate(anchr1, a->rot); cpVect r2 = cpvrotate(anchr2, b->rot); cpVect delta = cpvsub(cpvadd(b->p, r2), cpvadd(a->p, r1)); cpFloat dist = cpvlength(delta); cpVect n = dist ? cpvmult(delta, 1.0f/dist) : cpvzero; cpFloat f_spring = (dist - rlen)*k; // Calculate the world relative velocities of the anchor points. cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); // Calculate the damping force. // This really should be in the impulse solver and can produce problems when using large damping values. cpFloat vrn = cpvdot(cpvsub(v2, v1), n); cpFloat f_damp = vrn*cpfmin(dmp, 1.0f/(dt*(a->m_inv + b->m_inv))); // Apply! cpVect f = cpvmult(n, f_spring + f_damp); cpBodyApplyForce(a, f, r1); cpBodyApplyForce(b, cpvneg(f), r2); } //int //cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max) //{ // cpFloat ke = body->m*cpvdot(body->v, body->v); // cpFloat re = body->i*body->w*body->w; // // if(ke + re > body->m*dvsq) // body->active = 1; // else if(body->active) // body->active = (body->active + 1)%(max + 1); // else { // body->v = cpvzero; // body->v_bias = cpvzero; // body->w = 0.0f; // body->w_bias = 0.0f; // } // // return body->active; //} libtuxcap-1.4.0/tuxcap/chipmunk/cpShape.c0000644000175000017500000001000310670737717020251 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "chipmunk.h" unsigned int SHAPE_ID_COUNTER = 0; void cpResetShapeIdCounter(void) { SHAPE_ID_COUNTER = 0; } cpShape* cpShapeInit(cpShape *shape, cpShapeType type, cpBody *body) { shape->type = type; shape->id = SHAPE_ID_COUNTER; SHAPE_ID_COUNTER++; assert(body != NULL); shape->body = body; shape->e = 0.0f; shape->u = 0.0f; shape->surface_v = cpvzero; shape->collision_type = 0; shape->group = 0; shape->layers = 0xFFFF; shape->data = NULL; cpShapeCacheBB(shape); return shape; } void cpShapeDestroy(cpShape *shape) { if(shape->destroy) shape->destroy(shape); } void cpShapeFree(cpShape *shape) { if(shape) cpShapeDestroy(shape); free(shape); } cpBB cpShapeCacheBB(cpShape *shape) { cpBody *body = shape->body; shape->bb = shape->cacheData(shape, body->p, body->rot); return shape->bb; } cpCircleShape * cpCircleShapeAlloc(void) { return (cpCircleShape *)calloc(1, sizeof(cpCircleShape)); } static inline cpBB bbFromCircle(const cpVect c, const cpFloat r) { return cpBBNew(c.x-r, c.y-r, c.x+r, c.y+r); } static cpBB cpCircleShapeCacheData(cpShape *shape, cpVect p, cpVect rot) { cpCircleShape *circle = (cpCircleShape *)shape; circle->tc = cpvadd(p, cpvrotate(circle->c, rot)); return bbFromCircle(circle->tc, circle->r); } cpCircleShape * cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset) { circle->c = offset; circle->r = radius; circle->shape.cacheData = &cpCircleShapeCacheData; circle->shape.destroy = NULL; cpShapeInit((cpShape *)circle, CP_CIRCLE_SHAPE, body); return circle; } cpShape * cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset) { return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset); } cpSegmentShape * cpSegmentShapeAlloc(void) { return (cpSegmentShape *)calloc(1, sizeof(cpSegmentShape)); } static cpBB cpSegmentShapeCacheData(cpShape *shape, cpVect p, cpVect rot) { cpSegmentShape *seg = (cpSegmentShape *)shape; seg->ta = cpvadd(p, cpvrotate(seg->a, rot)); seg->tb = cpvadd(p, cpvrotate(seg->b, rot)); seg->tn = cpvrotate(seg->n, rot); cpFloat l,r,s,t; if(seg->ta.x < seg->tb.x){ l = seg->ta.x; r = seg->tb.x; } else { l = seg->tb.x; r = seg->ta.x; } if(seg->ta.y < seg->tb.y){ s = seg->ta.y; t = seg->tb.y; } else { s = seg->tb.y; t = seg->ta.y; } cpFloat rad = seg->r; return cpBBNew(l - rad, s - rad, r + rad, t + rad); } cpSegmentShape * cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r) { seg->a = a; seg->b = b; seg->n = cpvperp(cpvnormalize(cpvsub(b, a))); seg->r = r; seg->shape.cacheData = &cpSegmentShapeCacheData; seg->shape.destroy = NULL; cpShapeInit((cpShape *)seg, CP_SEGMENT_SHAPE, body); return seg; } cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r) { return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r); } libtuxcap-1.4.0/tuxcap/chipmunk/cpSpace.h0000644000175000017500000000762410670737717020270 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Number of frames that contact information should persist. extern int cp_contact_persistence; // User collision pair function. typedef int (*cpCollFunc)(cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data); // Structure for holding collision pair function information. // Used internally. typedef struct cpCollPairFunc { unsigned int a; unsigned int b; cpCollFunc func; void *data; } cpCollPairFunc; typedef struct cpSpace{ // Number of iterations to use in the impulse solver. int iterations; // int sleepTicks; // Self explanatory. cpVect gravity; cpFloat damping; // Time stamp. Is incremented on every call to cpSpaceStep(). int stamp; // The static and active shape spatial hashes. cpSpaceHash *staticShapes; cpSpaceHash *activeShapes; // List of bodies in the system. cpArray *bodies; // List of active arbiters for the impulse solver. cpArray *arbiters; // Persistant contact set. cpHashSet *contactSet; // List of joints in the system. cpArray *joints; // Set of collisionpair functions. cpHashSet *collFuncSet; // Default collision pair function. cpCollPairFunc defaultPairFunc; } cpSpace; // Basic allocation/destruction functions. cpSpace* cpSpaceAlloc(void); cpSpace* cpSpaceInit(cpSpace *space); cpSpace* cpSpaceNew(void); void cpSpaceDestroy(cpSpace *space); void cpSpaceFree(cpSpace *space); // Convenience function. Frees all referenced entities. (bodies, shapes and joints) void cpSpaceFreeChildren(cpSpace *space); // Collision pair function management functions. void cpSpaceAddCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b, cpCollFunc func, void *data); void cpSpaceRemoveCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b); void cpSpaceSetDefaultCollisionPairFunc(cpSpace *space, cpCollFunc func, void *data); // Add and remove entities from the system. void cpSpaceAddShape(cpSpace *space, cpShape *shape); void cpSpaceAddStaticShape(cpSpace *space, cpShape *shape); void cpSpaceAddBody(cpSpace *space, cpBody *body); void cpSpaceAddJoint(cpSpace *space, cpJoint *joint); void cpSpaceRemoveShape(cpSpace *space, cpShape *shape); void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape); void cpSpaceRemoveBody(cpSpace *space, cpBody *body); void cpSpaceRemoveJoint(cpSpace *space, cpJoint *joint); // Iterator function for iterating the bodies in a space. typedef void (*cpSpaceBodyIterator)(cpBody *body, void *data); void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data); // Spatial hash management functions. void cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count); void cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count); void cpSpaceRehashStatic(cpSpace *space); // Update the space. void cpSpaceStep(cpSpace *space, cpFloat dt); libtuxcap-1.4.0/tuxcap/chipmunk/cpArbiter.h0000644000175000017500000000614710670737717020624 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Determines how fast penetrations resolve themselves. extern cpFloat cp_bias_coef; // Amount of allowed penetration. Used to reduce vibrating contacts. extern cpFloat cp_collision_slop; // Data structure for contact points. typedef struct cpContact{ // Contact point and normal. cpVect p, n; // Penetration distance. cpFloat dist; // Calculated by cpArbiterPreStep(). cpVect r1, r2; cpFloat nMass, tMass, bounce; // Persistant contact information. cpFloat jnAcc, jtAcc, jBias; cpFloat bias; // Hash value used to (mostly) uniquely identify a contact. unsigned int hash; } cpContact; // Contacts are always allocated in groups. cpContact* cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, unsigned int hash); // Sum the contact impulses. (Can be used after cpSpaceStep() returns) cpVect cpContactsSumImpulses(cpContact *contacts, int numContacts); cpVect cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts); // Data structure for tracking collisions between shapes. typedef struct cpArbiter{ // Information on the contact points between the objects. int numContacts; cpContact *contacts; // The two shapes involved in the collision. cpShape *a, *b; // Calculated by cpArbiterPreStep(). cpFloat u, e; cpVect target_v; // Time stamp of the arbiter. (from cpSpace) int stamp; } cpArbiter; // Basic allocation/destruction functions. cpArbiter* cpArbiterAlloc(void); cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b, int stamp); cpArbiter* cpArbiterNew(cpShape *a, cpShape *b, int stamp); void cpArbiterDestroy(cpArbiter *arb); void cpArbiterFree(cpArbiter *arb); // These functions are all intended to be used internally. // Inject new contact points into the arbiter while preserving contact history. void cpArbiterInject(cpArbiter *arb, cpContact *contacts, int numContacts); // Precalculate values used by the solver. void cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv); // Run an iteration of the solver on the arbiter. void cpArbiterApplyImpulse(cpArbiter *arb); libtuxcap-1.4.0/tuxcap/chipmunk/cpArray.c0000644000175000017500000000474110670737717020303 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "chipmunk.h" #define CP_ARRAY_INCREMENT 10 // NOTE: cpArray is rarely used and will probably go away. cpArray* cpArrayAlloc(void) { return (cpArray *)calloc(1, sizeof(cpArray)); } cpArray* cpArrayInit(cpArray *arr, int size) { arr->num = 0; size = (size ? size : CP_ARRAY_INCREMENT); arr->max = size; arr->arr = (void **)malloc(size*sizeof(void**)); return arr; } cpArray* cpArrayNew(int size) { return cpArrayInit(cpArrayAlloc(), size); } void cpArrayDestroy(cpArray *arr) { free(arr->arr); } void cpArrayFree(cpArray *arr) { if(!arr) return; cpArrayDestroy(arr); free(arr); } void cpArrayPush(cpArray *arr, void *object) { if(arr->num == arr->max){ arr->max += CP_ARRAY_INCREMENT; arr->arr = (void **)realloc(arr->arr, arr->max*sizeof(void**)); } arr->arr[arr->num] = object; arr->num++; } void cpArrayDeleteIndex(cpArray *arr, int index) { int last = --arr->num; arr->arr[index] = arr->arr[last]; } void cpArrayDeleteObj(cpArray *arr, void *obj) { for(int i=0; inum; i++){ if(arr->arr[i] == obj){ cpArrayDeleteIndex(arr, i); return; } } } void cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data) { for(int i=0; inum; i++) iterFunc(arr->arr[i], data); } int cpArrayContains(cpArray *arr, void *ptr) { for(int i=0; inum; i++) if(arr->arr[i] == ptr) return 1; return 0; } libtuxcap-1.4.0/tuxcap/chipmunk/prime.h0000644000175000017500000000405010670737720020006 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Used for resizing hash tables. // Values approximately double. static int primes[] = { 5, //2^2 + 1 11, //2^3 + 3 17, //2^4 + 1 37, //2^5 + 5 67, //2^6 + 3 131, //2^7 + 3 257, //2^8 + 1 521, //2^9 + 9 1031, //2^10 + 7 2053, //2^11 + 5 4099, //2^12 + 3 8209, //2^13 + 17 16411, //2^14 + 27 32771, //2^15 + 3 65537, //2^16 + 1 131101, //2^17 + 29 262147, //2^18 + 3 524309, //2^19 + 21 1048583, //2^20 + 7 2097169, //2^21 + 17 4194319, //2^22 + 15 8388617, //2^23 + 9 16777259, //2^24 + 43 33554467, //2^25 + 35 67108879, //2^26 + 15 134217757, //2^27 + 29 268435459, //2^28 + 3 536870923, //2^29 + 11 1073741827, //2^30 + 3 0, }; static int next_prime(int n) { int i = 0; while(n > primes[i]){ i++; assert(primes[i]); // realistically this should never happen } return primes[i]; } libtuxcap-1.4.0/tuxcap/chipmunk/cpSpaceHash.c0000644000175000017500000002322710670737717021064 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include "chipmunk.h" #include "prime.h" static cpHandle* cpHandleAlloc(void) { return (cpHandle *)malloc(sizeof(cpHandle)); } static cpHandle* cpHandleInit(cpHandle *hand, void *obj) { hand->obj = obj; hand->retain = 0; hand->stamp = 0; return hand; } static cpHandle* cpHandleNew(void *obj) { return cpHandleInit(cpHandleAlloc(), obj); } static inline void cpHandleRetain(cpHandle *hand) { hand->retain++; } static inline void cpHandleFree(cpHandle *hand) { free(hand); } static inline void cpHandleRelease(cpHandle *hand) { hand->retain--; if(hand->retain == 0) cpHandleFree(hand); } cpSpaceHash* cpSpaceHashAlloc(void) { return (cpSpaceHash *)calloc(1, sizeof(cpSpaceHash)); } // Frees the old table, and allocates a new one. static void cpSpaceHashAllocTable(cpSpaceHash *hash, int numcells) { free(hash->table); hash->numcells = numcells; hash->table = (cpSpaceHashBin **)calloc(numcells, sizeof(cpSpaceHashBin *)); } // Equality function for the handleset. static int handleSetEql(void *obj, void *elt) { cpHandle *hand = (cpHandle *)elt; return (obj == hand->obj); } // Transformation function for the handleset. static void * handleSetTrans(void *obj, void *unused) { cpHandle *hand = cpHandleNew(obj); cpHandleRetain(hand); return hand; } cpSpaceHash* cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpaceHashBBFunc bbfunc) { cpSpaceHashAllocTable(hash, next_prime(numcells)); hash->celldim = celldim; hash->bbfunc = bbfunc; hash->bins = NULL; hash->handleSet = cpHashSetNew(0, &handleSetEql, &handleSetTrans); hash->stamp = 1; return hash; } cpSpaceHash* cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc) { return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc); } static inline void clearHashCell(cpSpaceHash *hash, int index) { cpSpaceHashBin *bin = hash->table[index]; while(bin){ cpSpaceHashBin *next = bin->next; // Release the lock on the handle. cpHandleRelease(bin->handle); // Recycle the bin. bin->next = hash->bins; hash->bins = bin; bin = next; } hash->table[index] = NULL; } // Clear all cells in the hashtable. static void clearHash(cpSpaceHash *hash) { for(int i=0; inumcells; i++) clearHashCell(hash, i); } // Free the recycled hash bins. static void freeBins(cpSpaceHash *hash) { cpSpaceHashBin *bin = hash->bins; while(bin){ cpSpaceHashBin *next = bin->next; free(bin); bin = next; } } // Hashset iterator function to free the handles. static void handleFreeWrap(void *elt, void *unused) { cpHandle *hand = (cpHandle *)elt; cpHandleFree(hand); } void cpSpaceHashDestroy(cpSpaceHash *hash) { clearHash(hash); freeBins(hash); // Free the handles. cpHashSetEach(hash->handleSet, &handleFreeWrap, NULL); cpHashSetFree(hash->handleSet); free(hash->table); } void cpSpaceHashFree(cpSpaceHash *hash) { if(!hash) return; cpSpaceHashDestroy(hash); free(hash); } void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells) { // Clear the hash to release the old handle locks. clearHash(hash); hash->celldim = celldim; cpSpaceHashAllocTable(hash, next_prime(numcells)); } // Return true if the chain contains the handle. static inline int containsHandle(cpSpaceHashBin *bin, cpHandle *hand) { while(bin){ if(bin->handle == hand) return 1; bin = bin->next; } return 0; } // Get a recycled or new bin. static inline cpSpaceHashBin * getEmptyBin(cpSpaceHash *hash) { cpSpaceHashBin *bin = hash->bins; // Make a new one if necessary. if(bin == NULL) return (cpSpaceHashBin *)malloc(sizeof(cpSpaceHashBin)); hash->bins = bin->next; return bin; } // The hash function itself. static inline unsigned int hash_func(unsigned int x, unsigned int y, unsigned int n) { return (x*2185031351ul ^ y*4232417593ul) % n; } static inline void hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb) { // Find the dimensions in cell coordinates. cpFloat dim = hash->celldim; int l = bb.l/dim; int r = bb.r/dim; int b = bb.b/dim; int t = bb.t/dim; int n = hash->numcells; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int index = hash_func(i,j,n); cpSpaceHashBin *bin = hash->table[index]; // Don't add an object twice to the same cell. if(containsHandle(bin, hand)) continue; cpHandleRetain(hand); // Insert a new bin for the handle in this cell. cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; hash->table[index] = newBin; } } } void cpSpaceHashInsert(cpSpaceHash *hash, void *obj, unsigned int id, cpBB bb) { cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, id, obj, NULL); hashHandle(hash, hand, bb); } void cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, unsigned int id) { cpHandle *hand = (cpHandle *)cpHashSetFind(hash->handleSet, id, obj); hashHandle(hash, hand, hash->bbfunc(obj)); } // Hashset iterator function for rehashing the spatial hash. (hash hash hash hash?) static void handleRehashHelper(void *elt, void *data) { cpHandle *hand = (cpHandle *)elt; cpSpaceHash *hash = (cpSpaceHash *)data; hashHandle(hash, hand, hash->bbfunc(hand->obj)); } void cpSpaceHashRehash(cpSpaceHash *hash) { clearHash(hash); // Rehash all of the handles. cpHashSetEach(hash->handleSet, &handleRehashHelper, hash); } void cpSpaceHashRemove(cpSpaceHash *hash, void *obj, unsigned int id) { cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, id, obj); hand->obj = NULL; cpHandleRelease(hand); } // Used by the cpSpaceHashEach() iterator. typedef struct eachPair { cpSpaceHashIterator func; void *data; } eachPair; // Calls the user iterator function. (Gross I know.) static void eachHelper(void *elt, void *data) { cpHandle *hand = (cpHandle *)elt; eachPair *pair = (eachPair *)data; pair->func(hand->obj, pair->data); } // Iterate over the objects in the spatial hash. void cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data) { // Bundle the callback up to send to the hashset iterator. eachPair pair = {func, data}; cpHashSetEach(hash->handleSet, &eachHelper, &pair); } // Calls the callback function for the objects in a given chain. static inline void query(cpSpaceHash *hash, cpSpaceHashBin *bin, void *obj, cpSpaceHashQueryFunc func, void *data) { for(; bin; bin = bin->next){ cpHandle *hand = bin->handle; void *other = hand->obj; // Skip over certain conditions if( // Have we already tried this pair in this query? hand->stamp == hash->stamp // Is obj the same as other? || obj == other // Has other been removed since the last rehash? || !other ) continue; func(obj, other, data); // Stamp that the handle was checked already against this object. hand->stamp = hash->stamp; } } void cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data) { // Get the dimensions in cell coordinates. cpFloat dim = hash->celldim; int l = bb.l/dim; int r = bb.r/dim; int b = bb.b/dim; int t = bb.t/dim; int n = hash->numcells; // Iterate over the cells and query them. for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int index = hash_func(i,j,n); query(hash, hash->table[index], obj, func, data); } } // Increment the stamp. hash->stamp++; } // Similar to struct eachPair above. typedef struct queryRehashPair { cpSpaceHash *hash; cpSpaceHashQueryFunc func; void *data; } queryRehashPair; // Hashset iterator func used with cpSpaceHashQueryRehash(). static void handleQueryRehashHelper(void *elt, void *data) { cpHandle *hand = (cpHandle *)elt; // Unpack the user callback data. queryRehashPair *pair = (queryRehashPair *)data; cpSpaceHash *hash = pair->hash; cpSpaceHashQueryFunc func = pair->func; cpFloat dim = hash->celldim; int n = hash->numcells; void *obj = hand->obj; cpBB bb = hash->bbfunc(obj); int l = bb.l/dim; int r = bb.r/dim; int b = bb.b/dim; int t = bb.t/dim; for(int i=l; i<=r; i++){ for(int j=b; j<=t; j++){ int index = hash_func(i,j,n); cpSpaceHashBin *bin = hash->table[index]; if(containsHandle(bin, hand)) continue; query(hash, bin, obj, func, pair->data); cpHandleRetain(hand); cpSpaceHashBin *newBin = getEmptyBin(hash); newBin->handle = hand; newBin->next = bin; hash->table[index] = newBin; } } // Increment the stamp for each object we hash. hash->stamp++; } void cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data) { clearHash(hash); queryRehashPair pair = {hash, func, data}; cpHashSetEach(hash->handleSet, &handleQueryRehashHelper, &pair); } libtuxcap-1.4.0/tuxcap/chipmunk/cpBody.h0000644000175000017500000000666310670737717020134 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ typedef struct cpBody{ // Mass and it's inverse. cpFloat m, m_inv; // Moment of inertia and it's inverse. cpFloat i, i_inv; // NOTE: v_bias and w_bias are used internally for penetration/joint correction. // Linear components of motion (position, velocity, and force) cpVect p, v, f, v_bias; // Angular components of motion (angle, angular velocity, and torque) cpFloat a, w, t, w_bias; // Unit length cpVect rot; // int active; } cpBody; // Basic allocation/destruction functions cpBody *cpBodyAlloc(void); cpBody *cpBodyInit(cpBody *body, cpFloat m, cpFloat i); cpBody *cpBodyNew(cpFloat m, cpFloat i); void cpBodyDestroy(cpBody *body); void cpBodyFree(cpBody *body); // Setters for some of the special properties (mandatory!) void cpBodySetMass(cpBody *body, cpFloat m); void cpBodySetMoment(cpBody *body, cpFloat i); void cpBodySetAngle(cpBody *body, cpFloat a); // Modify the velocity of an object so that it will void cpBodySlew(cpBody *body, cpVect pos, cpFloat dt); // Integration functions. void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt); void cpBodyUpdatePosition(cpBody *body, cpFloat dt); // Convert body local to world coordinates static inline cpVect cpBodyLocal2World(cpBody *body, cpVect v) { return cpvadd(body->p, cpvrotate(v, body->rot)); } // Convert world to body local coordinates static inline cpVect cpBodyWorld2Local(cpBody *body, cpVect v) { return cpvunrotate(cpvsub(v, body->p), body->rot); } // Apply an impulse (in world coordinates) to the body. static inline void cpBodyApplyImpulse(cpBody *body, cpVect j, cpVect r) { body->v = cpvadd(body->v, cpvmult(j, body->m_inv)); body->w += body->i_inv*cpvcross(r, j); } // Not intended for external use. Used by cpArbiter.c and cpJoint.c. static inline void cpBodyApplyBiasImpulse(cpBody *body, cpVect j, cpVect r) { body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv)); body->w_bias += body->i_inv*cpvcross(r, j); } // Zero the forces on a body. void cpBodyResetForces(cpBody *body); // Apply a force (in world coordinates) to a body. void cpBodyApplyForce(cpBody *body, cpVect f, cpVect r); // Apply a damped spring force between two bodies. void cpDampedSpring(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat rlen, cpFloat k, cpFloat dmp, cpFloat dt); //int cpBodyMarkLowEnergy(cpBody *body, cpFloat dvsq, int max); libtuxcap-1.4.0/tuxcap/chipmunk/cpCollision.c0000644000175000017500000002447011212025210021124 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include "chipmunk.h" typedef int (*collisionFunc)(cpShape*, cpShape*, cpContact**); static collisionFunc *colfuncs = NULL; // Add contact points for circle to circle collisions. // Used by several collision tests. static int circle2circleQuery(cpVect p1, cpVect p2, cpFloat r1, cpFloat r2, cpContact **con) { cpFloat mindist = r1 + r2; cpVect delta = cpvsub(p2, p1); cpFloat distsq = cpvlengthsq(delta); if(distsq >= mindist*mindist) return 0; cpFloat dist = sqrtf(distsq); // To avoid singularities, do nothing in the case of dist = 0. cpFloat non_zero_dist = (dist ? dist : INFINITY); // Allocate and initialize the contact. (*con) = (cpContact *)malloc(sizeof(cpContact)); cpContactInit( (*con), cpvadd(p1, cpvmult(delta, 0.5 + (r1 - 0.5*mindist)/non_zero_dist)), cpvmult(delta, 1.0/non_zero_dist), dist - mindist, 0 ); return 1; } // Collide circle shapes. static int circle2circle(cpShape *shape1, cpShape *shape2, cpContact **arr) { cpCircleShape *circ1 = (cpCircleShape *)shape1; cpCircleShape *circ2 = (cpCircleShape *)shape2; return circle2circleQuery(circ1->tc, circ2->tc, circ1->r, circ2->r, arr); } // Collide circles to segment shapes. static int circle2segment(cpShape *circleShape, cpShape *segmentShape, cpContact **con) { cpCircleShape *circ = (cpCircleShape *)circleShape; cpSegmentShape *seg = (cpSegmentShape *)segmentShape; // Calculate normal distance from segment. cpFloat dn = cpvdot(seg->tn, circ->tc) - cpvdot(seg->ta, seg->tn); cpFloat dist = fabs(dn) - circ->r - seg->r; if(dist > 0.0f) return 0; // Calculate tangential distance along segment. cpFloat dt = -cpvcross(seg->tn, circ->tc); cpFloat dtMin = -cpvcross(seg->tn, seg->ta); cpFloat dtMax = -cpvcross(seg->tn, seg->tb); // Decision tree to decide which feature of the segment to collide with. if(dt < dtMin){ if(dt < (dtMin - circ->r)){ return 0; } else { return circle2circleQuery(circ->tc, seg->ta, circ->r, seg->r, con); } } else { if(dt < dtMax){ cpVect n = (dn < 0.0f) ? seg->tn : cpvneg(seg->tn); (*con) = (cpContact *)malloc(sizeof(cpContact)); cpContactInit( (*con), cpvadd(circ->tc, cpvmult(n, circ->r + dist*0.5f)), n, dist, 0 ); return 1; } else { if(dt < (dtMax + circ->r)) { return circle2circleQuery(circ->tc, seg->tb, circ->r, seg->r, con); } else { return 0; } } } return 1; } // Helper function for allocating contact point lists. static cpContact * addContactPoint(cpContact **arr, int *max, int *num) { if(*arr == NULL){ // Allocate the array if it hasn't been done. (*max) = 2; (*num) = 0; (*arr) = (cpContact *)malloc((*max)*sizeof(cpContact)); } else if(*num == *max){ // Extend it if necessary. (*max) *= 2; (*arr) = (cpContact *)realloc(*arr, (*max)*sizeof(cpContact)); } cpContact *con = &(*arr)[*num]; (*num)++; return con; } // Find the minimum separating axis for the give poly and axis list. static inline int findMSA(cpPolyShape *poly, cpPolyShapeAxis *axes, int num, cpFloat *min_out) { int min_index = 0; cpFloat min = cpPolyShapeValueOnAxis(poly, axes->n, axes->d); if(min > 0.0) return -1; for(int i=1; i 0.0) { return -1; } else if(dist > min){ min = dist; min_index = i; } } (*min_out) = min; return min_index; } // Add contacts for penetrating vertexes. static inline int findVerts(cpContact **arr, cpPolyShape *poly1, cpPolyShape *poly2, cpVect n, cpFloat dist) { int max = 0; int num = 0; for(int i=0; inumVerts; i++){ cpVect v = poly1->tVerts[i]; if(cpPolyShapeContainsVert(poly2, v)) cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly1, i)); } for(int i=0; inumVerts; i++){ cpVect v = poly2->tVerts[i]; if(cpPolyShapeContainsVert(poly1, v)) cpContactInit(addContactPoint(arr, &max, &num), v, n, dist, CP_HASH_PAIR(poly2, i)); } // if(!num) // addContactPoint(arr, &size, &num, cpContactNew(shape1->body->p, n, dist, 0)); return num; } // Collide poly shapes together. static int poly2poly(cpShape *shape1, cpShape *shape2, cpContact **arr) { cpPolyShape *poly1 = (cpPolyShape *)shape1; cpPolyShape *poly2 = (cpPolyShape *)shape2; cpFloat min1; int mini1 = findMSA(poly2, poly1->tAxes, poly1->numVerts, &min1); if(mini1 == -1) return 0; cpFloat min2; int mini2 = findMSA(poly1, poly2->tAxes, poly2->numVerts, &min2); if(mini2 == -1) return 0; // There is overlap, find the penetrating verts if(min1 > min2) return findVerts(arr, poly1, poly2, poly1->tAxes[mini1].n, min1); else return findVerts(arr, poly1, poly2, cpvneg(poly2->tAxes[mini2].n), min2); } // Like cpPolyValueOnAxis(), but for segments. static inline float segValueOnAxis(cpSegmentShape *seg, cpVect n, cpFloat d) { cpFloat a = cpvdot(n, seg->ta) - seg->r; cpFloat b = cpvdot(n, seg->tb) - seg->r; return cpfmin(a, b) - d; } // Identify vertexes that have penetrated the segment. static inline void findPointsBehindSeg(cpContact **arr, int *max, int *num, cpSegmentShape *seg, cpPolyShape *poly, cpFloat pDist, cpFloat coef) { cpFloat dta = cpvcross(seg->tn, seg->ta); cpFloat dtb = cpvcross(seg->tn, seg->tb); cpVect n = cpvmult(seg->tn, coef); for(int i=0; inumVerts; i++){ cpVect v = poly->tVerts[i]; if(cpvdot(v, n) < cpvdot(seg->tn, seg->ta)*coef + seg->r){ cpFloat dt = cpvcross(seg->tn, v); if(dta >= dt && dt >= dtb){ cpContactInit(addContactPoint(arr, max, num), v, n, pDist, CP_HASH_PAIR(poly, i)); } } } } // This one is complicated and gross. Just don't go there... // TODO: Comment me! static int seg2poly(cpShape *shape1, cpShape *shape2, cpContact **arr) { cpSegmentShape *seg = (cpSegmentShape *)shape1; cpPolyShape *poly = (cpPolyShape *)shape2; cpPolyShapeAxis *axes = poly->tAxes; cpFloat segD = cpvdot(seg->tn, seg->ta); cpFloat minNorm = cpPolyShapeValueOnAxis(poly, seg->tn, segD) - seg->r; cpFloat minNeg = cpPolyShapeValueOnAxis(poly, cpvneg(seg->tn), -segD) - seg->r; if(minNeg > 0.0f || minNorm > 0.0f) return 0; int mini = 0; cpFloat poly_min = segValueOnAxis(seg, axes->n, axes->d); if(poly_min > 0.0f) return 0; for(int i=0; inumVerts; i++){ cpFloat dist = segValueOnAxis(seg, axes[i].n, axes[i].d); if(dist > 0.0f){ return 0; } else if(dist > poly_min){ poly_min = dist; mini = i; } } int max = 0; int num = 0; cpVect poly_n = cpvneg(axes[mini].n); cpVect va = cpvadd(seg->ta, cpvmult(poly_n, seg->r)); cpVect vb = cpvadd(seg->tb, cpvmult(poly_n, seg->r)); if(cpPolyShapeContainsVert(poly, va)) cpContactInit(addContactPoint(arr, &max, &num), va, poly_n, poly_min, CP_HASH_PAIR(seg, 0)); if(cpPolyShapeContainsVert(poly, vb)) cpContactInit(addContactPoint(arr, &max, &num), vb, poly_n, poly_min, CP_HASH_PAIR(seg, 1)); // Floating point precision problems here. // This will have to do for now. poly_min -= cp_collision_slop; if(minNorm >= poly_min || minNeg >= poly_min) { if(minNorm > minNeg) findPointsBehindSeg(arr, &max, &num, seg, poly, minNorm, 1.0f); else findPointsBehindSeg(arr, &max, &num, seg, poly, minNeg, -1.0f); } return num; } // This one is less gross, but still gross. // TODO: Comment me! static int circle2poly(cpShape *shape1, cpShape *shape2, cpContact **con) { cpCircleShape *circ = (cpCircleShape *)shape1; cpPolyShape *poly = (cpPolyShape *)shape2; cpPolyShapeAxis *axes = poly->tAxes; int mini = 0; cpFloat min = cpvdot(axes->n, circ->tc) - axes->d - circ->r; for(int i=0; inumVerts; i++){ cpFloat dist = cpvdot(axes[i].n, circ->tc) - axes[i].d - circ->r; if(dist > 0.0){ return 0; } else if(dist > min) { min = dist; mini = i; } } cpVect n = axes[mini].n; cpVect a = poly->tVerts[mini]; cpVect b = poly->tVerts[(mini + 1)%poly->numVerts]; cpFloat dta = cpvcross(n, a); cpFloat dtb = cpvcross(n, b); cpFloat dt = cpvcross(n, circ->tc); if(dt < dtb){ return circle2circleQuery(circ->tc, b, circ->r, 0.0f, con); } else if(dt < dta) { (*con) = (cpContact *)malloc(sizeof(cpContact)); cpContactInit( (*con), cpvsub(circ->tc, cpvmult(n, circ->r + min/2.0f)), cpvneg(n), min, 0 ); return 1; } else { return circle2circleQuery(circ->tc, a, circ->r, 0.0f, con); } } static void addColFunc(cpShapeType a, cpShapeType b, collisionFunc func) { colfuncs[a + b*CP_NUM_SHAPES] = func; } #ifdef __cplusplus extern "C" { #endif // Initializes the array of collision functions. // Called by cpInitChipmunk(). void cpInitCollisionFuncs(void) { if(!colfuncs) colfuncs = (collisionFunc *)calloc(CP_NUM_SHAPES*CP_NUM_SHAPES, sizeof(collisionFunc)); addColFunc(CP_CIRCLE_SHAPE, CP_CIRCLE_SHAPE, circle2circle); addColFunc(CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, circle2segment); addColFunc(CP_SEGMENT_SHAPE, CP_POLY_SHAPE, seg2poly); addColFunc(CP_CIRCLE_SHAPE, CP_POLY_SHAPE, circle2poly); addColFunc(CP_POLY_SHAPE, CP_POLY_SHAPE, poly2poly); } #ifdef __cplusplus } #endif int cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr) { // Their shape types must be in order. assert(a->type <= b->type); collisionFunc cfunc = colfuncs[a->type + b->type*CP_NUM_SHAPES]; return (cfunc) ? cfunc(a, b, arr) : 0; } libtuxcap-1.4.0/tuxcap/chipmunk/cpSpaceHash.h0000644000175000017500000000736710670737717021100 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // The spatial hash is Chipmunk's default (and currently only) spatial index type. // Based on a chained hash table. // Used internally to track objects added to the hash typedef struct cpHandle{ // Pointer to the object void *obj; // Retain count int retain; // Query stamp. Used to make sure two objects // aren't identified twice in the same query. int stamp; } cpHandle; // Linked list element for in the chains. typedef struct cpSpaceHashBin{ cpHandle *handle; struct cpSpaceHashBin *next; } cpSpaceHashBin; // BBox callback. Called whenever the hash needs a bounding box from an object. typedef cpBB (*cpSpaceHashBBFunc)(void *obj); typedef struct cpSpaceHash{ // Number of cells in the table. int numcells; // Dimentions of the cells. cpFloat celldim; // BBox callback. cpSpaceHashBBFunc bbfunc; // Hashset of all the handles. cpHashSet *handleSet; cpSpaceHashBin **table; // List of recycled bins. cpSpaceHashBin *bins; // Incremented on each query. See cpHandle.stamp. int stamp; } cpSpaceHash; //Basic allocation/destruction functions. cpSpaceHash *cpSpaceHashAlloc(void); cpSpaceHash *cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc); cpSpaceHash *cpSpaceHashNew(cpFloat celldim, int cells, cpSpaceHashBBFunc bbfunc); void cpSpaceHashDestroy(cpSpaceHash *hash); void cpSpaceHashFree(cpSpaceHash *hash); // Resize the hashtable. (Does not rehash! You must call cpSpaceHashRehash() if needed.) void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells); // Add an object to the hash. void cpSpaceHashInsert(cpSpaceHash *hash, void *obj, unsigned int id, cpBB bb); // Remove an object from the hash. void cpSpaceHashRemove(cpSpaceHash *hash, void *obj, unsigned int id); // Iterator function typedef void (*cpSpaceHashIterator)(void *obj, void *data); // Iterate over the objects in the hash. void cpSpaceHashEach(cpSpaceHash *hash, cpSpaceHashIterator func, void *data); // Rehash the contents of the hash. void cpSpaceHashRehash(cpSpaceHash *hash); // Rehash only a specific object. void cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, unsigned int id); // Query callback. typedef int (*cpSpaceHashQueryFunc)(void *obj1, void *obj2, void *data); // Query the hash for a given BBox. void cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data); // Run a query for the object, then insert it. (Optimized case) void cpSpaceHashQueryInsert(cpSpaceHash *hash, void *obj, cpBB bb, cpSpaceHashQueryFunc func, void *data); // Rehashes while querying for each object. (Optimized case) void cpSpaceHashQueryRehash(cpSpaceHash *hash, cpSpaceHashQueryFunc func, void *data); libtuxcap-1.4.0/tuxcap/chipmunk/cpHashSet.c0000644000175000017500000001166410670737717020566 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "chipmunk.h" #include "prime.h" void cpHashSetDestroy(cpHashSet *set) { // Free the chains. for(int i=0; isize; i++){ // Free the bins in the chain. cpHashSetBin *bin = set->table[i]; while(bin){ cpHashSetBin *next = bin->next; free(bin); bin = next; } } // Free the table. free(set->table); } void cpHashSetFree(cpHashSet *set) { if(set) cpHashSetDestroy(set); free(set); } cpHashSet * cpHashSetAlloc(void) { return (cpHashSet *)calloc(1, sizeof(cpHashSet)); } cpHashSet * cpHashSetInit(cpHashSet *set, int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans) { set->size = next_prime(size); set->entries = 0; set->eql = eqlFunc; set->trans = trans; set->default_value = NULL; set->table = (cpHashSetBin **)calloc(set->size, sizeof(cpHashSetBin *)); return set; } cpHashSet * cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc, cpHashSetTransFunc trans) { return cpHashSetInit(cpHashSetAlloc(), size, eqlFunc, trans); } static int setIsFull(cpHashSet *set) { return (set->entries >= set->size); } static void cpHashSetResize(cpHashSet *set) { // Get the next approximate doubled prime. int newSize = next_prime(set->size + 1); // Allocate a new table. cpHashSetBin **newTable = (cpHashSetBin **)calloc(newSize, sizeof(cpHashSetBin *)); // Iterate over the chains. for(int i=0; isize; i++){ // Rehash the bins into the new table. cpHashSetBin *bin = set->table[i]; while(bin){ cpHashSetBin *next = bin->next; int index = bin->hash%newSize; bin->next = newTable[index]; newTable[index] = bin; bin = next; } } free(set->table); set->table = newTable; set->size = newSize; } void * cpHashSetInsert(cpHashSet *set, unsigned int hash, void *ptr, void *data) { int index = hash%set->size; // Find the bin with the matching element. cpHashSetBin *bin = set->table[index]; while(bin && !set->eql(ptr, bin->elt)) bin = bin->next; // Create it necessary. if(!bin){ bin = (cpHashSetBin *)malloc(sizeof(cpHashSetBin)); bin->hash = hash; bin->elt = set->trans(ptr, data); // Transform the pointer. bin->next = set->table[index]; set->table[index] = bin; set->entries++; // Resize the set if it's full. if(setIsFull(set)) cpHashSetResize(set); } return bin->elt; } void * cpHashSetRemove(cpHashSet *set, unsigned int hash, void *ptr) { int index = hash%set->size; // Pointer to the previous bin pointer. cpHashSetBin **prev_ptr = &set->table[index]; // Pointer the the current bin. cpHashSetBin *bin = set->table[index]; // Find the bin while(bin && !set->eql(ptr, bin->elt)){ prev_ptr = &bin->next; bin = bin->next; } // Remove it if it exists. if(bin){ // Update the previos bin pointer to point to the next bin. (*prev_ptr) = bin->next; set->entries--; void *return_value = bin->elt; free(bin); return return_value; } return NULL; } void * cpHashSetFind(cpHashSet *set, unsigned int hash, void *ptr) { int index = hash%set->size; cpHashSetBin *bin = set->table[index]; while(bin && !set->eql(ptr, bin->elt)) bin = bin->next; return (bin ? bin->elt : set->default_value); } void cpHashSetEach(cpHashSet *set, cpHashSetIterFunc func, void *data) { for(int i=0; isize; i++){ cpHashSetBin *bin; for(bin = set->table[i]; bin; bin = bin->next) func(bin->elt, data); } } void cpHashSetReject(cpHashSet *set, cpHashSetRejectFunc func, void *data) { // Iterate over all the chains. for(int i=0; isize; i++){ // The rest works similarly to cpHashSetRemove() above. cpHashSetBin **prev_ptr = &set->table[i]; cpHashSetBin *bin = set->table[i]; while(bin){ cpHashSetBin *next = bin->next; if(func(bin->elt, data)){ prev_ptr = &bin->next; } else { (*prev_ptr) = next; set->entries--; free(bin); } bin = next; } } } libtuxcap-1.4.0/tuxcap/chipmunk/cpBB.h0000644000175000017500000000354610712171657017507 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ typedef struct cpBB{ cpFloat l, b, r ,t; } cpBB; static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) { cpBB bb = {l, b, r, t}; return bb; } static inline int cpBBintersects(const cpBB a, const cpBB b) { return (a.l<=b.r && b.l<=a.r && a.b<=b.t && b.b<=a.t); } static inline int cpBBcontainsBB(const cpBB bb, const cpBB other) { return (bb.l < other.l && bb.r > other.r && bb.b < other.b && bb.t > other.t); } static inline int cpBBcontainsVect(const cpBB bb, const cpVect v) { return (bb.l < v.x && bb.r > v.x && bb.b < v.y && bb.t > v.y); } cpVect cpBBClampVect(const cpBB bb, const cpVect v); // clamps the vector to lie within the bbox cpVect cpBBWrapVect(const cpBB bb, const cpVect v); // wrap a vector to a bbox libtuxcap-1.4.0/tuxcap/chipmunk/cpArray.h0000644000175000017500000000334310670737717020305 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // NOTE: cpArray is rarely used and will probably go away. typedef struct cpArray{ int num, max; void **arr; } cpArray; typedef void (*cpArrayIter)(void *ptr, void *data); cpArray *cpArrayAlloc(void); cpArray *cpArrayInit(cpArray *arr, int size); cpArray *cpArrayNew(int size); void cpArrayDestroy(cpArray *arr); void cpArrayFree(cpArray *arr); void cpArrayClear(cpArray *arr); void cpArrayPush(cpArray *arr, void *object); void cpArrayDeleteIndex(cpArray *arr, int index); void cpArrayDeleteObj(cpArray *arr, void *obj); void cpArrayEach(cpArray *arr, cpArrayIter iterFunc, void *data); int cpArrayContains(cpArray *arr, void *ptr); libtuxcap-1.4.0/tuxcap/chipmunk/cpShape.h0000644000175000017500000000706610670737717020275 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // For determinism, you can reset the shape id counter. void cpResetShapeIdCounter(void); // Enumeration of shape types. typedef enum cpShapeType{ CP_CIRCLE_SHAPE, CP_SEGMENT_SHAPE, CP_POLY_SHAPE, CP_NUM_SHAPES } cpShapeType; // Basic shape struct that the others inherit from. typedef struct cpShape{ cpShapeType type; // Called by cpShapeCacheBB(). cpBB (*cacheData)(struct cpShape *shape, cpVect p, cpVect rot); // Called to by cpShapeDestroy(). void (*destroy)(struct cpShape *shape); // Unique id used as the hash value. unsigned int id; // Cached BBox for the shape. cpBB bb; // User defined collision type for the shape. unsigned int collision_type; // User defined collision group for the shape. unsigned int group; // User defined layer bitmask for the shape. unsigned int layers; // User defined data pointer for the shape. void *data; // cpBody that the shape is attached to. cpBody *body; // Coefficient of restitution. (elasticity) cpFloat e; // Coefficient of friction. cpFloat u; // Surface velocity used when solving for friction. cpVect surface_v; } cpShape; // Low level shape initialization func. cpShape* cpShapeInit(cpShape *shape, cpShapeType type, cpBody *body); // Basic destructor functions. (allocation functions are not shared) void cpShapeDestroy(cpShape *shape); void cpShapeFree(cpShape *shape); // Cache the BBox of the shape. cpBB cpShapeCacheBB(cpShape *shape); // Circle shape structure. typedef struct cpCircleShape{ cpShape shape; // Center. (body space coordinates) cpVect c; // Radius. cpFloat r; // Transformed center. (world space coordinates) cpVect tc; } cpCircleShape; // Basic allocation functions for cpCircleShape. cpCircleShape *cpCircleShapeAlloc(void); cpCircleShape *cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset); cpShape *cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset); // Segment shape structure. typedef struct cpSegmentShape{ cpShape shape; // Endpoints and normal of the segment. (body space coordinates) cpVect a, b, n; // Radius of the segment. (Thickness) cpFloat r; // Transformed endpoints and normal. (world space coordinates) cpVect ta, tb, tn; } cpSegmentShape; // Basic allocation functions for cpSegmentShape. cpSegmentShape* cpSegmentShapeAlloc(void); cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r); cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r); libtuxcap-1.4.0/tuxcap/chipmunk/cpVect.h0000644000175000017500000000531310670737720020121 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ typedef struct cpVect{ cpFloat x,y; } cpVect; static const cpVect cpvzero={0.0f,0.0f}; static inline cpVect cpv(const cpFloat x, const cpFloat y) { cpVect v = {x, y}; return v; } static inline cpVect cpvadd(const cpVect v1, const cpVect v2) { return cpv(v1.x + v2.x, v1.y + v2.y); } static inline cpVect cpvneg(const cpVect v) { return cpv(-v.x, -v.y); } static inline cpVect cpvsub(const cpVect v1, const cpVect v2) { return cpv(v1.x - v2.x, v1.y - v2.y); } static inline cpVect cpvmult(const cpVect v, const cpFloat s) { return cpv(v.x*s, v.y*s); } static inline cpFloat cpvdot(const cpVect v1, const cpVect v2) { return v1.x*v2.x + v1.y*v2.y; } static inline cpFloat cpvcross(const cpVect v1, const cpVect v2) { return v1.x*v2.y - v1.y*v2.x; } static inline cpVect cpvperp(const cpVect v) { return cpv(-v.y, v.x); } static inline cpVect cpvrperp(const cpVect v) { return cpv(v.y, -v.x); } static inline cpVect cpvproject(const cpVect v1, const cpVect v2) { return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2)); } static inline cpVect cpvrotate(const cpVect v1, const cpVect v2) { return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x); } static inline cpVect cpvunrotate(const cpVect v1, const cpVect v2) { return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y); } cpFloat cpvlength(const cpVect v); cpFloat cpvlengthsq(const cpVect v); // no sqrt() call cpVect cpvnormalize(const cpVect v); cpVect cpvforangle(const cpFloat a); // convert radians to a normalized vector cpFloat cpvtoangle(const cpVect v); // convert a vector to radians char *cpvstr(const cpVect v); // get a string representation of a vector libtuxcap-1.4.0/tuxcap/chipmunk/LICENSE.txt0000644000175000017500000000213510670737717020354 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */libtuxcap-1.4.0/tuxcap/chipmunk/chipmunk.c0000644000175000017500000000373510712171657020512 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "stdlib.h" #include "chipmunk.h" #ifdef __cplusplus extern "C" { #endif void cpInitCollisionFuncs(void); #ifdef __cplusplus } #endif void cpInitChipmunk(void) { cpInitCollisionFuncs(); } cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset) { return (1.0f/2.0f)*m*(r1*r1 + r2*r2) + m*cpvdot(offset, offset); } cpFloat cpMomentForPoly(cpFloat m, const int numVerts, cpVect *verts, cpVect offset) { cpVect *tVerts = (cpVect *)calloc(numVerts, sizeof(cpVect)); for(int i=0; itVerts; cpFloat min = cpvdot(n, verts[0]); for(int i=1; inumVerts; i++) min = cpfmin(min, cpvdot(n, verts[i])); return min - d; } // Returns true if the polygon contains the vertex. static inline int cpPolyShapeContainsVert(cpPolyShape *poly, cpVect v) { cpPolyShapeAxis *axes = poly->tAxes; for(int i=0; inumVerts; i++){ cpFloat dist = cpvdot(axes[i].n, v) - axes[i].d; if(dist > 0.0) return 0; } return 1; } libtuxcap-1.4.0/tuxcap/chipmunk/cpArbiter.c0000644000175000017500000001456510670737717020622 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include "chipmunk.h" cpFloat cp_bias_coef = 0.1f; cpFloat cp_collision_slop = 0.1f; cpContact* cpContactInit(cpContact *con, cpVect p, cpVect n, cpFloat dist, unsigned int hash) { con->p = p; con->n = n; con->dist = dist; con->jnAcc = 0.0f; con->jtAcc = 0.0f; con->jBias = 0.0f; con->hash = hash; return con; } cpVect cpContactsSumImpulses(cpContact *contacts, int numContacts) { cpVect sum = cpvzero; for(int i=0; in, con->jnAcc); sum = cpvadd(sum, j); } return sum; } cpVect cpContactsSumImpulsesWithFriction(cpContact *contacts, int numContacts) { cpVect sum = cpvzero; for(int i=0; in); cpVect j = cpvadd(cpvmult(con->n, con->jnAcc), cpvmult(t, con->jtAcc)); sum = cpvadd(sum, j); } return sum; } cpArbiter* cpArbiterAlloc(void) { return (cpArbiter *)calloc(1, sizeof(cpArbiter)); } cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b, int stamp) { arb->numContacts = 0; arb->contacts = NULL; arb->a = a; arb->b = b; arb->stamp = stamp; return arb; } cpArbiter* cpArbiterNew(cpShape *a, cpShape *b, int stamp) { return cpArbiterInit(cpArbiterAlloc(), a, b, stamp); } void cpArbiterDestroy(cpArbiter *arb) { free(arb->contacts); } void cpArbiterFree(cpArbiter *arb) { if(arb) cpArbiterDestroy(arb); free(arb); } void cpArbiterInject(cpArbiter *arb, cpContact *contacts, int numContacts) { // Iterate over the possible pairs to look for hash value matches. for(int i=0; inumContacts; i++){ cpContact *old = &arb->contacts[i]; for(int j=0; jhash == old->hash){ // Copy the persistant contact information. new_contact->jnAcc = old->jnAcc; new_contact->jtAcc = old->jtAcc; } } } free(arb->contacts); arb->contacts = contacts; arb->numContacts = numContacts; } void cpArbiterPreStep(cpArbiter *arb, cpFloat dt_inv) { cpShape *shapea = arb->a; cpShape *shapeb = arb->b; arb->e = shapea->e * shapeb->e; arb->u = shapea->u * shapeb->u; arb->target_v = cpvsub(shapeb->surface_v, shapea->surface_v); cpBody *a = shapea->body; cpBody *b = shapeb->body; for(int i=0; inumContacts; i++){ cpContact *con = &arb->contacts[i]; // Calculate the offsets. con->r1 = cpvsub(con->p, a->p); con->r2 = cpvsub(con->p, b->p); // Calculate the mass normal. cpFloat mass_sum = a->m_inv + b->m_inv; cpFloat r1cn = cpvcross(con->r1, con->n); cpFloat r2cn = cpvcross(con->r2, con->n); cpFloat kn = mass_sum + a->i_inv*r1cn*r1cn + b->i_inv*r2cn*r2cn; con->nMass = 1.0f/kn; // Calculate the mass tangent. cpVect t = cpvperp(con->n); cpFloat r1ct = cpvcross(con->r1, t); cpFloat r2ct = cpvcross(con->r2, t); cpFloat kt = mass_sum + a->i_inv*r1ct*r1ct + b->i_inv*r2ct*r2ct; con->tMass = 1.0f/kt; // Calculate the target bias velocity. con->bias = -cp_bias_coef*dt_inv*cpfmin(0.0f, con->dist + cp_collision_slop); con->jBias = 0.0f; // Calculate the target bounce velocity. cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(con->r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(con->r2), b->w)); con->bounce = cpvdot(con->n, cpvsub(v2, v1))*arb->e; // Apply the previous accumulated impulse. cpVect j = cpvadd(cpvmult(con->n, con->jnAcc), cpvmult(t, con->jtAcc)); cpBodyApplyImpulse(a, cpvneg(j), con->r1); cpBodyApplyImpulse(b, j, con->r2); } } void cpArbiterApplyImpulse(cpArbiter *arb) { cpBody *a = arb->a->body; cpBody *b = arb->b->body; for(int i=0; inumContacts; i++){ cpContact *con = &arb->contacts[i]; cpVect n = con->n; cpVect r1 = con->r1; cpVect r2 = con->r2; // Calculate the relative bias velocities. cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n); // Calculate and clamp the bias impulse. cpFloat jbn = (con->bias - vbn)*con->nMass; cpFloat jbnOld = con->jBias; con->jBias = cpfmax(jbnOld + jbn, 0.0f); jbn = con->jBias - jbnOld; // Apply the bias impulse. cpVect jb = cpvmult(n, jbn); cpBodyApplyBiasImpulse(a, cpvneg(jb), r1); cpBodyApplyBiasImpulse(b, jb, r2); // Calculate the relative velocity. cpVect v1 = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); cpVect v2 = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); cpVect vr = cpvsub(v2, v1); cpFloat vrn = cpvdot(vr, n); // Calculate and clamp the normal impulse. cpFloat jn = -(con->bounce + vrn)*con->nMass; cpFloat jnOld = con->jnAcc; con->jnAcc = cpfmax(jnOld + jn, 0.0f); jn = con->jnAcc - jnOld; // Calculate the relative tangent velocity. cpVect t = cpvperp(n); cpFloat vrt = cpvdot(cpvadd(vr, arb->target_v), t); // Calculate and clamp the friction impulse. cpFloat jtMax = arb->u*con->jnAcc; cpFloat jt = -vrt*con->tMass; cpFloat jtOld = con->jtAcc; con->jtAcc = cpfmin(cpfmax(jtOld + jt, -jtMax), jtMax); jt = con->jtAcc - jtOld; // Apply the final impulse. cpVect j = cpvadd(cpvmult(n, jn), cpvmult(t, jt)); cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } } libtuxcap-1.4.0/tuxcap/chipmunk/cpCollision.h0000644000175000017500000000233710670737717021164 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ // Collides two cpShape structures. (this function is lonely :( ) int cpCollideShapes(cpShape *a, cpShape *b, cpContact **arr); libtuxcap-1.4.0/tuxcap/chipmunk/cpSpace.c0000644000175000017500000003072610712171657020252 0ustar inniyahinniyah/* Copyright (c) 2007 Scott Lembcke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include #include #include #include #include "chipmunk.h" int cp_contact_persistence = 3; // Equal function for contactSet. static int contactSetEql(void *ptr, void *elt) { cpShape **shapes = (cpShape **)ptr; cpShape *a = shapes[0]; cpShape *b = shapes[1]; cpArbiter *arb = (cpArbiter *)elt; return ((a == arb->a && b == arb->b) || (b == arb->a && a == arb->b)); } // Transformation function for contactSet. static void * contactSetTrans(void *ptr, void *data) { cpShape **shapes = (cpShape **)ptr; cpShape *a = shapes[0]; cpShape *b = shapes[1]; cpSpace *space = (cpSpace *)data; return cpArbiterNew(a, b, space->stamp); } // Collision pair function wrapper struct. typedef struct collFuncData { cpCollFunc func; void *data; } collFuncData; // Equals function for collFuncSet. static int collFuncSetEql(void *ptr, void *elt) { unsigned int *ids = (unsigned int *)ptr; unsigned int a = ids[0]; unsigned int b = ids[1]; cpCollPairFunc *pair = (cpCollPairFunc *)elt; return ((a == pair->a && b == pair->b) || (b == pair->a && a == pair->b)); } // Transformation function for collFuncSet. static void * collFuncSetTrans(void *ptr, void *data) { unsigned int *ids = (unsigned int *)ptr; collFuncData *funcData = (collFuncData *)data; cpCollPairFunc *pair = (cpCollPairFunc *)malloc(sizeof(cpCollPairFunc)); pair->a = ids[0]; pair->b = ids[1]; pair->func = funcData->func; pair->data = funcData->data; return pair; } // Default collision pair function. static int alwaysCollide(cpShape *a, cpShape *b, cpContact *arr, int numCon, cpFloat normal_coef, void *data) { return 1; } // BBfunc callback for the spatial hash. static cpBB bbfunc(void *ptr) { cpShape *shape = (cpShape *)ptr; return shape->bb; } // Iterator functions for destructors. static void freeWrap(void *ptr, void *unused){ free( ptr);} static void shapeFreeWrap(void *ptr, void *unused){ cpShapeFree((cpShape *) ptr);} static void arbiterFreeWrap(void *ptr, void *unused){ cpArbiterFree((cpArbiter *)ptr);} static void bodyFreeWrap(void *ptr, void *unused){ cpBodyFree((cpBody *) ptr);} static void jointFreeWrap(void *ptr, void *unused){ cpJointFree((cpJoint *) ptr);} cpSpace* cpSpaceAlloc(void) { return (cpSpace *)calloc(1, sizeof(cpSpace)); } #define DEFAULT_DIM_SIZE 100.0f #define DEFAULT_COUNT 1000 #define DEFAULT_ITERATIONS 10 cpSpace* cpSpaceInit(cpSpace *space) { space->iterations = DEFAULT_ITERATIONS; // space->sleepTicks = 300; space->gravity = cpvzero; space->damping = 1.0f; space->stamp = 0; space->staticShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, &bbfunc); space->activeShapes = cpSpaceHashNew(DEFAULT_DIM_SIZE, DEFAULT_COUNT, &bbfunc); space->bodies = cpArrayNew(0); space->arbiters = cpArrayNew(0); space->contactSet = cpHashSetNew(0, contactSetEql, contactSetTrans); space->joints = cpArrayNew(0); cpCollPairFunc pairFunc = {0, 0, alwaysCollide, NULL}; space->defaultPairFunc = pairFunc; space->collFuncSet = cpHashSetNew(0, collFuncSetEql, collFuncSetTrans); space->collFuncSet->default_value = &space->defaultPairFunc; return space; } cpSpace* cpSpaceNew(void) { return cpSpaceInit(cpSpaceAlloc()); } void cpSpaceDestroy(cpSpace *space) { cpSpaceHashFree(space->staticShapes); cpSpaceHashFree(space->activeShapes); cpArrayFree(space->bodies); cpArrayFree(space->joints); if(space->contactSet) cpHashSetEach(space->contactSet, &arbiterFreeWrap, NULL); cpHashSetFree(space->contactSet); cpArrayFree(space->arbiters); if(space->collFuncSet) cpHashSetEach(space->collFuncSet, &freeWrap, NULL); cpHashSetFree(space->collFuncSet); } void cpSpaceFree(cpSpace *space) { if(space) cpSpaceDestroy(space); free(space); } void cpSpaceFreeChildren(cpSpace *space) { cpSpaceHashEach(space->staticShapes, &shapeFreeWrap, NULL); cpSpaceHashEach(space->activeShapes, &shapeFreeWrap, NULL); cpArrayEach(space->bodies, &bodyFreeWrap, NULL); cpArrayEach(space->joints, &jointFreeWrap, NULL); } void cpSpaceAddCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b, cpCollFunc func, void *data) { unsigned int ids[] = {a, b}; unsigned int hash = CP_HASH_PAIR(a, b); // Remove any old function so the new one will get added. cpSpaceRemoveCollisionPairFunc(space, a, b); collFuncData funcData = {func, data}; cpHashSetInsert(space->collFuncSet, hash, ids, &funcData); } void cpSpaceRemoveCollisionPairFunc(cpSpace *space, unsigned int a, unsigned int b) { unsigned int ids[] = {a, b}; unsigned int hash = CP_HASH_PAIR(a, b); cpCollPairFunc *old_pair = (cpCollPairFunc *)cpHashSetRemove(space->collFuncSet, hash, ids); free(old_pair); } void cpSpaceSetDefaultCollisionPairFunc(cpSpace *space, cpCollFunc func, void *data) { cpCollPairFunc pairFunc = {0, 0, (func ? func : alwaysCollide), (func ? data : NULL)}; space->defaultPairFunc = pairFunc; } void cpSpaceAddShape(cpSpace *space, cpShape *shape) { cpSpaceHashInsert(space->activeShapes, shape, shape->id, shape->bb); } void cpSpaceAddStaticShape(cpSpace *space, cpShape *shape) { cpSpaceHashInsert(space->staticShapes, shape, shape->id, shape->bb); } void cpSpaceAddBody(cpSpace *space, cpBody *body) { cpArrayPush(space->bodies, body); } void cpSpaceAddJoint(cpSpace *space, cpJoint *joint) { cpArrayPush(space->joints, joint); } void cpSpaceRemoveShape(cpSpace *space, cpShape *shape) { cpSpaceHashRemove(space->activeShapes, shape, shape->id); } void cpSpaceRemoveStaticShape(cpSpace *space, cpShape *shape) { cpSpaceHashRemove(space->staticShapes, shape, shape->id); } void cpSpaceRemoveBody(cpSpace *space, cpBody *body) { cpArrayDeleteObj(space->bodies, body); } void cpSpaceRemoveJoint(cpSpace *space, cpJoint *joint) { cpArrayDeleteObj(space->joints, joint); } void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIterator func, void *data) { cpArray *bodies = space->bodies; for(int i=0; inum; i++) func((cpBody *)bodies->arr[i], data); } // Iterator function used for updating shape BBoxes. static void updateBBCache(void *ptr, void *unused) { cpShape *shape = (cpShape *)ptr; cpShapeCacheBB(shape); } void cpSpaceResizeStaticHash(cpSpace *space, cpFloat dim, int count) { cpSpaceHashResize(space->staticShapes, dim, count); cpSpaceHashRehash(space->staticShapes); } void cpSpaceResizeActiveHash(cpSpace *space, cpFloat dim, int count) { cpSpaceHashResize(space->activeShapes, dim, count); } void cpSpaceRehashStatic(cpSpace *space) { cpSpaceHashEach(space->staticShapes, &updateBBCache, NULL); cpSpaceHashRehash(space->staticShapes); } static inline int queryReject(cpShape *a, cpShape *b) { return // BBoxes must overlap !cpBBintersects(a->bb, b->bb) // Don't collide shapes attached to the same body. || a->body == b->body // Don't collide objects in the same non-zero group || (a->group && b->group && a->group == b->group) // Don't collide objects that don't share at least on layer. || !(a->layers & b->layers); } // Callback from the spatial hash. // TODO: Refactor this into separate functions? static int queryFunc(void *p1, void *p2, void *data) { // Cast the generic pointers from the spatial hash back to usefull types cpShape *a = (cpShape *)p1; cpShape *b = (cpShape *)p2; cpSpace *space = (cpSpace *)data; // Reject any of the simple cases if(queryReject(a,b)) return 0; // Shape 'a' should have the lower shape type. (required by cpCollideShapes() ) if(a->type > b->type){ cpShape *temp = a; a = b; b = temp; } // Find the collision pair function for the shapes. unsigned int ids[] = {a->collision_type, b->collision_type}; unsigned int hash = CP_HASH_PAIR(a->collision_type, b->collision_type); cpCollPairFunc *pairFunc = (cpCollPairFunc *)cpHashSetFind(space->collFuncSet, hash, ids); if(!pairFunc->func) return 0; // A NULL pair function means don't collide at all. // Narrow-phase collision detection. cpContact *contacts = NULL; int numContacts = cpCollideShapes(a, b, &contacts); if(!numContacts) return 0; // Shapes are not colliding. // The collision pair function requires objects to be ordered by their collision types. cpShape *pair_a = a; cpShape *pair_b = b; cpFloat normal_coef = 1.0f; // Swap them if necessary. if(pair_a->collision_type != pairFunc->a){ cpShape *temp = pair_a; pair_a = pair_b; pair_b = temp; normal_coef = -1.0f; } if(pairFunc->func(pair_a, pair_b, contacts, numContacts, normal_coef, pairFunc->data)){ // The collision pair function OKed the collision. Record the contact information. // Get an arbiter from space->contactSet for the two shapes. // This is where the persistant contact magic comes from. cpShape *shape_pair[] = {a, b}; cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->contactSet, CP_HASH_PAIR(a, b), shape_pair, space); // Timestamp the arbiter. arb->stamp = space->stamp; arb->a = a; arb->b = b; // TODO: Investigate why this is still necessary? // Inject the new contact points into the arbiter. cpArbiterInject(arb, contacts, numContacts); // Add the arbiter to the list of active arbiters. cpArrayPush(space->arbiters, arb); return numContacts; } else { // The collision pair function rejected the collision. free(contacts); return 0; } } // Iterator for active/static hash collisions. static void active2staticIter(void *ptr, void *data) { cpShape *shape = (cpShape *)ptr; cpSpace *space = (cpSpace *)data; cpSpaceHashQuery(space->staticShapes, shape, shape->bb, &queryFunc, space); } // Hashset reject func to throw away old arbiters. static int contactSetReject(void *ptr, void *data) { cpArbiter *arb = (cpArbiter *)ptr; cpSpace *space = (cpSpace *)data; if((space->stamp - arb->stamp) > cp_contact_persistence){ cpArbiterFree(arb); return 0; } return 1; } void cpSpaceStep(cpSpace *space, cpFloat dt) { if(!dt) return; // prevents div by zero. cpFloat dt_inv = 1.0f/dt; cpArray *bodies = space->bodies; cpArray *arbiters = space->arbiters; cpArray *joints = space->joints; // Empty the arbiter list. cpHashSetReject(space->contactSet, &contactSetReject, space); space->arbiters->num = 0; // Integrate velocities. cpFloat damping = pow(1.0f/space->damping, -dt); for(int i=0; inum; i++) cpBodyUpdateVelocity((cpBody *)bodies->arr[i], space->gravity, damping, dt); // Pre-cache BBoxes and shape data. cpSpaceHashEach(space->activeShapes, &updateBBCache, NULL); // Collide! cpSpaceHashEach(space->activeShapes, &active2staticIter, space); cpSpaceHashQueryRehash(space->activeShapes, &queryFunc, space); // Prestep the arbiters. for(int i=0; inum; i++) cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt_inv); // Prestep the joints. for(int i=0; inum; i++){ cpJoint *joint = (cpJoint *)joints->arr[i]; joint->preStep(joint, dt_inv); } // Run the impulse solver. for(int i=0; iiterations; i++){ for(int j=0; jnum; j++) cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]); for(int j=0; jnum; j++){ cpJoint *joint = (cpJoint *)joints->arr[j]; joint->applyImpulse(joint); } } // cpFloat dvsq = cpvdot(space->gravity, space->gravity); // dvsq *= dt*dt * space->damping*space->damping; // for(int i=0; inum; i++) // cpBodyMarkLowEnergy(bodies->arr[i], dvsq, space->sleepTicks); // Integrate positions. for(int i=0; inum; i++) cpBodyUpdatePosition((cpBody *)bodies->arr[i], dt); // Increment the stamp. space->stamp++; } libtuxcap-1.4.0/tuxcap/pythondemo1/0000755000175000017500000000000011212652053017137 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/pythondemo1/CMakeLists.txt0000644000175000017500000000407410762446645021725 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${PYTHON_INCLUDE_PATH} ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle ${libtuxcap_SOURCE_DIR}/tuxcap/pycap ) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../pythondemo1/Pythondemo1") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/pythondemo1/main.cpp0000644000175000017500000000032511062277514020577 0ustar inniyahinniyah#include "PycapApp.h" using namespace Sexy; int main(int argc, char** argv) { PycapApp app; SetAppResourceFolder("../images"); app.Init(argc, argv, false); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/pycap/0000755000175000017500000000000011212652053016004 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/pycap/PycapBoard.cpp0000644000175000017500000002574611112340453020547 0ustar inniyahinniyah//-------------------------------------------------- // PycapBoard // // Base game board for Pycap // Manages hooks to python game code // // Jarrad 'Farbs' Woods // W.P. van Paassen //-------------------------------------------------- // includes #include "PycapBoard.h" #include "PycapApp.h" #include "Graphics.h" #include #include // namespace using namespace Sexy; // functions //-------------------------------------------------- // PycapBoard //-------------------------------------------------- PycapBoard::PycapBoard() { // call python game init function PyObject* pInitFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "init" ); if ( pInitFunc ) { if ( PyCallable_Check( pInitFunc ) ) { PyObject_CallObject( pInitFunc, NULL ); } else { //PycapApp::sApp->Popup( StrFormat( "\"init\" found, but not callable" ) ); } } // grab frequently used python functions pUpdateFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "update" ); pDrawFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "draw" ); pKeyDownFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "keyDown" ); pKeyUpFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "keyUp" ); pExitGame = PyDict_GetItemString( PycapApp::sApp->pDict, "exitGame" ); pMouseEnterFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseEnter" ); pMouseLeaveFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseLeave" ); pMouseMoveFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseMove" ); pMouseDownFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseDown" ); pMouseUpFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseUp" ); pMouseWheelFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "mouseWheel" ); // legacy spelling if( !pKeyDownFunc ) pKeyDownFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "keydown" ); if( !pKeyUpFunc ) pKeyUpFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "keyup" ); // init remaining members graphics = NULL; // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in PycapBoard()" ); PyErr_Print(); return; } // request initial draw MarkDirty(); } //-------------------------------------------------- // ~PycapBoard //-------------------------------------------------- PycapBoard::~PycapBoard() { // call python shutdown function PyObject* pFiniFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "fini" ); if ( pFiniFunc && PyCallable_Check( pFiniFunc ) ) { PyObject_CallObject( pFiniFunc, NULL ); } // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in ~PycapBoard()" ); PyErr_Print(); } } //-------------------------------------------------- // Update //-------------------------------------------------- void PycapBoard::UpdateF( float delta ) { // call parent Widget::UpdateF( delta ); // Python exit-check // Checked on entering incase a non-update function has set it if ( pExitGame ) { PyObject* pExit = PyObject_CallObject( pExitGame, NULL ); if ( PyInt_Check( pExit ) && PyInt_AsLong( pExit ) != 0 ) { // drop the return value Py_DECREF( pExit ); // exit the program PycapApp::sApp->mShutdown = true; // no need to update return; } // drop the return value Py_DECREF( pExit ); } // Python update hook // The python code should call dirty if the screen needs to be redrawn if ( pUpdateFunc ) { PyObject* pArgs = PyTuple_New(1); PyObject* pDelta = PyFloat_FromDouble( delta ); PyTuple_SetItem( pArgs, 0, pDelta ); PyObject_CallObject( pUpdateFunc, pArgs ); Py_DECREF( pDelta ); Py_DECREF( pArgs ); } // Python exit-check // Checked on exiting updatef incase it has set it if ( pExitGame ) { PyObject* pExit = PyObject_CallObject( pExitGame, NULL ); if ( PyInt_Check( pExit ) && PyInt_AsLong( pExit ) != 0 ) { // drop the return value Py_DECREF( pExit ); // exit the program PycapApp::sApp->mShutdown = true; // no need to update return; } // drop the return value Py_DECREF( pExit ); } // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in Update" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // Draw //-------------------------------------------------- void PycapBoard::Draw( Graphics *g ) { // exit early if no python draw function if ( !pDrawFunc ) return; // enter draw code graphics = g; // call draw function PyObject_CallObject( pDrawFunc, NULL ); // exit draw code graphics = NULL; // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in Draw" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // KeyDown //-------------------------------------------------- void PycapBoard::KeyDown( KeyCode key ) { // exit early if no python keydown function if ( !pKeyDownFunc ) return; // Python keydown hook PyObject* pArgs = PyTuple_New(1); PyObject* pKey = PyInt_FromLong( key ); PyTuple_SetItem( pArgs, 0, pKey ); PyObject_CallObject( pKeyDownFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in KeyDown" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // KeyUp //-------------------------------------------------- void PycapBoard::KeyUp( KeyCode key ) { // exit early if no python keyup function if ( !pKeyUpFunc ) return; // Python keyup hook PyObject* pArgs = PyTuple_New(1); PyObject* pKey = PyInt_FromLong( key ); PyTuple_SetItem( pArgs, 0, pKey ); PyObject_CallObject( pKeyUpFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in KeyUp" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // MouseEnter //-------------------------------------------------- void PycapBoard::MouseEnter() { // call python function if it exists if( pMouseEnterFunc ) PyObject_CallObject( pMouseEnterFunc, NULL ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseEnter" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // MouseLeave //-------------------------------------------------- void PycapBoard::MouseLeave() { // call python function if it exists if( pMouseLeaveFunc ) PyObject_CallObject( pMouseLeaveFunc, NULL ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseLeave" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } //-------------------------------------------------- // MouseMove //-------------------------------------------------- void PycapBoard::MouseMove( int x, int y ) { // Python mouse move hook if( pMouseMoveFunc ) { PyObject* pArgs = PyTuple_New(2); PyObject* pX = PyInt_FromLong( x ); PyObject* pY = PyInt_FromLong( y ); PyTuple_SetItem( pArgs, 0, pX ); PyTuple_SetItem( pArgs, 1, pY ); PyObject_CallObject( pMouseMoveFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseMove" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } } //-------------------------------------------------- // MouseDrag //-------------------------------------------------- void PycapBoard::MouseDrag( int x, int y ) { // This gets called instead of mousemove when dragging. // For our purposes, they're the same... so do the same thing! MouseMove( x, y ); } //-------------------------------------------------- // MouseDown //-------------------------------------------------- void PycapBoard::MouseDown(int x, int y, int theBtnNum, int theClickCount) { // Python mouse down hook if( pMouseDownFunc ) { PyObject* pArgs = PyTuple_New(3); PyObject* pX = PyInt_FromLong( x ); PyObject* pY = PyInt_FromLong( y ); PyObject* pButton = PyInt_FromLong( theBtnNum ); PyTuple_SetItem( pArgs, 0, pX ); PyTuple_SetItem( pArgs, 1, pY ); PyTuple_SetItem( pArgs, 2, pButton ); PyObject_CallObject( pMouseDownFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseDown" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } } //-------------------------------------------------- // MouseUp //-------------------------------------------------- void PycapBoard::MouseUp(int x, int y, int theBtnNum, int theClickCount) { // Python mouse up hook if( pMouseUpFunc ) { PyObject* pArgs = PyTuple_New(3); PyObject* pX = PyInt_FromLong( x ); PyObject* pY = PyInt_FromLong( y ); PyObject* pButton = PyInt_FromLong( theBtnNum ); PyTuple_SetItem( pArgs, 0, pX ); PyTuple_SetItem( pArgs, 1, pY ); PyTuple_SetItem( pArgs, 2, pButton ); PyObject_CallObject( pMouseUpFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseUp" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } } //-------------------------------------------------- // MouseWheel //-------------------------------------------------- void PycapBoard::MouseWheel( int delta) { // Python mouse move hook if( pMouseWheelFunc ) { PyObject* pArgs = PyTuple_New(1); PyObject* pX = PyInt_FromLong( delta ); PyTuple_SetItem( pArgs, 0, pX ); PyObject_CallObject( pMouseWheelFunc, pArgs ); Py_DECREF( pArgs ); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in MouseWheel" ); PyErr_Print(); PycapApp::sApp->mShutdown = true; } } } libtuxcap-1.4.0/tuxcap/pycap/PycapApp.cpp0000644000175000017500000013563211112340453020234 0ustar inniyahinniyah//-------------------------------------------------- // PycapApp // // Pycap application object // // Jarrad 'Farbs' Woods // W.P. van Paassen // Tony Oakden //-------------------------------------------------- // includes #include #include "PycapApp.h" #include "PycapBoard.h" #include "WidgetManager.h" #include "Graphics.h" #include "Font.h" #include "SoundManager.h" #include "SoundInstance.h" #include "MusicInterface.h" #include "KeyCodes.h" #include "Common.h" #include "DDImage.h" #include "SexyMatrix.h" #include "Rect.h" #ifndef INITGUID #define INITGUID #endif #include // namespace using namespace Sexy; // static data definition PycapApp* PycapApp::sApp = NULL; // functions //-------------------------------------------------- // PycapApp //-------------------------------------------------- PycapApp::PycapApp() { // own members sApp = this; mBoard = NULL; mResources = NULL; mResFailed = false; mPythonPathSet = false; mPythonHomeSet = false; mBundled = false; //------------------- } //-------------------------------------------------- // ~PycapApp //-------------------------------------------------- PycapApp::~PycapApp() { // clean up board if necessary if( mBoard != NULL ) { mWidgetManager->RemoveWidget( mBoard ); delete mBoard; } // clean up resources object if( mResources != NULL ) { delete mResources; } // clean up app pointer if it's pointing to this if( sApp == this ) { sApp = NULL; } // clean up python Py_DECREF(pModule); // drop the module Py_Finalize(); // shut down the interpreter if (mBundled) { unsetenv("PYTHONPATH"); unsetenv("PYTHONHOME"); if (mPythonHomeSet) setenv("PYTHONHOME", mPythonHome.c_str(), 0); if (mPythonPathSet) setenv("PYTHONPATH", mPythonPath.c_str(), 0); } } //-------------------------------------------------- // Init //-------------------------------------------------- void PycapApp::Init(int argc, char*argv[], bool bundled) { // Set up python mBundled = bundled; if (mBundled) { char* env = getenv("PYTHONPATH"); if (env != NULL) { mPythonPathSet = true; mPythonPath = std::string(env); unsetenv("PYTHONPATH"); } env = getenv("PYTHONHOME"); if (env != NULL) { mPythonHomeSet = true; mPythonHome = std::string(env); unsetenv("PYTHONHOME"); } std::string dirname = GetFullPath(argv[0]); setenv("PYTHONPATH", GetFileDir(dirname).c_str(), 0); setenv("PYTHONHOME", dirname.c_str(), 0); } Py_Initialize(); PyRun_SimpleString("import sys"); if (GetAppResourceFolder() != "") { PyRun_SimpleString(("sys.path.append(\"" + GetAppResourceFolder() +"\")").c_str()); } else { SetAppResourceFolder(GetFileDir(std::string(argv[0]), true)); } if (!mBundled) { PyRun_SimpleString("import os"); PyRun_SimpleString(("sys.path.insert(0,os.path.abspath(os.path.dirname(\"" + std::string(argv[0]) + "\")))").c_str()); } // PyRun_SimpleString("print sys.path"); // Set up Pycap module static PyMethodDef resMethods[] = { {"markDirty", pMarkDirty, METH_VARARGS, "markDirty()\nMark the screen dirty & call a refresh."}, {"fillRect", pFillRect, METH_VARARGS, "fillRect( x, y, width, height )\nFill a specified rect with the current colour."}, {"setColour", pSetColour, METH_VARARGS, "setColour( red, green, blue, alpha )\nSet the draw colour. Use a value between 0 and 255 for each component."}, {"setFont", pSetFont, METH_VARARGS, "setFont( font )\nSet the active font."}, {"setColourize", pSetColourize, METH_VARARGS, "setColourize( on )\nEnable/Disable colourized drawing."}, {"drawLine", pDrawLine, METH_VARARGS, "draw a line using the start en end position"}, {"drawTri", pDrawTri, METH_VARARGS, "Fills a triangle"}, {"drawQuad", pDrawQuad, METH_VARARGS, "Fills a quad"}, {"drawImage", pDrawImage, METH_VARARGS, "drawImage( image, x, y )\nDraw an image resource at pixel coords."}, {"drawImageF", pDrawImageF, METH_VARARGS, "drawImageF( image, fx, fy )\nDraw an image resource at float coords."}, {"drawImageRot", pDrawImageRot, METH_VARARGS, "drawImageRot( image, x, y, angle )\nDraw an image resource at pixel coords rotated by a given angle."}, {"drawImageRotF", pDrawImageRotF, METH_VARARGS, "drawImageRot( image, x, y, angle )\nDraw an image resource at float coords rotated by a given angle."}, {"drawImageRotScaled", pDrawImageRotScaled, METH_VARARGS, "Rotate, scale and draw an image resource at float coords."}, {"drawImageScaled", pDrawImageScaled, METH_VARARGS, "drawImageScaled( image, x, y, width, height )\nScale and draw an image resource at int coords."}, {"drawString", pDrawString, METH_VARARGS, "drawString( string, x, y )\nWrite a given string to the screen using the current font."}, {"showMouse", pShowMouse, METH_VARARGS, "showMouse( show )\nShow or hide the mouse cursor."}, {"drawmodeNormal", pDrawmodeNormal, METH_VARARGS, "drawmodeNormal()\nSet the drawing mode to normal."}, {"drawmodeAdd", pDrawmodeAdd, METH_VARARGS, "drawmodeAdd()\nSet the drawing mode to additive."}, {"playSound", pPlaySound, METH_VARARGS, "playSound( sound, volume, panning, pitch )\nPlay a sound, providing id, and optionally volume, panning, and pitch adjust."}, {"readReg", pReadReg, METH_VARARGS, "readReg( key )\nRead an entry from the system registry."}, {"writeReg", pWriteReg, METH_VARARGS, "writeReg( key, data )\nWrite an entry to the system registry."}, {"playTune", pPlayTune, METH_VARARGS, "playTune( tune, loopCount )\nPlay a music tune, with optional loop parameter."}, {"stopTune", pStopTune, METH_VARARGS, "stopTune( tune )\nStop playing a musictune. If not specified, all tunes are stopped."}, {"setTuneVolume", pSetTuneVolume, METH_VARARGS, "setTuneVolume( index, volume )\nChange the volume for a song"}, {"setVolume", pSetVolume, METH_VARARGS, "setVolume( volume )\nChange the global volume for all music"}, {"setClipRect", pSetClipRect, METH_VARARGS, "setClipRect( x, y, width, height )\nSet the clipping rectangle."}, {"clearClipRect", pClearClipRect, METH_VARARGS, "clearClipRect()\nClear the clipping rectangle."}, {"setTranslation", pSetTranslation, METH_VARARGS, "setTranslation( x, y )\nSet the translation applied to all draw calls."}, {"setFullscreen", pSetFullscreen, METH_VARARGS, "setFullscreen( fullscreen )\nSet whether the app should be in fullscreen or windowed mode."}, {"getFullscreen", pGetFullscreen, METH_VARARGS, "getFullscreen()\nGet whether the app is in fullscreen or windowed mode."}, {"getKeyCode", pGetKeyCode, METH_VARARGS, "getKeyCode\n."}, {"allowAllAccess", pAllowAllAccess, METH_VARARGS, "allowAllAccess( fileName )\nTell the OS that all users can view and modify a file. Required for Vista."}, {"getAppDataFolder", pGetAppDataFolder, METH_VARARGS, "getAppDataFolder()\nGet the folder that game data should be saved to. Required for Vista."}, {"getAppResourceFolder", pGetAppResourceFolder, METH_VARARGS, "getAppResourceFolder()\nGet the folder where the game resources are stored. Required for GNU/Linux."}, {"getIs3DAccelerated", pGetIs3DAccelerated, METH_VARARGS, "getIs3DAccelerated()\nReturns if the game has 3D acceleration enabled"}, {"set3DAccelerated", pSet3DAccelerated, METH_VARARGS, "set whether application has 3D acceleration enabled or not"}, {"isKeyDown", pIsKeyDown, METH_VARARGS, "isKeyDown()\nReturns a boolean indicating if the queried key is down"}, {NULL, NULL, 0, NULL} }; Py_InitModule("Pycap", resMethods); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in PycapApp(), while importing Pycap module." ); PyErr_Print(); return; } // Open game module PyObject *pName; pName = PyString_FromString( "game" ); if (pName == NULL) { PyErr_SetString( PyExc_StandardError, "Failed to create PyString game.py." ); PyErr_Print(); return; } pModule = PyImport_Import(pName); if (pModule == NULL) { PyErr_SetString( PyExc_StandardError, "Failed to import game.py." ); PyErr_Print(); return; // we're screwed. } Py_DECREF(pName); pDict = PyModule_GetDict(pModule); // grab namespace dictionary //------------------- // Initialize members // inherited // read inherited members from python dictionary PyObject *iniDict; iniDict = PyDict_GetItemString( pDict, "appIni" ); if ( iniDict && PyDict_Check( iniDict ) ) { PyObject *inObject; inObject = PyDict_GetItemString( iniDict, "mCompanyName" ); if ( inObject && PyString_Check( inObject ) ) { mCompanyName = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mCompanyName correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mFullCompanyName" ); if ( inObject && PyString_Check( inObject ) ) { mFullCompanyName = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mFullCompanyName correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mProdName" ); if ( inObject && PyString_Check( inObject ) ) { mProdName = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mProdName correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mProductVersion" ); if ( inObject && PyString_Check( inObject ) ) { mProductVersion = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mProductVersion correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mTitle" ); if ( inObject && PyString_Check( inObject ) ) { mTitle = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mTitle correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mRegKey" ); if ( inObject && PyString_Check( inObject ) ) { mRegKey = PyString_AsString( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mRegKey correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mWidth" ); if ( inObject && PyInt_Check( inObject ) ) { mWidth = PyInt_AsLong( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mWidth correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mHeight" ); if ( inObject && PyInt_Check( inObject ) ) { mHeight = PyInt_AsLong( inObject ); } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mHeight correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mAutoEnable3D" ); if ( inObject && PyInt_Check( inObject ) ) { mAutoEnable3D = PyInt_AsLong( inObject ) == 1; } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mAutoEnable3D correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mVSyncUpdates" ); if ( inObject && PyInt_Check( inObject ) ) { mVSyncUpdates = PyInt_AsLong( inObject ) == 1; } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mVSyncUpdates correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mTest3D" ); if ( inObject && PyInt_Check( inObject ) ) { mTest3D = PyInt_AsLong( inObject ) == 1; } inObject = PyDict_GetItemString( iniDict, "mWaitForVSync" ); if ( inObject && PyInt_Check( inObject ) ) { mWaitForVSync = PyInt_AsLong( inObject ) == 1; } else { PyErr_SetString( PyExc_StandardError, "appIni doesn't specify mWaitForVSync correctly" ); PyErr_Print(); return; } inObject = PyDict_GetItemString( iniDict, "mWindowIconBMP" ); if ( inObject && PyString_Check( inObject ) ) { mWindowIconBMP = PyString_AsString( inObject ); } } else { PyErr_SetString( PyExc_StandardError, "appIni object is missing or not a dict" ); PyErr_Print(); return; } if (mRegKey.empty()) { mRegKey = "TuxCap"; } // call parent SexyAppBase::Init(); PyRun_SimpleString(("sys.path.append(\"" + GetAppDataFolder() + "\")").c_str()); // Redirect stdout and stderr to files (since we can't seem to use console output) if (!FileExists(GetAppDataFolder() + "out.txt")) { MkDir(GetAppDataFolder()); CreateFile(GetAppDataFolder() + "out.txt"); CreateFile(GetAppDataFolder() + "err.txt"); } PyRun_SimpleString( ( "sys.stdout = open( \"" + GetAppDataFolder() + "out.txt\", 'w' )" ).c_str() ); PyRun_SimpleString( ( "sys.stderr = open( \"" + GetAppDataFolder() + "err.txt\", 'w' )" ).c_str() ); } //-------------------------------------------------- // LoadingThreadProc //-------------------------------------------------- void PycapApp::LoadingThreadProc() { // call parent (empty at the moment, but a good habit) SexyAppBase::LoadingThreadProc(); // create the res object mResources = new PycapResources(); } //-------------------------------------------------- // LoadingThreadCompleted //-------------------------------------------------- void PycapApp::LoadingThreadCompleted() { // call parent SexyAppBase::LoadingThreadCompleted(); // check for a failed resource load (not using mLoadingFailed as this terminates the app badly) if( mResFailed ) { // Nothing much happens if we return before adding the board... just a black screen // Error message widget should be added here PyErr_SetString( PyExc_StandardError, "The game did not load properly. Sorry, but it's not going to work." ); PyErr_Print(); return; } // create the initial board object PycapBoard* newBoard = new PycapBoard(); // remove current board if appropriate if( mBoard != NULL ) { mWidgetManager->RemoveWidget( mBoard ); } // store link mBoard = newBoard; // resize the board to the application size newBoard->Resize( 0, 0, PycapApp::sApp->mWidth, PycapApp::sApp->mHeight ); // add the board widget mWidgetManager->AddWidget( newBoard ); // give the board focus mWidgetManager->SetFocus( newBoard ); } //-------------------------------------------------- // GotFocus //-------------------------------------------------- void PycapApp::GotFocus() { PyObject* pGFFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "gotFocus" ); if ( pGFFunc && PyCallable_Check( pGFFunc ) ) { PyObject_CallObject( pGFFunc, NULL ); } } //-------------------------------------------------- // LostFocus //-------------------------------------------------- void PycapApp::LostFocus() { PyObject* pLFFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "lostFocus" ); if ( pLFFunc && PyCallable_Check( pLFFunc ) ) { PyObject_CallObject( pLFFunc, NULL ); } } //-------------------------------------------------- // SwitchScreenMode //-------------------------------------------------- void PycapApp::SwitchScreenMode( bool wantWindowed, bool is3d ) { // Super SexyAppBase::SwitchScreenMode( wantWindowed, is3d ); // attempt to call python fullscreen or windowed notifier // failed attempts still notify, but notify correctly if ( mIsWindowed ) { // windowed PyObject* pWFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "onWindowed" ); if ( pWFunc && PyCallable_Check( pWFunc ) ) { PyObject_CallObject( pWFunc, NULL ); } } else { // fullscreen PyObject* pFSFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "onFullscreen" ); if ( pFSFunc && PyCallable_Check( pFSFunc ) ) { PyObject_CallObject( pFSFunc, NULL ); } } } //-------------------------------------------------- // pMarkDirty //-------------------------------------------------- PyObject* PycapApp::pMarkDirty( PyObject* self, PyObject* args ) { // mark the board as dirty sApp->mBoard->MarkDirty(); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetColour //-------------------------------------------------- PyObject* PycapApp::pSetColour( PyObject* self, PyObject* args ) { // parse the arguments int r, g, b, a; if( !PyArg_ParseTuple( args, "iiii", &r, &g, &b, &a ) ) { PyErr_SetString( PyExc_StandardError, "setColour: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "SetColour() failed: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // create new colour object, set colour graphics->SetColor( Color( r, g, b, a ) ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetFont //-------------------------------------------------- PyObject* PycapApp::pSetFont( PyObject* self, PyObject* args ) { // parse the arguments int i; if( !PyArg_ParseTuple( args, "i", &i ) ) { PyErr_SetString( PyExc_StandardError, "setFont: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "setFont() failed: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the font Font* font = sApp->mResources->getFont( i ); if( !font ) { // throw an exception PyErr_SetString( PyExc_StandardError, "setFont: Failed to reference font." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // set the active font graphics->SetFont( font ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetColourize //-------------------------------------------------- PyObject* PycapApp::pSetColourize( PyObject* self, PyObject* args ) { // parse the arguments int colourize; if( !PyArg_ParseTuple( args, "i", &colourize ) ) { PyErr_SetString( PyExc_StandardError, "setColourize: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "setColourize: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // create new colour object, set colour graphics->SetColorizeImages( colourize != 0 ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pFillRect //-------------------------------------------------- PyObject* PycapApp::pFillRect( PyObject* self, PyObject* args ) { // parse the arguments int x, y, w, h; if( !PyArg_ParseTuple( args, "iiii", &x, &y, &w, &h ) ) { PyErr_SetString( PyExc_StandardError, "fillRect: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "fillRect: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // create new colour object, set colour graphics->FillRect( x, y, w, h ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawLine //-------------------------------------------------- PyObject* PycapApp::pDrawLine( PyObject* self, PyObject* args ) { // parse the arguments int sx, sy, ex, ey; if( !PyArg_ParseTuple( args, "iiii", &sx, &sy, &ex, &ey ) ) { PyErr_SetString( PyExc_StandardError, "drawLine: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawLine: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // draw the line graphics->DrawLine(sx, sy, ex, ey); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawImage //-------------------------------------------------- PyObject* PycapApp::pDrawImage( PyObject* self, PyObject* args ) { // parse the arguments int i, x, y; if( !PyArg_ParseTuple( args, "iii", &i, &x, &y ) ) { PyErr_SetString( PyExc_StandardError, "drawImage: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImage: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "drawImage: Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // perform the blit graphics->DrawImage( image, x, y ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawImageF //-------------------------------------------------- PyObject* PycapApp::pDrawImageF( PyObject* self, PyObject* args ) { // parse the arguments int i; float x, y; if( !PyArg_ParseTuple( args, "iff", &i, &x, &y ) ) { PyErr_SetString( PyExc_StandardError, "drawImageF: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImageF: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "drawImageF: Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // perform the blit graphics->DrawImageF( image, x, y ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawImageRot //-------------------------------------------------- PyObject* PycapApp::pDrawImageRot( PyObject* self, PyObject* args ) { // parse the arguments int i; float x, y, r; if( !PyArg_ParseTuple( args, "ifff", &i, &x, &y, &r ) ) { PyErr_SetString( PyExc_StandardError, "drawImageRot: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImageRot: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "drawImageRot: Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // perform the blit graphics->DrawImageRotated( image, (int)x, (int)y, r ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawImageRotF //-------------------------------------------------- PyObject* PycapApp::pDrawImageRotF( PyObject* self, PyObject* args ) { // parse the arguments int i; float x, y, r; if( !PyArg_ParseTuple( args, "ifff", &i, &x, &y, &r ) ) { PyErr_SetString( PyExc_StandardError, "drawImageRotF: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImageRotF: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "drawImageRotF: Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // perform the blit graphics->DrawImageRotatedF( image, x, y, r ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawImageScaled //-------------------------------------------------- PyObject* PycapApp::pDrawImageScaled( PyObject* self, PyObject* args ) { // parse the arguments int i; float x, y, w, h; if( !PyArg_ParseTuple( args, "iffff", &i, &x, &y, &w, &h ) ) { PyErr_SetString( PyExc_StandardError, "drawImageScaled: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImageScaled: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "drawImageScaled:Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // perform the blit if (sApp->Is3DAccelerated()) graphics->DrawImage( image, (int)x, (int)y, (int)w, (int)h ); else { if (w < 0.0) { w = -w; graphics->DrawImageMirror(image, Rect((int)(x - w),(int)y,(int)w,(int)h), Rect(0,0, image->mWidth, image->mHeight), true); } else { graphics->DrawImage( image, (int)x, (int)y, (int)w, (int)h ); } } // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawString //-------------------------------------------------- PyObject* PycapApp::pDrawString( PyObject* self, PyObject* args ) { // parse the arguments char* string; float x, y; if( !PyArg_ParseTuple( args, "sff", &string, &x, &y ) ) { PyErr_SetString( PyExc_StandardError, "drawString: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawString: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // perform the blit graphics->DrawString( string, (int)x, (int)y ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pShowMouse //-------------------------------------------------- PyObject* PycapApp::pShowMouse( PyObject* self, PyObject* args ) { // parse the arguments int show; if( !PyArg_ParseTuple( args, "i", &show ) ) { PyErr_SetString( PyExc_StandardError, "showMouse: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // test argument if( show ) { sApp->SetCursor( CURSOR_POINTER ); } else { sApp->SetCursor( CURSOR_NONE ); } // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawmodeNormal //-------------------------------------------------- PyObject* PycapApp::pDrawmodeNormal( PyObject* self, PyObject* args ) { // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawmodeNormal: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // set the draw mode graphics->SetDrawMode( Graphics::DRAWMODE_NORMAL ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawmodeAdd //-------------------------------------------------- PyObject* PycapApp::pDrawmodeAdd( PyObject* self, PyObject* args ) { // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawmodeAdd: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // set the draw mode graphics->SetDrawMode( Graphics::DRAWMODE_ADDITIVE ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pPlaySound //-------------------------------------------------- PyObject* PycapApp::pPlaySound( PyObject* self, PyObject* args ) { // parse the arguments // required int index; // optional float volume = 1.0f; float panning = 0.0f; float pitchAdjust = 0.0f; if( !PyArg_ParseTuple( args, "i|fff", &index, &volume, &panning, &pitchAdjust ) ) { PyErr_SetString( PyExc_StandardError, "playSound: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that the sound exists if( !sApp->mResources->soundExists( index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to reference sound." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // set the sound parameters SoundInstance* sound = sApp->mSoundManager->GetSoundInstance( index ); if( sound ) { sound->SetVolume( volume ); sound->SetPan( int( panning * 1000.0f ) ); sound->AdjustPitch( pitchAdjust ); // play the sound sound->Play( false, true ); // Play sound. Always auto-release the instance. } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to reference sound." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pReadReg //-------------------------------------------------- PyObject* PycapApp::pReadReg( PyObject* self, PyObject* args ) { // parse the arguments char* key; if( !PyArg_ParseTuple( args, "s", &key ) ) { PyErr_SetString( PyExc_StandardError, "readReg: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // attempt to read the string std::string string; if( sApp->RegistryReadString( key, &string ) ) { // return string from registry return Py_BuildValue( "s", string.c_str() ); } Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pWriteReg //-------------------------------------------------- PyObject* PycapApp::pWriteReg( PyObject* self, PyObject* args ) { // parse the arguments char* key; char* string; if( !PyArg_ParseTuple( args, "ss", &key, &string ) ) { PyErr_SetString( PyExc_StandardError, "writeReg: failed to parse arguments" ); PyErr_Print(); return Py_BuildValue( "i", 0 ); } // attempt to write the string // return whether or not we succeeded ('tho I'll probably just ignore it most of the time) if( sApp->RegistryWriteString( key, string ) ) { // success return Py_BuildValue( "i", 1 ); } else { // failure return Py_BuildValue( "i", 0 ); } } //-------------------------------------------------- // pPlayTune //-------------------------------------------------- PyObject* PycapApp::pPlayTune( PyObject* self, PyObject* args ) { // parse the arguments int i; int repeatCount = 0; //do not loop if( !PyArg_ParseTuple( args, "i|i", &i, &repeatCount ) ) { PyErr_SetString( PyExc_StandardError, "playTune: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } int index = sApp->mResources->getTune( i ); if( index == -1 ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to reference tune." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } sApp->mMusicInterface->PlayMusic( i, 0, repeatCount == 0); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pStopTune //-------------------------------------------------- PyObject* PycapApp::pStopTune( PyObject* self, PyObject* args ) { // parse the arguments int i = -1; if( !PyArg_ParseTuple( args, "|i", &i ) ) { PyErr_SetString( PyExc_StandardError, "stopTune: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } int index = sApp->mResources->getTune( i ); if( index == -1 ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to reference tune." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } sApp->mMusicInterface->StopMusic( i ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetVolume //-------------------------------------------------- PyObject* PycapApp::pSetVolume( PyObject* self, PyObject* args ) { // parse the arguments float vol; if( !PyArg_ParseTuple( args, "f", &vol ) ) { PyErr_SetString( PyExc_StandardError, "setVolume: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } sApp->mMusicInterface->SetVolume( (double)vol); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetTuneVolume //-------------------------------------------------- PyObject* PycapApp::pSetTuneVolume( PyObject* self, PyObject* args ) { // parse the arguments int index; float vol; if( !PyArg_ParseTuple( args, "if", &index, &vol ) ) { PyErr_SetString( PyExc_StandardError, "setTuneVolume: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } sApp->mMusicInterface->SetSongVolume( index, (double)vol); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetClipRect //-------------------------------------------------- PyObject* PycapApp::pSetClipRect( PyObject* self, PyObject* args ) { // parse the arguments int x, y, w, h; if( !PyArg_ParseTuple( args, "iiii", &x, &y, &w, &h ) ) { PyErr_SetString( PyExc_StandardError, "setClipRect: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "setClipRect: Not currently drawing" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // set the clip region graphics->SetClipRect( x,y,w,h ); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pClearClipRect //-------------------------------------------------- PyObject* PycapApp::pClearClipRect( PyObject* self, PyObject* args ) { // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "ClearClipRect() failed: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // clear the clip region graphics->ClearClipRect(); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetTranslation //-------------------------------------------------- PyObject* PycapApp::pSetTranslation( PyObject* self, PyObject* args ) { // parse the arguments int x, y; if( !PyArg_ParseTuple( args, "ii", &x, &y ) ) { PyErr_SetString( PyExc_StandardError, "setTranslation: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "setTranslation: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // set the translation graphics->mTransX = x; graphics->mTransY = y; // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSetFullscreen //-------------------------------------------------- PyObject* PycapApp::pSetFullscreen( PyObject* self, PyObject* args ) { // parse the arguments int fullscreen; if( !PyArg_ParseTuple( args, "i", &fullscreen ) ) { PyErr_SetString( PyExc_StandardError, "setFullScreen: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // Super sApp->SwitchScreenMode(!fullscreen, sApp->Is3DAccelerated()); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pGetFullscreen //-------------------------------------------------- PyObject* PycapApp::pGetFullscreen( PyObject* self, PyObject* args ) { if( sApp->mIsWindowed ) { return Py_BuildValue( "i", 0 ); } else { return Py_BuildValue( "i", 1 ); } } //-------------------------------------------------- // pAllowAllAccess //-------------------------------------------------- PyObject* PycapApp::pAllowAllAccess( PyObject* self, PyObject* args ) { // parse the arguments char* fileName; if( !PyArg_ParseTuple( args, "s", &fileName ) ) { PyErr_SetString( PyExc_StandardError, "allowAllAccess: failed to parse arguments" ); PyErr_Print(); return Py_BuildValue( "i", 0 ); } // attempt to unlock the file // return whether or not we succeeded ('tho I'll probably just ignore it most of the time) if( AllowAllAccess( fileName ) ) { // success return Py_BuildValue( "i", 1 ); } else { // failure return Py_BuildValue( "i", 0 ); } } PyObject* PycapApp::pGetKeyCode( PyObject* self, PyObject* args ) { // parse the arguments char* key; if( !PyArg_ParseTuple( args, "s", &key ) ) { PyErr_SetString( PyExc_StandardError, "getKeyCode: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } KeyCode k = GetKeyCodeFromName(key); // success return Py_BuildValue( "i", k ); } //-------------------------------------------------- // pGetIs3DAccelerated //-------------------------------------------------- PyObject* PycapApp::pGetIs3DAccelerated( PyObject* self, PyObject* args ) { if( sApp->Is3DAccelerated() ) { return Py_BuildValue( "i", 1 ); } else { return Py_BuildValue( "i", 0 ); } } //-------------------------------------------------- // pIsKeyDown //-------------------------------------------------- PyObject* PycapApp::pIsKeyDown( PyObject* self, PyObject* args ) { // parse the arguments int keycode; if( !PyArg_ParseTuple( args, "i", &keycode ) ) { PyErr_SetString( PyExc_StandardError, "isKeyDown: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } if (gSexyAppBase->mWidgetManager->mKeyDown[keycode]) return Py_BuildValue( "i", 1 ); return Py_BuildValue( "i", 0 ); } //-------------------------------------------------- // pGetAppDataFolder //-------------------------------------------------- PyObject* PycapApp::pGetAppDataFolder( PyObject* self, PyObject* args ) { // get the folder string std::string string = GetAppDataFolder(); // convert foler name to a python string & return it return Py_BuildValue( "s", string.c_str() ); } //-------------------------------------------------- // pGetAppResourceFolder //-------------------------------------------------- PyObject* PycapApp::pGetAppResourceFolder( PyObject* self, PyObject* args ) { // get the folder string std::string string = GetAppResourceFolder(); // convert foler name to a python string & return it return Py_BuildValue( "s", string.c_str() ); } //-------------------------------------------------- // pDrawImageRotScaled //-------------------------------------------------- PyObject* PycapApp::pDrawImageRotScaled( PyObject* self, PyObject* args ) { // parse the arguments int i; float x, y, r,scaleX,scaleY; if( !PyArg_ParseTuple( args, "ifffff", &i, &x, &y, &r ,&scaleX,&scaleY) ) { PyErr_SetString( PyExc_StandardError, "drawImageRotScaled: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawImageRotScaled: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // get the image Image* image = sApp->mResources->getImage( i ); if( !image ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to reference image." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } if (sApp->Is3DAccelerated()) { Sexy::Transform t; t.Scale(scaleX, scaleY); t.RotateRad(r); t.Translate(image->GetWidth() / 2, image->GetHeight() / 2); // perform the blit graphics->DrawImageTransform(image, t, x, y); } // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pSet3DAccelerated //-------------------------------------------------- PyObject* PycapApp::pSet3DAccelerated( PyObject* self, PyObject* args ) { int accelerate; if( !PyArg_ParseTuple( args, "i", &accelerate ) ) { PyErr_SetString( PyExc_StandardError, "set3DAccelerated: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } sApp->SwitchScreenMode(sApp->mIsWindowed, accelerate); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //functions by Tony Oakden //-------------------------------------------------- // pDrawQuad //-------------------------------------------------- PyObject* PycapApp::pDrawQuad( PyObject* self, PyObject* args ) { // parse the arguments int x1, y1, x2, y2,x3, y3, x4, y4; if( !PyArg_ParseTuple( args, "iiiiiiii", &x1, &y1, &x2, &y2, &x3, &y3, &x4, &y4 ) ) { PyErr_SetString( PyExc_StandardError, "drawQuad: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawQuad failed: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } Point qaudPoints[4]; qaudPoints[0] = Point(x1, y1); qaudPoints[1] = Point(x2, y2); qaudPoints[2] = Point(x3, y3); qaudPoints[3] = Point(x4, y4); graphics->PolyFill(qaudPoints, 4); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pDrawTri //-------------------------------------------------- PyObject* PycapApp::pDrawTri( PyObject* self, PyObject* args ) { // parse the arguments int x1, y1, x2, y2, x3, y3; if( !PyArg_ParseTuple( args, "iiiiii", &x1, &y1, &x2, &y2, &x3, &y3) ) { PyErr_SetString( PyExc_StandardError, "drawTri: failed to parse arguments" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } // check that we're currently drawing Graphics* graphics = sApp->mBoard->getGraphics(); if( !graphics ) { // fail, 'cos we can only do this while drawing PyErr_SetString( PyExc_StandardError, "drawTri() failed: Not currently drawing!" ); PyErr_Print(); Py_INCREF( Py_None ); return Py_None; } Point triPoints[3]; triPoints[0] = Point(x1, y1); triPoints[1] = Point(x2, y2); triPoints[2] = Point(x3, y3); graphics->PolyFill(triPoints, 3); // return, 'cos we're done Py_INCREF( Py_None ); return Py_None; } libtuxcap-1.4.0/tuxcap/pycap/PycapApp.h0000644000175000017500000001415011112340453017670 0ustar inniyahinniyah//-------------------------------------------------- // PycapApp // // Pycap application object // // Jarrad 'Farbs' Woods // W.P. van Paassen // Tony Oakden //-------------------------------------------------- #ifndef __PYCAPAPP_H__ #define __PYCAPAPP_H__ // includes #include "PycapResources.h" #include "SexyAppBase.h" #include #include // use the Sexy namespace namespace Sexy { // class declarations class PycapBoard; // Tutorial Application class class PycapApp : public SexyAppBase { //------------ // functions //------------ public: // constructor / destructor PycapApp(); virtual ~PycapApp(); // Standard SexyApp functions virtual void Init(int argc, char*argv[], bool bundled=false); virtual void LoadingThreadProc(); virtual void LoadingThreadCompleted(); virtual void GotFocus(); virtual void LostFocus(); virtual void SwitchScreenMode( bool wantWindowed, bool is3d ); // Accessor functions const PycapResources* getRes() { return mResources; } const bool midiInitialized() { return true; } bool isPythonBundled() { return mBundled; } // Status reporting functions void resLoadFailed() { mResFailed = true; } // Python helpers bool checkPyError(); //---------- // members //---------- public: static PycapApp* sApp; // static link to most recent app object (lazy implementation of singleton) PyObject* pModule; // python game module PyObject* pDict; // dictionary containing python module's namespace. This is a borrowed reference, so it needn't be decref-ed. private: PycapBoard* mBoard; // the board currently in use PycapResources* mResources; // all global images, sounds, fonts etc bool mResFailed; // whether the application should quit due to global resource loading failure or not std::string mPythonHome; std::string mPythonPath; bool mPythonHomeSet; bool mPythonPathSet; bool mBundled; // pycap module functions static PyObject* pMarkDirty( PyObject* self, PyObject* args ); // cause a draw call static PyObject* pSetColour( PyObject* self, PyObject* args ); // set the current colour static PyObject* pSetFont( PyObject* self, PyObject* args ); // set the current font static PyObject* pSetColourize( PyObject* self, PyObject* args ); // set the current colour static PyObject* pFillRect( PyObject* self, PyObject* args ); // fill a rect using the current colour static PyObject* pDrawLine( PyObject* self, PyObject* args ); // draw a line using the start en end position static PyObject* pDrawTri( PyObject* self, PyObject* args ); // Draw a Triangle using currently selected color static PyObject* pDrawQuad( PyObject* self, PyObject* args ); // Draw a quad using currently selected color static PyObject* pDrawImage( PyObject* self, PyObject* args ); // draw an image resource using int position static PyObject* pDrawImageF( PyObject* self, PyObject* args ); // draw an image resource using float position static PyObject* pDrawImageRot( PyObject* self, PyObject* args ); // draw a rotated image using int position static PyObject* pDrawImageRotF( PyObject* self, PyObject* args ); // draw a rotated image using float position static PyObject* pDrawImageRotScaled( PyObject* self, PyObject* args ); // draw a rotated and scaled image using float position static PyObject* pDrawImageScaled( PyObject* self, PyObject* args ); // draw a scaled image using int position static PyObject* pDrawString( PyObject* self, PyObject* args ); // draw a string using the current font static PyObject* pShowMouse( PyObject* self, PyObject* args ); // set the mouse cursor on or off static PyObject* pDrawmodeNormal( PyObject* self, PyObject* args ); // set the drawing mode to normal static PyObject* pDrawmodeAdd( PyObject* self, PyObject* args ); // set the drawing mode to additive static PyObject* pPlaySound( PyObject* self, PyObject* args ); // play a sound static PyObject* pReadReg( PyObject* self, PyObject* args ); // read from the system registry static PyObject* pWriteReg( PyObject* self, PyObject* args ); // write to the system registry static PyObject* pPlayTune( PyObject* self, PyObject* args ); // play a midi file static PyObject* pStopTune( PyObject* self, PyObject* args ); // stop playing a midi file (or all files if none specified) static PyObject* pSetTuneVolume( PyObject* self, PyObject* args ); // change the volume for a song played by the app static PyObject* pSetVolume( PyObject* self, PyObject* args ); // change the global volume for all music played by the app static PyObject* pSetClipRect( PyObject* self, PyObject* args ); // set the clipping rectangle used by all draw calls static PyObject* pClearClipRect( PyObject* self, PyObject* args ); // clear the clipping rectangle used by all draw calls (actually returns it to screen size) static PyObject* pSetTranslation( PyObject* self, PyObject* args ); // set the translation applied to subsequent draw calls static PyObject* pSetFullscreen( PyObject* self, PyObject* args ); // set whether the app should be in fullscreen or windowed mode static PyObject* pGetFullscreen( PyObject* self, PyObject* args ); // get whether the app is in fullscreen or windowed mode static PyObject* pAllowAllAccess( PyObject* self, PyObject* args ); // tell the OS that all users can view and modify a file. Required for Vista static PyObject* pGetKeyCode( PyObject* self, PyObject* args ); // return a key's keycode static PyObject* pGetAppDataFolder( PyObject* self, PyObject* args ); // get the folder that game data should be saved to. Required for Vista static PyObject* pGetAppResourceFolder( PyObject* self, PyObject* args ); // get the folder where the game resources are stored. Required for GNU/Linux. static PyObject* pGetIs3DAccelerated( PyObject* self, PyObject* args ); // returns if the game has 3D acceleration enabled static PyObject* pSet3DAccelerated( PyObject* self, PyObject* args ); // set whether application has 3D acceleration enabled or not static PyObject* pIsKeyDown( PyObject* self, PyObject* args ); // returns a boolean indicating if the queried key is down }; } #endif // __PYCAPAPP_H__ libtuxcap-1.4.0/tuxcap/pycap/PycapBoard.h0000644000175000017500000000404011112340453020174 0ustar inniyahinniyah//-------------------------------------------------- // PycapBoard // // Base game board for Pycap // Manages hooks to python game code // // Jarrad 'Farbs' Woods // W.P. van Paassen //-------------------------------------------------- #ifndef __PYCAPBOARD_H__ #define __PYCAPBOARD_H__ #include "Widget.h" #include // use the Sexy namespace namespace Sexy { // class declarations class Graphics; // Pycap Board Application class class PycapBoard : public Widget { //------------ // functions //------------ public: // constructor / destructor PycapBoard(); virtual ~PycapBoard(); // Standard Widget functions virtual void Draw( Graphics* g ); virtual void UpdateF( float delta ); virtual void KeyDown( KeyCode theKey ); virtual void KeyUp( KeyCode theKey ); virtual void MouseEnter(); virtual void MouseLeave(); virtual void MouseMove(int x, int y); virtual void MouseDrag(int x, int y); virtual void MouseDown(int x, int y, int theBtnNum, int theClickCount); virtual void MouseUp(int x, int y, int theBtnNum, int theClickCount); virtual void MouseWheel(int delta); // Accessors Graphics* getGraphics() { return graphics; } // latest graphics context, or NULL if there is none currently active. //---------- // members //---------- private: PyObject* pUpdateFunc; // python game update hook PyObject* pDrawFunc; // python game draw hook PyObject* pKeyDownFunc; // python game keydown hook PyObject* pKeyUpFunc; // python game keyup hook PyObject* pExitGame; // python exit game test hook PyObject* pMouseEnterFunc; // python game mouse enter hook PyObject* pMouseLeaveFunc; // python game mouse leave hook PyObject* pMouseMoveFunc; // python game mouse move hook PyObject* pMouseDownFunc; // python game mouse down hook PyObject* pMouseUpFunc; // python game mouse up hook PyObject* pMouseWheelFunc; // python game mouse wheel movement hook Graphics* graphics; // pointer to the latest graphics context. This should only be used if canDraw is true, but I won't enforce it. }; } #endif // __PYCAPBOARD_H__ libtuxcap-1.4.0/tuxcap/pycap/PycapResources.cpp0000644000175000017500000013053311202747630021471 0ustar inniyahinniyah//-------------------------------------------------- // PycapResources // // Pycap application resources // Handles access to images, sounds etc by python // // Jarrad 'Farbs' Woods // W.P. van Paassen // Tony Oakden //-------------------------------------------------- // includes #include "PycapResources.h" #include "PycapApp.h" #include "DDImage.h" #include "ImageFont.h" //#include "SysFont.h" #include "SoundManager.h" #include "MusicInterface.h" #ifndef INITGUID #define INITGUID #endif #include // namespace using namespace Sexy; // static data definition PycapResources* PycapResources::sRes = NULL; // functions //-------------------------------------------------- // PycapResources //-------------------------------------------------- PycapResources::PycapResources() { //-------------------------------- // Initialize non-resource members sRes = this; //-------------------------------- //--------------------------- // Set up PycapRes module static PyMethodDef resMethods[] = { {"loadImage", pLoadImage, METH_VARARGS, "loadImage( fileName )\nLoad an image from file, and return its resource index."}, {"imageWidth", pImageWidth, METH_VARARGS, "imageWidth( image )\nGet the width of an image resource."}, {"imageHeight", pImageHeight, METH_VARARGS, "imageHeight( image )\nGet the height of an image resource."}, {"unloadImage", pUnloadImage, METH_VARARGS, "unloadImage( image )\nUnload an image created by loadImage."}, {"loadFont", pLoadFont, METH_VARARGS, "loadFont( fileName )\nLoad an image font from file, and return its resource index."}, {"sysFont", pSysFont, METH_VARARGS, "sysFont( fontName )\nCreate an instance of a system font and return its resource index."}, {"stringWidth", pStringWidth, METH_VARARGS, "stringWidth( string, font )\nGet the width of a string drawn using a given font."}, {"fontAscent", pFontAscent, METH_VARARGS, "fontAscent( font )\nGet the ascent of a given font."}, {"unloadFont", pUnloadFont, METH_VARARGS, "unloadFont( font )\nUnload a font created by loadFont or sysFont."}, {"setFontScale", pSetFontScale, METH_VARARGS, "setFontScale( font, scale )\nSet the draw scale of an image font object."}, {"loadSound", pLoadSound, METH_VARARGS, "loadSound( fileName )\nLoad a sound file, and return its resource index."}, {"unloadSound", pUnloadSound, METH_VARARGS, "unloadSound( sound )\nUnload a sound file from its resource index."}, {"loadTune", pLoadTune, METH_VARARGS, "loadTune( fileName )\nLoad a music file, and return its resource index."}, {"unloadTune", pUnloadTune, METH_VARARGS, "unloadTune( tune )\nUnload a music file created by loadTune."}, {"getPixel", pGetPixel, METH_VARARGS, "getPixel( image, x, y )\nReturns a tuple representing the colour and alpha data of the specified pixel."}, {"setPixel", pSetPixel, METH_VARARGS, "setPixel( image, x, y, r, g, b, a )\nSets the colour and alpha data of the specified pixel. Change will not be visible on screen until refreshPixels is called."}, {"refreshPixels", pRefreshPixels, METH_VARARGS, "refreshPixels( image )\nSubmits pixel data changes to the image. Without calling this setPixel will have no visible effect. This only needs to be called once to send all setPixel changes though, so try to batch up all your changes into one refresh."}, {"imageGreyScale", pImageGreyScale, METH_VARARGS, "convert an image to grey scale"}, {"imageGetHighBound", pImageGetHighBound, METH_VARARGS, "Get the highest none alpha pixel"}, {"imageGetLowBound", pImageGetLowBound, METH_VARARGS, "Get the lowest none alpha pixel"}, {"mashPalette", pMashPalette, METH_VARARGS, ""}, {"mashImage", pMashImage, METH_VARARGS, ""}, {NULL, NULL, 0, NULL} }; Py_InitModule("PycapRes", resMethods); // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in PycapResources(), while importing PycapRes." ); PyErr_Print(); return; } //-------------------------------- //--------------------------- // Load and process resources PyObject* pLoadFunc = PyDict_GetItemString( PycapApp::sApp->pDict, "loadBase" ); if ( pLoadFunc && PyCallable_Check( pLoadFunc ) ) { PyObject_CallObject( pLoadFunc, NULL ); } // general error location warning if (PyErr_Occurred()) { PyErr_SetString( PyExc_StandardError, "Some kind of python error occurred in PycapResources(), while running loadBase." ); PyErr_Print(); return; } //--------------------------- } //-------------------------------------------------- // ~PycapResources //-------------------------------------------------- PycapResources::~PycapResources() { //------------------------------ // Clean up non-resource members if( sRes == this ) { sRes = NULL; } //------------------------------ //------------------- // Clean up resources // images for( std::vector::iterator iit = images.begin(); iit != images.end(); ++iit ) { delete *iit; } images.clear(); freeImages.clear(); // fonts for( std::vector::iterator fit = fonts.begin(); fit != fonts.end(); ++fit ) { delete *fit; } fonts.clear(); freeFonts.clear(); // sounds PycapApp::sApp->mSoundManager->ReleaseSounds(); sounds.clear(); freeSounds.clear(); // music for( std::vector::iterator tit = tunes.begin(); tit != tunes.end(); ++tit ) { if (*tit != -1) PycapApp::sApp->mMusicInterface->UnloadMusic(*tit); } //------------------- } //-------------------------------------------------- // getImage //-------------------------------------------------- Image* PycapResources::getImage( int index ) { // check bounds if( index >= sRes->images.size() ) { // exit, returning None/NULL return NULL; } // return a pointer to the image object (or NULL if it's been unloaded) return images[index]; } //-------------------------------------------------- // loadImage //-------------------------------------------------- Image* PycapResources::loadImage( const std::string& fileName ) { Image* newImage = (DDImage*) PycapApp::sApp->GetImage( fileName ); if( newImage == NULL ) { PycapApp::sApp->resLoadFailed(); PyErr_SetString( PyExc_StandardError, ("Image " + fileName + "could not be loaded").c_str() ); PyErr_Print(); return NULL; } // palletize ( (DDImage*)newImage )->Palletize(); // attempt to palletize, don't worry if it fails // return new image return newImage; } //-------------------------------------------------- // getFont //-------------------------------------------------- Font* PycapResources::getFont( int index ) { // check bounds if( index >= sRes->fonts.size() ) { // exit, returning None/NULL return NULL; } // return a pointer to the font object (or NULL if it's been unloaded) return fonts[index]; } //-------------------------------------------------- // loadFont //-------------------------------------------------- Font* PycapResources::loadFont( const std::string& fileName ) { ImageFont* newFont = new ImageFont( PycapApp::sApp, fileName ); if( !newFont->mFontData->mInitialized ) { delete newFont; PycapApp::sApp->resLoadFailed(); PyErr_SetString( PyExc_StandardError, ("Font " + fileName + "could not be loaded").c_str() ); PyErr_Print(); return NULL; } // return new font return newFont; } //-------------------------------------------------- // sysFont //-------------------------------------------------- Font* PycapResources::sysFont( const std::string& faceName, int pointSize, int script, bool bold, bool italics, bool underline ) { #if 0 SysFont* newFont = new SysFont( PycapApp::sApp, faceName, pointSize, script, bold, italics, underline ); if( !newFont->mHFont ) { delete newFont; PycapApp::sApp->resLoadFailed(); //PycapApp::sApp->Popup( faceName + " system font could not be created." ); return NULL; } // return new font return newFont; #else PyErr_SetString( PyExc_StandardError, ("System Font " + faceName + "could not be loaded").c_str() ); PyErr_Print(); return NULL; #endif } //-------------------------------------------------- // getSound //-------------------------------------------------- bool PycapResources::soundExists( int index ) { // check bounds if( index >= sRes->sounds.size() ) { // out of bounds, so sound doesn't exist return false; } // return whether the sound exists or not from our record return sounds[index]; } //-------------------------------------------------- // loadSound //-------------------------------------------------- bool PycapResources::loadSound( int id, const std::string& fileName ) { // attempt to load if( !PycapApp::sApp->mSoundManager->LoadSound( id, fileName ) ) { // report error PycapApp::sApp->resLoadFailed(); PyErr_SetString( PyExc_StandardError, ("Sound " + fileName + "could not be loaded").c_str() ); PyErr_Print(); return false; } // success! return true; } //-------------------------------------------------- // getTune //-------------------------------------------------- int PycapResources::getTune( int index ) { if (index == -1) { return tunes.size() - 1; } // check bounds if( index >= sRes->tunes.size()) { // exit, returning None/NULL return -1; } return index; } //-------------------------------------------------- // pLoadImage //-------------------------------------------------- PyObject* PycapResources::pLoadImage( PyObject* self, PyObject* args ) { // parse the arguments char* filename; if( !PyArg_ParseTuple( args, "s", &filename ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "loadImage: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // load from the file Image* newImage = sRes->loadImage( filename ); if( !newImage ) { // throw an exception PyErr_SetString( PyExc_StandardError, "loadImage: Failed to load image file"); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // add image to our collection int index; // test for free slot if( sRes->freeImages.empty() ) { // add new entry in images sRes->images.push_back( newImage ); // set index index = sRes->images.size() - 1; } else { // set index index = sRes->freeImages.back(); // reuse slot ( sRes->images[index] ) = newImage; // remove free index sRes->freeImages.pop_back(); } // return image index value return Py_BuildValue( "i", index ); } //-------------------------------------------------- // pImageWidth //-------------------------------------------------- PyObject* PycapResources::pImageWidth( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "imageWidth: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get image width: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get image width: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // return image index value return Py_BuildValue( "i", sRes->images[index]->mWidth ); } //-------------------------------------------------- // pImageHeight //-------------------------------------------------- PyObject* PycapResources::pImageHeight( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "imageHeight: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get image height: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get image height: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // return image index value return Py_BuildValue( "i", sRes->images[index]->mHeight ); } //-------------------------------------------------- // pUnloadImage //-------------------------------------------------- PyObject* PycapResources::pUnloadImage( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "unloadImage: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload image: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // unload the image delete sRes->images[index]; sRes->images[index] = NULL; // record empty slot sRes->freeImages.push_front( index ); // done return Py_None; } //-------------------------------------------------- // pLoadFont //-------------------------------------------------- PyObject* PycapResources::pLoadFont( PyObject* self, PyObject* args ) { // parse the arguments char* filename; if( !PyArg_ParseTuple( args, "s", &filename ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "loadFont: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // load from the file Font* newFont = sRes->loadFont( filename ); if( !newFont ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to load a font file." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // add font to our collection int index; // test for free slot if( sRes->freeFonts.empty() ) { // add new entry in fonts sRes->fonts.push_back( newFont ); // set index index = sRes->fonts.size() - 1; } else { // set index index = sRes->freeFonts.back(); // reuse slot ( sRes->fonts[index] ) = newFont; // remove free index sRes->freeFonts.pop_back(); } // return font index value return Py_BuildValue( "i", index ); } //-------------------------------------------------- // pSysFont //-------------------------------------------------- PyObject* PycapResources::pSysFont( PyObject* self, PyObject* args ) { #if 0 // parse the arguments // required char* faceName; int pointSize; // optional int script = ANSI_CHARSET; int bold = 0; int italics = 0; int underline = 0; if( !PyArg_ParseTuple( args, "si|iiii", &faceName, &pointSize, &script, &bold, &italics, &underline ) ) return NULL; // create Font* newFont = sRes->sysFont( faceName, pointSize, script, bold != 0, italics != 0, underline != 0 ); if( !newFont ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to create a system font." ); // exit, returning None/NULL return NULL; } // add font to our collection int index; // test for free slot if( sRes->freeFonts.empty() ) { // add new entry in fonts sRes->fonts.push_back( newFont ); // set index index = sRes->fonts.size() - 1; } else { // set index index = sRes->freeFonts.back(); // reuse slot ( sRes->fonts[index] ) = newFont; // remove free index sRes->freeFonts.pop_back(); } // return font index value return Py_BuildValue( "i", index ); #else // throw an exception PyErr_SetString( PyExc_StandardError, "sysfont: not supported!!" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; #endif } //-------------------------------------------------- // pStringWidth //-------------------------------------------------- PyObject* PycapResources::pStringWidth( PyObject* self, PyObject* args ) { // parse the arguments char* string; int index; if( !PyArg_ParseTuple( args, "si", &string, &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "stringWidth: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->fonts.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get string width: Font index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->fonts[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get string width: Font not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // return string width using font return Py_BuildValue( "i", sRes->fonts[index]->StringWidth( string ) ); } //-------------------------------------------------- // pFontAscent //-------------------------------------------------- PyObject* PycapResources::pFontAscent( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "fontAscent: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->fonts.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get font height: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->fonts[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get font height: Font not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // return font ascent value return Py_BuildValue( "i", sRes->fonts[index]->mAscent ); } //-------------------------------------------------- // pUnloadFont //-------------------------------------------------- PyObject* PycapResources::pUnloadFont( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "unloadFont: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->fonts.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload font: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->fonts[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload font: Font not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // unload the font delete sRes->fonts[index]; sRes->fonts[index] = NULL; // record empty slot sRes->freeFonts.push_front( index ); // done return Py_None; } //-------------------------------------------------- // pSetFontScale //-------------------------------------------------- PyObject* PycapResources::pSetFontScale( PyObject* self, PyObject* args ) { // parse the arguments int index; float scale; if( !PyArg_ParseTuple( args, "if", &index, &scale ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "setFontScale: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->fonts.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set font point: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->fonts[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set font point font: Font not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // cast to a supporting font type ImageFont* imageFont = dynamic_cast( sRes->fonts[index] ); if( !imageFont ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set font point font: Only supported by image fonts." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // set scale imageFont->SetScale( scale ); // done return Py_None; } //-------------------------------------------------- // pLoadSound //-------------------------------------------------- PyObject* PycapResources::pLoadSound( PyObject* self, PyObject* args ) { // parse the arguments char* filename; if( !PyArg_ParseTuple( args, "s", &filename ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "loadSound: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // find a free slot // (Popcap's sound manager requires us to choose one) int slot; if( sRes->freeSounds.empty() ) { slot = sRes->sounds.size(); } else { slot = sRes->freeSounds.back(); } // attempt to load from the file if( !sRes->loadSound( slot, filename ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to load a sound file." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // record that we've added the sound if( sRes->freeSounds.empty() ) { // add new entry in sounds sRes->sounds.push_back( true ); } else { // reuse slot ( sRes->sounds[slot] ) = true; // remove free index sRes->freeSounds.pop_back(); } // return sound index value return Py_BuildValue( "i", slot ); } //-------------------------------------------------- // pUnloadSound //-------------------------------------------------- PyObject* PycapResources::pUnloadSound( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "unloadSound: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->sounds.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload sound: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( !sRes->sounds[index] ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't unload sound: Sound not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // unload the sound PycapApp::sApp->mSoundManager->ReleaseSound( index ); sRes->sounds[index] = false; // record empty slot sRes->freeSounds.push_front( index ); // done return Py_None; } //-------------------------------------------------- // pLoadTune //-------------------------------------------------- PyObject* PycapResources::pLoadTune( PyObject* self, PyObject* args ) { // parse the arguments char* filename; if( !PyArg_ParseTuple( args, "s", &filename ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "loadTune: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } int index = sRes->tunes.size(); if (!PycapApp::sApp->mMusicInterface->LoadMusic( index, filename )) { // throw an exception PyErr_SetString( PyExc_StandardError, "Failed to load a music file." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } sRes->tunes.push_back(index); // return tune index value return Py_BuildValue( "i", index ); } //-------------------------------------------------- // pUnloadTune //-------------------------------------------------- PyObject* PycapResources::pUnloadTune( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "unloadTune: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } if (index >= sRes->tunes.size()) { // throw an exception PyErr_SetString( PyExc_StandardError, "Unable to unload music, invalid index!" ); // exit, returning None/NULL return Py_None; } std::vector::iterator it = std::find(sRes->tunes.begin(),sRes->tunes.end(), index); if (it != sRes->tunes.end()) { PycapApp::sApp->mMusicInterface->UnloadMusic( index ); *it = -1; } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Unable to unload music, music not found!" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // done return Py_None; } //-------------------------------------------------- // pGetPixel //-------------------------------------------------- PyObject* PycapResources::pGetPixel( PyObject* self, PyObject* args ) { // parse the arguments int index; int x, y; if( !PyArg_ParseTuple( args, "iii", &index, &x, &y ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "getPixel: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get pixel for image: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get pixel for image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // grab pixels DDImage* image = (DDImage*)(sRes->images[index]); if( image ) { uint32_t* bits = image->GetBits(); if( bits ) { // get requested pixel if( x < image->GetWidth() && y < image->GetHeight() ) { // grab uint32_t p = bits[ x + y * image->GetWidth() ]; // extract colour values unsigned char alpha = (unsigned char) (p >> 24); unsigned char red = (unsigned char) ((p >> 16) & 0xFF); unsigned char green = (unsigned char) ((p >> 8) & 0xFF); unsigned char blue = (unsigned char) (p & 0xFF); // return colour values return Py_BuildValue( "iiii", red, green, blue, alpha ); } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get pixel: Coordinate is out of image bounds." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get pixel for image: GetBits() failed." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't get pixel for image: Image wouldn't cast to DDImage." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } //-------------------------------------------------- // pSetPixel //-------------------------------------------------- PyObject* PycapResources::pSetPixel( PyObject* self, PyObject* args ) { // parse the arguments int index; int x, y; int r, g, b, a; if( !PyArg_ParseTuple( args, "iiiiiii", &index, &x, &y, &r, &g, &b, &a ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "setPixel: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set pixel for image: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set pixel for image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // grab pixels DDImage* image = (DDImage*)(sRes->images[index]); if( image ) { uint32_t* bits = image->GetBits(); if( bits ) { // set requested pixel if( x < image->GetWidth() && y < image->GetHeight() ) { // set bits[ x + y * image->GetWidth() ] = (((uint32_t)a) << 24) | // alpha (((uint32_t)r) << 16) | // red (((uint32_t)g) << 8) | // green (((uint32_t)b) << 0); // blue // done Py_INCREF( Py_None ); return Py_None; } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set pixel: Coordinate is out of image bounds." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set pixel for image: GetBits() failed." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't set pixel for image: Image wouldn't cast to DDImage." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } //-------------------------------------------------- // pRefreshPixels //-------------------------------------------------- PyObject* PycapResources::pRefreshPixels( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "refreshPixels: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't refresh pixels for image: Index out of range." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't refresh pixels for image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // grab image DDImage* image = (DDImage*)(sRes->images[index]); if( image ) { // update image->BitsChanged(); // done Py_INCREF( Py_None ); return Py_None; } else { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't refresh pixels for image: Image wouldn't cast to DDImage." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } } struct PaletteMashLookup { uint32_t OldValue; uint32_t NewValue; }; //-------------------------------------------------- // pMashPalette //-------------------------------------------------- PyObject* PycapResources::pMashPalette( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "mashPalette: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't mash palette for image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // pixels DDImage* image = (DDImage*)(sRes->images[index]); if( image ) { uint32_t* bits = image->GetBits(); if( bits ) { // palette lookup goes here std::list lookup; // pass through image, remapping palette entries as they're found for( int i = 0; i < image->GetWidth() * image->GetHeight(); ++i ) { // grab pixel uint32_t p = bits[i]; uint32_t m; // try to find in palette bool done = false; for( std::list::iterator it = lookup.begin(); !done && it != lookup.end(); ++it ) { // match? if( ( *it ).OldValue == ( p & 0xffffff ) ) { // match! m = ( *it ).NewValue; done = true; } } // add new entry if not found if( !done ) { PaletteMashLookup newEntry; newEntry.OldValue = p & 0xffffff; newEntry.NewValue = Rand() & 0xffffff; m = newEntry.NewValue; lookup.push_back( newEntry ); } // set new pixel value p = ( p & 0xff000000 ) | m; bits[i] = p; } // update image data image->BitsChanged(); // clean up lookup.empty(); } } // done Py_INCREF( Py_None ); return Py_None; } //-------------------------------------------------- // pMashImage //-------------------------------------------------- PyObject* PycapResources::pMashImage( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "mashImage: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_StandardError, "Couldn't mash image: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // pixels DDImage* image = (DDImage*)(sRes->images[index]); if( image ) { uint32_t* bits = image->GetBits(); if( bits ) { // store strips in here uint32_t* strip = new uint32_t[image->GetWidth()]; // for each line for( int y = 0; y < image->GetHeight(); ++y ) { // copy line into buffer memcpy( strip, &bits[ image->GetWidth() * y ], image->GetWidth() * sizeof( uint32_t ) ); // pick an offset int offset = rand() % image->GetWidth(); // copy from buffer back into line memcpy( &bits[ image->GetWidth() * y ], &strip[offset], ( image->GetWidth() - offset ) * sizeof( uint32_t ) ); memcpy( &bits[ image->GetWidth() * y + image->GetWidth() - offset ], strip, offset * sizeof( uint32_t ) ); } // update image data image->BitsChanged(); // clean up delete[] strip; } } // done Py_INCREF( Py_None ); return Py_None; } //functions by Tony Oakden PyObject* PycapResources::pImageGreyScale( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "imageGreyScale: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } DDImage* image = (DDImage*)(sRes->images[index]); uint32_t* bits = image->GetBits(); // 3. Now we will loop over each pixel in the image. The size of the bits array // is simply the width times the height. for (int i = 0; i < image->GetWidth() * image->GetHeight(); i++) { // 4. Get the ARGB color value for this pixel uint32_t c = bits[i]; // 5. To illustrate the ARGB storage format, we will assign each // component to a variable, although we're actually only going to care // about the RGB values, for this particular example. The 4 lines below // extract out the individual ARGB values. unsigned char alpha = (unsigned char) (c >> 24); unsigned char red = (unsigned char) ((c >> 16) & 0xFF); unsigned char green = (unsigned char) ((c >> 8) & 0xFF); unsigned char blue = (unsigned char) (c & 0xFF); // 6. Just like the Color class, the ARGB values are from 0-255. // Let's alter these to produce a grayscale image using one of many // conversion methods. This method uses 30% of the red value, // 59% of the green value, and 11% of the blue value: uint32_t gray = (uint32_t) ((float)red * 0.30f + (float)green * 0.59f + (float)blue * 0.11f); // 7. Now we need to put the pixel data back into the image's data. // We do the opposite of how we extracted the ARGB values above and // use a left shift instead of a right shift: // alpha red green blue //bits[i] = (alpha << 24) | (gray << 16) | (gray << 8) | gray; bits[i] = (alpha << 24) | (alpha<< 16) | (gray << 8) | gray; } // The image won't use this modified data until we inform it that we've // done some messing around with it. We do that with the BitsChanged() // function call. After that, we're all done! Pretty simple. It just // depends on what you want to actually do with the RGBA data. Extracting // the information and putting it back is as simple as a few shifts. image->BitsChanged(); Py_INCREF( Py_None ); return Py_None; } PyObject* PycapResources::pImageGetLowBound( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "imageGetLowBound: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } DDImage* image = (DDImage*)(sRes->images[index]); uint32_t* bits = image->GetBits(); int imageHeight = image->GetHeight(); int imageWidth = image->GetWidth(); for (int row = imageHeight -1; row > 0; row--) { for (int collumn = 0; collumn < imageWidth; collumn+=2) { uint32_t index = ( row*imageWidth) + collumn; uint32_t c = bits[index]; unsigned char alpha = (unsigned char) (c >> 24); if (alpha > 20) { return Py_BuildValue( "i", row); } } } image->BitsChanged(); return Py_BuildValue( "i", 0); //only get here if the image contains no alpha above 20 } PyObject* PycapResources::pImageGetHighBound( PyObject* self, PyObject* args ) { // parse the arguments int index; if( !PyArg_ParseTuple( args, "i", &index ) ) { // throw an exception PyErr_SetString( PyExc_StandardError, "imageGetHighBound: failed to parse arguments" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for out of range if( index >= sRes->images.size() ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale" ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } // test for already unloaded if( sRes->images[index] == NULL ) { // throw an exception PyErr_SetString( PyExc_IOError, "Couldn't convert to grey scale: Image not loaded." ); PyErr_Print(); // exit, returning None/NULL Py_INCREF( Py_None ); return Py_None; } DDImage* image = (DDImage*)(sRes->images[index]); uint32_t* bits = image->GetBits(); int imageHeight = image->GetHeight(); int imageWidth = image->GetWidth(); for (int row = 0; row < imageHeight; row++) { for (int collumn = 0; collumn < imageWidth; collumn+=2) { uint32_t index = ( row*imageWidth) + collumn; uint32_t c = bits[index]; unsigned char alpha = (unsigned char) (c >> 24); if (alpha > 20) return Py_BuildValue( "i", row ); } } return Py_BuildValue( "i", 0); //only get here if the image contains no alpha above 20 } libtuxcap-1.4.0/tuxcap/pycap/main.cpp0000644000175000017500000000023210751373006017436 0ustar inniyahinniyah#include "PycapApp.h" using namespace Sexy; int main(int argc, char** argv) { PycapApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/pycap/PopCap Framework License.txt0000644000175000017500000000353610751405646023232 0ustar inniyahinniyahPopCap Games Framework License Version 1.0 Copyright (c) 2005 PopCap Games. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code or derived libraries, whether source code or binary, must include a copy of this PopCap Games Framework License in its entirety. 2. The end-user documentation included with a work which contains any portion of the PopCap Games Framework must include the following acknowledgment: "This product includes portions of the PopCap Games Framework (http://developer.popcap.com/)." Alternatively, this acknowledgment may appear in the software itself, wherever such third-party acknowledgments normally appear. 3. The names "PopCap" and "PopCap Games" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact bizdev@popcap.com. 4. Products derived from this software may not be called "PopCap", nor may "PopCap" appear in their name, without prior written permission of PopCap Games. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGMENT AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL POPCAP GAMES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. libtuxcap-1.4.0/tuxcap/pycap/PycapResources.h0000644000175000017500000001133511112340453021124 0ustar inniyahinniyah//-------------------------------------------------- // PycapResources // // Pycap application resources // Handles access to images, sounds etc by python // // Jarrad 'Farbs' Woods // W.P. van Paassen // Tony Oakden //-------------------------------------------------- // includes #include "SexyAppBase.h" #include #include #ifndef __PYCAPRESOURCES_H__ #define __PYCAPRESOURCES_H__ #include // use the Sexy namespace namespace Sexy { // class declarations class Image; class Font; class ImageFont; //class SysFont; // Pycap Resources class class PycapResources { //------------ // functions //------------ public: // constructor / destructor PycapResources(); // create object and load resources. Also sets up resource management module. virtual ~PycapResources(); // destroy object, clean up resources. This probably shouldn't leave the res management module active, but it does. Meh. // resource accessors Image* getImage( int index ); Font* getFont( int index ); bool soundExists( int index ); int getTune( int index ); private: // resource loading Image* loadImage( const std::string& fileName ); // attempt load an image and convert pallete Font* loadFont( const std::string& fileName ); // attempt load an image font Font* sysFont( // attempt to create a system font const std::string& faceName, int pointSize, int script, bool bold, bool italics, bool underline ); bool loadSound( int id, const std::string& fileName ); // attempt load a sound into a given slot // Python resource handling functions // Resources are simply referenced by index. Failed prints errors to err.txt. static PyObject* pLoadImage( PyObject* self, PyObject* args ); // attempt to load an image and convert palette. Returns image index on success. static PyObject* pImageWidth( PyObject* self, PyObject* args ); // get width of an image resource. static PyObject* pImageHeight( PyObject* self, PyObject* args ); // get height of an image resource. static PyObject* pUnloadImage( PyObject* self, PyObject* args ); // attempt to unload a given image. static PyObject* pLoadFont( PyObject* self, PyObject* args ); // attempt to load a font. Returns font index on success. static PyObject* pSysFont( PyObject* self, PyObject* args ); // attempt to create a system font. Returns font index on success. static PyObject* pStringWidth( PyObject* self, PyObject* args ); // get width of a string if drawn with a specific font. static PyObject* pFontAscent( PyObject* self, PyObject* args ); // get ascent of a font. static PyObject* pUnloadFont( PyObject* self, PyObject* args ); // attempt to unload a given font. static PyObject* pSetFontScale( PyObject* self, PyObject* args ); // set the draw scale of an image font object static PyObject* pLoadSound( PyObject* self, PyObject* args ); // attempt to load a sound. static PyObject* pUnloadSound( PyObject* self, PyObject* args ); // attempt to unload a given sound. static PyObject* pLoadTune( PyObject* self, PyObject* args ); // attempt to load a music file static PyObject* pUnloadTune( PyObject* self, PyObject* args ); // attempt to unload a given music file. static PyObject* pGetPixel( PyObject* self, PyObject* args ); // attempt to read pixel data from a locked image. static PyObject* pSetPixel( PyObject* self, PyObject* args ); // attempt to set pixel data from a locked image. static PyObject* pRefreshPixels( PyObject* self, PyObject* args ); // attempt to refresh an image from memory data. static PyObject* pMashPalette( PyObject* self, PyObject* args ); // write garbage into the specified image's palette :) static PyObject* pMashImage( PyObject* self, PyObject* args ); // distort image data in some way static PyObject* pImageGreyScale( PyObject* self, PyObject* args ); // convert image to grey scale. static PyObject* pImageGetLowBound( PyObject* self, PyObject* args ); // Get the lowest none alpha pixel. static PyObject* pImageGetHighBound( PyObject* self, PyObject* args ); // Get the highest none alpha pixel. //---------- // members //---------- public: // instance static PycapResources* sRes; // reference to self. Assumes use as a singleton (very ugly) private: // resources std::vector images; // collection of image objects std::list freeImages; // list of empty image slots std::vector fonts; // collection of font objects std::list freeFonts; // list of empty font slots std::vector sounds; // flags indicating whether sounds are valid std::list freeSounds; // list of empty sound slots std::vector tunes; // collection of music segment objects }; } #endif // __PYCPRESOURCES_H__ libtuxcap-1.4.0/tuxcap/physicsdemo2/0000755000175000017500000000000011212652053017301 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/physicsdemo2/GameApp.cpp0000644000175000017500000001207311062533667021336 0ustar inniyahinniyah#include "GameApp.h" #include "Board.h" #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Physicsdemo"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Physicsdemo2"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 640; mHeight = 480; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. // // When 3D mode is on, the standard drawing routines will automatically use // their hardware rendering versions, which in truns makes the game run faster. // You do not need to do anything different when drawing in 2D or 3D mode. // Although if 3D mode is disabled, you will most likely want to do less // drawing intensive operations like additive drawing, colorization, // real-time flipping/mirroring, etc. //mAutoEnable3D = true; mBoard = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. mWidgetManager->RemoveWidget(mBoard); delete mBoard; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // Now that we're done loading everything we need (which wasn't // anything in this particular demo), we need to get the main // game screen up and running: That is our "Board" class, and // it will handle all the drawing, updating, and input processing // for most of the game. mBoard = new Board(this); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); mWidgetManager->SetFocus(mBoard); } libtuxcap-1.4.0/tuxcap/physicsdemo2/CMakeLists.txt0000644000175000017500000000402210762446645022060 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp Board.cpp GameApp.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../Physicsdemo2") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/physicsdemo2/Board.h0000644000175000017500000001363110757336467020532 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// // This file must be included so that we can derive our Board class from it #include "Widget.h" #include "PhysicsListener.h" #include "Physics.h" #include // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public PhysicsListener { private: GameApp* mApp; Physics* physics; Color c; void InitDemo(); public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); virtual void KeyDown(KeyCode theKey); //physics functions virtual void DrawPhysicsObject(PhysicsObject* object, Graphics* g); virtual bool HandleTypedCollision(CollisionObject* col); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/physicsdemo2/GameApp.h0000644000175000017500000000612110667046272021001 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; class GameApp : public SexyAppBase { private: Board* mBoard; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/physicsdemo2/main.cpp0000644000175000017500000000022710667046272020747 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/physicsdemo2/Board.cpp0000644000175000017500000002127610757336467021071 0ustar inniyahinniyah/* W.P. van Paassen */ #include "Board.h" #include "GameApp.h" #include "Graphics.h" #include "SexyVector.h" // See the Draw method for more information on using the Color class. #include "Color.h" // We're going to add our own button widget, which requires knowing about the // WidgetManager. #include "WidgetManager.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; physics = new Physics(); physics->SetPhysicsListener(this); physics->Init(); c = Color(128,128,128); InitDemo(); } void Board::InitDemo() { physics->SetSteps(2); physics->ResizeStaticHash(20.0f,999); physics->SetGravity(SexyVector2(0,100)); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(0,475), SexyVector2(639, 475), 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(SexyVector2(639,0), SexyVector2(639, 475), 0.0f,1.0f,1.0f); obj->SetCollisionType(2); int num = 4; SexyVector2 verts[] = { SexyVector2(-15,-15), SexyVector2(-15, 15), SexyVector2( 15, 15), SexyVector2( 15,-15), }; for(int i=0; i<47; i++){ int j = i + 1; SexyVector2 a(i*10, i*10); SexyVector2 b(j*10, i*10); SexyVector2 c(j*10, j*10); PhysicsObject* obj = physics->CreateStaticObject(); obj->AddSegmentShape(a, b, 0.0f,1.0f,1.0f); obj = physics->CreateStaticObject(); obj->AddSegmentShape(b, c, 0.0f,1.0f,1.0f); } obj = physics->CreateObject(1.0f, physics->ComputeMomentForPoly(1.0f, num, verts, SexyVector2(0.0f,0.0f))); obj->AddPolyShape(num, verts, SexyVector2(0.0f,0.0f),0.0f,1.5f); obj->SetPosition(SexyVector2(40, 0)); obj->SetCollisionType(1); physics->RegisterCollisionType(1,2); /* trigger collision between square (user defined type 1) and right wall (user defined type 2) */ } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { physics->UnregisterCollisionType(1,2); delete physics; } ////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// void Board::Update() { // Let the parent class update as well. This will increment // the variable mUpdateCnt which is an integer that indicates // how many times the Update() method has been called. Since our // Board class is updated 100 times per second, this variable will // increment 100 times per second. As you will see in later demos, // we will use this variable for animation since its value represents // hundredths of a second, which is for almost all games a good // enough timer value and doesn't rely on the system clock function // call. Widget::Update(); physics->Update(); // For this and most of the other demos, you will see the function // below called every Update() call. MarkDirty() tells the widget // manager that something has changed graphically in the widget and // that it needs to be repainted. All widgets follow this convention. // In general, if you don't need // to update your drawing every time you call the Update method // (the most common case is when the game is paused) you should // NOT mark dirty. Why? If you aren't marking dirty every frame, // then you aren't drawing every frame and thus you use less CPU // time. Because people like to multitask, or they may be on a laptop // with limited battery life, using less CPU time lets people do // other things besides play your game. Of course, everyone // will want to play your game at all times, but it's good to be // nice to those rare people that might want to read email or // do other things at the same time. // In this particular demo, we // won't be nice, as the purpose is to bring you up to speed as // quickly as possible, and so we'll dispense with optimizations // for now, so you can concentrate on other core issues first. // In general, this is the last method called in the Update // function, but that is not necessary. In fact, the MarkDirty // function can be called anywhere, in any method (although // calling it in the Draw method doesn't make sense since it is // already drawing) and even multiple times. Calling it multiple // times does not do anything: only the first call makes a difference. MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // The Graphics object, "g", is // automatically created and passed to this method by the // WidgetManager and can be thought of as the main screen // bitmap/canvas upon which all drawing will be done. This object // is double buffered automatically so you don't need to worry // about those details. All you need to do is instruct the object // that you would like to draw something to it, and when the // WidgetManager gets done letting all widgets draw to the // Graphics object, it will then blit everything to the screen // at once. // First, let's start by clearing the screen to black. // As you'll recall from Demo1, we set the color with SetColor // and pass in a Color object that contains either 3 or 4 parameters, // that represent the r,g,b,a values (alpha is 255 if only 3 specified). g->SetColor(Color(255, 255, 255)); g->FillRect(0, 0, mWidth, mHeight); // Now let's try drawing a stretched image. We'll draw the original image // stretched to twice its size. Drawing a stretched image is exactly like // drawing a normal image, except that you have two extra parameters: // the stretched width and height. You can use this to draw a shrunk version // of the image as well (which we'll do second) physics->Draw(g); } void Board::DrawPhysicsObject(PhysicsObject* object, Graphics* g) { g->SetColor(Color(128,128,128)); if (object->GetShapeType() == object->SEGMENT_SHAPE) { SexyVector2 startpos = object->GetSegmentShapeBegin(); SexyVector2 endpos = object->GetSegmentShapeEnd(); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } else if (object->GetShapeType() == object->POLY_SHAPE) { g->SetColor(c); int num = object->GetNumberVertices(); for (int i = 0; i < num - 1; ++i) { SexyVector2 startpos = object->GetVertex(i); SexyVector2 endpos = object->GetVertex(i + 1); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } SexyVector2 startpos = object->GetVertex(num - 1); SexyVector2 endpos = object->GetVertex(0); g->DrawLine((int)startpos.x, (int)startpos.y, (int)endpos.x,(int)endpos.y); } g->SetColor(Color(0,0,255)); SexyVector2 pos = object->GetPosition(); g->DrawLine((int)pos.x, (int)pos.y, (int)pos.x + 1,(int)pos.y); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); } void Board::KeyDown(KeyCode theKey) { if (theKey == KEYCODE_SPACE) { physics->Clear(); physics->Init(); InitDemo(); } } /* watch it!, this is being called for every step in which a collision occurres, so in case of physics->SetSteps(3) it might get called 3 times in every Board->Update(). */ bool Board::HandleTypedCollision(CollisionObject* col){ /* Watch it! col->points and col are invalid when this function exits, so if you want to store its data, copy it! col->object1 and col->object2 are not invalidated upon return */ /*gets called when square collides with right wall */ c = Color(0,255,0); /*return true to make the collision happen, return false to cancel the collision*/ return true; } libtuxcap-1.4.0/tuxcap/demo4/0000755000175000017500000000000011212652053015700 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/demo4/Res.h0000644000175000017500000000771010643254671016622 0ustar inniyahinniyah#ifndef __Res_H__ #define __Res_H__ namespace Sexy { class ResourceManager; class Image; class Font; Image* LoadImageById(ResourceManager *theManager, int theId); bool ExtractResourcesByName(ResourceManager *theManager, const char *theName); // Game Resources bool ExtractGameResources(ResourceManager *theMgr); extern Image* IMAGE_BG0; extern Image* IMAGE_BG1; extern Image* IMAGE_BG2; extern Image* IMAGE_BUTTON_DOWN; extern Image* IMAGE_BUTTON_NORMAL; extern Image* IMAGE_BUTTON_OVER; extern Image* IMAGE_CHECKBOX; extern Image* IMAGE_DIALOG_BOX; extern Image* IMAGE_DIALOG_BUTTON; extern Image* IMAGE_ROBOTROBOT; extern Image* IMAGE_SLIDER_THUMB; extern Image* IMAGE_SLIDER_TRACK; extern int SOUND_MUTATOR; extern int SOUND_TIMER; // Hungarr Resources bool ExtractHungarrResources(ResourceManager *theMgr); extern Image* IMAGE_ATOMIC_EXPLOSION; extern Image* IMAGE_BOMB_RADIAL_DEATH; extern Image* IMAGE_HUNGARR_BEAM_DOWN; extern Image* IMAGE_HUNGARR_BEAM_LEFT; extern Image* IMAGE_HUNGARR_BEAM_RIGHT; extern Image* IMAGE_HUNGARR_BEAM_UP; extern Image* IMAGE_HUNGARR_HORIZ; extern Image* IMAGE_HUNGARR_SMALL; extern Image* IMAGE_HUNGARR_VERT; extern Image* IMAGE_PARTICLE_LIGHTNING; extern Image* IMAGE_PLANETS; extern Image* IMAGE_SPARK; extern int SOUND_BEAM_HIT; extern int SOUND_BEAM_MOVING; extern int SOUND_BUTTON; extern int SOUND_EXPLOSION; extern int SOUND_GAME_OVER_CLICK; extern int SOUND_GAME_OVER_RESTART; extern int SOUND_GAME_OVER_STATS; extern int SOUND_GAME_OVER_TEXT; extern int SOUND_LEVEL_UP1; extern int SOUND_LEVEL_UP2; extern int SOUND_LEVEL_UP3; extern int SOUND_LEVEL_UP4; extern int SOUND_MAGZAP; extern int SOUND_PLANET; extern int SOUND_PLANET_HIT; extern int SOUND_REGION_FILLED; // Init Resources bool ExtractInitResources(ResourceManager *theMgr); extern Font* FONT_DEFAULT; extern Font* FONT_HUNGARR; extern Image* IMAGE_CUSTOM_DRAGGING; extern Image* IMAGE_CUSTOM_HAND; extern Image* IMAGE_CUSTOM_POINTER; extern Image* IMAGE_CUSTOM_TEXT; extern Image* IMAGE_HUNGARR_LOGO; // TitleScreen Resources bool ExtractTitleScreenResources(ResourceManager *theMgr); extern Image* IMAGE_LOADER_BAR; extern Image* IMAGE_LOADER_LOADINGTXT; extern int SOUND_CONTINUE; enum ResourceId { FONT_DEFAULT_ID, FONT_HUNGARR_ID, IMAGE_CUSTOM_POINTER_ID, IMAGE_CUSTOM_HAND_ID, IMAGE_CUSTOM_DRAGGING_ID, IMAGE_CUSTOM_TEXT_ID, IMAGE_HUNGARR_LOGO_ID, IMAGE_LOADER_BAR_ID, IMAGE_LOADER_LOADINGTXT_ID, SOUND_CONTINUE_ID, SOUND_MUTATOR_ID, SOUND_TIMER_ID, IMAGE_ROBOTROBOT_ID, IMAGE_CHECKBOX_ID, IMAGE_BG0_ID, IMAGE_BG1_ID, IMAGE_BG2_ID, IMAGE_BUTTON_DOWN_ID, IMAGE_BUTTON_OVER_ID, IMAGE_BUTTON_NORMAL_ID, IMAGE_DIALOG_BOX_ID, IMAGE_DIALOG_BUTTON_ID, IMAGE_SLIDER_TRACK_ID, IMAGE_SLIDER_THUMB_ID, IMAGE_HUNGARR_SMALL_ID, IMAGE_HUNGARR_BEAM_UP_ID, IMAGE_HUNGARR_BEAM_DOWN_ID, IMAGE_HUNGARR_BEAM_LEFT_ID, IMAGE_HUNGARR_BEAM_RIGHT_ID, IMAGE_HUNGARR_HORIZ_ID, IMAGE_HUNGARR_VERT_ID, IMAGE_ATOMIC_EXPLOSION_ID, IMAGE_BOMB_RADIAL_DEATH_ID, IMAGE_PLANETS_ID, IMAGE_SPARK_ID, IMAGE_PARTICLE_LIGHTNING_ID, SOUND_MAGZAP_ID, SOUND_BUTTON_ID, SOUND_PLANET_ID, SOUND_LEVEL_UP1_ID, SOUND_LEVEL_UP2_ID, SOUND_EXPLOSION_ID, SOUND_BEAM_HIT_ID, SOUND_PLANET_HIT_ID, SOUND_BEAM_MOVING_ID, SOUND_LEVEL_UP4_ID, SOUND_LEVEL_UP3_ID, SOUND_GAME_OVER_CLICK_ID, SOUND_GAME_OVER_STATS_ID, SOUND_GAME_OVER_RESTART_ID, SOUND_GAME_OVER_TEXT_ID, SOUND_REGION_FILLED_ID, RESOURCE_ID_MAX }; Image* GetImageById(int theId); Font* GetFontById(int theId); int GetSoundById(int theId); ResourceId GetIdByImage(Image *theImage); ResourceId GetIdByFont(Font *theFont); ResourceId GetIdBySound(int theSound); const char* GetStringIdById(int theId); ResourceId GetIdByStringId(const char *theStringId); } // namespace Sexy #endif libtuxcap-1.4.0/tuxcap/demo4/GameApp.cpp0000644000175000017500000004340411062533666017736 0ustar inniyahinniyah#include "GameApp.h" #include "TitleScreen.h" #include "Board.h" #include "WidgetManager.h" #include "MusicInterface.h" // We will be accessing the resource manager in this demo, so include it's header #include "ResourceManager.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::GameApp() { // mProdName is used for internal purposes to indicate the game that we're working on mProdName = "Demo 4"; // For internal uses, indicates the current product version mProductVersion = "1.0"; // This is the text that appears in the title bar of the application window mTitle = StringToSexyStringFast("TuxCap: " + mProdName + " - " + mProductVersion); // Indicates the registry location where all registry keys will be read from // and written to. This is stored under the HKEY_CURRENT_USER tree on // Windows systems. mRegKey = "TuxCap\\Demo4"; // Set the application width/height in terms of pixels here. Let's // use a different resolution from Demo 1 just for fun. mWidth = 800; mHeight = 600; // By setting this to true, the framework will automatically check to see // if hardware acceleration can be turned on. This doesn't guarantee that it // WILL be turned on, however. Some cards just aren't compatible or have // known issues. Also, cards with less than 8MB of video RAM aren't supported. // There are ways to override the 3D enabled settings, which we will discuss // in a later demo. As a side note, if you want to see if you app is // running with 3D acceleration, first enable debug keys by pressing // CTRL-ALT-D and then press F9. To toggle 3D on/off, press F8. That is just // for testing purposes. //mAutoEnable3D = true; mBoard = NULL; mTitleScreen = NULL; // See Board::UpdateF for a very lengthy explanation of this and smooth motion mVSyncUpdates = true; // mWaitForVSync = true; // mSoftVSyncWait = false; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// GameApp::~GameApp() { // Remove our "Board" class which was, in this particular demo, // responsible for all our game drawing and updating. // All widgets MUST be removed from the widget manager before deletion. // More information on the basics of widgets can be found in the Board // class file. If you tried to delete the Board widget before removing // it, you will get an assert. Because our board might not have been // added (if you shut down the app before closing the loading screen), // only remove it if it isn't null. if (mBoard != NULL) mWidgetManager->RemoveWidget(mBoard); // Take a look at TitleScreen::ButtonDepress if you haven't already. // It explains a function called SafeDeleteWidget. Notice that we're // directly deleting the widget here: that is because when our app's // destructor is called, it's at the very end of the shutdown sequence // and the safe delete widget list will NOT be processed. Thus we // have to delete the memory manually. delete mBoard; // If you shut down the app before closing the loading screen, then // it will need to be removed here. The rational for the next two // steps is the same as for Board: if (mTitleScreen != NULL) mWidgetManager->RemoveWidget(mTitleScreen); delete mTitleScreen; // We should also free up all the resources that we loaded // for ALL the resource groups. Deleting a group that was // already deleted doesn't do anything, it's ignored. mResourceManager->DeleteResources("Init"); mResourceManager->DeleteResources("TitleScreen"); mResourceManager->DeleteResources("Game"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::Init() { // Let the parent class perform any needed initializations first. // This should always be done. SexyAppBase::Init(); // We need to tell the resource manager to read in all the groups // and information from that main group we made, called ResourceManifest, // in the file "properties/resources.xml". The path/filename are // by default set up to load that file, so you must name it exactly as such. // This doesn't load any resources: it just parses the data and sets // things up for loading. LoadResourceManifest(); // Next, we want to load our absolutely necessary files that have to // be loaded before anything else can run. You'll notice in the resources.xml // file that we created a group called Init that contains these resources. // You may call it whatever you like. Let's load those resources now. // We do that by calling the LoadResources method of our mResourceManager // variable and specifying in quotes the name of the resource group to // load. This string is case sensitive. if (!mResourceManager->LoadResources("Init")) { mLoadingFailed = true; // This will display an informative error message indicating exactly // what went wrong in the resource loading process. ShowResourceError(true); return; } // Now we've loaded the resources, but we need to extract them. // Extraction is the phase that converts sound files to raw WAV // files, and sets up and initializes fonts and palletizes images. // The ResourceGen.exe program, when it generates C++ code for our // resources, also creates a function for EVERY resource group of the // form: ExtractResources, where is the exact name // of the resource group you made. In our case, we made an "Init" // group, so we have an ExtractInitResources method. You pass to it // the pointer to the resource manager. Because an error can occur // during this step, you should make sure to check for it. if (!ExtractInitResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // We also need to load our title screen graphics in, since you can't // display the title screen without any graphics. For an explanation of why // we placed this in a separate group from Init, see properties/resources.xml. // This code works exactly like the above did for the Init group. if (!mResourceManager->LoadResources("TitleScreen")) { mLoadingFailed = true; ShowResourceError(true); return; } if (!ExtractTitleScreenResources(mResourceManager)) { mLoadingFailed = true; ShowResourceError(true); return; } // Now let's create and add our title screen to the widget manager mTitleScreen = new TitleScreen(this); mTitleScreen->Resize(0, 0, mWidth, mHeight); // Let's let the title screen initialize it's widgets and data // before adding it to the widget manager: mTitleScreen->Init(); mWidgetManager->AddWidget(mTitleScreen); // Let's also load in some music to play. We use the mMusicInterface // member for all our music needs, which requires the BassMusicInterface.h // header to be loaded, since we use the library BASS to play our music. // We can load in WAV, OGG, or MP3 files. BASS also supports a number // of tracker formats, such as .it, .xm, .mod, etc. It also supports // a format called MO3, which is a compressed version of a tracker // file. For this example, we will use the MO3 from AstroPop. // Why? Cause it's ours and we won't get sued for using it. // We load our file manually, we do not use the resource manager for this. // The first parameter is the ID to associate the song with. Just as sounds // have IDs, so do music tracks. mMusicInterface->LoadMusic(0, "music/music.mo3"); // Let's load another copy of the file. Why? In order to fade from one // track to another, we need two instances of the track on different // channels. Let's load it again and give it a different ID, 1. mMusicInterface->LoadMusic(1, "music/music.mo3"); // Now we need to start playing a track. Because we are using an MO3 // and because the original format was a .it (Impulse Tracker) file, // there are actually multiple songs inside of it, differentiated // by various offsets. If you were just playing a single MP3 or OGG // or WAV file instead of a tracker file, you would ignore this // and use the default offset of 0 for the start of the song. // Because the person that made the song file was nice and // told us which offsets equated to which song pieces, I already // know the magic offset numbers. In this particular case, the // song for the intro screen is at offset 0, and the song // for the main game music is at offset 9. Our music artist // also was kind enough to put in tracker looping commands, // so you'll notice that the songs play over and over. A discussion // of tracker file formats is beyond the scope of this. Again, // if you are just playing a WAV/OGG/MP3, you use offset 0 (the default) // to indicate that you want to start playing from the start of the song. // // You can use PlayMusic to instantly play the track, or, like below, // you can use FadeIn to smoothly fade the song in. The first parameter // for both methods is the channel or song id that was used when the // track was first loaded (In our case, either 0 or 1 works). For both, // the second parameter is the offset to start playing at. Again, I just // happen to know that the intro song is at offset 0. For FadeIn, the // third parameter is how quickly to fade in, out of 1.0. The last parameter // for both indicates whether or not you want to loop. This is kind of weird, // but specify "false" to loop and "true" to not loop. mMusicInterface->FadeIn(0, 0, 0.002, false); // We'll cover changing the music and sound volumes in a later demo. // Next, we need to know how many resources there are to load. // This is necessary so we can display our progress bar on the title screen // and make it be the appropriate length. There's a variable in SexyAppBase // called mNumLoadingThreadTasks which holds the number of resources to // load in the LoadingThreadProc function. You get the number of resources // in a given group with a call to the resource manager's GetNumResources function // for each of your groups that you are going to load: mNumLoadingThreadTasks = mResourceManager->GetNumResources("Game"); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadProc() { // This time, things are different. We aren't manually loading // our fonts, sounds, and images. The resource manager is doing // it for us. For each of the groups that we want to load, // we first have to instruct the resource manager to begin the // loading phase and initialize its internal variables. // We do that with the StartLoadResources method and pass in the // exact string name of the group to begin loading: mResourceManager->StartLoadResources("Game"); // Now we need to load each individual resource. We will loop, // calling LoadNextResource at the start. When it returns false, // there are no more resources to load for the current group. // LoadNextResource knows what group to load from because // of the call to StartLoadResources above: while (mResourceManager->LoadNextResource()) { // The SexyAppBase variable, mCompletedLoadingThreadTasks, indicates the // total number of resources that have so far been loaded. This is used // to tell our loading screen the % progress we've made. See TitleScreen::Draw // for an example of how this is used. We need to increment this value // ourselves everytime we load a resource: mCompletedLoadingThreadTasks++; // If there was an error loading our resource, the resource manager // will tell us to shut down by setting mShutdown to true. If that // happened, immediately abort and return: if (mShutdown) return; // Remember in demos 1-3 how we had the Board class call MarkDirty // every update? Well, the title screen doesn't need to be such a hog. // The title screen only needs to repaint when its progress bar changes // size. The progress bar only changes size when a resource gets loaded. // Because the game app is the only one that knows when this happens, // the game app will be the one to tell the title screen that it's a // dirty, dirty widget and that it needs a good and proper repainting. // You COULD make an update method for the title screen and mark dirty // every frame. But because this consumes more CPU time, it will take // longer to load our resources. And since you want the loading time // to be as quick as possible, you should only repaint when you need to. mTitleScreen->MarkDirty(); } // Just like in our Init function, after loading resources we // need to extract them. Let's do that. Let's also ask the resource // manager if an error occurred in the above loop that we // didn't yet catch. We do that with the HadError method: if (mResourceManager->HadError() || !ExtractGameResources(mResourceManager)) { ShowResourceError(false); mLoadingFailed = true; return; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::LoadingThreadCompleted() { // Let the base app class also know that we have completed SexyAppBase::LoadingThreadCompleted(); // When we're actually loading resources, we'll set the // mLoadingFailed variable to "true" if there were any problems // encountered along the way. If that is the case, just return // because we won't want the user to get to the main menu or any // other part of the game. We will want them to exit out. if (mLoadingFailed) return; // We aren't going to make and add the Board class here like we // did in the previous demos. Instead, since we are done loading // everything, we're going to tell the title screen that // we're done and that it should unhide the continue link and let // the user enter the game. mTitleScreen->LoadingComplete(); // Remember: since we didn't give our title screen an Update method, // this class is responsible for telling it when to repaint. If we // don't mark it dirty, you won't see the hyperlink widget // appear. So mark it dirty now: mTitleScreen->MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::TitleScreenIsFinished() { // This function is called by the title screen when the user clicks // on the hyperlink widget to continue. At this point, the title screen // has already removed itself and its widgets and we should set up our // Board class and begin the game. Let's also set our title screen // pointer to NULL, since it will be safely deleted automatically at a // later point, and we don't want to delete it twice. mTitleScreen = NULL; mBoard = new Board(this); // Now that the title screen is done, we don't need its resources // wasting memory. Let's delete all of its resources. We do that // by calling DeleteResources and specifying the exact name of the // resource group we want to free up: mResourceManager->DeleteResources("TitleScreen"); // This is a very important step: Because the Board class is a widget // (see Board.h/.cpp for more details) we need to tell it what // dimensions it has and where to place it. // By default a widget is invisible because its // width/height are 0, 0. Since the Board class is our main // drawing area and game logic class, we want to make it the // same size as the application. For this particular demo, that means // 800x600. We will use mWidth and mHeight though, as those were // already set to the proper resolution in GameApp::Init(). mBoard->Resize(0, 0, mWidth, mHeight); // Also an important step is to add the newly created Board widget to // the widget manager so that it will automatically have its update, draw, // and input processing methods called. mWidgetManager->AddWidget(mBoard); // Let's fade out the intro song and fade in the main game music. // FadeOut works just like FadeIn did in Init() but with some // slightly different parameters. The first, is like with FadeIn and // PlayMusic, the channel or song id that you want to mess with. // The second indicates that the song fading out should stop when // done, if it is true. The final parameter indicates how fast // to fade out, and is from 0 to 1. mMusicInterface->FadeOut(0, true, 0.004); // Let's fade in the main game music. This is the same as in Init. // The only difference is we're using 1 instead of 0 for our song id. // Why? Well, channel/song id 0 is being used to fade out the // previously playing track, we can't use it to also fade in. // That's why we loaded another copy of the song into channel 1. // Again, as explained in Init, I happen to know that offset 9 // is the start of the main game music. mMusicInterface->FadeIn(1, 9, 0.002, false); // We'll cover changing the music and sound volumes in a later demo. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void GameApp::HandleCmdLineParam(const std::string& theParamName, const std::string& theParamValue) { // If you wanted to, in here you could examine command line parameters and their values. // We actually don't care to, in this. The purpose was to show you how you'd do it, // and this function is the one you use to read those values. We'll just print the // parameters out for now: #if 0 OutputDebugString(StrFormat("theParamName = \"%s\", theParamValue = \"%s\"", theParamName.c_str(), theParamValue.c_str()).c_str()); #endif } libtuxcap-1.4.0/tuxcap/demo4/TitleScreen.cpp0000644000175000017500000002152610641010426020630 0ustar inniyahinniyah#include "TitleScreen.h" #include "GameApp.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" // Now that we're on our 4th demo, the reason for including the headers // below should be apparent. If you forgot, review demos 1-3. #include "Font.h" #include "Graphics.h" #include "Image.h" #include "WidgetManager.h" #include "Rect.h" // A new class: the HyperlinkWidget. It acts and resembles a standard // WWW hyperlink. #include "HyperlinkWidget.h" using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::TitleScreen(GameApp *pApp) { mApp = pApp; mContinueLink = NULL; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// TitleScreen::~TitleScreen() { delete mContinueLink; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Init(void) { // A hyperlink widget is basically the same thing as a button widget // but with some slight differences. It is meant to emulate the look // and feel of an internet hyperlink. We create the widget the // same way we created a button widget in Demo3, specifying that // this class is to listen to the widget events. mContinueLink = new HyperlinkWidget(1, this); // We need to set the font to use. In previous demos, we had // a variable inside of GameApp that held the font. Now that we're // using the resource manager, we'll use the main (and only) one // that we declared from there. Remember how we named it FONT_DEFAULT? // Well, you can use that name exactly now to reference it. mContinueLink->SetFont(FONT_DEFAULT); // Like the button widget, we can set the text to display: mContinueLink->mLabel = _S("CLICK TO CONTINUE"); // And like the button widget, we can set the default and over colors. // We don't use the SetColor method though, we just directly // set mColor and mOverColor: mContinueLink->mColor = Color(255, 255, 255); mContinueLink->mOverColor = Color(0, 255, 0); mContinueLink->mUnderlineSize = 1; // We're not going to place the widget just yet. Why? Well, // the TitleScreen hasn't been added to the widget manager. // We'll wait until the AddedToManager method is called before // adding it, just like in Demo3. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::AddedToManager(WidgetManager *theWidgetManager) { Widget::AddedToManager(theWidgetManager); // Just like with the button widget from Demo3, we're going to add our // hyperlink widget in this method. However, we want the link to be // invisible at first. Why? Well, while we're loading our resources, // we don't want the user to be able to just start the game. We want // them to wait until it's all loaded and ready to go. Once everything // is loaded, then we'll make it visible and let them click to play. // We do that with the SetVisible command: mContinueLink->SetVisible(false); // Just making it invisible isn't enough. Technically the user could // still click on it even though they can't see it. We have to // disable the widget to prevent it from receiving input: mContinueLink->SetDisabled(true); // Let's resize it to be at the bottom of the screen, and to be exactly // the width/height of the lable that we set. Again, we use our friend // the Resize function. However, note that we're setting the height to // be a bit larger than that of the string. That's because the underline // part of the hyperlink widget (whose thickness can be controlled via mUnderlineSize) // draws a little below the string. If you didn't make the height a little // larger, the line would be clipped and thus wouldn't be visible. Clipping // is discussed in the next demo. int labelWidth = FONT_DEFAULT->StringWidth(mContinueLink->mLabel); int labelHeight = FONT_DEFAULT->GetHeight(); mContinueLink->Resize( mWidth / 2 - labelWidth / 2, mHeight - labelHeight - 40, labelWidth, labelHeight+4); // Almost done. Let's make it so that when the user mouses over the widget, // that the cursor changes from the standard Windows arrow to a hand icon. // We do that by setting the variable mDoFinger to true. This instructs the // WidgetManager to chagne the cursor to the hand/finger icon when the mouse // is inside the widget's bounds, and to reset it back to the arrow when it // is not. Note that ALL widgets have this functionality. mContinueLink->mDoFinger = true; // And finally, we add the widget just like we added the button widget // from demo 3 and the Board widget. theWidgetManager->AddWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::RemovedFromManager(WidgetManager *theWidgetManager) { // This is just like what we did in Board in Demo3. // Let our parent class know about the removal, and get rid // of our hyperlink widget. Widget::RemovedFromManager(theWidgetManager); theWidgetManager->RemoveWidget(mContinueLink); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::Draw(Graphics *g) { // Instead of having to say Color(0, 0, 0) or Color(255, 255, 255) // for black/white, you can use Color::Black and Color::White. g->SetColor(Color::Black); g->FillRect(0, 0, mWidth, mHeight); // We want to draw our loader bar to indicate the progress made in // loading all our resources. As you recalll, GameApp::LoadingThreadProc is // the thread that is actually loading everything. The app has a function, // GetLoadingThreadProgress, that returns a value from 0.0 to 1.0 indicating // the % complete it is. We will multiply this % complete by the width // of our progress bar, so that we give the illusion of a growing bar. int loaderBarWidth = IMAGE_LOADER_BAR->GetWidth(); int drawWidth = (int)(mApp->GetLoadingThreadProgress() * loaderBarWidth); if (drawWidth > 0) { // As you may recall from Demo3 where we drew the frames of animation // for the lightning image, the DrawImage call can take a source rectangle // which indicates what chunk of the original image we want to draw. // In our case, we want to start from from the upper left corner of // the loader bar, but we only want to draw "drawWidth" wide. This will // give the illusion that the progress bar is expanding as the resources // are loaded in. g->DrawImage(IMAGE_LOADER_BAR, mWidth / 2 - loaderBarWidth / 2, 400, Rect(0, 0, drawWidth, IMAGE_LOADER_BAR->GetHeight())); } // If our hyperlink widget is false, let's instead draw some // "Loading" text (er, actually in this case it's an image) where // it is located. if (mContinueLink->mVisible == false) g->DrawImage(IMAGE_LOADER_LOADINGTXT, mContinueLink->mX, mContinueLink->mY - 20); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::LoadingComplete() { // Since the app told us that we're done loading all our resources, // let's unhide and enable our continue link so the user can start // playing. mContinueLink->SetVisible(true); mContinueLink->SetDisabled(false); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void TitleScreen::ButtonDepress(int theId) { if (theId == 1) { // Our hyperlink widget was pressed. We want to remove ourselves // and the hyperlink widget, and tell the app to display the // main board and get the game started. // You might be thinking, "If I delete the title screen and // hyperlink, won't I crash the program?" Yes, you will. That's // why we aren't going to delete them using "delete". We're going // to use SexyAppBase's SafeDeleteWidget method. This places the // widget in a queue that is processed after all widgets and data // get processed, and is then deleted at a time that is safe // and appropriate. We still have to remove ourself and the // hyperlink widget from the WidgetManager. We can easily access // the WidgetManager, as it is a public variable in our game app. mApp->mWidgetManager->RemoveWidget(this); mApp->mWidgetManager->RemoveWidget(mContinueLink); mApp->SafeDeleteWidget(this); mApp->SafeDeleteWidget(mContinueLink); mContinueLink = NULL; // Now let's tell the game app that it's ok to add the board widget: mApp->TitleScreenIsFinished(); } } libtuxcap-1.4.0/tuxcap/demo4/CMakeLists.txt0000644000175000017500000000402110762446645020456 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL Magick++ audiere GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp TitleScreen.cpp Board.cpp GameApp.cpp Res.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../demo_4") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/demo4/Board.h0000644000175000017500000003477010641010426017110 0ustar inniyahinniyah#ifndef __BOARD_H__ #define __BOARD_H__ ////////////////////////////////////////////////////////////////////////// // Board.h // // This is the third class to look at in this particular demo // (after main.cpp and GameApp.h/.cpp). The Board class is where most of // your actual game programming will go. It is here that we will do // all our game drawing, updating, and input processing. Of course, in // a larger application, you would probably do drawing and updating in // multiple files, but you would still most likely use something similar // to a Board class as the master game logic class. // // The reason that the Board class is a widget is because when a widget // is added to the GameApp's WidgetManager, it will automatically have its // Update and Draw methods called, and it will automatically receive input // at the appropriate times. Furthermore, by making it a widget and adding // it to the WidgetManager, the game logic loop, Update(), will be guaranteed // to run at a standard 100FPS on all machines. This is extremely important // as you always want your logic code to run at the same speed, but want // the drawing code to run as fast as possible. That way on faster machines // your program doesn't run its logic faster than on a slower machine. // // You can think of the Board as a canvas upon which we do all our // drawing, and a central hub where if we need to, we instruct other // classes where and when to draw to. ////////////////////////////////////////////////////////////////////////// #include "Widget.h" #include "ButtonListener.h" // Because we're going to be learning about some new widgets, we // need to include some more listener classes so we can respond to each one. #include "EditListener.h" #include "CheckboxListener.h" #include "ListListener.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // Forward declare the graphics class. You will see the graphics class used // and explained in Board.cpp: it is the main object used to draw all // images, fonts, etc. class Graphics; // We maintain a pointer to the main game application in the Board class. // The main game app contains functions that are often times needed // by the Board class, such as registry reading/writing, file reading/writing, // etc. class GameApp; // forward declare the widgets we're going to use in this demo: class ButtonWidget; class EditWidget; class Checkbox; class ListWidget; class ScrollbarWidget; // In this demo, we're going to do some more advanced things like // handle the two cases where Board is added and removed from the // WidgetManager. class WidgetManager; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// class Board : public Widget, public ButtonListener, public EditListener, public CheckboxListener, public ListListener { private: GameApp* mApp; ButtonWidget* mButton1; // We'll use these buttons for sound playing ButtonWidget* mButton2; // These are explained in the C++ code, they are the new widgets we're learning about. EditWidget* mEditWidget; Checkbox* mCheckboxWidget; ListWidget* mListWidget; ScrollbarWidget* mScrollbarWidget; SexyString mText; // When we press enter on the edit box, we'll set this string and print it // Both are floats to ensure that the only difference in the movement demo // is the fact that one is updated in UpdateF and the other is in Update. float mMotionX; // For our movement example, this is the X coordinate of the image as it moves rightward float mUpdateFMotionX;// Same as above, but only modified in UpdateF, to illustrate the difference in motion public: ////////////////////////////////////////////////////////////////////////// // Function: Board // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// Board(GameApp* theApp); virtual ~Board(); ////////////////////////////////////////////////////////////////////////// // Function: EditWidgetText // Parameters: // theId - Integer ID of the edit widget sending this message // theString - The contents of the edit widget // // Returns: none // // Purpose: Called whenever the return/enter key is pressed on // an edit widget. ////////////////////////////////////////////////////////////////////////// void EditWidgetText(int theId, const std::string& theString); ////////////////////////////////////////////////////////////////////////// // Function: AllowChar // Parameters: // theId - Integer ID of the edit widget sending this message // theChar - Character just typed in // // Returns: // true - Indicates that the character is acceptible // false - Indicates that the character is invalid // // Purpose: Whenever an ASCII character is typed into the edit box, // this method is called first. If the method returns true, then the // character just typed is accepted and appended to the current edit widget // string. If it returns false, the character is rejected and is not added. ////////////////////////////////////////////////////////////////////////// bool AllowChar(int theId, char theChar); ////////////////////////////////////////////////////////////////////////// // Function: CheckboxChecked // Parameters: // theId - Integer ID of the checkbox widget sending this message // checked - Boolean indicating if the widget is checked or not // // Returns: none // // Purpose: Whenever a checkbox widget is checked or unchecked, this // method is called. We're not actually going to do anything with this, // we're just listing it here as an example of how you'd implement a // function to respond to that event. ////////////////////////////////////////////////////////////////////////// void CheckboxChecked(int theId, bool checked) {;} ////////////////////////////////////////////////////////////////////////// // Function: ListClicked // Parameters: // theId - Integer ID of the listbox widget sending this message // theIdx - Integer indicating the index of the item selected in the list // theClickCount - An integer indicating which mouse button // was pressed. One of the following: // 1: Left button // 2: Double-left-click // 3: Middle button // -1: Right button // -2: Double-right-click // // Returns: none // // Purpose: Called any time a list widget is clicked on. The list // widget by default doesn't automatically select the item you clicked on, // it instead calls this method and in here you manually select the item. // This is to allow you to prevent the selection of certain items, such as // disabled items, etc. ////////////////////////////////////////////////////////////////////////// void ListClicked(int theId, int theIdx, int theClickCount); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this function // is the main method that is responsible for all graphical and textual // displaying. ////////////////////////////////////////////////////////////////////////// virtual void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: Update // Parameters: none // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager, this method // is GUARANTEED to be called 100 times per second (100FPS) and is where // all main game logic is performed. Of course, if you had a larger more // complex game, you'd most likely divide your logic between several // other files, but this is commonly the central place where all game // logic begins and is executed. ////////////////////////////////////////////////////////////////////////// virtual void Update(); ////////////////////////////////////////////////////////////////////////// // Function: UpdateF // Parameters: // theFrac - The number of updates this time slice represents. // // Returns: none // // Purpose: // There has been a fundamental temporal aliasing issue in the previous // demos because games run at a 100 Hz Update rate while the user's monitor // is refreshing at some other rate, generally between 60 and 85 Hz. The fixed // 100 Hz Update rate is convenient because it allows game logic to proceed // independantly from the refresh rate, but in some cases it's worth the extra // trouble of updating at a variable rate in order to provide smoother animation, // as in the case of a scrolling background, a shark with words written on it, // or an Arkanoid ball. // // To illustrate the aliasing problem, imagine a ball that is supposed to move // 200 pixels per second, running on a 75 Hz monitor. The update rate of the // game is 100 Hz, so that means that we will add 2 pixels to the ball position // every update, and there will be 1.33 updates per monitor refresh (on average). // That means that that 2 out of every 3 monitor refreshes will show the ball // moving 2 pixels, and and the third will show it moving 4 pixels. That isn't // smooth motion. The correct solution would be for the ball to move 2.67 // pixels every monitor refresh. But how do we do that? // // To support smooth motion, we use UpdateF. Widget::UpdateF is similar to // Widget::Update, but Widget::UpdateF gets a float passed into it that // represents how many Update's this time slice represents. In the 75 Hz // example, UpdateF would always be called with 1.33. Update has certainly // not been made obsolete, however, and you can choose which // parts of your game logic should be in Update and which should be in // UpdateF. To facilitate cooperation and good behavior between the two // update methods, there are some rules they follow: Updating always occurs // in blocks, with one or two Update calls followed immediately with an // UpdateF call. This means that the application will never get the chance // to draw or process input between an Update and a Draw without calling // UpdateF in the middle. Therefore, you can assume that focus won't be // lost, nor will input change between an Update and an UpdateF, and you'll // know that you'll have a chance to finalize your state in UpdateF so things // can be left dangling (whatever that means for your app) after Update. // You are also guaranteed that the value passed in to UpdateF will be between // 1.67 (for a 60 Hz monitor) and 1.0 (for a 100 Hz monitor). Even if the // monitor is 60 Hz but the computer is only fast enough to draw at 30 FPS // you will get two Update blocks in a row before the draw, so it will still // appear to your app as if you are updating at 60 Hz. // // IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT // // In order to fully use this, you need to set up a few things. // Set GameApp::mVSyncUpdates to true, override UpdateF(float theFrac), // and move some code from Update that used to look like // this: "mPos += 1.5;", changing it to "mPos += 1.5 * theFrac;". // Check out the C++ code for an example of motion using both Update and // UpdateF. // // IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT IMPORTANT // // Because UpdateF is called a variable number of times per second, // you do NOT want to put game logic in it that needs to remain framerate // independant. Use UpdateF ONLY for movement related operations, and not // for your main game code. // // If you really want to avoid shearing in windowed mode, you can // set GameApp::mWaitForVSync to true and set GameApp::mSoftVSyncWait // to false. NOTE: This winds up doing some busy waiting and consumes // more processor time. // IMPORTANT: YOU MUST ALSO DELETE THE FOLLOWING REGISTRY KEY: // Whereever your registry settings are stored // (HKEY_LOCAL_MACHINE\SOFTWARE\SexyAppFramework\Demo4 for this case), // you must delete the key "WaitForVSync". This is VERY important, and it // won't work otherwise. ////////////////////////////////////////////////////////////////////////// virtual void UpdateF(float theFrac); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// virtual void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the Board class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// virtual void RemovedFromManager(WidgetManager* theWidgetManager); }; } #endif // __BOARD_H__ libtuxcap-1.4.0/tuxcap/demo4/GameApp.h0000644000175000017500000001105410641010426017361 0ustar inniyahinniyah#ifndef __GAMEAPP_H__ #define __GAMEAPP_H__ ////////////////////////////////////////////////////////////////////////// // GameApp.h // // This is what drives the whole game. In here, you derive your class // from SexyAppBase and implement common game tasks, such as // responding to widgets (covered later), initializing and loading // resources, setting up the various game screens, etc. // All applications at minimum must have a class that derives from // SexyAppBase. // // The GameApp class is used to do such things as create the main // menu screen, create the main game class (where all drawing/updating/ // interaction takes place), etc. ////////////////////////////////////////////////////////////////////////// #include "SexyAppBase.h" // We place all our classes inside the "Sexy" namespace to avoid name collisions // with other libraries that might be added. namespace Sexy { // The GameApp class will be responsible for creating a class by the name // of "Board", which we will use to do all the game's drawing, input processing, // etc. Board is the second most important class and is where almost all of your // game logic code will originate from. It is a widget, which allows for // easy and automatic invocation of its update, drawing, and input processing // functions. See the "Board" class for more details. class Board; // We're going to be responsible for creating and adding the title screen widget class TitleScreen; class GameApp : public SexyAppBase { private: Board* mBoard; TitleScreen* mTitleScreen; public: GameApp(); virtual ~GameApp(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Initializes the application. Sets the resolution, overrides // any default settings, and if there is a loader/intro screen (not in this demo) // creates it and displays it. The framework will then automatically // call the LoadingThreadProc() method after this method returns. ////////////////////////////////////////////////////////////////////////// virtual void Init(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadProc // Parameters: none // Returns: none // // Purpose: Loads all resources in a separate thread. If there is a // loader/intro screen (not in this demo), would also update the // loader progress indicator. When the function returns, the // LoadingThreadCompleted() method is automatically called. ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadProc(); ////////////////////////////////////////////////////////////////////////// // Function: LoadingThreadCompleted // Parameters: none // Returns: none // // Purpose: Called when LoadingThreadProc is complete and all resources // have been loaded. It is in this function that you would then set up // your main menu or similar screen. For this particular demo however, // we will go straight to the main game class, "Board". ////////////////////////////////////////////////////////////////////////// virtual void LoadingThreadCompleted(); ////////////////////////////////////////////////////////////////////////// // Function: TitleScreenIsFinished // Parameters: none // Returns: none // // Purpose: Called by the TitleScreen widget when it is about to close // down, this indicates that we should now add the board widget and // start the game. ////////////////////////////////////////////////////////////////////////// void TitleScreenIsFinished(); ////////////////////////////////////////////////////////////////////////// // Function: HandleCmdLineParam // Parameters: // theParamName - The name of the parameter, will be of the form // "-paramname". Note the "-" prefix. // theParamValue - The parameter associated with the param name, // or "" if none. // // Returns: none // // Purpose: This function lets you parse command line parameters and // their associated values. Command line parameters are of the form: // -paramname or -paramname="some value" // Example: // Demo4.exe -debug -printmsg="A test message" results in: // // theParamName = "-debug", theParamValue = "" // theParamName = "-printmsg", theParamValue = "A test message" ////////////////////////////////////////////////////////////////////////// virtual void HandleCmdLineParam(const std::string& theParamName, const std::string& theParamValue); }; } #endif // __GAMEAPP_H__ libtuxcap-1.4.0/tuxcap/demo4/Res.cpp0000644000175000017500000003023310643254671017151 0ustar inniyahinniyah#include "Res.h" #include "ResourceManager.h" using namespace Sexy; #pragma warning(disable:4311 4312) static bool gNeedRecalcVariableToIdMap = false; bool Sexy::ExtractResourcesByName(ResourceManager *theManager, const char *theName) { if (strcmp(theName,"Game")==0) return ExtractGameResources(theManager); if (strcmp(theName,"Hungarr")==0) return ExtractHungarrResources(theManager); if (strcmp(theName,"Init")==0) return ExtractInitResources(theManager); if (strcmp(theName,"TitleScreen")==0) return ExtractTitleScreenResources(theManager); return false; } Sexy::ResourceId Sexy::GetIdByStringId(const char *theStringId) { typedef std::map MyMap; static MyMap aMap; if(aMap.empty()) { for(int i=0; isecond; } // Game Resources Image* Sexy::IMAGE_BG0; Image* Sexy::IMAGE_BG1; Image* Sexy::IMAGE_BG2; Image* Sexy::IMAGE_BUTTON_DOWN; Image* Sexy::IMAGE_BUTTON_NORMAL; Image* Sexy::IMAGE_BUTTON_OVER; Image* Sexy::IMAGE_CHECKBOX; Image* Sexy::IMAGE_DIALOG_BOX; Image* Sexy::IMAGE_DIALOG_BUTTON; Image* Sexy::IMAGE_ROBOTROBOT; Image* Sexy::IMAGE_SLIDER_THUMB; Image* Sexy::IMAGE_SLIDER_TRACK; int Sexy::SOUND_MUTATOR; int Sexy::SOUND_TIMER; bool Sexy::ExtractGameResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_BG0 = aMgr.GetImageThrow("IMAGE_BG0"); IMAGE_BG1 = aMgr.GetImageThrow("IMAGE_BG1"); IMAGE_BG2 = aMgr.GetImageThrow("IMAGE_BG2"); IMAGE_BUTTON_DOWN = aMgr.GetImageThrow("IMAGE_BUTTON_DOWN"); IMAGE_BUTTON_NORMAL = aMgr.GetImageThrow("IMAGE_BUTTON_NORMAL"); IMAGE_BUTTON_OVER = aMgr.GetImageThrow("IMAGE_BUTTON_OVER"); IMAGE_CHECKBOX = aMgr.GetImageThrow("IMAGE_CHECKBOX"); IMAGE_DIALOG_BOX = aMgr.GetImageThrow("IMAGE_DIALOG_BOX"); IMAGE_DIALOG_BUTTON = aMgr.GetImageThrow("IMAGE_DIALOG_BUTTON"); IMAGE_ROBOTROBOT = aMgr.GetImageThrow("IMAGE_ROBOTROBOT"); IMAGE_SLIDER_THUMB = aMgr.GetImageThrow("IMAGE_SLIDER_THUMB"); IMAGE_SLIDER_TRACK = aMgr.GetImageThrow("IMAGE_SLIDER_TRACK"); SOUND_MUTATOR = aMgr.GetSoundThrow("SOUND_MUTATOR"); SOUND_TIMER = aMgr.GetSoundThrow("SOUND_TIMER"); } catch(ResourceManagerException&) { return false; } return true; } // Hungarr Resources Image* Sexy::IMAGE_ATOMIC_EXPLOSION; Image* Sexy::IMAGE_BOMB_RADIAL_DEATH; Image* Sexy::IMAGE_HUNGARR_BEAM_DOWN; Image* Sexy::IMAGE_HUNGARR_BEAM_LEFT; Image* Sexy::IMAGE_HUNGARR_BEAM_RIGHT; Image* Sexy::IMAGE_HUNGARR_BEAM_UP; Image* Sexy::IMAGE_HUNGARR_HORIZ; Image* Sexy::IMAGE_HUNGARR_SMALL; Image* Sexy::IMAGE_HUNGARR_VERT; Image* Sexy::IMAGE_PARTICLE_LIGHTNING; Image* Sexy::IMAGE_PLANETS; Image* Sexy::IMAGE_SPARK; int Sexy::SOUND_BEAM_HIT; int Sexy::SOUND_BEAM_MOVING; int Sexy::SOUND_BUTTON; int Sexy::SOUND_EXPLOSION; int Sexy::SOUND_GAME_OVER_CLICK; int Sexy::SOUND_GAME_OVER_RESTART; int Sexy::SOUND_GAME_OVER_STATS; int Sexy::SOUND_GAME_OVER_TEXT; int Sexy::SOUND_LEVEL_UP1; int Sexy::SOUND_LEVEL_UP2; int Sexy::SOUND_LEVEL_UP3; int Sexy::SOUND_LEVEL_UP4; int Sexy::SOUND_MAGZAP; int Sexy::SOUND_PLANET; int Sexy::SOUND_PLANET_HIT; int Sexy::SOUND_REGION_FILLED; bool Sexy::ExtractHungarrResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_ATOMIC_EXPLOSION = aMgr.GetImageThrow("IMAGE_ATOMIC_EXPLOSION"); IMAGE_BOMB_RADIAL_DEATH = aMgr.GetImageThrow("IMAGE_BOMB_RADIAL_DEATH"); IMAGE_HUNGARR_BEAM_DOWN = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_DOWN"); IMAGE_HUNGARR_BEAM_LEFT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_LEFT"); IMAGE_HUNGARR_BEAM_RIGHT = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_RIGHT"); IMAGE_HUNGARR_BEAM_UP = aMgr.GetImageThrow("IMAGE_HUNGARR_BEAM_UP"); IMAGE_HUNGARR_HORIZ = aMgr.GetImageThrow("IMAGE_HUNGARR_HORIZ"); IMAGE_HUNGARR_SMALL = aMgr.GetImageThrow("IMAGE_HUNGARR_SMALL"); IMAGE_HUNGARR_VERT = aMgr.GetImageThrow("IMAGE_HUNGARR_VERT"); IMAGE_PARTICLE_LIGHTNING = aMgr.GetImageThrow("IMAGE_PARTICLE_LIGHTNING"); IMAGE_PLANETS = aMgr.GetImageThrow("IMAGE_PLANETS"); IMAGE_SPARK = aMgr.GetImageThrow("IMAGE_SPARK"); SOUND_BEAM_HIT = aMgr.GetSoundThrow("SOUND_BEAM_HIT"); SOUND_BEAM_MOVING = aMgr.GetSoundThrow("SOUND_BEAM_MOVING"); SOUND_BUTTON = aMgr.GetSoundThrow("SOUND_BUTTON"); SOUND_EXPLOSION = aMgr.GetSoundThrow("SOUND_EXPLOSION"); SOUND_GAME_OVER_CLICK = aMgr.GetSoundThrow("SOUND_GAME_OVER_CLICK"); SOUND_GAME_OVER_RESTART = aMgr.GetSoundThrow("SOUND_GAME_OVER_RESTART"); SOUND_GAME_OVER_STATS = aMgr.GetSoundThrow("SOUND_GAME_OVER_STATS"); SOUND_GAME_OVER_TEXT = aMgr.GetSoundThrow("SOUND_GAME_OVER_TEXT"); SOUND_LEVEL_UP1 = aMgr.GetSoundThrow("SOUND_LEVEL_UP1"); SOUND_LEVEL_UP2 = aMgr.GetSoundThrow("SOUND_LEVEL_UP2"); SOUND_LEVEL_UP3 = aMgr.GetSoundThrow("SOUND_LEVEL_UP3"); SOUND_LEVEL_UP4 = aMgr.GetSoundThrow("SOUND_LEVEL_UP4"); SOUND_MAGZAP = aMgr.GetSoundThrow("SOUND_MAGZAP"); SOUND_PLANET = aMgr.GetSoundThrow("SOUND_PLANET"); SOUND_PLANET_HIT = aMgr.GetSoundThrow("SOUND_PLANET_HIT"); SOUND_REGION_FILLED = aMgr.GetSoundThrow("SOUND_REGION_FILLED"); } catch(ResourceManagerException&) { return false; } return true; } // Init Resources Font* Sexy::FONT_DEFAULT; Font* Sexy::FONT_HUNGARR; Image* Sexy::IMAGE_CUSTOM_DRAGGING; Image* Sexy::IMAGE_CUSTOM_HAND; Image* Sexy::IMAGE_CUSTOM_POINTER; Image* Sexy::IMAGE_CUSTOM_TEXT; Image* Sexy::IMAGE_HUNGARR_LOGO; bool Sexy::ExtractInitResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { FONT_DEFAULT = aMgr.GetFontThrow("FONT_DEFAULT"); FONT_HUNGARR = aMgr.GetFontThrow("FONT_HUNGARR"); IMAGE_CUSTOM_DRAGGING = aMgr.GetImageThrow("IMAGE_CUSTOM_DRAGGING"); IMAGE_CUSTOM_HAND = aMgr.GetImageThrow("IMAGE_CUSTOM_HAND"); IMAGE_CUSTOM_POINTER = aMgr.GetImageThrow("IMAGE_CUSTOM_POINTER"); IMAGE_CUSTOM_TEXT = aMgr.GetImageThrow("IMAGE_CUSTOM_TEXT"); IMAGE_HUNGARR_LOGO = aMgr.GetImageThrow("IMAGE_HUNGARR_LOGO"); } catch(ResourceManagerException&) { return false; } return true; } // TitleScreen Resources Image* Sexy::IMAGE_LOADER_BAR; Image* Sexy::IMAGE_LOADER_LOADINGTXT; int Sexy::SOUND_CONTINUE; bool Sexy::ExtractTitleScreenResources(ResourceManager *theManager) { gNeedRecalcVariableToIdMap = true; ResourceManager &aMgr = *theManager; try { IMAGE_LOADER_BAR = aMgr.GetImageThrow("IMAGE_LOADER_BAR"); IMAGE_LOADER_LOADINGTXT = aMgr.GetImageThrow("IMAGE_LOADER_LOADINGTXT"); SOUND_CONTINUE = aMgr.GetSoundThrow("SOUND_CONTINUE"); } catch(ResourceManagerException&) { return false; } return true; } static void* gResources[] = { &FONT_DEFAULT, &FONT_HUNGARR, &IMAGE_CUSTOM_POINTER, &IMAGE_CUSTOM_HAND, &IMAGE_CUSTOM_DRAGGING, &IMAGE_CUSTOM_TEXT, &IMAGE_HUNGARR_LOGO, &IMAGE_LOADER_BAR, &IMAGE_LOADER_LOADINGTXT, &SOUND_CONTINUE, &SOUND_MUTATOR, &SOUND_TIMER, &IMAGE_ROBOTROBOT, &IMAGE_CHECKBOX, &IMAGE_BG0, &IMAGE_BG1, &IMAGE_BG2, &IMAGE_BUTTON_DOWN, &IMAGE_BUTTON_OVER, &IMAGE_BUTTON_NORMAL, &IMAGE_DIALOG_BOX, &IMAGE_DIALOG_BUTTON, &IMAGE_SLIDER_TRACK, &IMAGE_SLIDER_THUMB, &IMAGE_HUNGARR_SMALL, &IMAGE_HUNGARR_BEAM_UP, &IMAGE_HUNGARR_BEAM_DOWN, &IMAGE_HUNGARR_BEAM_LEFT, &IMAGE_HUNGARR_BEAM_RIGHT, &IMAGE_HUNGARR_HORIZ, &IMAGE_HUNGARR_VERT, &IMAGE_ATOMIC_EXPLOSION, &IMAGE_BOMB_RADIAL_DEATH, &IMAGE_PLANETS, &IMAGE_SPARK, &IMAGE_PARTICLE_LIGHTNING, &SOUND_MAGZAP, &SOUND_BUTTON, &SOUND_PLANET, &SOUND_LEVEL_UP1, &SOUND_LEVEL_UP2, &SOUND_EXPLOSION, &SOUND_BEAM_HIT, &SOUND_PLANET_HIT, &SOUND_BEAM_MOVING, &SOUND_LEVEL_UP4, &SOUND_LEVEL_UP3, &SOUND_GAME_OVER_CLICK, &SOUND_GAME_OVER_STATS, &SOUND_GAME_OVER_RESTART, &SOUND_GAME_OVER_TEXT, &SOUND_REGION_FILLED, NULL }; Image* Sexy::LoadImageById(ResourceManager *theManager, int theId) { return (*((Image**)gResources[theId]) = theManager->LoadImage(GetStringIdById(theId))); } Image* Sexy::GetImageById(int theId) { return *(Image**)gResources[theId]; } Font* Sexy::GetFontById(int theId) { return *(Font**)gResources[theId]; } int Sexy::GetSoundById(int theId) { return *(int*)gResources[theId]; } static Sexy::ResourceId GetIdByVariable(const void *theVariable) { typedef std::map MyMap; static MyMap aMap; if(gNeedRecalcVariableToIdMap) { gNeedRecalcVariableToIdMap = false; aMap.clear(); for(int i=0; isecond; } Sexy::ResourceId Sexy::GetIdByImage(Image *theImage) { return GetIdByVariable(theImage); } Sexy::ResourceId Sexy::GetIdByFont(Font *theFont) { return GetIdByVariable(theFont); } Sexy::ResourceId Sexy::GetIdBySound(int theSound) { return GetIdByVariable((void*)theSound); } const char* Sexy::GetStringIdById(int theId) { switch(theId) { case FONT_DEFAULT_ID: return "FONT_DEFAULT"; case FONT_HUNGARR_ID: return "FONT_HUNGARR"; case IMAGE_CUSTOM_POINTER_ID: return "IMAGE_CUSTOM_POINTER"; case IMAGE_CUSTOM_HAND_ID: return "IMAGE_CUSTOM_HAND"; case IMAGE_CUSTOM_DRAGGING_ID: return "IMAGE_CUSTOM_DRAGGING"; case IMAGE_CUSTOM_TEXT_ID: return "IMAGE_CUSTOM_TEXT"; case IMAGE_HUNGARR_LOGO_ID: return "IMAGE_HUNGARR_LOGO"; case IMAGE_LOADER_BAR_ID: return "IMAGE_LOADER_BAR"; case IMAGE_LOADER_LOADINGTXT_ID: return "IMAGE_LOADER_LOADINGTXT"; case SOUND_CONTINUE_ID: return "SOUND_CONTINUE"; case SOUND_MUTATOR_ID: return "SOUND_MUTATOR"; case SOUND_TIMER_ID: return "SOUND_TIMER"; case IMAGE_ROBOTROBOT_ID: return "IMAGE_ROBOTROBOT"; case IMAGE_CHECKBOX_ID: return "IMAGE_CHECKBOX"; case IMAGE_BG0_ID: return "IMAGE_BG0"; case IMAGE_BG1_ID: return "IMAGE_BG1"; case IMAGE_BG2_ID: return "IMAGE_BG2"; case IMAGE_BUTTON_DOWN_ID: return "IMAGE_BUTTON_DOWN"; case IMAGE_BUTTON_OVER_ID: return "IMAGE_BUTTON_OVER"; case IMAGE_BUTTON_NORMAL_ID: return "IMAGE_BUTTON_NORMAL"; case IMAGE_DIALOG_BOX_ID: return "IMAGE_DIALOG_BOX"; case IMAGE_DIALOG_BUTTON_ID: return "IMAGE_DIALOG_BUTTON"; case IMAGE_SLIDER_TRACK_ID: return "IMAGE_SLIDER_TRACK"; case IMAGE_SLIDER_THUMB_ID: return "IMAGE_SLIDER_THUMB"; case IMAGE_HUNGARR_SMALL_ID: return "IMAGE_HUNGARR_SMALL"; case IMAGE_HUNGARR_BEAM_UP_ID: return "IMAGE_HUNGARR_BEAM_UP"; case IMAGE_HUNGARR_BEAM_DOWN_ID: return "IMAGE_HUNGARR_BEAM_DOWN"; case IMAGE_HUNGARR_BEAM_LEFT_ID: return "IMAGE_HUNGARR_BEAM_LEFT"; case IMAGE_HUNGARR_BEAM_RIGHT_ID: return "IMAGE_HUNGARR_BEAM_RIGHT"; case IMAGE_HUNGARR_HORIZ_ID: return "IMAGE_HUNGARR_HORIZ"; case IMAGE_HUNGARR_VERT_ID: return "IMAGE_HUNGARR_VERT"; case IMAGE_ATOMIC_EXPLOSION_ID: return "IMAGE_ATOMIC_EXPLOSION"; case IMAGE_BOMB_RADIAL_DEATH_ID: return "IMAGE_BOMB_RADIAL_DEATH"; case IMAGE_PLANETS_ID: return "IMAGE_PLANETS"; case IMAGE_SPARK_ID: return "IMAGE_SPARK"; case IMAGE_PARTICLE_LIGHTNING_ID: return "IMAGE_PARTICLE_LIGHTNING"; case SOUND_MAGZAP_ID: return "SOUND_MAGZAP"; case SOUND_BUTTON_ID: return "SOUND_BUTTON"; case SOUND_PLANET_ID: return "SOUND_PLANET"; case SOUND_LEVEL_UP1_ID: return "SOUND_LEVEL_UP1"; case SOUND_LEVEL_UP2_ID: return "SOUND_LEVEL_UP2"; case SOUND_EXPLOSION_ID: return "SOUND_EXPLOSION"; case SOUND_BEAM_HIT_ID: return "SOUND_BEAM_HIT"; case SOUND_PLANET_HIT_ID: return "SOUND_PLANET_HIT"; case SOUND_BEAM_MOVING_ID: return "SOUND_BEAM_MOVING"; case SOUND_LEVEL_UP4_ID: return "SOUND_LEVEL_UP4"; case SOUND_LEVEL_UP3_ID: return "SOUND_LEVEL_UP3"; case SOUND_GAME_OVER_CLICK_ID: return "SOUND_GAME_OVER_CLICK"; case SOUND_GAME_OVER_STATS_ID: return "SOUND_GAME_OVER_STATS"; case SOUND_GAME_OVER_RESTART_ID: return "SOUND_GAME_OVER_RESTART"; case SOUND_GAME_OVER_TEXT_ID: return "SOUND_GAME_OVER_TEXT"; case SOUND_REGION_FILLED_ID: return "SOUND_REGION_FILLED"; default: return ""; } } libtuxcap-1.4.0/tuxcap/demo4/TitleScreen.h0000644000175000017500000001074110641010426020272 0ustar inniyahinniyah#ifndef __TITLE_SCREEN_H__ #define __TITLE_SCREEN_H__ #include "Widget.h" #include "ButtonListener.h" namespace Sexy { class GameApp; class Graphics; class WidgetManager; // A new widget that we'll be learning about. It's explained in the .CPP code. class HyperlinkWidget; // If you forgot about the ButtonListener class, you should review Demo3. // The hyperlink widget is essentially the same thing as a button widget, // and emits the same messages that a button does. Thus, to act on its // messages we derive from the ButtonListener class. class TitleScreen : public Widget, public ButtonListener { private: GameApp* mApp; HyperlinkWidget* mContinueLink; public: ////////////////////////////////////////////////////////////////////////// // Function: TitleScreen // Parameters: // theApp - Pointer to the main application class // // Returns: none ////////////////////////////////////////////////////////////////////////// TitleScreen(GameApp* pApp); virtual ~TitleScreen(); ////////////////////////////////////////////////////////////////////////// // Function: Init // Parameters: none // Returns: none // // Purpose: Called BEFORE the title screen is added to the widget manager // by GameApp. This initializes some things like the images used for // our hyperlink widget. ////////////////////////////////////////////////////////////////////////// void Init(void); ////////////////////////////////////////////////////////////////////////// // Function: AddedToManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // added to its list of widgets. Every widget gets this function // called when it is first added. It useful to use this function to // set up any other widgets that the class might contain, such as buttons. ////////////////////////////////////////////////////////////////////////// void AddedToManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: RemovedFromManager // Parameters: // theWidgetManager - Pointer to the main widget manager from // GameApp. // // Returns: none // // Purpose: This function is automatically called by the widget manager // which also passes a pointer to itself, when the TitleScreen class is // removed from its list of widgets. Every widget gets this function // called when it is finally removed. It useful to use this function to // also remove any widgets that were added and created in AddedToManager. ////////////////////////////////////////////////////////////////////////// void RemovedFromManager(WidgetManager* theWidgetManager); ////////////////////////////////////////////////////////////////////////// // Function: ButtonDepress // Parameters: // theId - Integer ID of the button that was clicked // // Returns: none // // Purpose: This method is called by the WidgetManager when a button widget // is first pressed and THEN released. You can use ButtonPress if you want // to know when the button is first pressed (before it is released). // theId is the integer ID that was assigned to the button when it was // first created. ////////////////////////////////////////////////////////////////////////// virtual void ButtonDepress(int theId); ////////////////////////////////////////////////////////////////////////// // Function: Draw // Parameters: // g - Graphics object used to draw all images and fonts to the screen. // // Returns: none // // Purpose: Called automatically by GameApp's WidgetManager. This is where // we'll do all our display routines for the loading screen. ////////////////////////////////////////////////////////////////////////// void Draw(Graphics* g); ////////////////////////////////////////////////////////////////////////// // Function: LoadingComplete // Parameters: none // Returns: none // // Purpose: Called manually by GameApp when we are done loading all // resources, to let the title screen know that it should unhide and // enable the continue link, so the user can start playing the game. ////////////////////////////////////////////////////////////////////////// void LoadingComplete(); }; } #endif //__TITLE_SCREEN_H__ libtuxcap-1.4.0/tuxcap/demo4/main.cpp0000644000175000017500000000022710641010426017326 0ustar inniyahinniyah#include "GameApp.h" using namespace Sexy; int main(int argc, char** argv) { GameApp app; app.Init(); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/tuxcap/demo4/Board.cpp0000644000175000017500000004557510706205240017452 0ustar inniyahinniyah#include "Board.h" #include "GameApp.h" // Contains all the resources from the resources.xml file in our // properties directory. See that file for more information. #include "Res.h" // You should remember these files from the previous demos #include "Graphics.h" #include "Color.h" #include "Rect.h" #include "ButtonWidget.h" #include "WidgetManager.h" #include "ImageFont.h" // The following are needed for some new widgets we're going to learn about: #include "EditWidget.h" #include "Checkbox.h" #include "ListWidget.h" #include "ScrollbarWidget.h" #include "ScrollListener.h" // As part of our pitch shifted sound example, we'll need to // access the sound manager in our GameApp class as well as // individual sound instances: #include "SoundManager.h" #include "SoundInstance.h" // Used for file I/O: #include "Buffer.h" // The SexyAppFramework resides in the "Sexy" namespace. As a convenience, // you'll see in all the .cpp files "using namespace Sexy" to avoid // having to prefix everything with Sexy:: using namespace Sexy; ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::Board(GameApp* theApp) { mApp = theApp; mButton1 = NULL; mButton2 = NULL; mEditWidget = NULL; mCheckboxWidget = NULL; mListWidget = NULL; mScrollbarWidget = NULL; mMotionX = mUpdateFMotionX = 0; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// Board::~Board() { delete mButton1; delete mButton2; delete mEditWidget; delete mCheckboxWidget; delete mListWidget; delete mScrollbarWidget; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Update() { Widget::Update(); // As an example to illustrate the difference between smooth motion via UpdateF // and the traditional motion via Update, we'll udpate the two MotionX variables // separately. if ((mMotionX += 2.0f) >= mWidth) mMotionX = (float) -IMAGE_ROBOTROBOT->GetWidth(); MarkDirty(); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::UpdateF(float theFrac) { // This is very similar to Update, except that since this function // gets called a different number of times depending on the refresh // rate of the monitor, "theFrac" can be a variable number, and we // need to multiply our normal motion change of 5.0 pixels per // update by "theFrac" to get our smooth motion. See the header // comment for this function in Board.h for more details. if ((mUpdateFMotionX += 2.0f * theFrac) >= mWidth) mUpdateFMotionX = (float) -IMAGE_ROBOTROBOT->GetWidth(); // No need to MarkDirty: We're doing it in Board::Update already. } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::Draw(Graphics* g) { // Clear the screen to black g->SetColor(Color(0, 0, 0)); g->FillRect(0, 0, mWidth, mHeight); // Draw the image first using the standard method, with the coordinate // updated via Board::Update as an example of non-smooth motion. // Let's also print some text too. g->SetFont(FONT_DEFAULT); g->SetColor(Color(255, 255, 255)); g->DrawString(_S("Non smooth motion is jerky"), 10, 100); // What's this? A new DrawImage function? Yes. Believe it. It is true. // DrawImageF is just like it's best friend, DrawImage except that // it takes floating point values instead of integer ones. This is // slower than DrawImage, as the resulting image is anti-aliased to // give the illusion of moving at sub-pixel increments. A common // optimization technique at PopCap is to use DrawImageF // for motion when the user has a supported 3D card and DrawImage if // the user has to run in software mode. g->DrawImageF(IMAGE_ROBOTROBOT, mMotionX, 120.0f); // Now let's draw the image but using the smooth motion amounts: g->DrawString(_S("Smooth motion is silky smoothness"), 10, 200); g->DrawImageF(IMAGE_ROBOTROBOT, mUpdateFMotionX, 220.0f); // Let's draw the currently selected list item: g->DrawString(mText, mListWidget->mX, mListWidget->mY + mListWidget->mHeight + 20); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::AddedToManager(WidgetManager* theWidgetManager) { // At this point, the Board class has already been added to the // widget manager. We should call our parent class' method // so that it can be sure to perform any needed tasks, first. Widget::AddedToManager(theWidgetManager); // You should remember how to create buttons from Demo3. If not, // go back and review. We're going to make two buttons which we'll use // to do some sound playing when clicked. mButton1 = new ButtonWidget(1, this); mButton1->Resize(5, 5, 100, 50); mButton1->SetFont(FONT_DEFAULT); mButton1->mLabel = _S("Sound Left"); theWidgetManager->AddWidget(mButton1); mButton2 = new ButtonWidget(2, this); mButton2->Resize(106, 5, 100, 50); mButton2->SetFont(FONT_DEFAULT); mButton2->mLabel = _S("Sound Right"); theWidgetManager->AddWidget(mButton2); // Let's set up our edit widget, shall we? The constructor is // just like it is with all widgets that emit messages: first parameter // is the ID to use, second is the class that will listen to its events. // We're reusing some IDs here because an edit widget isn't a button // widget and thus the IDs won't be confused. In your app however, you // will most likely just want to use unique enums or numbers to assign // to each specific widget. mEditWidget = new EditWidget(1, this); // We can't type in text if we don't have a font! Set one: mEditWidget->SetFont(FONT_DEFAULT); // Let's also set a maximum number of characters allowed. // How about 15: mEditWidget->mMaxChars = 15; // If we wanted to emulate a password edit box, we could set // mEditWidget->mPasswordChar. Any character typed in would // then be visually replaced by mPasswordChar. We don't // want to do that in this demo though. mEditWidget->Resize(10, 300, 100, 15); theWidgetManager->AddWidget(mEditWidget); // Let's create a checkbox now. The checkbox widget does NOT // have any default drawing methods, unlike the other widgets. // You have to specify two images when creating a new one: // an unchecked and a checked image. There is another option though: // at PopCap it's common to place both the checked and unchecked image // into one image file. Observe how we handle this mind warp: mCheckboxWidget = new Checkbox(IMAGE_CHECKBOX, IMAGE_CHECKBOX, 1, this); // No way! The check AND unchecked images are the same! Yes. Indeed. // But we're not done. Now, we need to tell the checkbox that // it has to use a different part of the image for checked and a different // part for unchecked. This is just like drawing a chunk of an image // by specifying a Rect. For this particular image, the first cel // contains the unchecked state and the second contains the checked one: int checkWidth = IMAGE_CHECKBOX->GetWidth() / 2; mCheckboxWidget->mUncheckedRect = Rect(0, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); mCheckboxWidget->mCheckedRect = Rect(checkWidth, 0, checkWidth, IMAGE_CHECKBOX->GetHeight()); // Now add it and resize it mCheckboxWidget->Resize(200, 300, checkWidth, IMAGE_CHECKBOX->GetHeight()); theWidgetManager->AddWidget(mCheckboxWidget); // Let's create our list box. The first parameter is the id, second // is the font to use, and third is who's going to listen to its events: mListWidget = new ListWidget(1, FONT_DEFAULT, this); // This next line instructs the list box to draw an outline around itself mListWidget->mDrawOutline = true; // Now we need to set up the colors to use for the listbox. We create // a 2D array containing RGB values, which we pass via SetColors. // An explanation of each of the colors is below: int listWidgetColors[][3] = { {255, 255, 255}, //Background color {255, 0, 0}, //Outline color {0, 0, 0}, //Plain text not hilited {0, 0, 255}, //Text color when mouse is over text {128, 128, 128}, //Color of the bar displayed when an item is selected {190, 0, 80} //Color of the text if it has the bar behind it and mouse is not over it }; // Now we set the colors, and tell it that we're setting 6 of them mListWidget->SetColors(listWidgetColors, 6); // Let's create a scrollbar for the list widget. // The list widget is already a scrollbar listener, so we will // specify it as the widget responsible for dealing with the // scrollbar's messages. mScrollbarWidget = new ScrollbarWidget(1, mListWidget); // We also need to let the list widget know that it actually has a scrollbar. // That way, it will automatically resize it as items are added/removed. // IMPORTANT: You should do this before resizing the widgets. mListWidget->mScrollbar = mScrollbarWidget; // Now resize the list widget mListWidget->Resize(300, 300, 100, 100); // Let's resize the scrollbar to the right of the list box. Instead of using // Resize(...), we use ResizeScrollbar to indicate that the entire scrollbar, // arrows and thumb included, are to be evenly resized. This will appropriately // scale all the items in the scrollbar. mScrollbarWidget->ResizeScrollbar(mListWidget->mX + mListWidget->mWidth, mListWidget->mY, 25, // an arbitrary width for the bar itself mListWidget->mHeight); // Let's make the scrollbar invisible until there are enough items in the list box // to make them all not fit mScrollbarWidget->SetInvisIfNoScroll(true); theWidgetManager->AddWidget(mListWidget); theWidgetManager->AddWidget(mScrollbarWidget); // If you check out Board::EditWidgetText you'll see that we write out the // contents of the list box to disk every time something is added to it, or // it is cleared. For files that were created from a buffer, we can read // the data back into a buffer for ease of use. // // IMPORTANT: You can NOT load files into a buffer if they were not // created from a buffer in the first place. Thus, loading a random // text or binary file is not a good idea, since the buffer will // have no way to identify the datatypes beyond just a standard byte. // Plase read Board::EditWidgetText for an explanation of writing // with buffers. // // Let's load in the contents of that file, if it exists, // and repopulate the list box with it. The first step is to create // a Buffer object. The Buffer object will contain all the data // in the file: Buffer buffer; // Check if the file exists: if (mApp->FileExists("list_items.dat")) { // Read in all the data from the file. It will be stored in a format // unique to the Buffer object: if (!mApp->ReadBufferFromFile("list_items.dat", &buffer)) { // error, the file was corrupted or some other error occurred #if 0 mApp->Popup("Could not read contents of list_items.txt"); #endif } // In Board::EditWidgetText we wrote out all the strings // via buffer.WriteString. The order in which data is written // to the buffer is the order in which it is read. Thus, if // you wrote out 2 integers, a string, and 10 booleans, when // reading from the buffer you'd first ask for the 2 integers, // then the string, then the 10 booleans. This is important: // the order DOES matter. If you asked to read a string when // a long was actually the next element in the file, you'd // get an error. Buffers are very useful for userprofiles or // data files like that where you can guarantee an explicit // file format. while (!buffer.AtEnd()) mListWidget->AddLine(StringToSexyStringFast(buffer.ReadString()), true); } // If you read Board::ListClicked, you'll see that we // wrote the last selected item from the list box to the registry. // Let's read that value in, if it exists, and set the mText // variable to it so that it displays on screen. We use the // RegsitryRead... functions to grab values from the regsitry. // The values are assumed to be in the registry location that you // set by setting the mRegKey variable in GameApp's constructor. // The functions return false if there was an error reading the // key or the key doesn't exist: #if 0 mApp->RegistryReadString("ListItem", &SexyStringToStringFast(mText)); #endif } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::RemovedFromManager(WidgetManager* theWidgetManager) { // This is called after we've been removed from the widget manager. // Again, we should let our base class do anything it needs to, first. Widget::RemovedFromManager(theWidgetManager); // We should now also remove any widgets we are responsible for. theWidgetManager->RemoveWidget(mButton1); theWidgetManager->RemoveWidget(mButton2); theWidgetManager->RemoveWidget(mEditWidget); theWidgetManager->RemoveWidget(mCheckboxWidget); theWidgetManager->RemoveWidget(mListWidget); theWidgetManager->RemoveWidget(mScrollbarWidget); } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::ButtonDepress(int theId) { if (theId == 1) { // Our "left" button was clicked. Let's play a sound // in the left speaker with a slight pitch shift. // In order to play a pitch shifted sample, we have to do more // than just say "PlaySample." We have to get a pointer to the sound // instance that represents our sound effect. We do that by asking the // app's sound manager to return us a sound instance, and we tell it // the ID of the sound file that we want. Let's do that now, // using the sound "SOUND_MUTATOR" which we set up in properties/resources.xml: SoundInstance* sample = mApp->mSoundManager->GetSoundInstance(SOUND_MUTATOR); // It's good to make sure the sample isn't NULL. It would be NULL if you // specified an invalid sound id. if (sample != NULL) { //Now we actually adjust the pitch. Specify the number of //steps to raise (positive) or lower (negative) the original sound by. //We'll just arbitrarily choose 13. sample->AdjustPitch(13); //Let's make it play on the left speaker only. We set a panning value //in decibels, which for DirectX range from -10000 to +10000, where //-10000 is fully left and +10000 is fully right: sample->SetPan(-10000); // Now we have the sample play. This is again slightly different than // our PlaySample from previous demos. The first parameter indicates // whether or not we want the sample to loop (in this case, no), and // the second indicates whether the memory taken up by this special // sound instance pointer should be reclaimed when the sample is done // playing. If true, then the pointer will be invalid once its // done playing, sine the memory will be reclaimed. If false, the // memory won't be reclaimed and you'll have to do it yourself. sample->Play(false, true); } } else if (theId == 2) { // Let's do the same as we did for the left button, except make it // play on the right speaker and pitch shift it down SoundInstance* sample = mApp->mSoundManager->GetSoundInstance(SOUND_MUTATOR); if (sample != NULL) { sample->AdjustPitch(-5); sample->SetPan(10000); sample->Play(false, true); } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::EditWidgetText(int theId, const std::string& theString) { // This is called when enter is pressed. Let's add the string // to the list box and tell it to sort it alphabetically, if the string // isn't blank. if (theString.length() > 0) { // Let's also clear everything out of the list box if the user types // in the word "CLEAR". StringToUpper is found in Common.h and returns // the uppercase version of the string. if (StringToUpper(theString) == "CLEAR") mListWidget->RemoveAll(); else mListWidget->AddLine(StringToSexyStringFast(theString), true); // Now clear the edit box mEditWidget->SetText(_S("")); // As an example of saving data to files, let's write out the contents // of the list box. Instead of using the C or C++ way of // file I/O, we use buffers. As you'll see in a later demo, // buffers are useful for the demo playback system and are a powerful // feature of the framework. Plus, they make file I/O easy. The first // step is to make a buffer: Buffer buffer; // And now all we do is say WriteString. There are other methods // for writing other data types too: for (unsigned int i = 0; i < mListWidget->mLines.size(); i++) buffer.WriteString(SexyStringToStringFast(mListWidget->mLines.at(i))); // Now we need to write the buffer to disk. GameApp can help us out with // that. This data is saved in a special binary format that allows // us to read the data easily back into another buffer later. mApp->WriteBufferToFile("list_items.dat", &buffer); // That's it! } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// bool Board::AllowChar(int theId, char theChar) { // As an example of denying input, let's prevent the user // from typing in the following: :-+.@#$%^&*() switch (theChar) { case ':': case '-': case '+': case '.': case '@': case '#': case '$': case '%': case '^': case '&': case '*': case '(': case ')': return false; default: return true; } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// void Board::ListClicked(int theId, int theIdx, int theClickCount) { if (theId == 1) { // Actually select the index. This is done to allow us to // block the selection, if we chose to. mListWidget->SetSelect(theIdx); // And update the text that's displaying on screen... // The strings are stored in the list widget's mLines variable // and the one clicked can be indexed via theIdx. mText = mListWidget->mLines[theIdx]; // As an example of writing to the registry, let's write this value // and later on load it in when we restart the app. You'll notice // a bunch of RegistryWrite... functions in SexyAppBase. Each one // of these takes as first argument the name of the value to // add to the registry. The second argument is the actual data // to store in that value. The value is saved under the registry // location that you set in GameApp's constructor when you // set the mRegKey variable. The function returns false // if there was an error, such as a lack of permission: #if 0 if (!mApp->RegistryWriteString("ListItem", SexyStringToStringFast(mText))) mApp->Popup("Couldn't save \"ListItem\" to registry"); #endif } } libtuxcap-1.4.0/tuxcap/pythondemo2/0000755000175000017500000000000011212652053017140 5ustar inniyahinniyahlibtuxcap-1.4.0/tuxcap/pythondemo2/CMakeLists.txt0000644000175000017500000000407410762446645021726 0ustar inniyahinniyahINCLUDE_DIRECTORIES(${libtuxcap_SOURCE_DIR}/tuxcap/include ${PYTHON_INCLUDE_PATH} ${libtuxcap_SOURCE_DIR}/tuxcap/chipmunk ${libtuxcap_SOURCE_DIR}/tuxcap/hgeparticle ${libtuxcap_SOURCE_DIR}/tuxcap/pycap ) #Declare any external dependencies that your project may have here. #examples include: ITK, VTK, JPEG, PNG, OpenGL, ZLIB, Perl, Java #If you're not sure what name to use, look in the Modules directory of your #cmake install and check that a file named Find(Package).cmake exists SET(Required_Packages #list packages here #SDL OpenGL GLU SDL_mixer ) #this foreach loads all of the packages that you specified as required. #It shouldn't need to be modified. FOREACH(Package ${Required_Packages}) LOADPACKAGE(${Package}) ENDFOREACH(Package) #Set any libraries that your project depends on. #examples: ITKCommon, VTKRendering, etc SET(Libraries #list libraries here #SDL SDL_mixer Magick++ GL GLU tuxcap ) #the following block of code is an example of how to build an executable in #cmake. Unmodified, it will add an executable called "MyExe" to the project. #MyExe will be built using the files MyClass.h and MyClass.cxx, and it will #be linked to all the libraries you specified above. #You can build more than one executable per project SET(MY_SOURCES main.cpp) IF(APPLE) SET(MY_SOURCES ${MY_SOURCES} ${libtuxcap_SOURCE_DIR}/tuxcap/lib/SDLMain.m) ENDIF(APPLE) SET(CurrentExe "../../pythondemo2/Pythondemo2") ADD_EXECUTABLE(${CurrentExe} ${MY_SOURCES}) TARGET_LINK_LIBRARIES(${CurrentExe} ${Libraries}) #the following line is an example of how to add a test to your project. #Testname is the title for this particular test. ExecutableToRun is the #program which will be running this test. It can either be a part of this #project or an external executable. After that list any args that are needed #for this test. Include as many tests as you like. If your project doesn't have #any tests you can comment out or delete the following line. #ADD_TEST(Testname ExecutableToRun arg1 arg2 arg3) #Once you're done modifying this template, you should rename it to "CMakeLists.txt" libtuxcap-1.4.0/tuxcap/pythondemo2/main.cpp0000644000175000017500000000032411062277514020577 0ustar inniyahinniyah#include "PycapApp.h" using namespace Sexy; int main(int argc, char** argv) { PycapApp app; SetAppResourceFolder("../images"); app.Init(argc,argv, false); app.Start(); app.Shutdown(); return 0; } libtuxcap-1.4.0/TODO0000644000175000017500000000016510766723533014075 0ustar inniyahinniyah* flash support (in progress) * pak support * wide screen support * in-game widget and particle editor (in progress) libtuxcap-1.4.0/PopCap Framework License.txt0000644000175000017500000000353610641010413020570 0ustar inniyahinniyahPopCap Games Framework License Version 1.0 Copyright (c) 2005 PopCap Games. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code or derived libraries, whether source code or binary, must include a copy of this PopCap Games Framework License in its entirety. 2. The end-user documentation included with a work which contains any portion of the PopCap Games Framework must include the following acknowledgment: "This product includes portions of the PopCap Games Framework (http://developer.popcap.com/)." Alternatively, this acknowledgment may appear in the software itself, wherever such third-party acknowledgments normally appear. 3. The names "PopCap" and "PopCap Games" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact bizdev@popcap.com. 4. Products derived from this software may not be called "PopCap", nor may "PopCap" appear in their name, without prior written permission of PopCap Games. THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGMENT AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL POPCAP GAMES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.