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 "video/renderbackend.h" 31 #include "util/math/fife_math.h" 32 #include "util/log/logger.h" 33 #include "model/structures/instance.h" 34 #include "model/structures/layer.h" 35 #include "model/structures/location.h" 36 #include "view/camera.h" 37 38 #include "renderernode.h" 39 40 41 namespace FIFE { 42 static Logger _log(LM_VIEWVIEW); 43 44 class NodeInstanceDeleteListener : public InstanceDeleteListener { 45 public: NodeInstanceDeleteListener(RendererNode * node)46 NodeInstanceDeleteListener(RendererNode* node) { 47 m_node = node; 48 } ~NodeInstanceDeleteListener()49 virtual ~NodeInstanceDeleteListener() {} 50 onInstanceDeleted(Instance * instance)51 virtual void onInstanceDeleted(Instance* instance) { 52 m_node->removeInstance(instance, false); 53 } 54 55 private: 56 RendererNode* m_node; 57 }; 58 RendererNode(Instance * attached_instance,const Location & relative_location,Layer * relative_layer,const Point & relative_point)59 RendererNode::RendererNode(Instance* attached_instance, const Location &relative_location, Layer* relative_layer, const Point &relative_point): 60 m_instance(NULL), 61 m_location(relative_location), 62 m_layer(relative_layer), 63 m_point(relative_point), 64 m_listener(NULL) { 65 addInstance(attached_instance); 66 } RendererNode(Instance * attached_instance,const Location & relative_location,const Point & relative_point)67 RendererNode::RendererNode(Instance* attached_instance, const Location &relative_location, const Point &relative_point): 68 m_instance(NULL), 69 m_location(relative_location), 70 m_layer(NULL), 71 m_point(relative_point), 72 m_listener(NULL) { 73 addInstance(attached_instance); 74 } RendererNode(Instance * attached_instance,Layer * relative_layer,const Point & relative_point)75 RendererNode::RendererNode(Instance* attached_instance, Layer* relative_layer, const Point &relative_point): 76 m_instance(NULL), 77 m_location(NULL), 78 m_layer(relative_layer), 79 m_point(relative_point), 80 m_listener(NULL) { 81 addInstance(attached_instance); 82 } RendererNode(Instance * attached_instance,const Point & relative_point)83 RendererNode::RendererNode(Instance* attached_instance, const Point &relative_point): 84 m_instance(NULL), 85 m_location(NULL), 86 m_layer(NULL), 87 m_point(relative_point), 88 m_listener(NULL) { 89 addInstance(attached_instance); 90 } RendererNode(const Location & attached_location,Layer * relative_layer,const Point & relative_point)91 RendererNode::RendererNode(const Location &attached_location, Layer* relative_layer, const Point &relative_point): 92 m_instance(NULL), 93 m_location(attached_location), 94 m_layer(relative_layer), 95 m_point(relative_point), 96 m_listener(NULL) { 97 } RendererNode(const Location & attached_location,const Point & relative_point)98 RendererNode::RendererNode(const Location &attached_location, const Point &relative_point): 99 m_instance(NULL), 100 m_location(attached_location), 101 m_layer(NULL), 102 m_point(relative_point), 103 m_listener(NULL) { 104 } RendererNode(Layer * attached_layer,const Point & relative_point)105 RendererNode::RendererNode(Layer* attached_layer, const Point &relative_point): 106 m_instance(NULL), 107 m_location(NULL), 108 m_layer(attached_layer), 109 m_point(relative_point), 110 m_listener(NULL) { 111 } RendererNode(const Point & attached_point)112 RendererNode::RendererNode(const Point &attached_point): 113 m_instance(NULL), 114 m_location(NULL), 115 m_layer(NULL), 116 m_point(attached_point), 117 m_listener(NULL) { 118 } RendererNode(const RendererNode & old)119 RendererNode::RendererNode(const RendererNode& old): 120 m_instance(NULL), 121 m_location(old.m_location), 122 m_layer(old.m_layer), 123 m_point(old.m_point), 124 m_listener(NULL) { 125 addInstance(old.m_instance); 126 } operator =(const RendererNode & source)127 RendererNode& RendererNode::operator=(const RendererNode &source) { 128 if (this != &source) { 129 changeInstance(source.m_instance); 130 m_location = source.m_location; 131 m_layer = source.m_layer; 132 m_point = source.m_point; 133 } 134 return *this; 135 } ~RendererNode()136 RendererNode::~RendererNode() { 137 removeInstance(m_instance); 138 delete m_listener; 139 } 140 setAttached(Instance * attached_instance,const Location & relative_location,const Point & relative_point)141 void RendererNode::setAttached(Instance* attached_instance, const Location &relative_location, const Point &relative_point) { 142 changeInstance(attached_instance); 143 m_location = relative_location; 144 m_point = relative_point; 145 } setAttached(Instance * attached_instance,const Location & relative_location)146 void RendererNode::setAttached(Instance* attached_instance, const Location &relative_location) { 147 changeInstance(attached_instance); 148 m_location = relative_location; 149 } setAttached(Instance * attached_instance,const Point & relative_point)150 void RendererNode::setAttached(Instance* attached_instance, const Point &relative_point) { 151 changeInstance(attached_instance); 152 m_point = relative_point; 153 } setAttached(Instance * attached_instance)154 void RendererNode::setAttached(Instance* attached_instance) { 155 changeInstance(attached_instance); 156 } setAttached(const Location & attached_location,const Point & relative_point)157 void RendererNode::setAttached(const Location &attached_location, const Point &relative_point) { 158 changeInstance(NULL); 159 m_location = attached_location; 160 m_point = relative_point; 161 } setAttached(const Location & attached_location)162 void RendererNode::setAttached(const Location &attached_location) { 163 changeInstance(NULL); 164 m_location = attached_location; 165 } setAttached(Layer * attached_layer)166 void RendererNode::setAttached(Layer* attached_layer) { 167 m_layer = attached_layer; 168 } setAttached(const Point & attached_point)169 void RendererNode::setAttached(const Point &attached_point) { 170 changeInstance(NULL); 171 m_location = NULL; 172 m_point = attached_point; 173 } 174 setRelative(const Location & relative_location)175 void RendererNode::setRelative(const Location &relative_location) { 176 if(m_instance == NULL) { 177 FL_WARN(_log, LMsg("RendererNode::setRelative(Location) - ") << "No instance attached."); 178 } 179 m_location = relative_location; 180 } setRelative(const Location & relative_location,Point relative_point)181 void RendererNode::setRelative(const Location &relative_location, Point relative_point) { 182 if(m_instance == NULL) { 183 FL_WARN(_log, LMsg("RendererNode::setRelative(Location, Point) - ") << "No instance attached."); 184 } 185 m_location = relative_location; 186 m_point = relative_point; 187 } setRelative(const Point & relative_point)188 void RendererNode::setRelative(const Point &relative_point) { 189 if(m_instance == NULL || m_location == NULL) { 190 FL_WARN(_log, LMsg("RendererNode::setRelative(Point) - ") << "No instance or location attached."); 191 } 192 m_point = relative_point; 193 } 194 getAttachedInstance()195 Instance* RendererNode::getAttachedInstance() { 196 if(m_instance == NULL) { 197 FL_WARN(_log, LMsg("RendererNode::getAttachedInstance() - ") << "No instance attached."); 198 } 199 return m_instance; 200 } getAttachedLocation()201 Location RendererNode::getAttachedLocation() { 202 if(m_instance != NULL || m_location == NULL) { 203 FL_WARN(_log, LMsg("RendererNode::getAttachedLocation() - ") << "No location attached."); 204 } 205 return m_location; 206 } getAttachedLayer()207 Layer* RendererNode::getAttachedLayer() { 208 if(m_layer == NULL) { 209 FL_WARN(_log, LMsg("RendererNode::getAttachedLayer() - ") << "No layer attached."); 210 } 211 return m_layer; 212 } getAttachedPoint()213 Point RendererNode::getAttachedPoint() { 214 if(m_instance != NULL || m_location != NULL) { 215 FL_WARN(_log, LMsg("RendererNode::getAttachedPoint() - ") << "No point attached."); 216 } 217 return m_point; 218 } 219 getOffsetLocation()220 Location RendererNode::getOffsetLocation() { 221 if(m_instance == NULL || m_location == NULL) { 222 FL_WARN(_log, LMsg("RendererNode::getOffsetLocation() - ") << "No location as offset used."); 223 } 224 return m_location; 225 } getOffsetPoint()226 Point RendererNode::getOffsetPoint() { 227 if(m_instance == NULL && m_location == NULL) { 228 FL_WARN(_log, LMsg("RendererNode::getOffsetPoint() - ") << "No point as offset used."); 229 } 230 return m_point; 231 } 232 getInstance()233 Instance* RendererNode::getInstance() { 234 return m_instance; 235 } getLocation()236 Location RendererNode::getLocation() { 237 return m_location; 238 } getLocationRef()239 const Location& RendererNode::getLocationRef() { 240 return m_location; 241 } getLayer()242 Layer* RendererNode::getLayer() { 243 return m_layer; 244 } getPoint()245 Point RendererNode::getPoint() { 246 return m_point; 247 } getPointRef()248 const Point& RendererNode::getPointRef() { 249 return m_point; 250 } 251 addInstance(Instance * instance)252 void RendererNode::addInstance(Instance* instance) { 253 checkDeleteListener(); 254 m_instance = instance; 255 if (m_instance) { 256 m_instance->addDeleteListener(m_listener); 257 } 258 } 259 changeInstance(Instance * instance)260 void RendererNode::changeInstance(Instance* instance) { 261 if (m_instance == instance) { 262 return; 263 } 264 checkDeleteListener(); 265 if (m_instance) { 266 m_instance->removeDeleteListener(m_listener); 267 } 268 m_instance = instance; 269 if (m_instance) { 270 m_instance->addDeleteListener(m_listener); 271 } 272 } 273 removeInstance(Instance * instance,bool listener)274 void RendererNode::removeInstance(Instance* instance, bool listener) { 275 if (m_instance == instance && instance) { 276 if (listener) { 277 m_instance->removeDeleteListener(m_listener); 278 } 279 m_instance = NULL; 280 } 281 } 282 checkDeleteListener()283 void RendererNode::checkDeleteListener() { 284 if (m_listener) { 285 return; 286 } 287 m_listener = new NodeInstanceDeleteListener(this); 288 } 289 getCalculatedPoint(Camera * cam,Layer * layer,const bool zoomed)290 Point RendererNode::getCalculatedPoint(Camera* cam, Layer* layer, const bool zoomed) { 291 ScreenPoint p; 292 if(m_instance != NULL) { 293 if(m_layer == NULL) { 294 m_layer = m_instance->getLocationRef().getLayer(); 295 } 296 if(m_location != NULL) { 297 p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates() + m_location.getMapCoordinates()); 298 } else { 299 p = cam->toScreenCoordinates(m_instance->getLocationRef().getMapCoordinates()); 300 } 301 } else if(m_location != NULL) { 302 if(m_layer == NULL) { 303 m_layer = m_location.getLayer(); 304 } 305 p = cam->toScreenCoordinates(m_location.getMapCoordinates()); 306 } else if(m_layer == NULL) { 307 // FIXME 308 FL_WARN(_log, LMsg("RendererNode::getCalculatedPoint(Camera, Layer) - ") << "No layer attached. So we use the first active layer of the renderer."); 309 setAttached(layer); 310 } 311 if(zoomed) { 312 return Point(round(m_point.x * cam->getZoom()) + p.x, round(m_point.y * cam->getZoom()) + p.y); 313 } else { 314 return Point(m_point.x + p.x, m_point.y + p.y); 315 } 316 317 } 318 } 319