1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 */
22
23 #include "common/rect.h"
24 #include "graphics/surface.h"
25 #include "graphics/transparent_surface.h"
26
27 #include "sludge/allfiles.h"
28 #include "sludge/backdrop.h"
29 #include "sludge/event.h"
30 #include "sludge/fileset.h"
31 #include "sludge/graphics.h"
32 #include "sludge/imgloader.h"
33 #include "sludge/moreio.h"
34 #include "sludge/newfatal.h"
35 #include "sludge/people.h"
36 #include "sludge/sludge.h"
37 #include "sludge/sludger.h"
38 #include "sludge/sprites.h"
39 #include "sludge/zbuffer.h"
40
41 namespace Sludge {
42
43 // This function is only used to kill text font
forgetSpriteBank(SpriteBank & forgetme)44 void GraphicsManager::forgetSpriteBank(SpriteBank &forgetme) {
45 // kill the sprite bank
46 if (forgetme.myPalette.pal) {
47 delete[] forgetme.myPalette.pal;
48 forgetme.myPalette.pal = NULL;
49 delete[] forgetme.myPalette.r;
50 forgetme.myPalette.r = NULL;
51 delete[] forgetme.myPalette.g;
52 forgetme.myPalette.g = NULL;
53 delete[] forgetme.myPalette.b;
54 forgetme.myPalette.b = NULL;
55 }
56
57 if (forgetme.sprites) {
58 for (int i = 0; i < forgetme.total; ++i) {
59 forgetme.sprites[i].surface.free();
60 forgetme.sprites[i].burnSurface.free();
61 }
62
63 delete []forgetme.sprites;
64 forgetme.sprites = NULL;
65 }
66 }
67
reserveSpritePal(SpritePalette & sP,int n)68 bool GraphicsManager::reserveSpritePal(SpritePalette &sP, int n) {
69 if (sP.pal) {
70 delete[] sP.pal;
71 delete[] sP.r;
72 delete[] sP.g;
73 delete[] sP.b;
74 }
75
76 sP.pal = new uint16[n];
77 if (!checkNew(sP.pal))
78 return false;
79
80 sP.r = new byte[n];
81 if (!checkNew(sP.r))
82 return false;
83 sP.g = new byte[n];
84 if (!checkNew(sP.g))
85 return false;
86 sP.b = new byte[n];
87 if (!checkNew(sP.b))
88 return false;
89 sP.total = n;
90 return (bool)(sP.pal != NULL) && (sP.r != NULL) && (sP.g != NULL) && (sP.b != NULL);
91 }
92
loadSpriteBank(int fileNum,SpriteBank & loadhere,bool isFont)93 bool GraphicsManager::loadSpriteBank(int fileNum, SpriteBank &loadhere, bool isFont) {
94
95 int total, spriteBankVersion = 0, howmany = 0, startIndex = 0;
96 byte *data;
97
98 setResourceForFatal(fileNum);
99 if (!g_sludge->_resMan->openFileFromNum(fileNum))
100 return fatal("Can't open sprite bank / font");
101
102 loadhere.isFont = isFont;
103
104 Common::SeekableReadStream *readStream = g_sludge->_resMan->getData();
105 total = readStream->readUint16BE();
106 if (!total) {
107 spriteBankVersion = readStream->readByte();
108 if (spriteBankVersion == 1) {
109 total = 0;
110 } else {
111 total = readStream->readUint16BE();
112 }
113 }
114
115 if (total <= 0)
116 return fatal("No sprites in bank or invalid sprite bank file");
117 if (spriteBankVersion > 3)
118 return fatal("Unsupported sprite bank file format");
119
120 loadhere.total = total;
121 loadhere.sprites = new Sprite[total];
122 if (!checkNew(loadhere.sprites))
123 return false;
124 byte **spriteData = new byte *[total];
125 if (!checkNew(spriteData))
126 return false;
127
128 // version 1, 2, read how many now
129 if (spriteBankVersion && spriteBankVersion < 3) {
130 howmany = readStream->readByte();
131 startIndex = 1;
132 }
133
134 // version 3, sprite is png
135 if (spriteBankVersion == 3) {
136 debugC(2, kSludgeDebugGraphics, "png sprite");
137 for (int i = 0; i < total; i++) {
138 loadhere.sprites[i].xhot = readStream->readSint16LE();
139 loadhere.sprites[i].yhot = readStream->readSint16LE();
140 if (!ImgLoader::loadPNGImage(readStream, &loadhere.sprites[i].surface, false)) {
141 return fatal("fail to read png sprite");
142 }
143 }
144 g_sludge->_resMan->finishAccess();
145 setResourceForFatal(-1);
146 return true;
147 }
148
149 // version 0, 1, 2
150 for (int i = 0; i < total; i++) {
151 uint picwidth, picheight;
152 // load sprite width, height, relative position
153 if (spriteBankVersion == 2) {
154 picwidth = readStream->readUint16BE();
155 picheight = readStream->readUint16BE();
156 loadhere.sprites[i].xhot = readStream->readSint16LE();
157 loadhere.sprites[i].yhot = readStream->readSint16LE();
158 } else {
159 picwidth = (byte)readStream->readByte();
160 picheight = (byte)readStream->readByte();
161 loadhere.sprites[i].xhot = readStream->readByte();
162 loadhere.sprites[i].yhot = readStream->readByte();
163 }
164
165 // init data
166 loadhere.sprites[i].surface.create(picwidth, picheight, *g_sludge->getScreenPixelFormat());
167 if (isFont) {
168 loadhere.sprites[i].burnSurface.create(picwidth, picheight, *g_sludge->getScreenPixelFormat());
169 }
170 data = (byte *)new byte[picwidth * (picheight + 1)];
171 if (!checkNew(data))
172 return false;
173 memset(data + picwidth * picheight, 0, picwidth);
174 spriteData[i] = data;
175
176 // read color
177 if (spriteBankVersion == 2) { // RUN LENGTH COMPRESSED DATA
178 uint size = picwidth * picheight;
179 uint pip = 0;
180
181 while (pip < size) {
182 byte col = readStream->readByte();
183 int looper;
184 if (col > howmany) {
185 col -= howmany + 1;
186 looper = readStream->readByte() + 1;
187 } else
188 looper = 1;
189
190 while (looper--) {
191 data[pip++] = col;
192 }
193 }
194 } else { // RAW DATA
195 uint bytes_read = readStream->read(data, picwidth * picheight);
196 if (bytes_read != picwidth * picheight && readStream->err()) {
197 warning("Reading error in loadSpriteBank.");
198 }
199 }
200 }
201
202 // read howmany for version 0
203 if (!spriteBankVersion) {
204 howmany = readStream->readByte();
205 startIndex = readStream->readByte();
206 }
207
208 // Make palette for version 0, 1, 2
209 if (!reserveSpritePal(loadhere.myPalette, howmany + startIndex))
210 return false;
211 for (int i = 0; i < howmany; i++) {
212 loadhere.myPalette.r[i + startIndex] = (byte)readStream->readByte();
213 loadhere.myPalette.g[i + startIndex] = (byte)readStream->readByte();
214 loadhere.myPalette.b[i + startIndex] = (byte)readStream->readByte();
215 loadhere.myPalette.pal[i + startIndex] =
216 (uint16)g_sludge->getOrigPixelFormat()->RGBToColor(
217 loadhere.myPalette.r[i + startIndex],
218 loadhere.myPalette.g[i + startIndex],
219 loadhere.myPalette.b[i + startIndex]);
220 }
221 loadhere.myPalette.originalRed = loadhere.myPalette.originalGreen = loadhere.myPalette.originalBlue = 255;
222
223 // convert
224 for (int i = 0; i < total; i++) {
225 int fromhere = 0;
226 int transColour = -1;
227 int size = loadhere.sprites[i].surface.w * loadhere.sprites[i].surface.h;
228 while (fromhere < size) {
229 byte s = spriteData[i][fromhere++];
230 if (s) {
231 transColour = s;
232 break;
233 }
234 }
235 fromhere = 0;
236 for (int y = 0; y < loadhere.sprites[i].surface.h; y++) {
237 for (int x = 0; x < loadhere.sprites[i].surface.w; x++) {
238 byte *target = (byte *)loadhere.sprites[i].surface.getBasePtr(x, y);
239 byte s = spriteData[i][fromhere++];
240 if (s) {
241 target[0] = (byte)255;
242 target[1] = (byte)loadhere.myPalette.b[s];
243 target[2] = (byte)loadhere.myPalette.g[s];
244 target[3] = (byte)loadhere.myPalette.r[s];
245 transColour = s;
246 } else if (transColour >= 0) {
247 target[0] = (byte)0;
248 target[1] = (byte)loadhere.myPalette.b[transColour];
249 target[2] = (byte)loadhere.myPalette.g[transColour];
250 target[3] = (byte)loadhere.myPalette.r[transColour];
251 }
252 if (isFont) {
253 target = (byte *)loadhere.sprites[i].burnSurface.getBasePtr(x, y);
254 if (s)
255 target[0] = loadhere.myPalette.r[s];
256 target[1] = (byte)255;
257 target[2] = (byte)255;
258 target[3] = (byte)255;
259 }
260 }
261 }
262 delete[] spriteData[i];
263 }
264 delete[] spriteData;
265 spriteData = NULL;
266
267 g_sludge->_resMan->finishAccess();
268
269 setResourceForFatal(-1);
270
271 return true;
272 }
273
274 // pasteSpriteToBackDrop uses the colour specified by the setPasteColour (or setPasteColor)
pasteSpriteToBackDrop(int x1,int y1,Sprite & single,const SpritePalette & fontPal)275 void GraphicsManager::pasteSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal) {
276 // kill zBuffer
277 if (_zBuffer->originalNum >= 0 && _zBuffer->sprites) {
278 int num = _zBuffer->originalNum;
279 killZBuffer();
280 _zBuffer->originalNum = num;
281 }
282
283 //TODO: shader: useLightTexture
284 x1 -= single.xhot;
285 y1 -= single.yhot;
286 Graphics::TransparentSurface tmp(single.surface, false);
287 tmp.blit(_backdropSurface, x1, y1, Graphics::FLIP_NONE, nullptr,
288 TS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
289 }
290
291 // burnSpriteToBackDrop adds text in the colour specified by setBurnColour
292 // using the differing brightness levels of the font to achieve an anti-aliasing effect.
burnSpriteToBackDrop(int x1,int y1,Sprite & single,const SpritePalette & fontPal)293 void GraphicsManager::burnSpriteToBackDrop(int x1, int y1, Sprite &single, const SpritePalette &fontPal) {
294 // kill zBuffer
295 if (_zBuffer->originalNum >= 0 && _zBuffer->sprites) {
296 int num = _zBuffer->originalNum;
297 killZBuffer();
298 _zBuffer->originalNum = num;
299 }
300
301 //TODO: shader: useLightTexture
302 x1 -= single.xhot;
303 y1 -= single.yhot - 1;
304 Graphics::TransparentSurface tmp(single.surface, false);
305 tmp.blit(_backdropSurface, x1, y1, Graphics::FLIP_NONE, nullptr,
306 TS_RGB(_currentBurnR, _currentBurnG, _currentBurnB));
307 }
308
fontSprite(bool flip,int x,int y,Sprite & single,const SpritePalette & fontPal)309 void GraphicsManager::fontSprite(bool flip, int x, int y, Sprite &single, const SpritePalette &fontPal) {
310 float x1 = (float)x - (float)single.xhot / _cameraZoom;
311 float y1 = (float)y - (float)single.yhot / _cameraZoom;
312
313 // Use Transparent surface to scale and blit
314 Graphics::TransparentSurface tmp(single.surface, false);
315 tmp.blit(_renderSurface, x1, y1, (flip ? Graphics::FLIP_H : Graphics::FLIP_NONE), 0, TS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
316
317 if (single.burnSurface.getPixels() != nullptr) {
318 Graphics::TransparentSurface tmp2(single.burnSurface, false);
319 tmp2.blit(_renderSurface, x1, y1, (flip ? Graphics::FLIP_H : Graphics::FLIP_NONE), 0, TS_RGB(fontPal.originalRed, fontPal.originalGreen, fontPal.originalBlue));
320
321 }
322 }
323
fontSprite(int x,int y,Sprite & single,const SpritePalette & fontPal)324 void GraphicsManager::fontSprite(int x, int y, Sprite &single, const SpritePalette &fontPal) {
325 fontSprite(false, x, y, single, fontPal);
326 }
327
flipFontSprite(int x,int y,Sprite & single,const SpritePalette & fontPal)328 void GraphicsManager::flipFontSprite(int x, int y, Sprite &single, const SpritePalette &fontPal) {
329 fontSprite(true, x, y, single, fontPal);
330 }
331
duplicateSurface(Graphics::Surface * surface)332 Graphics::Surface *GraphicsManager::duplicateSurface(Graphics::Surface *surface) {
333 Graphics::Surface *res = new Graphics::Surface();
334 res->copyFrom(*surface);
335 return res;
336 }
337
blendColor(Graphics::Surface * blitted,uint32 color,Graphics::TSpriteBlendMode mode)338 void GraphicsManager::blendColor(Graphics::Surface *blitted, uint32 color, Graphics::TSpriteBlendMode mode) {
339 Graphics::TransparentSurface tmp;
340 tmp.create(blitted->w, blitted->h, blitted->format);
341 tmp.fillRect(Common::Rect(0, 0, tmp.w, tmp.h), color);
342 tmp.blit(*blitted, 0, 0, Graphics::FLIP_NONE, nullptr, TS_ARGB(255, 255, 255, 255), blitted->w, blitted->h, mode);
343 tmp.free();
344 }
345
applyLightmapToSprite(Graphics::Surface * & blitted,OnScreenPerson * thisPerson,bool mirror,int x,int y,int x1,int y1,int diffX,int diffY)346 Graphics::Surface *GraphicsManager::applyLightmapToSprite(Graphics::Surface *&blitted, OnScreenPerson *thisPerson, bool mirror, int x, int y, int x1, int y1, int diffX, int diffY) {
347 Graphics::Surface * toDetele = nullptr;
348
349 // if light map is used
350 bool light = !(thisPerson->extra & EXTRA_NOLITE);
351
352 // apply light map and set light map color
353 byte curLight[3];
354 if (light && _lightMap.getPixels()) {
355 if (_lightMapMode == LIGHTMAPMODE_HOTSPOT) {
356 int lx = x + _cameraX;
357 int ly = y + _cameraY;
358 if (lx < 0 || ly < 0 || lx >= (int)_sceneWidth || ly >= (int)_sceneHeight) {
359 curLight[0] = curLight[1] = curLight[2] = 255;
360 } else {
361 byte *target = (byte *)_lightMap.getBasePtr(lx, ly);
362 curLight[0] = target[3];
363 curLight[1] = target[2];
364 curLight[2] = target[1];
365 }
366 } else if (_lightMapMode == LIGHTMAPMODE_PIXEL) {
367 curLight[0] = curLight[1] = curLight[2] = 255;
368
369 toDetele = blitted = duplicateSurface(blitted);
370
371 // apply light map texture
372 Graphics::TransparentSurface tmp(_lightMap, false);
373 Common::Rect rect_none(x1, y1, x1 + diffX, y1 + diffY);
374 Common::Rect rect_h(_sceneWidth - x1 - diffX, y1, _sceneWidth - x1, y1 + diffY);
375 tmp.blit(*blitted, 0, 0,
376 (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE),
377 (mirror ? &rect_h : &rect_none),
378 TS_ARGB(255, 255, 255, 255),
379 blitted->w, blitted->h, Graphics::BLEND_MULTIPLY);
380 }
381 } else {
382 curLight[0] = curLight[1] = curLight[2] = 255;
383 }
384
385 // calculate light map color
386 float fr, fg, fb;
387 fr = fg = fb = 0.0F;
388 if (thisPerson->colourmix) {
389 fr = curLight[0]*thisPerson->r * thisPerson->colourmix / 65025 / 255.0F;
390 fg = curLight[1]*thisPerson->g * thisPerson->colourmix / 65025 / 255.0F;
391 fb = curLight[2]*thisPerson->b * thisPerson->colourmix / 65025 / 255.0F;
392 }
393
394 uint32 primaryColor = TS_ARGB((uint8)(255 - thisPerson->transparency),
395 (uint8)(fr + curLight[0] * (255 - thisPerson->colourmix) / 255.f),
396 (uint8)(fg + curLight[1] * (255 - thisPerson->colourmix) / 255.f),
397 (uint8)(fb + curLight[2] * (255 - thisPerson->colourmix) / 255.f));
398
399 uint32 secondaryColor = TS_ARGB(0, (uint8)(fr * 255), (uint8)(fg * 255), (uint8)(fb * 255));
400
401 // apply primary color
402 if (primaryColor != (uint32)TS_ARGB(255, 255, 255, 255)) {
403 if (!toDetele) {
404 toDetele = blitted = duplicateSurface(blitted);
405 blendColor(blitted, primaryColor, Graphics::BLEND_MULTIPLY);
406 }
407 }
408
409 // apply secondary light map color
410 if (secondaryColor != 0x0) {
411 if (!toDetele) {
412 toDetele = blitted = duplicateSurface(blitted);
413 }
414 blendColor(blitted, secondaryColor, Graphics::BLEND_ADDITIVE);
415 }
416 return toDetele;
417 }
418
scaleSprite(Sprite & single,const SpritePalette & fontPal,OnScreenPerson * thisPerson,bool mirror)419 bool GraphicsManager::scaleSprite(Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, bool mirror) {
420 float x = thisPerson->x;
421 float y = thisPerson->y;
422
423 float scale = thisPerson->scale;
424 bool useZB = !(thisPerson->extra & EXTRA_NOZB);
425
426 if (scale <= 0.05)
427 return false;
428
429 int diffX = (int)(((float)single.surface.w) * scale);
430 int diffY = (int)(((float)single.surface.h) * scale);
431
432 float x1, y1, x2, y2;
433
434 if (thisPerson->extra & EXTRA_FIXTOSCREEN) {
435 x = x / _cameraZoom;
436 y = y / _cameraZoom;
437 if (single.xhot < 0)
438 x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale / _cameraZoom);
439 else
440 x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale / _cameraZoom);
441 y1 = y - (int)((single.yhot - thisPerson->floaty) * scale / _cameraZoom);
442 x2 = x1 + (int)(diffX / _cameraZoom);
443 y2 = y1 + (int)(diffY / _cameraZoom);
444 } else {
445 x -= _cameraX;
446 y -= _cameraY;
447 if (single.xhot < 0)
448 x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale);
449 else
450 x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale);
451 y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
452 x2 = x1 + diffX;
453 y2 = y1 + diffY;
454 }
455
456 Graphics::Surface *blitted = &single.surface;
457 Graphics::Surface *ptr = applyLightmapToSprite(blitted, thisPerson, mirror, x, y, x1, y1, diffX, diffY);
458
459 // Use Transparent surface to scale and blit
460 if (!_zBuffer->numPanels) {
461 Graphics::TransparentSurface tmp(*blitted, false);
462 tmp.blit(_renderSurface, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, TS_ARGB(255, 255, 255, 255), diffX, diffY);
463 if (ptr) {
464 ptr->free();
465 delete ptr;
466 ptr = nullptr;
467 }
468 } else {
469 int d = useZB ? y + _cameraY : (y + _cameraY > _sceneHeight * 0.6 ? _sceneHeight + 1 : 0);
470 addSpriteDepth(blitted, d, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), diffX, diffY, ptr);
471 }
472
473 // Are we pointing at the sprite?
474 if (_vm->_evtMan->mouseX() >= x1 && _vm->_evtMan->mouseX() <= x2
475 && _vm->_evtMan->mouseY() >= y1 && _vm->_evtMan->mouseY() <= y2) {
476 if (thisPerson->extra & EXTRA_RECTANGULAR)
477 return true;
478
479 // check if point to non transparent part
480 int pixelx = (int)(single.surface.w * (_vm->_evtMan->mouseX() - x1) / (x2 - x1));
481 int pixely = (int)(single.surface.h * (_vm->_evtMan->mouseY() - y1) / (y2 - y1));
482 uint32 *colorPtr = (uint32 *)single.surface.getBasePtr(pixelx, pixely);
483
484 uint8 a, r, g, b;
485 g_sludge->getScreenPixelFormat()->colorToARGB(*colorPtr, a, r, g, b);
486 return a != 0;
487 }
488 return false;
489 }
490
resetSpriteLayers(ZBufferData * pz,int x,int y,bool upsidedown)491 void GraphicsManager::resetSpriteLayers(ZBufferData *pz, int x, int y, bool upsidedown) {
492 if (_spriteLayers->numLayers > 0)
493 killSpriteLayers();
494 _spriteLayers->numLayers = pz->numPanels;
495 debugC(3, kSludgeDebugZBuffer, "%i zBuffer layers", _spriteLayers->numLayers);
496 for (int i = 0; i < _spriteLayers->numLayers; ++i) {
497 SpriteDisplay *node = new SpriteDisplay(x, y, (upsidedown ? Graphics::FLIP_V : Graphics::FLIP_NONE), &pz->sprites[i], pz->sprites[i].w, pz->sprites[i].h);
498 _spriteLayers->layer[i].push_back(node);
499 debugC(3, kSludgeDebugZBuffer, "Layer %i is of depth %i", i, pz->panel[i]);
500 }
501 }
502
addSpriteDepth(Graphics::Surface * ptr,int depth,int x,int y,Graphics::FLIP_FLAGS flip,int width,int height,bool freeAfterUse)503 void GraphicsManager::addSpriteDepth(Graphics::Surface *ptr, int depth, int x, int y, Graphics::FLIP_FLAGS flip, int width, int height, bool freeAfterUse) {
504 int i;
505 for (i = 1; i < _zBuffer->numPanels; ++i) {
506 if (_zBuffer->panel[i] >= depth) {
507 break;
508 }
509 }
510 --i;
511 debugC(3, kSludgeDebugZBuffer, "Add sprite of Y-value : %i in layer %i", depth, i);
512
513 SpriteDisplay *node = new SpriteDisplay(x, y, flip, ptr, width, height, freeAfterUse);
514 _spriteLayers->layer[i].push_back(node);
515 }
516
displaySpriteLayers()517 void GraphicsManager::displaySpriteLayers() {
518 for (int i = 0; i < _spriteLayers->numLayers; ++i) {
519 debugC(3, kSludgeDebugGraphics, "Display layer %i with %i sprites", i, _spriteLayers->layer[i].size());
520 SpriteLayer::iterator it;
521 for (it = _spriteLayers->layer[i].begin(); it != _spriteLayers->layer[i].end(); ++it) {
522 Graphics::TransparentSurface tmp(*(*it)->surface, false);
523 tmp.blit(_renderSurface, (*it)->x, (*it)->y, (*it)->flip, nullptr, TS_ARGB(255, 255, 255, 255), (*it)->width, (*it)->height);
524 }
525 }
526 killSpriteLayers();
527 }
528
killSpriteLayers()529 void GraphicsManager::killSpriteLayers() {
530 for (int i = 0; i < _spriteLayers->numLayers; ++i) {
531 SpriteLayer::iterator it;
532 for (it = _spriteLayers->layer[i].begin(); it != _spriteLayers->layer[i].end(); ++it) {
533 if ((*it)->freeAfterUse) {
534 (*it)->surface->free();
535 delete (*it)->surface;
536 (*it)->surface = nullptr;
537 }
538 delete (*it);
539 (*it) = nullptr;
540 }
541 _spriteLayers->layer[i].clear();
542 }
543 _spriteLayers->numLayers = 0;
544 }
545
546 // Paste a scaled sprite onto the backdrop
fixScaleSprite(int x,int y,Sprite & single,const SpritePalette & fontPal,OnScreenPerson * thisPerson,int camX,int camY,bool mirror)547 void GraphicsManager::fixScaleSprite(int x, int y, Sprite &single, const SpritePalette &fontPal, OnScreenPerson *thisPerson, int camX, int camY, bool mirror) {
548
549 float scale = thisPerson->scale;
550 bool useZB = !(thisPerson->extra & EXTRA_NOZB);
551
552 if (scale <= 0.05)
553 return;
554
555 int diffX = (int)(((float)single.surface.w) * scale);
556 int diffY = (int)(((float)single.surface.h) * scale);
557 int x1;
558 if (single.xhot < 0)
559 x1 = x - (int)((mirror ? (float)(single.surface.w - single.xhot) : (float)(single.xhot + 1)) * scale);
560 else
561 x1 = x - (int)((mirror ? (float)(single.surface.w - (single.xhot + 1)) : (float)single.xhot) * scale);
562 int y1 = y - (int)((single.yhot - thisPerson->floaty) * scale);
563
564 Graphics::Surface *blitted = &single.surface;
565 Graphics::Surface *ptr = applyLightmapToSprite(blitted, thisPerson, mirror, x, y, x1, y1, diffX, diffY);
566
567 // draw backdrop
568 drawBackDrop();
569
570 // draw zBuffer
571 if (_zBuffer->numPanels) {
572 drawZBuffer((int)(x1 + camX), (int)(y1 + camY), false);
573 }
574
575 // draw sprite
576 if (!_zBuffer->numPanels) {
577 Graphics::TransparentSurface tmp(single.surface, false);
578 tmp.blit(_renderSurface, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), nullptr, TS_ARGB(255, 255, 255, 255), diffX, diffY);
579 if (ptr) {
580 ptr->free();
581 delete ptr;
582 ptr = nullptr;
583 }
584 } else {
585 int d = useZB ? y + _cameraY : (y + _cameraY > _sceneHeight * 0.6 ? _sceneHeight + 1 : 0);
586 addSpriteDepth(&single.surface, d, x1, y1, (mirror ? Graphics::FLIP_H : Graphics::FLIP_NONE), diffX, diffY, ptr);
587 }
588
589 // draw all
590 displaySpriteLayers();
591
592 // copy screen to backdrop
593 _backdropSurface.copyFrom(_renderSurface);
594 }
595
596 } // End of namespace Sludge
597