| 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 | |
| 8 | const int LAYER_DEFAULT_TILESET = -1; |
| 9 | |
| 10 | void CMapRenderer::Clear() |
| 11 | { |
| 12 | for(auto &pLayer : m_vpRenderLayers) |
| 13 | pLayer->Unload(); |
| 14 | m_vpRenderLayers.clear(); |
| 15 | } |
| 16 | |
| 17 | void 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 | |
| 143 | void 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 | |
| 177 | int 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 | |