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 "ags/engine/ac/walk_behind.h"
24 #include "ags/shared/ac/common.h"
25 #include "ags/shared/ac/common_defines.h"
26 #include "ags/engine/ac/game_state.h"
27 #include "ags/engine/gfx/graphics_driver.h"
28 #include "ags/shared/gfx/bitmap.h"
29 #include "ags/globals.h"
30
31 namespace AGS3 {
32
33 using namespace AGS::Shared;
34 using namespace AGS::Engine;
35
update_walk_behind_images()36 void update_walk_behind_images() {
37 int ee, rr;
38 int bpp = (_GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth() + 7) / 8;
39 Bitmap *wbbmp;
40 for (ee = 1; ee < MAX_WALK_BEHINDS; ee++) {
41 update_polled_stuff_if_runtime();
42
43 if (_G(walkBehindRight)[ee] > 0) {
44 wbbmp = BitmapHelper::CreateTransparentBitmap(
45 (_G(walkBehindRight)[ee] - _G(walkBehindLeft)[ee]) + 1,
46 (_G(walkBehindBottom)[ee] - _G(walkBehindTop)[ee]) + 1,
47 _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth());
48 int yy, startX = _G(walkBehindLeft)[ee], startY = _G(walkBehindTop)[ee];
49 for (rr = startX; rr <= _G(walkBehindRight)[ee]; rr++) {
50 for (yy = startY; yy <= _G(walkBehindBottom)[ee]; yy++) {
51 if (_GP(thisroom).WalkBehindMask->GetScanLine(yy)[rr] == ee) {
52 for (int ii = 0; ii < bpp; ii++)
53 wbbmp->GetScanLineForWriting(yy - startY)[(rr - startX) * bpp + ii] = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetScanLine(yy)[rr * bpp + ii];
54 }
55 }
56 }
57
58 update_polled_stuff_if_runtime();
59
60 if (_G(walkBehindBitmap)[ee] != nullptr) {
61 _G(gfxDriver)->DestroyDDB(_G(walkBehindBitmap)[ee]);
62 }
63 _G(walkBehindBitmap)[ee] = _G(gfxDriver)->CreateDDBFromBitmap(wbbmp, false);
64 delete wbbmp;
65 }
66 }
67
68 _G(walkBehindsCachedForBgNum) = _GP(play).bg_frame;
69 }
70
71
recache_walk_behinds()72 void recache_walk_behinds() {
73 if (_G(walkBehindExists)) {
74 free(_G(walkBehindExists));
75 free(_G(walkBehindStartY));
76 free(_G(walkBehindEndY));
77 }
78
79 _G(walkBehindExists) = (char *)malloc(_GP(thisroom).WalkBehindMask->GetWidth());
80 _G(walkBehindStartY) = (int *)malloc(_GP(thisroom).WalkBehindMask->GetWidth() * sizeof(int));
81 _G(walkBehindEndY) = (int *)malloc(_GP(thisroom).WalkBehindMask->GetWidth() * sizeof(int));
82 _G(noWalkBehindsAtAll) = 1;
83
84 int ee, rr, tmm;
85 const int NO_WALK_BEHIND = 100000;
86 for (ee = 0; ee < MAX_WALK_BEHINDS; ee++) {
87 _G(walkBehindLeft)[ee] = NO_WALK_BEHIND;
88 _G(walkBehindTop)[ee] = NO_WALK_BEHIND;
89 _G(walkBehindRight)[ee] = 0;
90 _G(walkBehindBottom)[ee] = 0;
91
92 if (_G(walkBehindBitmap)[ee] != nullptr) {
93 _G(gfxDriver)->DestroyDDB(_G(walkBehindBitmap)[ee]);
94 _G(walkBehindBitmap)[ee] = nullptr;
95 }
96 }
97
98 update_polled_stuff_if_runtime();
99
100 for (ee = 0; ee < _GP(thisroom).WalkBehindMask->GetWidth(); ee++) {
101 _G(walkBehindExists)[ee] = 0;
102 for (rr = 0; rr < _GP(thisroom).WalkBehindMask->GetHeight(); rr++) {
103 tmm = _GP(thisroom).WalkBehindMask->GetScanLine(rr)[ee];
104 //tmm = _getpixel(_GP(thisroom).WalkBehindMask,ee,rr);
105 if ((tmm >= 1) && (tmm < MAX_WALK_BEHINDS)) {
106 if (!_G(walkBehindExists)[ee]) {
107 _G(walkBehindStartY)[ee] = rr;
108 _G(walkBehindExists)[ee] = tmm;
109 _G(noWalkBehindsAtAll) = 0;
110 }
111 _G(walkBehindEndY)[ee] = rr + 1; // +1 to allow bottom line of screen to work
112
113 if (ee < _G(walkBehindLeft)[tmm]) _G(walkBehindLeft)[tmm] = ee;
114 if (rr < _G(walkBehindTop)[tmm]) _G(walkBehindTop)[tmm] = rr;
115 if (ee > _G(walkBehindRight)[tmm]) _G(walkBehindRight)[tmm] = ee;
116 if (rr > _G(walkBehindBottom)[tmm]) _G(walkBehindBottom)[tmm] = rr;
117 }
118 }
119 }
120
121 if (_G(walkBehindMethod) == DrawAsSeparateSprite) {
122 update_walk_behind_images();
123 }
124 }
125
126 } // namespace AGS3
127