Mercurial > fife-parpg
comparison engine/core/view/camera.cpp @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children | ab09325f901e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*************************************************************************** | |
2 * Copyright (C) 2005-2008 by the FIFE team * | |
3 * http://www.fifengine.de * | |
4 * This file is part of FIFE. * | |
5 * * | |
6 * FIFE is free software; you can redistribute it and/or modify * | |
7 * it under the terms of the GNU General Public License as published by * | |
8 * the Free Software Foundation; either version 2 of the License, or * | |
9 * (at your option) any later version. * | |
10 * * | |
11 * This program 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 * | |
14 * GNU General Public License for more details. * | |
15 * * | |
16 * You should have received a copy of the GNU General Public License * | |
17 * along with this program; if not, write to the * | |
18 * Free Software Foundation, Inc., * | |
19 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * | |
20 ***************************************************************************/ | |
21 | |
22 // Standard C++ library includes | |
23 | |
24 // 3rd party library includes | |
25 #include <SDL.h> | |
26 | |
27 // FIFE includes | |
28 // These includes are split up in two parts, separated by one empty line | |
29 // First block: files included from the FIFE root src directory | |
30 // Second block: files included from the same folder | |
31 | |
32 #include "model/metamodel/grids/cellgrid.h" | |
33 #include "model/metamodel/action.h" | |
34 #include "model/metamodel/timeprovider.h" | |
35 #include "model/structures/map.h" | |
36 #include "model/structures/layer.h" | |
37 #include "model/structures/instancetree.h" | |
38 #include "model/structures/instance.h" | |
39 #include "model/structures/location.h" | |
40 #include "util/log/logger.h" | |
41 #include "util/math/fife_math.h" | |
42 #include "util/time/timemanager.h" | |
43 #include "video/renderbackend.h" | |
44 #include "video/image.h" | |
45 #include "video/imagepool.h" | |
46 #include "video/animation.h" | |
47 #include "video/animationpool.h" | |
48 | |
49 #include "camera.h" | |
50 #include "visual.h" | |
51 | |
52 | |
53 namespace FIFE { | |
54 static Logger _log(LM_CAMERA); | |
55 | |
56 Camera::Camera(const std::string& id, | |
57 Layer *layer, | |
58 Rect viewport, | |
59 ExactModelCoordinate emc, | |
60 RenderBackend* renderbackend, | |
61 ImagePool* ipool, | |
62 AnimationPool* apool): | |
63 m_id(id), | |
64 m_matrix(), | |
65 m_inverse_matrix(), | |
66 m_tilt(0), | |
67 m_rotation(0), | |
68 m_zoom(1), | |
69 m_location(), | |
70 m_prev_origo(ScreenPoint(0,0,0)), | |
71 m_cur_origo(ScreenPoint(0,0,0)), | |
72 m_viewport(), | |
73 m_screen_cell_width(1), | |
74 m_screen_cell_height(1), | |
75 m_reference_scale(1), | |
76 m_enabled(true), | |
77 m_attachedto(NULL), | |
78 m_image_dimensions(), | |
79 m_iswarped(false), | |
80 m_renderers(), | |
81 m_pipeline(), | |
82 m_updated(false), | |
83 m_renderbackend(renderbackend), | |
84 m_ipool(ipool), | |
85 m_apool(apool), | |
86 m_layer_to_instances() { | |
87 m_location.setLayer(layer); | |
88 m_location.setExactLayerCoordinates(emc); | |
89 m_viewport = viewport; | |
90 } | |
91 | |
92 Camera::~Camera() { | |
93 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin(); | |
94 for(; r_it != m_renderers.end(); ++r_it) { | |
95 delete r_it->second; | |
96 } | |
97 m_renderers.clear(); | |
98 } | |
99 | |
100 void Camera::setTilt(double tilt) { | |
101 m_tilt = tilt; | |
102 updateReferenceScale(); | |
103 updateMatrices(); | |
104 m_iswarped = true; | |
105 } | |
106 | |
107 double Camera::getTilt() const { | |
108 return m_tilt; | |
109 } | |
110 | |
111 void Camera::setRotation(double rotation) { | |
112 m_rotation = rotation; | |
113 updateReferenceScale(); | |
114 updateMatrices(); | |
115 m_iswarped = true; | |
116 } | |
117 | |
118 double Camera::getRotation() const { | |
119 return m_rotation; | |
120 } | |
121 | |
122 void Camera::setZoom(double zoom) { | |
123 m_zoom = zoom; | |
124 if (m_zoom < 0.001) { | |
125 m_zoom = 0.001; | |
126 } | |
127 updateMatrices(); | |
128 m_iswarped = true; | |
129 } | |
130 | |
131 double Camera::getZoom() const { | |
132 return m_zoom; | |
133 } | |
134 | |
135 void Camera::setCellImageDimensions(unsigned int width, unsigned int height) { | |
136 m_screen_cell_width = width; | |
137 m_screen_cell_height = height; | |
138 updateReferenceScale(); | |
139 updateMatrices(); | |
140 m_iswarped = true; | |
141 } | |
142 | |
143 void Camera::setLocation(const Location& location) { | |
144 // initialize first set properly | |
145 if ((m_prev_origo == m_cur_origo) && (m_prev_origo == ScreenPoint(0,0,0))) { | |
146 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0)); | |
147 m_prev_origo = m_cur_origo; | |
148 } | |
149 m_location = location; | |
150 | |
151 CellGrid* cg = NULL; | |
152 if (m_location.getLayer()) { | |
153 cg = m_location.getLayer()->getCellGrid(); | |
154 } else { | |
155 throw Exception("Location without layer given to Camera::setLocation"); | |
156 } | |
157 if (!cg) { | |
158 throw Exception("Camera layer has no cellgrid specified"); | |
159 } | |
160 | |
161 updateMatrices(); | |
162 | |
163 m_prev_origo = m_cur_origo; | |
164 m_cur_origo = toScreenCoordinates(ExactModelCoordinate(0,0,0)); | |
165 } | |
166 | |
167 Point Camera::getCellImageDimensions() { | |
168 return getCellImageDimensions(m_location.getLayer()); | |
169 } | |
170 | |
171 Point Camera::getCellImageDimensions(Layer* layer) { | |
172 if (layer == m_location.getLayer()) { | |
173 return Point( m_screen_cell_width, m_screen_cell_height ); | |
174 } | |
175 std::map<Layer*, Point>::iterator it = m_image_dimensions.find(layer); | |
176 if (it != m_image_dimensions.end()) { | |
177 return it->second; | |
178 } | |
179 Point p; | |
180 CellGrid* cg = layer->getCellGrid(); | |
181 assert(cg); | |
182 DoublePoint dimensions = getLogicalCellDimensions(layer); | |
183 p.x = static_cast<int>(round(m_reference_scale * dimensions.x)); | |
184 p.y = static_cast<int>(round(m_reference_scale * dimensions.y)); | |
185 m_image_dimensions[layer] = p; | |
186 return p; | |
187 } | |
188 | |
189 Location Camera::getLocation() const { | |
190 return m_location; | |
191 } | |
192 | |
193 Location& Camera::getLocationRef() { | |
194 return m_location; | |
195 } | |
196 | |
197 void Camera::setViewPort(const Rect& viewport) { | |
198 m_viewport = viewport; | |
199 } | |
200 | |
201 const Rect& Camera::getViewPort() const { | |
202 return m_viewport; | |
203 } | |
204 | |
205 void Camera::setEnabled(bool enabled) { | |
206 m_enabled = enabled; | |
207 } | |
208 | |
209 bool Camera::isEnabled() { | |
210 return m_enabled; | |
211 } | |
212 | |
213 void Camera::updateMatrices() { | |
214 double scale = m_reference_scale; | |
215 m_matrix.loadScale(scale, scale, scale); | |
216 if (m_location.getLayer()) { | |
217 CellGrid* cg = m_location.getLayer()->getCellGrid(); | |
218 if (cg) { | |
219 ExactModelCoordinate pt = m_location.getMapCoordinates(); | |
220 m_matrix.applyTranslate( -pt.x *m_reference_scale,-pt.y *m_reference_scale, 0); | |
221 } | |
222 } | |
223 scale = m_zoom; | |
224 m_matrix.applyScale(scale, scale, scale); | |
225 m_matrix.applyRotate(-m_rotation, 0.0, 0.0, 1.0); | |
226 m_matrix.applyRotate(-m_tilt, 1.0, 0.0, 0.0); | |
227 m_inverse_matrix = m_matrix.inverse(); | |
228 } | |
229 | |
230 void Camera::calculateZValue(ScreenPoint& screen_coords) { | |
231 int dy = -(screen_coords.y - toScreenCoordinates(m_location.getMapCoordinates()).y); | |
232 screen_coords.z = static_cast<int>(tan(m_tilt * (M_PI / 180.0)) * static_cast<double>(dy)); | |
233 } | |
234 | |
235 ExactModelCoordinate Camera::toMapCoordinates(ScreenPoint screen_coords, bool z_calculated) { | |
236 if (!z_calculated) { | |
237 calculateZValue(screen_coords); | |
238 } | |
239 screen_coords.x -= m_viewport.w / 2; | |
240 screen_coords.y -= m_viewport.h / 2; | |
241 | |
242 return m_inverse_matrix * intPt2doublePt(screen_coords); | |
243 } | |
244 | |
245 ScreenPoint Camera::toScreenCoordinates(ExactModelCoordinate elevation_coords) { | |
246 ExactModelCoordinate p = elevation_coords; | |
247 ScreenPoint pt = doublePt2intPt( m_matrix* p ); | |
248 pt.x += m_viewport.w / 2; | |
249 pt.y += m_viewport.h / 2; | |
250 return pt; | |
251 } | |
252 | |
253 DoublePoint Camera::getLogicalCellDimensions(Layer* layer) { | |
254 CellGrid* cg = NULL; | |
255 if (layer) { | |
256 cg = layer->getCellGrid(); | |
257 } | |
258 assert(cg); | |
259 | |
260 ModelCoordinate cell(0,0); | |
261 std::vector<ExactModelCoordinate> vertices; | |
262 cg->getVertices(vertices, cell); | |
263 | |
264 DoubleMatrix mtx; | |
265 mtx.loadRotate(m_rotation, 0.0, 0.0, 1.0); | |
266 mtx.applyRotate(m_tilt, 1.0, 0.0, 0.0); | |
267 double x1, x2, y1, y2; | |
268 for (unsigned int i = 0; i < vertices.size(); i++) { | |
269 vertices[i] = cg->toMapCoordinates(vertices[i]); | |
270 vertices[i] = mtx * vertices[i]; | |
271 if (i == 0) { | |
272 x1 = x2 = vertices[0].x; | |
273 y1 = y2 = vertices[0].y; | |
274 } else { | |
275 x1 = std::min(vertices[i].x, x1); | |
276 x2 = std::max(vertices[i].x, x2); | |
277 y1 = std::min(vertices[i].y, y1); | |
278 y2 = std::max(vertices[i].y, y2); | |
279 } | |
280 } | |
281 return DoublePoint( x2 - x1, y2 - y1 ); | |
282 } | |
283 | |
284 void Camera::updateReferenceScale() { | |
285 DoublePoint dim = getLogicalCellDimensions(m_location.getLayer()); | |
286 m_reference_scale = static_cast<double>(m_screen_cell_width) / dim.x; | |
287 | |
288 FL_DBG(_log, "Updating reference scale"); | |
289 FL_DBG(_log, LMsg(" tilt=") << m_tilt << " rot=" << m_rotation); | |
290 FL_DBG(_log, LMsg(" m_screen_cell_width=") << m_screen_cell_width); | |
291 } | |
292 | |
293 void Camera::getMatchingInstances(ScreenPoint screen_coords, Layer& layer, std::list<Instance*>& instances) { | |
294 instances.clear(); | |
295 const std::vector<Instance*>& layer_instances = m_layer_to_instances[&layer]; | |
296 std::vector<Instance*>::const_iterator instance_it = layer_instances.end(); | |
297 while (instance_it != layer_instances.begin()) { | |
298 --instance_it; | |
299 Instance* i = (*instance_it); | |
300 InstanceVisual* visual = i->getVisual<InstanceVisual>(); | |
301 InstanceVisualCacheItem& vc = visual->getCacheItem(this); | |
302 if ((vc.dimensions.contains(Point(screen_coords.x, screen_coords.y)))) { | |
303 assert(vc.image); | |
304 Uint8 r, g, b, a; | |
305 int x = screen_coords.x - vc.dimensions.x; | |
306 int y = screen_coords.y - vc.dimensions.y; | |
307 if (m_zoom != 1.0) { | |
308 double fx = static_cast<double>(x); | |
309 double fy = static_cast<double>(y); | |
310 double fow = static_cast<double>(vc.image->getWidth()); | |
311 double foh = static_cast<double>(vc.image->getHeight()); | |
312 double fsw = static_cast<double>(vc.dimensions.w); | |
313 double fsh = static_cast<double>(vc.dimensions.h); | |
314 x = static_cast<int>(round(fx / fsw * fow)); | |
315 y = static_cast<int>(round(fy / fsh * foh)); | |
316 } | |
317 vc.image->getPixelRGBA(x, y, &r, &b, &g, &a); | |
318 // instance is hit with mouse if not totally transparent | |
319 if (a != 0) { | |
320 instances.push_back(i); | |
321 } | |
322 } | |
323 } | |
324 } | |
325 | |
326 void Camera::getMatchingInstances(Location& loc, std::list<Instance*>& instances, bool use_exactcoordinates) { | |
327 instances.clear(); | |
328 const std::vector<Instance*>& layer_instances = m_layer_to_instances[loc.getLayer()]; | |
329 std::vector<Instance*>::const_iterator instance_it = layer_instances.end(); | |
330 while (instance_it != layer_instances.begin()) { | |
331 --instance_it; | |
332 Instance* i = (*instance_it); | |
333 if (use_exactcoordinates) { | |
334 if (i->getLocationRef().getExactLayerCoordinatesRef() == loc.getExactLayerCoordinatesRef()) { | |
335 instances.push_back(i); | |
336 } | |
337 } else { | |
338 if (i->getLocationRef().getLayerCoordinates() == loc.getLayerCoordinates()) { | |
339 instances.push_back(i); | |
340 } | |
341 } | |
342 } | |
343 } | |
344 | |
345 void Camera::attach(Instance *instance) { | |
346 m_attachedto = instance; | |
347 } | |
348 | |
349 void Camera::detach() { | |
350 m_attachedto = NULL; | |
351 } | |
352 | |
353 void Camera::update() { | |
354 if( !m_attachedto ) { | |
355 return; | |
356 } | |
357 Location loc(m_location); | |
358 loc.setExactLayerCoordinates( m_attachedto->getLocationRef().getExactLayerCoordinates(m_location.getLayer()) ); | |
359 setLocation(loc); | |
360 updateMatrices(); | |
361 } | |
362 | |
363 void Camera::refresh() { | |
364 updateMatrices(); | |
365 m_iswarped = true; | |
366 } | |
367 | |
368 void Camera::resetUpdates() { | |
369 m_iswarped = false; | |
370 m_prev_origo = m_cur_origo; | |
371 } | |
372 | |
373 bool pipelineSort(const RendererBase* lhs, const RendererBase* rhs) { | |
374 return (lhs->getPipelinePosition() < rhs->getPipelinePosition()); | |
375 } | |
376 | |
377 void Camera::addRenderer(RendererBase* renderer) { | |
378 renderer->setRendererListener(this); | |
379 m_renderers[renderer->getName()] = renderer; | |
380 if (renderer->isEnabled()) { | |
381 m_pipeline.push_back(renderer); | |
382 } | |
383 m_pipeline.sort(pipelineSort); | |
384 } | |
385 | |
386 void Camera::onRendererPipelinePositionChanged(RendererBase* renderer) { | |
387 m_pipeline.sort(pipelineSort); | |
388 } | |
389 | |
390 void Camera::onRendererEnabledChanged(RendererBase* renderer) { | |
391 assert(m_renderers[renderer->getName()]); | |
392 if (renderer->isEnabled()) { | |
393 FL_LOG(_log, LMsg("Enabling renderer ") << renderer->getName()); | |
394 m_pipeline.push_back(renderer); | |
395 m_pipeline.sort(pipelineSort); | |
396 } else { | |
397 m_pipeline.remove(renderer); | |
398 } | |
399 } | |
400 | |
401 RendererBase* Camera::getRenderer(const std::string& name) { | |
402 return m_renderers[name]; | |
403 } | |
404 | |
405 class InstanceDistanceSort { | |
406 public: | |
407 Camera* cam; | |
408 inline bool operator()(const Instance* lhs, const Instance* rhs) { | |
409 InstanceVisual* liv = lhs->getVisual<InstanceVisual>(); | |
410 InstanceVisual* riv = rhs->getVisual<InstanceVisual>(); | |
411 InstanceVisualCacheItem& lic = liv->getCacheItem(cam); | |
412 InstanceVisualCacheItem& ric = riv->getCacheItem(cam); | |
413 if (lic.screenpoint.z == ric.screenpoint.z) { | |
414 return liv->getStackPosition() < riv->getStackPosition(); | |
415 } | |
416 return lic.screenpoint.z < ric.screenpoint.z; | |
417 } | |
418 }; | |
419 | |
420 void Camera::resetRenderers() { | |
421 std::map<std::string, RendererBase*>::iterator r_it = m_renderers.begin(); | |
422 for (; r_it != m_renderers.end(); ++r_it) { | |
423 Map* map = m_location.getMap(); | |
424 r_it->second->reset(); | |
425 r_it->second->activateAllLayers(map); | |
426 } | |
427 } | |
428 | |
429 void Camera::render() { | |
430 ScreenPoint cammove = getLatestMovement(); | |
431 | |
432 Map* map = m_location.getMap(); | |
433 if (!map) { | |
434 FL_ERR(_log, "No map for camera found"); | |
435 return; | |
436 } | |
437 //if ((!map->isChanged()) && (!m_iswarped) && (cammove == ScreenPoint(0,0,0))) { | |
438 // return; | |
439 //} | |
440 | |
441 const unsigned long curtime = TimeManager::instance()->getTime(); | |
442 | |
443 // update each layer | |
444 m_renderbackend->pushClipArea(getViewPort()); | |
445 | |
446 m_layer_to_instances.clear(); | |
447 | |
448 const std::list<Layer*>& layers = map->getLayers(); | |
449 std::list<Layer*>::const_iterator layer_it = layers.begin(); | |
450 for (;layer_it != layers.end(); ++layer_it) { | |
451 | |
452 // sort instances on layer based on stack position + camera distance. done only once | |
453 // here instead passing it to each renderer. | |
454 // instances are checked first if their image intersects with the viewport. | |
455 // this reduces processing load during sorting later | |
456 std::vector<Instance*> allinstances((*layer_it)->getInstances()); | |
457 std::vector<Instance*>::const_iterator instance_it = allinstances.begin(); | |
458 std::vector<Instance*>& instances_to_render = m_layer_to_instances[*layer_it]; | |
459 for (;instance_it != allinstances.end(); ++instance_it) { | |
460 Instance* instance = *instance_it; | |
461 InstanceVisual* visual = instance->getVisual<InstanceVisual>(); | |
462 InstanceVisualCacheItem& vc = visual->getCacheItem(this); | |
463 | |
464 // use cached values if there is no need to do full recalculation | |
465 ScreenPoint drawpt; | |
466 int angle = 0; | |
467 if (m_updated && (!m_iswarped) && (!(instance->getChangeInfo() & (ICHANGE_LOC | ICHANGE_ROTATION))) && (vc.image)) { | |
468 int pos_estimate_x = vc.screenpoint.x - cammove.x; | |
469 int pos_estimate_y = vc.screenpoint.y - cammove.y; | |
470 int pos_estimate_z = vc.screenpoint.z - cammove.z; | |
471 angle = vc.facing_angle; | |
472 //std::cout << "orig x = " << drawpt.x << ", est x = " << pos_estimate_x << "\n"; | |
473 //std::cout << "orig y = " << drawpt.y << ", est y = " << pos_estimate_y << "\n"; | |
474 drawpt.x = pos_estimate_x; | |
475 drawpt.y = pos_estimate_y; | |
476 drawpt.z = pos_estimate_z; | |
477 //drawpt.z = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ).z; | |
478 } else { | |
479 drawpt = toScreenCoordinates( instance->getLocationRef().getMapCoordinates() ); | |
480 vc.facing_angle = angle = getAngleBetween(instance->getLocationRef(), instance->getFacingLocation()); | |
481 } | |
482 angle += instance->getRotation(); | |
483 | |
484 Image* image = NULL; | |
485 Action* action = instance->getCurrentAction(); | |
486 if (action) { | |
487 FL_DBG(_log, "Instance has action"); | |
488 int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(angle); | |
489 | |
490 Animation& animation = m_apool->getAnimation(animation_id); | |
491 int animtime = scaleTime(instance->getTotalTimeMultiplier(), instance->getActionRuntime()) % animation.getDuration(); | |
492 image = animation.getFrameByTimestamp(animtime); | |
493 } else { | |
494 FL_DBG(_log, "No action"); | |
495 int imageid = vc.getStaticImageIndexByAngle(angle, instance); | |
496 FL_DBG(_log, LMsg("Instance does not have action, using static image with id ") << imageid); | |
497 if (imageid >= 0) { | |
498 image = &m_ipool->getImage(imageid); | |
499 } else { | |
500 // there was no static image for instance, trying default action | |
501 action = instance->getObject()->getDefaultAction(); | |
502 if (action) { | |
503 int animation_id = action->getVisual<ActionVisual>()->getAnimationIndexByAngle(angle); | |
504 Animation& animation = m_apool->getAnimation(animation_id); | |
505 int animtime = scaleTime(instance->getTotalTimeMultiplier(), curtime) % animation.getDuration(); | |
506 image = animation.getFrameByTimestamp(animtime); | |
507 } | |
508 } | |
509 } | |
510 if (image) { | |
511 vc.image = image; | |
512 vc.screenpoint = drawpt; | |
513 | |
514 int w = image->getWidth(); | |
515 int h = image->getHeight(); | |
516 drawpt.x -= w / 2; | |
517 drawpt.x += image->getXShift(); | |
518 drawpt.y -= h / 2; | |
519 drawpt.y += image->getYShift(); | |
520 Rect r = Rect(drawpt.x, drawpt.y, w, h); | |
521 | |
522 vc.dimensions = r; | |
523 if (m_zoom != 1.0) { | |
524 // NOTE: Due to image alignment, there is additional additions and substractions on image dimensions | |
525 // There's probabaly some better solution for this, but works "good enough" for now. | |
526 // In case additions / substractions are removed, gaps appear between tiles. | |
527 r.w = static_cast<unsigned int>(ceil(static_cast<double>(vc.dimensions.w) * m_zoom)) + 2; | |
528 r.h = static_cast<unsigned int>(ceil(static_cast<double>(vc.dimensions.h) * m_zoom)) + 2; | |
529 int xo = static_cast<int>(ceil(static_cast<double>(vc.image->getXShift()) * m_zoom)) - vc.image->getXShift(); | |
530 int yo = static_cast<int>(ceil(static_cast<double>(vc.image->getYShift()) * m_zoom)) - vc.image->getYShift(); | |
531 r.x = vc.dimensions.x - static_cast<unsigned int>(ceil(static_cast<double>(r.w - vc.dimensions.w) / 2)) + xo - 1; | |
532 r.y = vc.dimensions.y - static_cast<unsigned int>(ceil(static_cast<double>(r.h - vc.dimensions.h) / 2)) + yo - 1; | |
533 vc.dimensions = r; | |
534 } | |
535 | |
536 if (vc.dimensions.intersects(getViewPort())) { | |
537 instances_to_render.push_back(instance); | |
538 } | |
539 } | |
540 } | |
541 | |
542 InstanceDistanceSort ids; | |
543 ids.cam = this; | |
544 std::stable_sort(instances_to_render.begin(), instances_to_render.end(), ids); | |
545 | |
546 std::list<RendererBase*>::iterator r_it = m_pipeline.begin(); | |
547 for (; r_it != m_pipeline.end(); ++r_it) { | |
548 if ((*r_it)->isActivedLayer(*layer_it)) { | |
549 (*r_it)->render(this, *layer_it, instances_to_render); | |
550 } | |
551 } | |
552 } | |
553 m_renderbackend->popClipArea(); | |
554 resetUpdates(); | |
555 m_updated = true; | |
556 } | |
557 | |
558 } |