the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 261 lines 6.7 kB view raw
1#include "stdafx.h" 2#include "StitchSlot.h" 3#include "Texture.h" 4#include "TextureHolder.h" 5#include "TextureManager.h" 6#include "StitchedTexture.h" 7#include "Stitcher.h" 8 9void Stitcher::_init(const wstring &name, int maxWidth, int maxHeight, bool forcePowerOfTwo, int forcedScale) 10{ 11 this->name = name; 12 this->maxWidth = maxWidth; 13 this->maxHeight = maxHeight; 14 this->forcePowerOfTwo = forcePowerOfTwo; 15 this->forcedScale = forcedScale; 16 17 // 4J init 18 storageX = 0; 19 storageY = 0; 20 stitchedTexture = NULL; 21} 22 23Stitcher::Stitcher(const wstring &name, int maxWidth, int maxHeight, bool forcePowerOfTwo) 24{ 25 _init(name, maxWidth, maxHeight, forcePowerOfTwo, 0); 26} 27 28Stitcher::Stitcher(const wstring &name, int maxWidth, int maxHeight, bool forcePowerOfTwo, int forcedScale) 29{ 30 _init(name, maxWidth, maxHeight, forcePowerOfTwo, forcedScale); 31} 32 33int Stitcher::getWidth() 34{ 35 return storageX; 36} 37 38int Stitcher::getHeight() 39{ 40 return storageY; 41} 42 43void Stitcher::addTexture(TextureHolder *textureHolder) 44{ 45 if (forcedScale > 0) 46 { 47 textureHolder->setForcedScale(forcedScale); 48 } 49 texturesToBeStitched.insert(textureHolder); 50} 51 52Texture *Stitcher::constructTexture(bool mipmap) 53{ 54 if (forcePowerOfTwo) 55 { 56 storageX = smallestEncompassingPowerOfTwo(storageX); 57 storageY = smallestEncompassingPowerOfTwo(storageY); 58 } 59 60 stitchedTexture = TextureManager::getInstance()->createTexture(name, Texture::TM_DYNAMIC, storageX, storageY, Texture::TFMT_RGBA, mipmap); 61 stitchedTexture->fill(stitchedTexture->getRect(), 0xffff0000); 62 63 vector<StitchSlot *> *slots = gatherAreas(); 64 for (int index = 0; index < slots->size(); index++) 65 { 66 StitchSlot *slot = slots->at(index); 67 TextureHolder *textureHolder = slot->getHolder(); 68 stitchedTexture->blit(slot->getX(), slot->getY(), textureHolder->getTexture(), textureHolder->isRotated()); 69 } 70 delete slots; 71 TextureManager::getInstance()->registerName(name, stitchedTexture); 72 73 return stitchedTexture; 74} 75 76void Stitcher::stitch() 77{ 78 //TextureHolder[] textureHolders = texturesToBeStitched.toArray(new TextureHolder[texturesToBeStitched.size()]); 79 //Arrays.sort(textureHolders); 80 81 stitchedTexture = NULL; 82 83 //for (int i = 0; i < textureHolders.length; i++) 84 for(AUTO_VAR(it, texturesToBeStitched.begin()); it != texturesToBeStitched.end(); ++it) 85 { 86 TextureHolder *textureHolder = *it; //textureHolders[i]; 87 88 if (!addToStorage(textureHolder)) 89 { 90 app.DebugPrintf("Stitcher exception!\n"); 91#ifndef _CONTENT_PACKAGE 92 __debugbreak(); 93#endif 94 //throw new StitcherException(textureHolder); 95 } 96 } 97} 98 99vector<StitchSlot *> *Stitcher::gatherAreas() 100{ 101 vector<StitchSlot *> *result = new vector<StitchSlot *>(); 102 103 //for (StitchSlot slot : storage) 104 for(AUTO_VAR(it, storage.begin()); it != storage.end(); ++it) 105 { 106 StitchSlot *slot = *it; 107 slot->collectAssignments(result); 108 } 109 110 return result; 111} 112 113// Based on: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 114int Stitcher::smallestEncompassingPowerOfTwo(int input) 115{ 116 int result = input - 1; 117 result |= result >> 1; 118 result |= result >> 2; 119 result |= result >> 4; 120 result |= result >> 8; 121 result |= result >> 16; 122 return result + 1; 123} 124 125bool Stitcher::addToStorage(TextureHolder *textureHolder) 126{ 127 for (int i = 0; i < storage.size(); i++) 128 { 129 if (storage.at(i)->add(textureHolder)) 130 { 131 return true; 132 } 133 134 // Try rotated 135 textureHolder->rotate(); 136 if (storage.at(i)->add(textureHolder)) 137 { 138 return true; 139 } 140 141 // Undo rotation 142 textureHolder->rotate(); 143 } 144 145 return expand(textureHolder); 146} 147 148/** 149* Expand the current storage to take in account the new texture. 150* This should only be called if it didn't fit anywhere. 151* 152* @param textureHolder 153* @return Boolean indicating if it could accommodate for the growth 154*/ 155bool Stitcher::expand(TextureHolder *textureHolder) 156{ 157 int minDistance = min(textureHolder->getHeight(), textureHolder->getWidth()); 158 bool firstAddition = storageX == 0 && storageY == 0; 159 160 // It couldn't fit, decide which direction to grow to 161 bool growOnX; 162 if (forcePowerOfTwo) 163 { 164 int xCurrentSize = smallestEncompassingPowerOfTwo(storageX); 165 int yCurrentSize = smallestEncompassingPowerOfTwo(storageY); 166 int xNewSize = smallestEncompassingPowerOfTwo(storageX + minDistance); 167 int yNewSize = smallestEncompassingPowerOfTwo(storageY + minDistance); 168 169 bool xCanGrow = xNewSize <= maxWidth; 170 bool yCanGrow = yNewSize <= maxHeight; 171 172 if (!xCanGrow && !yCanGrow) 173 { 174 return false; 175 } 176 177 // Even if the smallest side fits the larger might not >.> 178 int maxDistance = max(textureHolder->getHeight(), textureHolder->getWidth()); 179 // TODO: This seems wrong ... 180 if (firstAddition && !xCanGrow && !(smallestEncompassingPowerOfTwo(storageY + maxDistance) <= maxHeight)) 181 { 182 return false; 183 } 184 185 bool xWillGrow = xCurrentSize != xNewSize; 186 bool yWillGrow = yCurrentSize != yNewSize; 187 188 if (xWillGrow ^ yWillGrow) 189 { 190 // Either grows 191 //only pick X if it can grow AND it wanted to grow 192 // if !xCanGrow then yCanGrow 193 194 195 growOnX = xWillGrow && xCanGrow; 196 } 197 else 198 { 199 // Both or Neither grow -- smallest side wins 200 growOnX = xCanGrow && xCurrentSize <= yCurrentSize; 201 } 202 } 203 else 204 { 205 // We need to figure out to either expand 206 bool xCanGrow = (storageX + minDistance) <= maxWidth; 207 bool yCanGrow = (storageY + minDistance) <= maxHeight; 208 209 if (!xCanGrow && !yCanGrow) 210 { 211 return false; 212 } 213 214 // Prefer growing on X when its: first addition *or* its the smaller of the two sides 215 growOnX = (firstAddition || storageX <= storageY) && xCanGrow; 216 } 217 218 StitchSlot *slot; 219 if (growOnX) 220 { 221 if (textureHolder->getWidth() > textureHolder->getHeight()) 222 { 223 textureHolder->rotate(); 224 } 225 226 // Grow the 'Y' when it has no size yet 227 if (storageY == 0) 228 { 229 storageY = textureHolder->getHeight(); 230 } 231 232 int newSlotWidth = textureHolder->getWidth(); 233 // 4J Stu - If we are expanding the texture, then allocate the full powerOfTwo size that we are going to eventually create 234 if (forcePowerOfTwo) 235 { 236 newSlotWidth = smallestEncompassingPowerOfTwo(storageX + newSlotWidth) - storageX; 237 } 238 slot = new StitchSlot(storageX, 0, newSlotWidth, storageY); 239 //storageX += textureHolder->getWidth(); 240 storageX += newSlotWidth; 241 } 242 else 243 { 244 int newSlotHeight = textureHolder->getHeight(); 245 // 4J Stu - If we are expanding the texture, then allocate the full powerOfTwo size that we are going to eventually create 246 if (forcePowerOfTwo) 247 { 248 newSlotHeight = smallestEncompassingPowerOfTwo(storageY + newSlotHeight) - storageY; 249 } 250 251 // grow on Y 252 slot = new StitchSlot(0, storageY, storageX, newSlotHeight); 253 //storageY += textureHolder->getHeight(); 254 storageY += newSlotHeight; 255 } 256 257 slot->add(textureHolder); 258 storage.push_back(slot); 259 260 return true; 261}