diff --git a/CMakeLists.txt b/CMakeLists.txt index a084257ab..883634bd5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2304,6 +2304,8 @@ if(CLIENT) editor_trackers.h editor_ui.h explanations.cpp + layer_selector.cpp + layer_selector.h map_grid.cpp map_grid.h map_view.cpp diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp index 4fa8dfc18..a9e89e2dd 100644 --- a/src/game/editor/editor.cpp +++ b/src/game/editor/editor.cpp @@ -3849,7 +3849,7 @@ void CEditor::RenderLayers(CUIRect LayersBox) } static bool s_ScrollToSelectionNext = false; - const bool ScrollToSelection = SelectLayerByTile() || s_ScrollToSelectionNext; + const bool ScrollToSelection = LayerSelector()->SelectByTile() || s_ScrollToSelectionNext; s_ScrollToSelectionNext = false; // render layers @@ -4386,69 +4386,6 @@ void CEditor::RenderLayers(CUIRect LayersBox) } } -bool CEditor::SelectLayerByTile() -{ - // ctrl+rightclick a map index to select the layer that has a tile there - static int s_Selected = 0; - int MatchedGroup = -1; - int MatchedLayer = -1; - int Matches = 0; - bool IsFound = false; - if(Input()->ModifierIsPressed() && UI()->HotItem() == &m_MapEditorId && UI()->MouseButtonClicked(1)) - { - for(size_t g = 0; g < m_Map.m_vpGroups.size(); g++) - { - for(size_t l = 0; l < m_Map.m_vpGroups[g]->m_vpLayers.size(); l++) - { - if(IsFound) - continue; - if(m_Map.m_vpGroups[g]->m_vpLayers[l]->m_Type != LAYERTYPE_TILES) - continue; - - std::shared_ptr pTiles = std::static_pointer_cast(m_Map.m_vpGroups[g]->m_vpLayers[l]); - - float aMapping[4]; - m_Map.m_vpGroups[g]->Mapping(aMapping); - int x = aMapping[0] + (aMapping[2] - aMapping[0]) / 2; - int y = aMapping[1] + (aMapping[3] - aMapping[1]) / 2; - x += UI()->MouseWorldX() - (MapView()->GetWorldOffset().x * m_Map.m_vpGroups[g]->m_ParallaxX / 100) - m_Map.m_vpGroups[g]->m_OffsetX; - y += UI()->MouseWorldY() - (MapView()->GetWorldOffset().y * m_Map.m_vpGroups[g]->m_ParallaxY / 100) - m_Map.m_vpGroups[g]->m_OffsetY; - x /= 32; - y /= 32; - - if(x < 0 || x >= pTiles->m_Width) - continue; - if(y < 0 || y >= pTiles->m_Height) - continue; - CTile Tile = pTiles->GetTile(x, y); - if(Tile.m_Index) - { - if(MatchedGroup == -1) - { - MatchedGroup = g; - MatchedLayer = l; - } - if(++Matches > s_Selected) - { - s_Selected++; - MatchedGroup = g; - MatchedLayer = l; - IsFound = true; - } - } - } - } - if(MatchedGroup != -1 && MatchedLayer != -1) - { - if(!IsFound) - s_Selected = 1; - SelectLayer(MatchedLayer, MatchedGroup); - return true; - } - } - return false; -} - bool CEditor::ReplaceImage(const char *pFileName, int StorageType, bool CheckDuplicate) { // check if we have that image already @@ -8424,6 +8361,7 @@ void CEditor::Init() m_vComponents.emplace_back(m_MapView); m_vComponents.emplace_back(m_MapSettingsBackend); + m_vComponents.emplace_back(m_LayerSelector); for(CEditorComponent &Component : m_vComponents) Component.Init(this); @@ -8530,6 +8468,56 @@ void CEditor::HandleCursorMovement() m_MouseWorldNoParaX = aPoints[0] + WorldWidth * (s_MouseX / Graphics()->WindowWidth()); m_MouseWorldNoParaY = aPoints[1] + WorldHeight * (s_MouseY / Graphics()->WindowHeight()); } + + OnMouseMove(s_MouseX, s_MouseY); +} + +void CEditor::OnMouseMove(float MouseX, float MouseY) +{ + m_vHoverTiles.clear(); + for(size_t g = 0; g < m_Map.m_vpGroups.size(); g++) + { + const std::shared_ptr pGroup = m_Map.m_vpGroups[g]; + for(size_t l = 0; l < pGroup->m_vpLayers.size(); l++) + { + const std::shared_ptr pLayer = pGroup->m_vpLayers[l]; + int LayerType = pLayer->m_Type; + if(LayerType != LAYERTYPE_TILES && + LayerType != LAYERTYPE_FRONT && + LayerType != LAYERTYPE_TELE && + LayerType != LAYERTYPE_SPEEDUP && + LayerType != LAYERTYPE_SWITCH && + LayerType != LAYERTYPE_TUNE) + continue; + + std::shared_ptr pTiles = std::static_pointer_cast(pLayer); + pGroup->MapScreen(); + float aPoints[4]; + pGroup->Mapping(aPoints); + float WorldWidth = aPoints[2] - aPoints[0]; + float WorldHeight = aPoints[3] - aPoints[1]; + CUIRect Rect; + Rect.x = aPoints[0] + WorldWidth * (MouseX / Graphics()->WindowWidth()); + Rect.y = aPoints[1] + WorldHeight * (MouseY / Graphics()->WindowHeight()); + Rect.w = 0; + Rect.h = 0; + RECTi r; + pTiles->Convert(Rect, &r); + pTiles->Clamp(&r); + int x = r.x; + int y = r.y; + + if(x < 0 || x >= pTiles->m_Width) + continue; + if(y < 0 || y >= pTiles->m_Height) + continue; + CTile Tile = pTiles->GetTile(x, y); + if(Tile.m_Index) + m_vHoverTiles.emplace_back(CHoverTile( + g, l, x, y, Tile)); + } + } + UI()->MapScreen(); } void CEditor::DispatchInputEvents() diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h index 17bbb192c..fe8761265 100644 --- a/src/game/editor/editor.h +++ b/src/game/editor/editor.h @@ -36,6 +36,7 @@ #include "editor_server_settings.h" #include "editor_trackers.h" #include "editor_ui.h" +#include "layer_selector.h" #include "map_view.h" #include "smooth_value.h" @@ -277,6 +278,7 @@ class CEditor : public IEditor std::vector> m_vComponents; CMapView m_MapView; + CLayerSelector m_LayerSelector; bool m_EditorWasUsedBefore = false; @@ -316,6 +318,7 @@ public: CMapView *MapView() { return &m_MapView; } const CMapView *MapView() const { return &m_MapView; } + CLayerSelector *LayerSelector() { return &m_LayerSelector; } CEditor() : m_ZoomEnvelopeX(1.0f, 0.1f, 600.0f), @@ -426,6 +429,27 @@ public: m_BrushDrawDestructive = true; } + class CHoverTile + { + public: + CHoverTile(int Group, int Layer, int x, int y, const CTile Tile) : + m_Group(Group), + m_Layer(Layer), + m_X(x), + m_Y(y), + m_Tile(Tile) + { + } + + int m_Group; + int m_Layer; + int m_X; + int m_Y; + const CTile m_Tile; + }; + std::vector m_vHoverTiles; + const std::vector &HoverTiles() const { return m_vHoverTiles; } + void Init() override; void OnUpdate() override; void OnRender() override; @@ -440,6 +464,7 @@ public: void ResetIngameMoved() override { m_IngameMoved = false; } void HandleCursorMovement(); + void OnMouseMove(float MouseX, float MouseY); void DispatchInputEvents(); void HandleAutosave(); bool PerformAutosave(); @@ -995,7 +1020,6 @@ public: void SelectGameLayer(); std::vector SortImages(); - bool SelectLayerByTile(); void DoAudioPreview(CUIRect View, const void *pPlayPauseButtonID, const void *pStopButtonID, const void *pSeekBarID, const int SampleID); diff --git a/src/game/editor/layer_selector.cpp b/src/game/editor/layer_selector.cpp new file mode 100644 index 000000000..9b4d50c17 --- /dev/null +++ b/src/game/editor/layer_selector.cpp @@ -0,0 +1,48 @@ +#include "editor.h" + +#include "layer_selector.h" + +void CLayerSelector::Init(CEditor *pEditor) +{ + CEditorComponent::Init(pEditor); + + m_SelectionOffset = 0; +} + +bool CLayerSelector::SelectByTile() +{ + // ctrl+rightclick a map index to select the layer that has a tile there + if(UI()->HotItem() != &Editor()->m_MapEditorId) + return false; + if(!Input()->ModifierIsPressed() || !UI()->MouseButtonClicked(1)) + return false; + + int MatchedGroup = -1; + int MatchedLayer = -1; + int Matches = 0; + bool IsFound = false; + for(auto HoverTile : Editor()->HoverTiles()) + { + if(MatchedGroup == -1) + { + MatchedGroup = HoverTile.m_Group; + MatchedLayer = HoverTile.m_Layer; + } + if(++Matches > m_SelectionOffset) + { + m_SelectionOffset++; + MatchedGroup = HoverTile.m_Group; + MatchedLayer = HoverTile.m_Layer; + IsFound = true; + break; + } + } + if(MatchedGroup != -1 && MatchedLayer != -1) + { + if(!IsFound) + m_SelectionOffset = 1; + Editor()->SelectLayer(MatchedLayer, MatchedGroup); + return true; + } + return false; +} diff --git a/src/game/editor/layer_selector.h b/src/game/editor/layer_selector.h new file mode 100644 index 000000000..93d6ed97c --- /dev/null +++ b/src/game/editor/layer_selector.h @@ -0,0 +1,15 @@ +#ifndef GAME_EDITOR_LAYER_SELECTOR_H +#define GAME_EDITOR_LAYER_SELECTOR_H + +#include "component.h" + +class CLayerSelector : public CEditorComponent +{ + int m_SelectionOffset; + +public: + void Init(CEditor *pEditor) override; + bool SelectByTile(); +}; + +#endif