Mercurial > fife-parpg
comparison engine/core/view/renderers/instancerenderer.cpp @ 571:edc9efe969c2
This commit should fix the coloring overlay bug exposed by the commit in revision 3386. The InstanceRenderer was caching the overlays based on whether the current image had changed. The fix takes into account the current image as well as the overlay color to decide whether or not the overlay needs to be reproduced.
author | vtchill@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Tue, 29 Jun 2010 02:26:28 +0000 |
parents | 7d88eddd2ec7 |
children | da381ecca97d |
comparison
equal
deleted
inserted
replaced
570:0e0a30f0eb20 | 571:edc9efe969c2 |
---|---|
57 InstanceRenderer::OutlineInfo::OutlineInfo(): | 57 InstanceRenderer::OutlineInfo::OutlineInfo(): |
58 r(0), | 58 r(0), |
59 g(0), | 59 g(0), |
60 b(0), | 60 b(0), |
61 width(1), | 61 width(1), |
62 dirty(false), | |
62 outline(NULL), | 63 outline(NULL), |
63 curimg(NULL) { | 64 curimg(NULL) { |
64 } | 65 } |
65 InstanceRenderer::ColoringInfo::ColoringInfo(): | 66 InstanceRenderer::ColoringInfo::ColoringInfo(): |
66 r(0), | 67 r(0), |
67 g(0), | 68 g(0), |
68 b(0), | 69 b(0), |
70 dirty(false), | |
69 overlay(NULL), | 71 overlay(NULL), |
70 curimg(NULL) { | 72 curimg(NULL) { |
71 } | 73 } |
72 | 74 |
73 InstanceRenderer::OutlineInfo::~OutlineInfo() { | 75 InstanceRenderer::OutlineInfo::~OutlineInfo() { |
159 vc.image->render(vc.dimensions, 255-trans); | 161 vc.image->render(vc.dimensions, 255-trans); |
160 } | 162 } |
161 } | 163 } |
162 | 164 |
163 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) { | 165 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) { |
164 if (info.curimg == vc.image) { | 166 if (!info.dirty && info.curimg == vc.image) { |
167 // optimization for outline that has not changed | |
165 return info.outline; | 168 return info.outline; |
166 } else { | 169 } else { |
167 info.curimg = vc.image; | 170 info.curimg = vc.image; |
168 } | 171 } |
169 | 172 |
220 } | 223 } |
221 | 224 |
222 // In case of OpenGL backend, SDLImage needs to be converted | 225 // In case of OpenGL backend, SDLImage needs to be converted |
223 info.outline = m_renderbackend->createImage(img->detachSurface()); | 226 info.outline = m_renderbackend->createImage(img->detachSurface()); |
224 delete img; | 227 delete img; |
228 | |
229 if (info.outline) { | |
230 // mark outline as not dirty since we created it here | |
231 info.dirty = false; | |
232 } | |
233 | |
225 return info.outline; | 234 return info.outline; |
226 } | 235 } |
227 | 236 |
228 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) { | 237 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) { |
229 if (info.curimg == vc.image) { | 238 if (!info.dirty && info.curimg == vc.image) { |
239 // optimization for coloring overlay that has not changed | |
230 return info.overlay; | 240 return info.overlay; |
231 } else { | 241 } |
242 else { | |
232 info.curimg = vc.image; | 243 info.curimg = vc.image; |
233 } | 244 } |
245 | |
234 if (info.overlay) { | 246 if (info.overlay) { |
235 delete info.overlay; // delete old mask | 247 delete info.overlay; // delete old mask |
236 info.overlay = NULL; | 248 info.overlay = NULL; |
237 } | 249 } |
250 | |
238 SDL_Surface* surface = vc.image->getSurface(); | 251 SDL_Surface* surface = vc.image->getSurface(); |
239 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags); | 252 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags); |
240 | 253 |
241 // needs to use SDLImage here, since GlImage does not support drawing primitives atm | 254 // needs to use SDLImage here, since GlImage does not support drawing primitives atm |
242 SDLImage* img = new SDLImage(overlay_surface); | 255 SDLImage* img = new SDLImage(overlay_surface); |
253 } | 266 } |
254 | 267 |
255 // In case of OpenGL backend, SDLImage needs to be converted | 268 // In case of OpenGL backend, SDLImage needs to be converted |
256 info.overlay = m_renderbackend->createImage(img->detachSurface()); | 269 info.overlay = m_renderbackend->createImage(img->detachSurface()); |
257 delete img; | 270 delete img; |
271 | |
272 if (info.overlay) { | |
273 // mark overlay coloring as not dirty since we created it here | |
274 info.dirty = false; | |
275 } | |
276 | |
258 return info.overlay; | 277 return info.overlay; |
259 } | 278 } |
260 | 279 |
261 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) { | 280 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) { |
262 OutlineInfo newinfo; | 281 OutlineInfo newinfo; |
263 newinfo.r = r; | 282 newinfo.r = r; |
264 newinfo.g = g; | 283 newinfo.g = g; |
265 newinfo.b = b; | 284 newinfo.b = b; |
266 newinfo.width = width; | 285 newinfo.width = width; |
286 newinfo.dirty = true; | |
267 | 287 |
268 // attempts to insert the element into the outline map | 288 // attempts to insert the element into the outline map |
269 // will return false in the second value of the pair if the instance already exists | 289 // will return false in the second value of the pair if the instance already exists |
270 // in the map and the first value of the pair will then be an iterator to the | 290 // in the map and the first value of the pair will then be an iterator to the |
271 // existing data for the instance | 291 // existing data for the instance |
272 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo)); | 292 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo)); |
273 | 293 |
274 if (insertiter.second == false) | 294 if (insertiter.second == false) { |
275 { | |
276 // the insertion did not happen because the instance | 295 // the insertion did not happen because the instance |
277 // already exists in the map so lets just update its outline info | 296 // already exists in the map so lets just update its outline info |
278 OutlineInfo& info = insertiter.first->second; | 297 OutlineInfo& info = insertiter.first->second; |
279 info.r = r; | 298 |
280 info.b = b; | 299 if (info.r != r || info.g != g || info.b != b || info.width != width) { |
281 info.g = g; | 300 // only update the outline info if its changed since the last call |
282 info.width = width; | 301 // flag the outline info as dirty so it will get processed during rendering |
302 info.r = r; | |
303 info.b = b; | |
304 info.g = g; | |
305 info.width = width; | |
306 info.dirty = true; | |
307 } | |
283 } | 308 } |
284 } | 309 } |
285 | 310 |
286 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) { | 311 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) { |
287 ColoringInfo newinfo; | 312 ColoringInfo newinfo; |
288 newinfo.r = r; | 313 newinfo.r = r; |
289 newinfo.g = g; | 314 newinfo.g = g; |
290 newinfo.b = b; | 315 newinfo.b = b; |
291 | 316 newinfo.dirty = true; |
317 | |
292 // attempts to insert the element into the coloring map | 318 // attempts to insert the element into the coloring map |
293 // will return false in the second value of the pair if the instance already exists | 319 // will return false in the second value of the pair if the instance already exists |
294 // in the map and the first value of the pair will then be an iterator to the | 320 // in the map and the first value of the pair will then be an iterator to the |
295 // existing data for the instance | 321 // existing data for the instance |
296 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo)); | 322 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo)); |
297 | 323 |
298 if (insertiter.second == false) | 324 if (insertiter.second == false) { |
299 { | |
300 // the insertion did not happen because the instance | 325 // the insertion did not happen because the instance |
301 // already exists in the map so lets just update its coloring info | 326 // already exists in the map so lets just update its coloring info |
302 ColoringInfo& info = insertiter.first->second; | 327 ColoringInfo& info = insertiter.first->second; |
303 info.r = r; | 328 |
304 info.b = b; | 329 if (info.r != r || info.g != g || info.b != b) { |
305 info.g = g; | 330 // only update the coloring info if its changed since the last call |
331 // flag the coloring info as dirty so it will get processed during rendering | |
332 info.r = r; | |
333 info.b = b; | |
334 info.g = g; | |
335 info.dirty = true; | |
336 } | |
306 } | 337 } |
307 } | 338 } |
308 | 339 |
309 void InstanceRenderer::removeOutlined(Instance* instance) { | 340 void InstanceRenderer::removeOutlined(Instance* instance) { |
310 m_instance_outlines.erase(instance); | 341 m_instance_outlines.erase(instance); |