1#include "map_renderer.h"
2
3#include <base/log.h>
4
5#include <game/map/envelope_manager.h>
6
7const int LAYER_DEFAULT_TILESET = -1;
8
9void CMapRenderer::Clear()
10{
11 for(auto &pLayer : m_vpRenderLayers)
12 pLayer->Unload();
13 m_vpRenderLayers.clear();
14}
15
16void CMapRenderer::Load(ERenderType Type, CLayers *pLayers, IMapImages *pMapImages, IEnvelopeEval *pEnvelopeEval, std::optional<FRenderUploadCallback> RenderCallbackOptional)
17{
18 Clear();
19
20 std::shared_ptr<CEnvelopeManager> pEnvelopeManager = std::make_shared<CEnvelopeManager>(args&: pEnvelopeEval, args: pLayers->Map());
21 bool PassedGameLayer = false;
22
23 for(int GroupId = 0; GroupId < pLayers->NumGroups(); GroupId++)
24 {
25 CMapItemGroup *pGroup = pLayers->GetGroup(Index: GroupId);
26 std::unique_ptr<CRenderLayer> pRenderLayerGroup = std::make_unique<CRenderLayerGroup>(args&: GroupId, args&: pGroup);
27 pRenderLayerGroup->OnInit(pGraphics: Graphics(), pTextRender: TextRender(), pRenderMap: RenderMap(), pEnvelopeManager, pMap: pLayers->Map(), pMapImages, FRenderUploadCallbackOptional&: RenderCallbackOptional);
28 if(!pRenderLayerGroup->IsValid())
29 {
30 log_error("map_renderer", "error group was null, group number = %d, total groups = %d", GroupId, pLayers->NumGroups());
31 log_error("map_renderer", "this is here to prevent a crash but the source of this is unknown, please report this for it to get fixed");
32 log_error("map_renderer", "we need mapname and crc and the map that caused this if possible, and anymore info you think is relevant");
33 continue;
34 }
35
36 for(int LayerId = 0; LayerId < pGroup->m_NumLayers; LayerId++)
37 {
38 CMapItemLayer *pLayer = pLayers->GetLayer(Index: pGroup->m_StartLayer + LayerId);
39 int LayerType = GetLayerType(pLayer, pLayers);
40 PassedGameLayer |= LayerType == LAYER_GAME;
41
42 if(Type == ERenderType::RENDERTYPE_BACKGROUND_FORCE || Type == ERenderType::RENDERTYPE_BACKGROUND)
43 {
44 if(PassedGameLayer)
45 return;
46 }
47 else if(Type == ERenderType::RENDERTYPE_FOREGROUND)
48 {
49 if(!PassedGameLayer)
50 continue;
51 }
52
53 if(pRenderLayerGroup)
54 m_vpRenderLayers.push_back(x: std::move(pRenderLayerGroup));
55
56 std::unique_ptr<CRenderLayer> pRenderLayer;
57
58 if(pLayer->m_Type == LAYERTYPE_TILES)
59 {
60 CMapItemLayerTilemap *pTileLayer = (CMapItemLayerTilemap *)pLayer;
61
62 switch(LayerType)
63 {
64 case LAYER_DEFAULT_TILESET:
65 pRenderLayer = std::make_unique<CRenderLayerTile>(
66 args&: GroupId,
67 args&: LayerId,
68 args&: pLayer->m_Flags,
69 args&: pTileLayer);
70 break;
71 case LAYER_GAME:
72 pRenderLayer = std::make_unique<CRenderLayerEntityGame>(
73 args&: GroupId,
74 args&: LayerId,
75 args&: pLayer->m_Flags,
76 args&: pTileLayer);
77 break;
78 case LAYER_FRONT:
79 pRenderLayer = std::make_unique<CRenderLayerEntityFront>(
80 args&: GroupId,
81 args&: LayerId,
82 args&: pLayer->m_Flags,
83 args&: pTileLayer);
84 break;
85 case LAYER_TELE:
86 pRenderLayer = std::make_unique<CRenderLayerEntityTele>(
87 args&: GroupId,
88 args&: LayerId,
89 args&: pLayer->m_Flags,
90 args&: pTileLayer);
91 break;
92 case LAYER_SPEEDUP:
93 pRenderLayer = std::make_unique<CRenderLayerEntitySpeedup>(
94 args&: GroupId,
95 args&: LayerId,
96 args&: pLayer->m_Flags,
97 args&: pTileLayer);
98 break;
99 case LAYER_SWITCH:
100 pRenderLayer = std::make_unique<CRenderLayerEntitySwitch>(
101 args&: GroupId,
102 args&: LayerId,
103 args&: pLayer->m_Flags,
104 args&: pTileLayer);
105 break;
106 case LAYER_TUNE:
107 pRenderLayer = std::make_unique<CRenderLayerEntityTune>(
108 args&: GroupId,
109 args&: LayerId,
110 args&: pLayer->m_Flags,
111 args&: pTileLayer);
112 break;
113 default:
114 dbg_assert_failed("Unknown LayerType %d", LayerType);
115 }
116 }
117 else if(pLayer->m_Type == LAYERTYPE_QUADS)
118 {
119 CMapItemLayerQuads *pQLayer = (CMapItemLayerQuads *)pLayer;
120
121 pRenderLayer = std::make_unique<CRenderLayerQuads>(
122 args&: GroupId,
123 args&: LayerId,
124 args&: pLayer->m_Flags,
125 args&: pQLayer);
126 }
127
128 // just ignore invalid layers from rendering
129 if(pRenderLayer)
130 {
131 pRenderLayer->OnInit(pGraphics: Graphics(), pTextRender: TextRender(), pRenderMap: RenderMap(), pEnvelopeManager, pMap: pLayers->Map(), pMapImages, FRenderUploadCallbackOptional&: RenderCallbackOptional);
132 if(pRenderLayer->IsValid())
133 {
134 pRenderLayer->Init();
135 m_vpRenderLayers.push_back(x: std::move(pRenderLayer));
136 }
137 }
138 }
139 }
140}
141
142void CMapRenderer::Render(const CRenderLayerParams &Params)
143{
144 float ScreenXLeft, ScreenYTop, ScreenXRight, ScreenYBottom;
145 Graphics()->GetScreen(pTopLeftX: &ScreenXLeft, pTopLeftY: &ScreenYTop, pBottomRightX: &ScreenXRight, pBottomRightY: &ScreenYBottom);
146
147 bool DoRenderGroup = true;
148 for(auto &pRenderLayer : m_vpRenderLayers)
149 {
150 if(pRenderLayer->IsGroup())
151 DoRenderGroup = pRenderLayer->DoRender(Params);
152
153 if(!DoRenderGroup)
154 continue;
155
156 if(pRenderLayer->DoRender(Params))
157 pRenderLayer->Render(Params);
158 }
159
160 // Reset clip from last group
161 Graphics()->ClipDisable();
162
163 // don't reset screen on background
164 if(Params.m_RenderType != ERenderType::RENDERTYPE_BACKGROUND && Params.m_RenderType != ERenderType::RENDERTYPE_BACKGROUND_FORCE)
165 {
166 // reset the screen like it was before
167 Graphics()->MapScreen(TopLeftX: ScreenXLeft, TopLeftY: ScreenYTop, BottomRightX: ScreenXRight, BottomRightY: ScreenYBottom);
168 }
169 else
170 {
171 // reset the screen to the default interface
172 Graphics()->MapScreenToInterface(CenterX: Params.m_Center.x, CenterY: Params.m_Center.y, Zoom: Params.m_Zoom);
173 }
174}
175
176int CMapRenderer::GetLayerType(const CMapItemLayer *pLayer, const CLayers *pLayers) const
177{
178 if(pLayer == (CMapItemLayer *)pLayers->GameLayer())
179 return LAYER_GAME;
180 else if(pLayer == (CMapItemLayer *)pLayers->FrontLayer())
181 return LAYER_FRONT;
182 else if(pLayer == (CMapItemLayer *)pLayers->SwitchLayer())
183 return LAYER_SWITCH;
184 else if(pLayer == (CMapItemLayer *)pLayers->TeleLayer())
185 return LAYER_TELE;
186 else if(pLayer == (CMapItemLayer *)pLayers->SpeedupLayer())
187 return LAYER_SPEEDUP;
188 else if(pLayer == (CMapItemLayer *)pLayers->TuneLayer())
189 return LAYER_TUNE;
190 return LAYER_DEFAULT_TILESET;
191}
192