1 /*************************************************************************** 2 * Copyright (C) 2005-2019 by the FIFE team * 3 * http://www.fifengine.net * 4 * This file is part of FIFE. * 5 * * 6 * FIFE is free software; you can redistribute it and/or * 7 * modify it under the terms of the GNU Lesser General Public * 8 * License as published by the Free Software Foundation; either * 9 * version 2.1 of the License, or (at your option) any later version. * 10 * * 11 * This library is distributed in the hope that it will be useful, * 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 14 * Lesser General Public License for more details. * 15 * * 16 * You should have received a copy of the GNU Lesser General Public * 17 * License along with this library; if not, write to the * 18 * Free Software Foundation, Inc., * 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 20 ***************************************************************************/ 21 22 // Standard C++ library includes 23 24 // 3rd party library includes 25 26 // FIFE includes 27 // These includes are split up in two parts, separated by one empty line 28 // First block: files included from the FIFE root src directory 29 // Second block: files included from the same folder 30 #include "util/log/logger.h" 31 #include "util/base/exception.h" 32 33 #include "model/structures/instance.h" 34 #include "model/metamodel/object.h" 35 #include "model/metamodel/action.h" 36 37 #include "visual.h" 38 39 40 namespace FIFE { 41 /** Logger to use for this source file. 42 * @relates Logger 43 */ 44 static Logger _log(LM_VIEW); 45 OverlayColors()46 OverlayColors::OverlayColors() { 47 } 48 OverlayColors(ImagePtr image)49 OverlayColors::OverlayColors(ImagePtr image): 50 m_image(image) { 51 } 52 OverlayColors(AnimationPtr animation)53 OverlayColors::OverlayColors(AnimationPtr animation): 54 m_animation(animation) { 55 } 56 ~OverlayColors()57 OverlayColors::~OverlayColors() { 58 } 59 setColorOverlayImage(ImagePtr image)60 void OverlayColors::setColorOverlayImage(ImagePtr image) { 61 m_image = image; 62 } 63 getColorOverlayImage()64 ImagePtr OverlayColors::getColorOverlayImage() { 65 return m_image; 66 } 67 setColorOverlayAnimation(AnimationPtr animation)68 void OverlayColors::setColorOverlayAnimation(AnimationPtr animation) { 69 m_animation = animation; 70 } 71 getColorOverlayAnimation()72 AnimationPtr OverlayColors::getColorOverlayAnimation() { 73 return m_animation; 74 } 75 changeColor(const Color & source,const Color & target)76 void OverlayColors::changeColor(const Color& source, const Color& target) { 77 std::pair<std::map<Color, Color>::iterator, bool> inserter = m_colorMap.insert(std::make_pair(source, target)); 78 if (!inserter.second) { 79 Color& c = inserter.first->second; 80 c.set(target.getR(), target.getG(), target.getB(), target.getAlpha()); 81 } 82 } 83 getColors()84 const std::map<Color, Color>& OverlayColors::getColors() { 85 return m_colorMap; 86 } 87 resetColors()88 void OverlayColors::resetColors() { 89 m_colorMap.clear(); 90 } 91 Visual2DGfx()92 Visual2DGfx::Visual2DGfx() { 93 } 94 ~Visual2DGfx()95 Visual2DGfx::~Visual2DGfx() { 96 } 97 ObjectVisual()98 ObjectVisual::ObjectVisual() { 99 } 100 create(Object * object)101 ObjectVisual* ObjectVisual::create(Object* object) { 102 if (object->getVisual<ObjectVisual>()) { 103 throw Duplicate("Object already contains visualization"); 104 } 105 ObjectVisual* v = new ObjectVisual(); 106 object->adoptVisual(v); 107 return v; 108 } 109 ~ObjectVisual()110 ObjectVisual::~ObjectVisual() { 111 } 112 addStaticImage(uint32_t angle,int32_t image_index)113 void ObjectVisual::addStaticImage(uint32_t angle, int32_t image_index) { 114 m_angle2img[angle % 360] = image_index; 115 } 116 getStaticImageIndexByAngle(int32_t angle)117 int32_t ObjectVisual::getStaticImageIndexByAngle(int32_t angle) { 118 int32_t closestMatch = 0; 119 return getIndexByAngle(angle, m_angle2img, closestMatch); 120 } 121 addStaticColorOverlay(uint32_t angle,const OverlayColors & colors)122 void ObjectVisual::addStaticColorOverlay(uint32_t angle, const OverlayColors& colors) { 123 OverlayColors t = colors; 124 m_map[angle % 360] = angle % 360; 125 std::pair<AngleColorOverlayMap::iterator, bool> inserter = m_colorOverlayMap.insert(std::make_pair(angle % 360, colors)); 126 if (!inserter.second) { 127 OverlayColors tmp = colors; 128 OverlayColors& c = inserter.first->second; 129 c.setColorOverlayImage(tmp.getColorOverlayImage()); 130 131 const std::map<Color, Color>& colorMap = tmp.getColors(); 132 std::map<Color, Color>::const_iterator it = colorMap.begin(); 133 for (; it != colorMap.end(); ++it) { 134 c.changeColor(it->first, it->second); 135 } 136 } 137 } 138 getStaticColorOverlay(int32_t angle)139 OverlayColors* ObjectVisual::getStaticColorOverlay(int32_t angle) { 140 if (m_colorOverlayMap.empty()) { 141 return 0; 142 } 143 int32_t closestMatch = 0; 144 return &m_colorOverlayMap[getIndexByAngle(angle, m_map, closestMatch)]; 145 } 146 removeStaticColorOverlay(int32_t angle)147 void ObjectVisual::removeStaticColorOverlay(int32_t angle) { 148 if (m_colorOverlayMap.empty()) { 149 return; 150 } 151 int32_t closestMatch = 0; 152 int32_t index = getIndexByAngle(angle, m_map, closestMatch); 153 m_colorOverlayMap.erase(index); 154 m_map.erase(index); 155 } 156 getClosestMatchingAngle(int32_t angle)157 int32_t ObjectVisual::getClosestMatchingAngle(int32_t angle) { 158 int32_t closestMatch = 0; 159 getIndexByAngle(angle, m_angle2img, closestMatch); 160 return closestMatch; 161 } 162 getStaticImageAngles(std::vector<int32_t> & angles)163 void ObjectVisual::getStaticImageAngles(std::vector<int32_t>& angles) { 164 angles.clear(); 165 type_angle2id::const_iterator i(m_angle2img.begin()); 166 while (i != m_angle2img.end()) { 167 angles.push_back(i->first); 168 ++i; 169 } 170 } 171 InstanceVisual()172 InstanceVisual::InstanceVisual(): 173 m_transparency(0), 174 m_visible(true), 175 m_stackposition(0), 176 m_instance(NULL) { 177 } 178 create(Instance * instance)179 InstanceVisual* InstanceVisual::create(Instance* instance) { 180 if (instance->getVisual<InstanceVisual>()) { 181 throw Duplicate("Instance already contains visualization"); 182 } 183 InstanceVisual* v = new InstanceVisual(); 184 instance->setVisual(v); 185 v->m_instance = instance; 186 return v; 187 } 188 ~InstanceVisual()189 InstanceVisual::~InstanceVisual() { 190 } 191 setTransparency(uint8_t transparency)192 void InstanceVisual::setTransparency(uint8_t transparency) { 193 if (m_transparency != transparency) { 194 m_transparency = transparency; 195 m_instance->callOnTransparencyChange(); 196 } 197 } 198 getTransparency()199 uint8_t InstanceVisual::getTransparency() { 200 return m_transparency; 201 } 202 setVisible(bool visible)203 void InstanceVisual::setVisible(bool visible) { 204 if (m_visible != visible) { 205 m_visible = visible; 206 m_instance->callOnVisibleChange(); 207 } 208 } 209 isVisible()210 bool InstanceVisual::isVisible() { 211 return m_visible; 212 } 213 setStackPosition(int32_t stackposition)214 void InstanceVisual::setStackPosition(int32_t stackposition) { 215 if (m_stackposition != stackposition) { 216 m_stackposition = stackposition; 217 m_instance->callOnStackPositionChange(); 218 } 219 } 220 getStackPosition()221 int32_t InstanceVisual::getStackPosition() { 222 return m_stackposition; 223 } 224 ActionVisual()225 ActionVisual::ActionVisual(): m_animation_map(), m_map() { 226 } 227 create(Action * action)228 ActionVisual* ActionVisual::create(Action* action) { 229 if (action->getVisual<ActionVisual>()) { 230 throw Duplicate("Action already contains visualization"); 231 } 232 ActionVisual* v = new ActionVisual(); 233 action->adoptVisual(v); 234 return v; 235 } 236 ~ActionVisual()237 ActionVisual::~ActionVisual() { 238 } 239 addAnimation(uint32_t angle,AnimationPtr animationptr)240 void ActionVisual::addAnimation(uint32_t angle, AnimationPtr animationptr) { 241 m_animation_map[angle % 360] = animationptr; 242 m_map[angle % 360] = angle % 360; 243 } 244 getAnimationByAngle(int32_t angle)245 AnimationPtr ActionVisual::getAnimationByAngle(int32_t angle) { 246 int32_t closestMatch = 0; 247 return m_animation_map[getIndexByAngle(angle, m_map, closestMatch)]; 248 } 249 addAnimationOverlay(uint32_t angle,int32_t order,AnimationPtr animationptr)250 void ActionVisual::addAnimationOverlay(uint32_t angle, int32_t order, AnimationPtr animationptr) { 251 std::map<int32_t, AnimationPtr>& orderMap = m_animationOverlayMap[angle % 360]; 252 m_map[angle % 360] = angle % 360; 253 orderMap.insert(std::pair<int32_t, AnimationPtr>(order, animationptr)); 254 } 255 getAnimationOverlay(int32_t angle)256 std::map<int32_t, AnimationPtr> ActionVisual::getAnimationOverlay(int32_t angle) { 257 int32_t closestMatch = 0; 258 return m_animationOverlayMap[getIndexByAngle(angle, m_map, closestMatch)]; 259 } 260 removeAnimationOverlay(uint32_t angle,int32_t order)261 void ActionVisual::removeAnimationOverlay(uint32_t angle, int32_t order) { 262 if (m_animationOverlayMap.empty()) { 263 return; 264 } 265 int32_t closestMatch = 0; 266 AngleAnimationOverlayMap::iterator it = m_animationOverlayMap.find(getIndexByAngle(angle, m_map, closestMatch)); 267 if (it != m_animationOverlayMap.end()) { 268 it->second.erase(order); 269 if (it->second.empty()) { 270 m_animationOverlayMap.erase(it); 271 } 272 } 273 } 274 addColorOverlay(uint32_t angle,const OverlayColors & colors)275 void ActionVisual::addColorOverlay(uint32_t angle, const OverlayColors& colors) { 276 m_map[angle % 360] = angle % 360; 277 std::pair<AngleColorOverlayMap::iterator, bool> inserter = m_colorOverlayMap.insert(std::make_pair(angle % 360, colors)); 278 if (!inserter.second) { 279 OverlayColors tmp = colors; 280 OverlayColors& c = inserter.first->second; 281 c.setColorOverlayAnimation(tmp.getColorOverlayAnimation()); 282 283 const std::map<Color, Color>& colorMap = tmp.getColors(); 284 std::map<Color, Color>::const_iterator it = colorMap.begin(); 285 for (; it != colorMap.end(); ++it) { 286 c.changeColor(it->first, it->second); 287 } 288 } 289 } 290 getColorOverlay(int32_t angle)291 OverlayColors* ActionVisual::getColorOverlay(int32_t angle) { 292 if (m_colorOverlayMap.empty()) { 293 return 0; 294 } 295 int32_t closestMatch = 0; 296 int32_t index = getIndexByAngle(angle, m_map, closestMatch); 297 if (m_colorOverlayMap.find(index) == m_colorOverlayMap.end()) { 298 return 0; 299 } 300 return &m_colorOverlayMap[getIndexByAngle(angle, m_map, closestMatch)]; 301 } 302 removeColorOverlay(int32_t angle)303 void ActionVisual::removeColorOverlay(int32_t angle) { 304 if (m_colorOverlayMap.empty()) { 305 return; 306 } 307 int32_t closestMatch = 0; 308 int32_t index = getIndexByAngle(angle, m_map, closestMatch); 309 m_colorOverlayMap.erase(index); 310 } 311 addColorOverlay(uint32_t angle,int32_t order,const OverlayColors & colors)312 void ActionVisual::addColorOverlay(uint32_t angle, int32_t order, const OverlayColors& colors) { 313 std::map<int32_t, OverlayColors>& orderMap = m_colorAnimationOverlayMap[angle % 360]; 314 m_map[angle % 360] = angle % 360; 315 std::pair<std::map<int32_t, OverlayColors>::iterator, bool> inserter = orderMap.insert(std::make_pair(order, colors)); 316 if (!inserter.second) { 317 OverlayColors tmp = colors; 318 OverlayColors& c = inserter.first->second; 319 c.setColorOverlayAnimation(tmp.getColorOverlayAnimation()); 320 321 const std::map<Color, Color>& colorMap = tmp.getColors(); 322 std::map<Color, Color>::const_iterator it = colorMap.begin(); 323 for (; it != colorMap.end(); ++it) { 324 c.changeColor(it->first, it->second); 325 } 326 } 327 } 328 getColorOverlay(int32_t angle,int32_t order)329 OverlayColors* ActionVisual::getColorOverlay(int32_t angle, int32_t order) { 330 if (m_colorAnimationOverlayMap.empty()) { 331 return 0; 332 } 333 334 int32_t closestMatch = 0; 335 AngleColorAnimationOverlayMap::iterator it = m_colorAnimationOverlayMap.find(getIndexByAngle(angle, m_map, closestMatch)); 336 if (it != m_colorAnimationOverlayMap.end()) { 337 std::map<int32_t, OverlayColors>::iterator sit = it->second.find(order); 338 if (sit != it->second.end()) { 339 return &it->second[order]; 340 } 341 } 342 return 0; 343 } 344 removeColorOverlay(int32_t angle,int32_t order)345 void ActionVisual::removeColorOverlay(int32_t angle, int32_t order) { 346 if (m_colorAnimationOverlayMap.empty()) { 347 return; 348 } 349 350 int32_t closestMatch = 0; 351 AngleColorAnimationOverlayMap::iterator it = m_colorAnimationOverlayMap.find(getIndexByAngle(angle, m_map, closestMatch)); 352 if (it != m_colorAnimationOverlayMap.end()) { 353 it->second.erase(order); 354 if (it->second.empty()) { 355 m_colorAnimationOverlayMap.erase(it); 356 } 357 } 358 } 359 getActionImageAngles(std::vector<int32_t> & angles)360 void ActionVisual::getActionImageAngles(std::vector<int32_t>& angles) { 361 angles.clear(); 362 type_angle2id::const_iterator i(m_map.begin()); 363 while (i != m_map.end()) { 364 angles.push_back(i->first); 365 ++i; 366 } 367 } 368 convertToOverlays(bool color)369 void ActionVisual::convertToOverlays(bool color) { 370 bool colorOverlay = color && !m_colorOverlayMap.empty(); 371 type_angle2id::const_iterator it = m_map.begin(); 372 for (; it != m_map.end(); ++it) { 373 addAnimationOverlay(it->first, 0, getAnimationByAngle(it->first)); 374 if (colorOverlay) { 375 OverlayColors* oldC = getColorOverlay(it->first); 376 if (oldC) { 377 OverlayColors c = OverlayColors(*oldC); 378 addColorOverlay(it->first, 0, c); 379 } 380 } 381 } 382 } 383 } 384