Mercurial > fife-parpg
comparison engine/core/view/renderers/instancerenderer.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 | 4e68022ed545 |
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 | |
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 "video/image.h" | |
32 #include "video/sdl/sdlimage.h" | |
33 #include "video/imagepool.h" | |
34 #include "video/animation.h" | |
35 #include "video/animationpool.h" | |
36 #include "util/math/fife_math.h" | |
37 #include "util/log/logger.h" | |
38 #include "model/metamodel/grids/cellgrid.h" | |
39 #include "model/metamodel/action.h" | |
40 #include "model/structures/instance.h" | |
41 #include "model/structures/layer.h" | |
42 #include "model/structures/location.h" | |
43 | |
44 #include "view/camera.h" | |
45 #include "view/visual.h" | |
46 #include "instancerenderer.h" | |
47 | |
48 | |
49 namespace FIFE { | |
50 static Logger _log(LM_VIEWVIEW); | |
51 | |
52 InstanceRenderer::OutlineInfo::OutlineInfo(): | |
53 r(0), | |
54 g(0), | |
55 b(0), | |
56 width(1), | |
57 outline(NULL), | |
58 curimg(NULL) { | |
59 } | |
60 InstanceRenderer::ColoringInfo::ColoringInfo(): | |
61 r(0), | |
62 g(0), | |
63 b(0), | |
64 overlay(NULL), | |
65 curimg(NULL) { | |
66 } | |
67 | |
68 InstanceRenderer::OutlineInfo::~OutlineInfo() { | |
69 delete outline; | |
70 } | |
71 | |
72 InstanceRenderer::ColoringInfo::~ColoringInfo() { | |
73 delete overlay; | |
74 } | |
75 | |
76 InstanceRenderer* InstanceRenderer::getInstance(IRendererContainer* cnt) { | |
77 return dynamic_cast<InstanceRenderer*>(cnt->getRenderer("InstanceRenderer")); | |
78 } | |
79 | |
80 InstanceRenderer::InstanceRenderer(RenderBackend* renderbackend, int position, ImagePool* imagepool, AnimationPool* animpool): | |
81 RendererBase(renderbackend, position), | |
82 m_imagepool(imagepool), | |
83 m_animationpool(animpool), | |
84 m_layer_to_outlinemap(), | |
85 m_layer_to_coloringmap() { | |
86 setEnabled(true); | |
87 } | |
88 | |
89 InstanceRenderer::InstanceRenderer(const InstanceRenderer& old): | |
90 RendererBase(old), | |
91 m_imagepool(old.m_imagepool), | |
92 m_animationpool(old.m_animationpool), | |
93 m_layer_to_outlinemap(), | |
94 m_layer_to_coloringmap() { | |
95 setEnabled(true); | |
96 } | |
97 | |
98 RendererBase* InstanceRenderer::clone() { | |
99 return new InstanceRenderer(*this); | |
100 } | |
101 | |
102 InstanceRenderer::~InstanceRenderer() { | |
103 } | |
104 | |
105 unsigned int scale(unsigned int val, double factor) { | |
106 return static_cast<unsigned int>(ceil(static_cast<double>(val) * factor)); | |
107 } | |
108 | |
109 void InstanceRenderer::render(Camera* cam, Layer* layer, std::vector<Instance*>& instances) { | |
110 FL_DBG(_log, "Iterating layer..."); | |
111 CellGrid* cg = layer->getCellGrid(); | |
112 if (!cg) { | |
113 FL_WARN(_log, "No cellgrid assigned to layer, cannot draw instances"); | |
114 return; | |
115 } | |
116 | |
117 bool potential_outlining = false; | |
118 InstanceToOutlines_t outline_i2o; | |
119 InstanceToOutlines_t::iterator outline_end; | |
120 | |
121 LayerToOutlineMap_t::iterator outline_l2i = m_layer_to_outlinemap.find(layer); | |
122 if (outline_l2i != m_layer_to_outlinemap.end()) { | |
123 potential_outlining = true; | |
124 outline_i2o = outline_l2i->second; | |
125 outline_end = outline_i2o.end(); | |
126 } | |
127 | |
128 bool potential_coloring = false; | |
129 InstanceToColoring_t coloring_i2o; | |
130 InstanceToColoring_t::iterator coloring_end; | |
131 | |
132 LayerToColoringMap_t::iterator coloring_l2i = m_layer_to_coloringmap.find(layer); | |
133 if (coloring_l2i != m_layer_to_coloringmap.end()) { | |
134 potential_coloring = true; | |
135 coloring_i2o = coloring_l2i->second; | |
136 coloring_end = coloring_i2o.end(); | |
137 } | |
138 | |
139 std::vector<Instance*>::const_iterator instance_it = instances.begin(); | |
140 for (;instance_it != instances.end(); ++instance_it) { | |
141 FL_DBG(_log, "Iterating instances..."); | |
142 Instance* instance = (*instance_it); | |
143 InstanceVisual* visual = instance->getVisual<InstanceVisual>(); | |
144 InstanceVisualCacheItem& vc = visual->getCacheItem(cam); | |
145 FL_DBG(_log, LMsg("Instance layer coordinates = ") << instance->getLocationRef().getLayerCoordinates()); | |
146 | |
147 if (potential_outlining) { | |
148 InstanceToOutlines_t::iterator outline_it = outline_i2o.find(instance); | |
149 if (outline_it != outline_end) { | |
150 bindOutline(outline_it->second, vc, cam)->render(vc.dimensions); | |
151 } | |
152 } | |
153 if (potential_coloring) { | |
154 InstanceToColoring_t::iterator coloring_it = coloring_i2o.find(instance); | |
155 if (coloring_it != coloring_end) { | |
156 bindColoring(coloring_it->second, vc, cam)->render(vc.dimensions); | |
157 continue; | |
158 } | |
159 } | |
160 vc.image->render(vc.dimensions); | |
161 } | |
162 } | |
163 | |
164 Image* InstanceRenderer::bindOutline(OutlineInfo& info, InstanceVisualCacheItem& vc, Camera* cam) { | |
165 if (info.curimg == vc.image) { | |
166 return info.outline; | |
167 } | |
168 if (info.outline) { | |
169 delete info.outline; // delete old mask | |
170 info.outline = NULL; | |
171 } | |
172 SDL_Surface* surface = vc.image->getSurface(); | |
173 SDL_Surface* outline_surface = SDL_ConvertSurface(surface, surface->format, surface->flags); | |
174 | |
175 // needs to use SDLImage here, since GlImage does not support drawing primitives atm | |
176 SDLImage* img = new SDLImage(outline_surface); | |
177 | |
178 // TODO: optimize... | |
179 uint8_t r, g, b, a = 0; | |
180 int prev_a = a; | |
181 | |
182 // vertical sweep | |
183 for (unsigned int x = 0; x < img->getWidth(); x ++) { | |
184 for (unsigned int y = 0; y < img->getHeight(); y ++) { | |
185 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a); | |
186 if ((a == 0 || prev_a == 0) && (a != prev_a)) { | |
187 if (a < prev_a) { | |
188 for (unsigned int yy = y; yy < y + info.width; yy++) { | |
189 img->putPixel(x, yy, info.r, info.g, info.b); | |
190 } | |
191 } else { | |
192 for (unsigned int yy = y - info.width; yy < y; yy++) { | |
193 img->putPixel(x, yy, info.r, info.g, info.b); | |
194 } | |
195 } | |
196 } | |
197 prev_a = a; | |
198 } | |
199 } | |
200 // horizontal sweep | |
201 for (unsigned int y = 0; y < img->getHeight(); y ++) { | |
202 for (unsigned int x = 0; x < img->getWidth(); x ++) { | |
203 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a); | |
204 if ((a == 0 || prev_a == 0) && (a != prev_a)) { | |
205 if (a < prev_a) { | |
206 for (unsigned int xx = x; xx < x + info.width; xx++) { | |
207 img->putPixel(xx, y, info.r, info.g, info.b); | |
208 } | |
209 } else { | |
210 for (unsigned int xx = x - info.width; xx < x; xx++) { | |
211 img->putPixel(xx, y, info.r, info.g, info.b); | |
212 } | |
213 } | |
214 } | |
215 prev_a = a; | |
216 } | |
217 } | |
218 | |
219 // In case of OpenGL backend, SDLImage needs to be converted | |
220 info.outline = m_renderbackend->createImage(img->detachSurface()); | |
221 delete img; | |
222 return info.outline; | |
223 } | |
224 | |
225 Image* InstanceRenderer::bindColoring(ColoringInfo& info, InstanceVisualCacheItem& vc, Camera* cam) { | |
226 if (info.curimg == vc.image) { | |
227 return info.overlay; | |
228 } | |
229 if (info.overlay) { | |
230 delete info.overlay; // delete old mask | |
231 info.overlay = NULL; | |
232 } | |
233 SDL_Surface* surface = vc.image->getSurface(); | |
234 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags); | |
235 | |
236 // needs to use SDLImage here, since GlImage does not support drawing primitives atm | |
237 SDLImage* img = new SDLImage(overlay_surface); | |
238 | |
239 uint8_t r, g, b, a = 0; | |
240 | |
241 for (unsigned int x = 0; x < img->getWidth(); x ++) { | |
242 for (unsigned int y = 0; y < img->getHeight(); y ++) { | |
243 vc.image->getPixelRGBA(x, y, &r, &g, &b, &a); | |
244 if (a > 0) { | |
245 img->putPixel(x, y, (r + info.r) >> 1, (g + info.g) >> 1, (b + info.b) >> 1); | |
246 } | |
247 } | |
248 } | |
249 | |
250 // In case of OpenGL backend, SDLImage needs to be converted | |
251 info.overlay = m_renderbackend->createImage(img->detachSurface()); | |
252 delete img; | |
253 return info.overlay; | |
254 } | |
255 | |
256 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) { | |
257 OutlineInfo info; | |
258 info.r = r; | |
259 info.g = g; | |
260 info.b = b; | |
261 info.width = width; | |
262 InstanceToOutlines_t& i2h = m_layer_to_outlinemap[instance->getLocation().getLayer()]; | |
263 i2h[instance] = info; | |
264 } | |
265 | |
266 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) { | |
267 ColoringInfo info; | |
268 info.r = r; | |
269 info.g = g; | |
270 info.b = b; | |
271 InstanceToColoring_t& i2h = m_layer_to_coloringmap[instance->getLocation().getLayer()]; | |
272 i2h[instance] = info; | |
273 } | |
274 | |
275 void InstanceRenderer::removeOutlined(Instance* instance) { | |
276 InstanceToOutlines_t& i2h = m_layer_to_outlinemap[instance->getLocation().getLayer()]; | |
277 i2h.erase(instance); | |
278 } | |
279 | |
280 void InstanceRenderer::removeColored(Instance* instance) { | |
281 InstanceToColoring_t& i2h = m_layer_to_coloringmap[instance->getLocation().getLayer()]; | |
282 i2h.erase(instance); | |
283 } | |
284 | |
285 void InstanceRenderer::removeAllOutlines() { | |
286 m_layer_to_outlinemap.clear(); | |
287 } | |
288 | |
289 void InstanceRenderer::removeAllColored() { | |
290 m_layer_to_coloringmap.clear(); | |
291 } | |
292 | |
293 void InstanceRenderer::reset() { | |
294 removeAllOutlines(); | |
295 removeAllColored(); | |
296 } | |
297 | |
298 } |