/*----------------------------------------------------------------------------*/ /* */ /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */ /* Copyright (c) 2005-2014 Rexx Language Association. All rights reserved. */ /* */ /* This program and the accompanying materials are made available under */ /* the terms of the Common Public License v1.0 which accompanies this */ /* distribution. A copy is also available at the following address: */ /* https://www.oorexx.org/license.html */ /* */ /* Redistribution and use in source and binary forms, with or */ /* without modification, are permitted provided that the following */ /* conditions are met: */ /* */ /* Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 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. */ /* */ /* Neither the name of Rexx Language Association nor the names */ /* of its contributors may 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. */ /* */ /*----------------------------------------------------------------------------*/ /** * oowalker.rex Animation demonstration (using a .rc file for the dialog * template.) * * The only real difference between this sample and the oowalk2.rex sample is * the way the bitmaps for the animation are loaded. Look at the initDialog() * method of the .WalkerDialog to see this difference. * * An animated button is used to simulate a man walking across the dialog. The * user can adjust the pace of the waling by setting the amount the man is * moved each time the button is redrawn and the delay between redrawing the * button. The button is drawn using a sequence of bitmaps that show the man * with different leg and arm positions. The user can also set how the man * 'walking' off the edge of the dialog is handled, smoothly or bouncy, by * using the "smooth corner wrap" check box. * * A 'got cha' point (!!!) is periodically drawn and if the man is close enough * to this 'danger,' the man is 'gotten' and the animation is stopped. Each * time the button is drawn, the !!! is over-drawn, so the !!! is only seen * as a flicker. * * Normally the dialog ends when the walker is gotten. However there is a * check box that allows the user to cancel this behavior and then restart the * animation. */ srcDir = locate() .application~useGlobalConstDir('O', srcDir"rc\walker.h") dlg = .WalkerDialog~new(srcDir"rc\walker.rc", , data.) if dlg~initCode \= 0 then do return 99 end dlg~execute("SHOWTOP") return 0 /*---------------------------- requires -----------------------------*/ ::requires "ooDialog.cls" ::requires "samplesSetup.rex" -- For sound path /*---------------------------- walker dialog ------------------------*/ ::class 'WalkerDialog' subclass RcDialog ::method initDialog expose bitmaps spriteButton quitCheckBox restartButton okButton -- Make button 105 a bitmap button. Bitmap buttons are owner-drawn and -- ooDialog will manage the 'drawing' of the button by painting a series of -- bitmaps on the button, using the AnimatedButton class. self~installBitmapButton(105, '', 0); -- Load the bitmaps from the bitmap files into an array. bitmaps = .array~new(8) do i= 1 to 8 bitmaps[i] = self~loadBitmap(.application~srcDir"bmp\wlkfig"i".bmp") end -- Create the animated button class and pass the array of bitmaps. spriteButton = .WalkButton~new(105, bitmaps, 0, 10, 2, 70, 120, 60, 10, 10, self) -- Use 'bouncy' operation when hitting edges. spriteButton~setSmooth(.false) -- Get things set up. self~connectButtonEvent(107, "CLICKED", onRestart) quitCheckBox = self~newCheckBox(106) restartButton = self~newPushButton(107) okButton = self~newPushButton(IDOK) quitCheckBox~check spriteButton~fillData(data.) spriteButton~suspendGotCha(.false) self~setDataStem(data.) ret = Play("tada.wav", n) -- Animate the button. spriteButton~run ::method doDataStemGet unguarded use strict arg data. self~getDataStem(data.) ::method doDataStemSet unguarded use strict arg data. self~setDataStem(data.) ::method onGotCha expose okButton use strict arg animatedButton, x, y okButton~disable self~writetoButton(105, x, y, "Got-cha", "Arial", 28, "BOLD") ret = play('gotcha.wav') animatedButton~stop call msSleep 1000 ::method maybeQuit expose quitCheckBox restartButton okButton if quitCheckBox~checked then return self~ok restartButton~enable okButton~enable ::method onRestart expose spriteButton restartButton restartButton~disable spriteButton~stopped = .false -- Suspend the 'GotCha' before we start the animated button. Otherwise the -- walker will be 'gotten' as soon as he starts. spriteButton~suspendGotCha(.true) spriteButton~run -- Give the walker time to 'walk' out of the danger zone before reactivating -- the 'GotCha.' delay = self~newEdit(103)~getText j = msSleep(2 * delay) spriteButton~suspendGotCha(.false) ::method ok self~stopAnimation return self~ok:super ::method cancel self~stopAnimation return self~cancel:super ::method stopAnimation private expose bitmaps spriteButton spriteButton~stop -- Wait until the animation sequence is finished. do while spriteButton~isRunning j = msSleep(30) end -- Now it is safe to delete the bitmaps. if bitmaps \== .nil then do i= 1 to 8 self~removeBitmap(bitmaps[i]) end -- Be sure we don't free the bitmaps twice. The WalkButton will invoke -- maybeQuit() which can cause stopAnimation() to be invoked twice. bitmaps = .nil /*------------------------------ animated button --------------------*/ ::class 'WalkButton' subclass AnimatedButton ::method run expose xDanger yDanger running xDanger = 300; yDanger = 70; running = .true reply 0 do until(self~stopped = 1) | (self~parentStopped = 1) self~doAnimatedSequence end -- Have the walker do one more sequence, gives the appearance of walking 'in -- in place.' self~doAnimatedSequence -- We are no longer running, tell the parent dialog to maybe quit. running = .false self~parentDlg~maybeQuit ::method doAnimatedSequence private expose xDanger yDanger self~moveseq self~parentDlg~doDataStemGet(data.) do k over data. if data.k~datatype('N') = 0 then data.k = 0 end self~setmove(data.101, data.102) self~setdelay(data.103) self~setsmooth(data.104) if self~stopped = 0 then self~parentDlg~writetoButton(105,xDanger,yDanger,"!!!","Arial",20,"BOLD") ::method isRunning unguarded expose running return running ::method suspendGotCha unguarded expose gotCha use strict arg suspend if suspend then gotCha = .false else gotCha = .true ::method hitright ret = play('ding.wav', 'YES') return 1 ::method hitleft ret = play('ding.wav', 'YESY') return 1 ::method hitbottom self~getsprite(s.) ret = play('chord.wav', 'YES') s.movey = -s.movey self~setsprite(s.) self~fillData(data.) self~parentDlg~doDataStemSet(data.) return 0 ::method hittop expose sprite. self~getsprite(s.) ret = play('chimes.wav', 'YES') s.movey = -s.movey self~setsprite(s.) self~fillData(data.) self~parentDlg~doDataStemSet(data.) return 0 ::method fillData expose quitCheckBox use arg data. if \ quitCheckBox~isA(.CheckBox) then quitCheckBox = self~parentDlg~newCheckBox(106) self~getSprite(msprite.) data.101 = msprite.movex data.102 = msprite.movey data.103 = msprite.delay data.104 = msprite.smooth if quitCheckBox~checked then data.106 = 1 else data.106 = 0 ::method movepos use arg px, py if self~stopped=0 then do self~movepos:super(px,py) self~checkDanger end ::method checkDanger expose xDanger yDanger gotCha self~getpos(cur.) if abs(cur.x+10-xDanger) <= 10 & abs(cur.y+55-yDanger) <= 30 then do if gotCha then self~parentDlg~onGotCha(self, xDanger-50, yDanger) end