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