guiAnimBitmapCtrl.cpp
Engine/source/gui/controls/guiAnimBitmapCtrl.cpp
Public Functions
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onCompleted , void , () , () , "triggered when an animation completes" )
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onFrame , void , (S32 frameIndex, S32 frame) , (frameIndex, frame) , "triggered when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> frame increments" )
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onLoop , void , () , () , "triggered when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> loop completes" )
Detailed Description
Public Functions
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onCompleted , void , () , () , "triggered when an animation completes" )
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onFrame , void , (S32 frameIndex, S32 frame) , (frameIndex, frame) , "triggered when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> frame increments" )
IMPLEMENT_CALLBACK(guiAnimBitmapCtrl , onLoop , void , () , () , "triggered when <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> loop completes" )
IMPLEMENT_CONOBJECT(guiAnimBitmapCtrl )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gui/controls/guiAnimBitmapCtrl.h" 26 27#include "console/console.h" 28#include "console/consoleTypes.h" 29#include "console/engineAPI.h" 30#include "gfx/gfxDevice.h" 31#include "gfx/gfxDrawUtil.h" 32 33 34 35IMPLEMENT_CONOBJECT(guiAnimBitmapCtrl); 36 37IMPLEMENT_CALLBACK(guiAnimBitmapCtrl, onLoop, void, (), 38 (), "triggered when a loop completes"); 39 40IMPLEMENT_CALLBACK(guiAnimBitmapCtrl, onCompleted, void, (), 41 (), "triggered when an animation completes"); 42 43IMPLEMENT_CALLBACK(guiAnimBitmapCtrl, onFrame, void, (S32 frameIndex, S32 frame), 44 (frameIndex, frame), "triggered when a frame increments"); 45 46guiAnimBitmapCtrl::guiAnimBitmapCtrl(void) 47{ 48 mAnimTexTiling = Point2I::One; 49 mAnimTexFramesString = NULL; 50 mAnimTexFrames.clear(); 51 mNumFrames = 0; 52 mCurFrameIndex = 0; 53 mFramesPerSec = 60; 54 mAnimateTexture = false; 55 mFrameTime = PlatformTimer::create(); 56 mLoop = true; 57 mPlay = true; 58 mReverse = false; 59 mFinished = false; 60} 61 62guiAnimBitmapCtrl::~guiAnimBitmapCtrl(void) 63{ 64 mAnimTexFrames.clear(); 65} 66void guiAnimBitmapCtrl::initPersistFields() 67{ 68 addField("AnimTexTiling", TYPEID< Point2I >(), Offset(mAnimTexTiling, guiAnimBitmapCtrl), 69 "@brief The number of frames, in rows and columns stored in textureName " 70 "(when animateTexture is true).\n\n" 71 "A maximum of 256 frames can be stored in a single texture when using " 72 "mAnimTexTiling. Value should be \"NumColumns NumRows\", for example \"4 4\"."); 73 addProtectedField("AnimTexFrames", TYPEID< StringTableEntry >(), Offset(mAnimTexFramesString, guiAnimBitmapCtrl), &ptSetFrameRanges, &defaultProtectedGetFn, 74 "@brief A list of frames and/or frame ranges to use for particle " 75 "animation if animateTexture is true.\n\n" 76 "Each frame token must be separated by whitespace. A frame token must be " 77 "a positive integer frame number or a range of frame numbers separated " 78 "with a '-'. The range separator, '-', cannot have any whitspace around " 79 "it.\n\n" 80 "Ranges can be specified to move through the frames in reverse as well " 81 "as forward (eg. 19-14). Frame numbers exceeding the number of tiles will " 82 "wrap.\n" 83 "@tsexample\n" 84 "mAnimTexFrames = \"0-16 20 19 18 17 31-21\";\n" 85 "@endtsexample\n"); 86 87 addField("loop", TypeBool, Offset(mLoop, guiAnimBitmapCtrl), "loop?"); 88 addField("play", TypeBool, Offset(mPlay, guiAnimBitmapCtrl), "play?"); 89 addField("reverse", TypeBool, Offset(mReverse, guiAnimBitmapCtrl), "play reversed?"); 90 addField("fps", TypeS32, Offset(mFramesPerSec, guiAnimBitmapCtrl), "Frame Rate"); 91 92 addProtectedField("curFrame", TypeS32, Offset(mCurFrameIndex, guiAnimBitmapCtrl), &ptSetFrame, &defaultProtectedGetFn, "Index of currently Displaying Frame "); 93 94 Parent::initPersistFields(); 95 removeField("wrap"); 96} 97 98bool guiAnimBitmapCtrl::onAdd() 99{ 100 if (Parent::onAdd() == false) 101 return false; 102 103 if (!mAnimTexFramesString || !mAnimTexFramesString[0]) 104 { 105 S32 n_tiles = mAnimTexTiling.x * mAnimTexTiling.y - 1; 106 for (S32 i = 0; i <= n_tiles; i++) 107 mAnimTexFrames.push_back(i); 108 mNumFrames = mAnimTexFrames.size() - 1; 109 if (mCurFrameIndex > mNumFrames) 110 mCurFrameIndex = mNumFrames; 111 return true; 112 } 113 114 return true; 115} 116 117bool guiAnimBitmapCtrl::ptSetFrame(void *object, const char *index, const char *data) 118{ 119 guiAnimBitmapCtrl *pData = static_cast<guiAnimBitmapCtrl*>(object); 120 121 if (!pData->mNumFrames) 122 { 123 pData->mCurFrameIndex = 0; 124 return false; 125 } 126 127 S32 val = dAtoi(data); 128 129 if (val < 0) 130 { 131 pData->mCurFrameIndex = pData->mNumFrames; 132 return false; 133 } 134 else if (val > pData->mNumFrames) 135 { 136 pData->mCurFrameIndex = 0; 137 return false; 138 }; 139 140 pData->mCurFrameIndex = val; 141 return true; 142} 143 144bool guiAnimBitmapCtrl::ptSetFrameRanges(void *object, const char *index, const char *data) 145{ 146 guiAnimBitmapCtrl *pData = static_cast<guiAnimBitmapCtrl*>(object); 147 148 // Here we parse mAnimTexFramesString into byte-size frame numbers in mAnimTexFrames. 149 // Each frame token must be separated by whitespace. 150 // A frame token must be a positive integer frame number or a range of frame numbers 151 // separated with a '-'. 152 // The range separator, '-', cannot have any whitspace around it. 153 // Ranges can be specified to move through the frames in reverse as well as forward. 154 // Frame numbers exceeding the number of tiles will wrap. 155 // example: 156 // "0-16 20 19 18 17 31-21" 157 158 S32 n_tiles = pData->mAnimTexTiling.x * pData->mAnimTexTiling.y - 1; 159 160 pData->mAnimTexFrames.clear(); 161 162 if (!data || !data[0]) 163 { 164 for (S32 i = 0; i <= n_tiles; i++) 165 pData->mAnimTexFrames.push_back(i); 166 pData->mNumFrames = pData->mAnimTexFrames.size() - 1; 167 if (pData->mCurFrameIndex > pData->mNumFrames) 168 pData->mCurFrameIndex = pData->mNumFrames; 169 return true; 170 } 171 dsize_t tokLen = dStrlen(data) + 1; 172 char* tokCopy = new char[tokLen]; 173 dStrcpy(tokCopy, data, tokLen); 174 175 char* currTok = dStrtok(tokCopy, " \t"); 176 while (currTok != NULL) 177 { 178 char* minus = dStrchr(currTok, '-'); 179 if (minus) 180 { 181 // add a range of frames 182 *minus = '\0'; 183 S32 range_a = dAtoi(currTok); 184 S32 range_b = dAtoi(minus + 1); 185 if (range_b < range_a) 186 { 187 // reverse frame range 188 for (S32 i = range_a; i >= range_b; i--) 189 pData->mAnimTexFrames.push_back(i); 190 } 191 else 192 { 193 // forward frame range 194 for (S32 i = range_a; i <= range_b; i++) 195 pData->mAnimTexFrames.push_back(i); 196 } 197 } 198 else 199 { 200 // add one frame 201 pData->mAnimTexFrames.push_back(dAtoi(currTok)); 202 } 203 currTok = dStrtok(NULL, " \t"); 204 } 205 206 // cleanup 207 delete[] tokCopy; 208 pData->mNumFrames = pData->mAnimTexFrames.size() - 1; 209 if (pData->mCurFrameIndex > pData->mNumFrames) 210 pData->mCurFrameIndex = pData->mNumFrames; 211 return true; 212} 213 214void guiAnimBitmapCtrl::onRender(Point2I offset, const RectI &updateRect) 215{ 216 if (mTextureObject) 217 { 218 if (mFrameTime->getElapsedMs() > 1000 / mFramesPerSec) //fps to msfp conversion 219 { 220 mFrameTime->reset(); 221 222 if (mPlay) 223 { 224 if (mReverse) //play backward 225 { 226 mCurFrameIndex--; 227 if (mCurFrameIndex < 0) 228 { 229 if (mLoop) 230 { 231 mCurFrameIndex = mNumFrames; 232 onLoop_callback(); 233 mFinished = false; 234 } 235 else 236 { 237 mCurFrameIndex = 0; 238 if (!mFinished) 239 onCompleted_callback(); 240 mFinished = true; 241 } 242 } 243 else 244 onFrame_callback(mCurFrameIndex, mAnimTexFrames[mCurFrameIndex]); 245 } 246 else // play forward 247 { 248 mCurFrameIndex++; 249 250 if (mCurFrameIndex > mNumFrames) 251 { 252 if (mLoop) 253 { 254 mCurFrameIndex = 0; 255 onLoop_callback(); 256 mFinished = false; 257 } 258 else 259 { 260 mCurFrameIndex = mNumFrames; 261 if (!mFinished) 262 onCompleted_callback(); 263 mFinished = true; 264 } 265 } 266 else 267 onFrame_callback(mCurFrameIndex, mAnimTexFrames[mCurFrameIndex]); 268 } 269 } 270 } 271 272 GFX->getDrawUtil()->clearBitmapModulation(); 273 GFX->getDrawUtil()->setBitmapModulation(mColor); 274 275 GFXTextureObject* texture = mTextureObject; 276 277 Point2I modifiedSRC = Point2I(texture->mBitmapSize.x / mAnimTexTiling.x, texture->mBitmapSize.y / mAnimTexTiling.y); 278 RectI srcRegion; 279 Point2I offsetSRC = Point2I::Zero; 280 281 offsetSRC.x = (texture->mBitmapSize.x / mAnimTexTiling.x) * (mAnimTexFrames[mCurFrameIndex] % mAnimTexTiling.x); 282 offsetSRC.y = (texture->mBitmapSize.y / mAnimTexTiling.y) * (mAnimTexFrames[mCurFrameIndex] / mAnimTexTiling.x); 283 284 srcRegion.set(offsetSRC, modifiedSRC); 285 286 GFX->getDrawUtil()->drawBitmapStretchSR(texture, updateRect, srcRegion, GFXBitmapFlip_None, GFXTextureFilterLinear, false); 287 } 288 289 if (mProfile->mBorder || !mTextureObject) 290 { 291 RectI rect(offset, getExtent()); 292 GFX->getDrawUtil()->drawRect(rect, mProfile->mBorderColor); 293 } 294 295 renderChildControls(offset, updateRect); 296} 297