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