| 1 | #include "map_renderer.h" |
| 2 | |
| 3 | #include <base/log.h> |
| 4 | |
| 5 | #include <game/map/envelope_manager.h> |
| 6 | |
| 7 | const int LAYER_DEFAULT_TILESET = -1; |
| 8 | |
| 9 | void CMapRenderer::Clear() |
| 10 | { |
| 11 | for(auto &pLayer : m_vpRenderLayers) |
| 12 | pLayer->Unload(); |
| 13 | m_vpRenderLayers.clear(); |
| 14 | } |
| 15 | |
| 16 | void 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 | |
| 142 | void 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 | |
| 176 | int 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 | |