mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 17:48:19 +00:00
Merge pull request #8618 from ChillerDragon/pr_editor_prompt
Add ctrl+p editor prompt (quick actions)
This commit is contained in:
commit
36f0bcc509
|
@ -2500,8 +2500,13 @@ if(CLIENT)
|
||||||
mapitems/sound.cpp
|
mapitems/sound.cpp
|
||||||
mapitems/sound.h
|
mapitems/sound.h
|
||||||
popups.cpp
|
popups.cpp
|
||||||
|
prompt.cpp
|
||||||
|
prompt.h
|
||||||
proof_mode.cpp
|
proof_mode.cpp
|
||||||
proof_mode.h
|
proof_mode.h
|
||||||
|
quick_action.h
|
||||||
|
quick_actions.cpp
|
||||||
|
quick_actions.h
|
||||||
smooth_value.cpp
|
smooth_value.cpp
|
||||||
smooth_value.h
|
smooth_value.h
|
||||||
tileart.cpp
|
tileart.cpp
|
||||||
|
|
|
@ -1074,11 +1074,9 @@ void CEditor::DoToolbarLayers(CUIRect ToolBar)
|
||||||
|
|
||||||
// proof button
|
// proof button
|
||||||
TB_Top.VSplitLeft(40.0f, &Button, &TB_Top);
|
TB_Top.VSplitLeft(40.0f, &Button, &TB_Top);
|
||||||
static int s_ProofButton = 0;
|
if(DoButton_Ex(&m_QuickActionProof, m_QuickActionProof.Label(), m_QuickActionProof.Active(), &Button, 0, m_QuickActionProof.Description(), IGraphics::CORNER_L))
|
||||||
if(DoButton_Ex(&s_ProofButton, "Proof", MapView()->ProofMode()->IsEnabled(), &Button, 0, "[ctrl+p] Toggles proof borders. These borders represent the area that a player can see with default zoom.", IGraphics::CORNER_L) ||
|
|
||||||
(m_Dialog == DIALOG_NONE && CLineInput::GetActiveInput() == nullptr && Input()->KeyPress(KEY_P) && ModPressed))
|
|
||||||
{
|
{
|
||||||
MapView()->ProofMode()->Toggle();
|
m_QuickActionProof.Call();
|
||||||
}
|
}
|
||||||
|
|
||||||
TB_Top.VSplitLeft(14.0f, &Button, &TB_Top);
|
TB_Top.VSplitLeft(14.0f, &Button, &TB_Top);
|
||||||
|
@ -1254,10 +1252,9 @@ void CEditor::DoToolbarLayers(CUIRect ToolBar)
|
||||||
// refocus button
|
// refocus button
|
||||||
{
|
{
|
||||||
TB_Bottom.VSplitLeft(50.0f, &Button, &TB_Bottom);
|
TB_Bottom.VSplitLeft(50.0f, &Button, &TB_Bottom);
|
||||||
static int s_RefocusButton = 0;
|
|
||||||
int FocusButtonChecked = MapView()->IsFocused() ? -1 : 1;
|
int FocusButtonChecked = MapView()->IsFocused() ? -1 : 1;
|
||||||
if(DoButton_Editor(&s_RefocusButton, "Refocus", FocusButtonChecked, &Button, 0, "[HOME] Restore map focus") || (m_Dialog == DIALOG_NONE && CLineInput::GetActiveInput() == nullptr && Input()->KeyPress(KEY_HOME)))
|
if(DoButton_Editor(&m_QuickActionRefocus, m_QuickActionRefocus.Label(), FocusButtonChecked, &Button, 0, m_QuickActionRefocus.Description()) || (m_Dialog == DIALOG_NONE && CLineInput::GetActiveInput() == nullptr && Input()->KeyPress(KEY_HOME)))
|
||||||
MapView()->Focus();
|
m_QuickActionRefocus.Call();
|
||||||
TB_Bottom.VSplitLeft(5.0f, nullptr, &TB_Bottom);
|
TB_Bottom.VSplitLeft(5.0f, nullptr, &TB_Bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4302,12 +4299,9 @@ void CEditor::RenderLayers(CUIRect LayersBox)
|
||||||
if(s_ScrollRegion.AddRect(AddGroupButton))
|
if(s_ScrollRegion.AddRect(AddGroupButton))
|
||||||
{
|
{
|
||||||
AddGroupButton.HSplitTop(RowHeight, &AddGroupButton, 0);
|
AddGroupButton.HSplitTop(RowHeight, &AddGroupButton, 0);
|
||||||
static int s_AddGroupButton = 0;
|
if(DoButton_Editor(&m_QuickActionAddGroup, m_QuickActionAddGroup.Label(), 0, &AddGroupButton, IGraphics::CORNER_R, m_QuickActionAddGroup.Description()))
|
||||||
if(DoButton_Editor(&s_AddGroupButton, "Add group", 0, &AddGroupButton, IGraphics::CORNER_R, "Adds a new group"))
|
|
||||||
{
|
{
|
||||||
m_Map.NewGroup();
|
m_QuickActionAddGroup.Call();
|
||||||
m_SelectedGroup = m_Map.m_vpGroups.size() - 1;
|
|
||||||
m_EditorHistory.RecordAction(std::make_shared<CEditorActionGroup>(this, m_SelectedGroup, false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4806,8 +4800,8 @@ void CEditor::RenderImagesList(CUIRect ToolBox)
|
||||||
{
|
{
|
||||||
AddImageButton.HSplitTop(5.0f, nullptr, &AddImageButton);
|
AddImageButton.HSplitTop(5.0f, nullptr, &AddImageButton);
|
||||||
AddImageButton.HSplitTop(RowHeight, &AddImageButton, nullptr);
|
AddImageButton.HSplitTop(RowHeight, &AddImageButton, nullptr);
|
||||||
if(DoButton_Editor(&s_AddImageButton, "Add", 0, &AddImageButton, 0, "Load a new image to use in the map"))
|
if(DoButton_Editor(&s_AddImageButton, m_QuickActionAddImage.Label(), 0, &AddImageButton, 0, m_QuickActionAddImage.Description()))
|
||||||
InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Add Image", "Add", "mapres", false, AddImage, this);
|
m_QuickActionAddImage.Call();
|
||||||
}
|
}
|
||||||
s_ScrollRegion.End();
|
s_ScrollRegion.End();
|
||||||
}
|
}
|
||||||
|
@ -5750,9 +5744,9 @@ void CEditor::RenderStatusbar(CUIRect View, CUIRect *pTooltipRect)
|
||||||
CUIRect Button;
|
CUIRect Button;
|
||||||
View.VSplitRight(100.0f, &View, &Button);
|
View.VSplitRight(100.0f, &View, &Button);
|
||||||
static int s_EnvelopeButton = 0;
|
static int s_EnvelopeButton = 0;
|
||||||
if(DoButton_Editor(&s_EnvelopeButton, "Envelopes", ButtonsDisabled ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES, &Button, 0, "Toggles the envelope editor.") == 1)
|
if(DoButton_Editor(&s_EnvelopeButton, m_QuickActionEnvelopes.Label(), m_QuickActionEnvelopes.Color(), &Button, 0, m_QuickActionEnvelopes.Description()) == 1)
|
||||||
{
|
{
|
||||||
m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES ? EXTRAEDITOR_NONE : EXTRAEDITOR_ENVELOPES;
|
m_QuickActionEnvelopes.Call();
|
||||||
}
|
}
|
||||||
|
|
||||||
View.VSplitRight(10.0f, &View, nullptr);
|
View.VSplitRight(10.0f, &View, nullptr);
|
||||||
|
@ -7919,7 +7913,7 @@ void CEditor::Render()
|
||||||
InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", true, CallbackSaveCopyMap, this);
|
InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", true, CallbackSaveCopyMap, this);
|
||||||
// ctrl+shift+s to save as
|
// ctrl+shift+s to save as
|
||||||
else if(Input()->KeyPress(KEY_S) && ModPressed && ShiftPressed)
|
else if(Input()->KeyPress(KEY_S) && ModPressed && ShiftPressed)
|
||||||
InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", true, CallbackSaveMap, this);
|
m_QuickActionSaveAs.Call();
|
||||||
// ctrl+s to save
|
// ctrl+s to save
|
||||||
else if(Input()->KeyPress(KEY_S) && ModPressed)
|
else if(Input()->KeyPress(KEY_S) && ModPressed)
|
||||||
{
|
{
|
||||||
|
@ -8362,6 +8356,7 @@ void CEditor::Init()
|
||||||
m_vComponents.emplace_back(m_MapView);
|
m_vComponents.emplace_back(m_MapView);
|
||||||
m_vComponents.emplace_back(m_MapSettingsBackend);
|
m_vComponents.emplace_back(m_MapSettingsBackend);
|
||||||
m_vComponents.emplace_back(m_LayerSelector);
|
m_vComponents.emplace_back(m_LayerSelector);
|
||||||
|
m_vComponents.emplace_back(m_Prompt);
|
||||||
for(CEditorComponent &Component : m_vComponents)
|
for(CEditorComponent &Component : m_vComponents)
|
||||||
Component.OnInit(this);
|
Component.OnInit(this);
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include "layer_selector.h"
|
#include "layer_selector.h"
|
||||||
#include "map_view.h"
|
#include "map_view.h"
|
||||||
#include "smooth_value.h"
|
#include "smooth_value.h"
|
||||||
|
#include <game/editor/prompt.h>
|
||||||
|
#include <game/editor/quick_action.h>
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -60,7 +62,8 @@ enum
|
||||||
|
|
||||||
DIALOG_NONE = 0,
|
DIALOG_NONE = 0,
|
||||||
DIALOG_FILE,
|
DIALOG_FILE,
|
||||||
DIALOG_MAPSETTINGS_ERROR
|
DIALOG_MAPSETTINGS_ERROR,
|
||||||
|
DIALOG_QUICK_PROMPT,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CEditorImage;
|
class CEditorImage;
|
||||||
|
@ -278,6 +281,7 @@ class CEditor : public IEditor
|
||||||
std::vector<std::reference_wrapper<CEditorComponent>> m_vComponents;
|
std::vector<std::reference_wrapper<CEditorComponent>> m_vComponents;
|
||||||
CMapView m_MapView;
|
CMapView m_MapView;
|
||||||
CLayerSelector m_LayerSelector;
|
CLayerSelector m_LayerSelector;
|
||||||
|
CPrompt m_Prompt;
|
||||||
|
|
||||||
bool m_EditorWasUsedBefore = false;
|
bool m_EditorWasUsedBefore = false;
|
||||||
|
|
||||||
|
@ -319,7 +323,18 @@ public:
|
||||||
const CMapView *MapView() const { return &m_MapView; }
|
const CMapView *MapView() const { return &m_MapView; }
|
||||||
CLayerSelector *LayerSelector() { return &m_LayerSelector; }
|
CLayerSelector *LayerSelector() { return &m_LayerSelector; }
|
||||||
|
|
||||||
|
void AddGroup();
|
||||||
|
void AddTileLayer();
|
||||||
|
void LayerSelectImage();
|
||||||
|
bool IsNonGameTileLayerSelected() const;
|
||||||
|
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description) CQuickAction m_QuickAction##name;
|
||||||
|
#include <game/editor/quick_actions.h>
|
||||||
|
#undef REGISTER_QUICK_ACTION
|
||||||
|
|
||||||
CEditor() :
|
CEditor() :
|
||||||
|
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description) m_QuickAction##name(text, description, callback, disabled, active, button_color),
|
||||||
|
#include <game/editor/quick_actions.h>
|
||||||
|
#undef REGISTER_QUICK_ACTION
|
||||||
m_ZoomEnvelopeX(1.0f, 0.1f, 600.0f),
|
m_ZoomEnvelopeX(1.0f, 0.1f, 600.0f),
|
||||||
m_ZoomEnvelopeY(640.0f, 0.1f, 32000.0f),
|
m_ZoomEnvelopeY(640.0f, 0.1f, 32000.0f),
|
||||||
m_MapSettingsCommandContext(m_MapSettingsBackend.NewContext(&m_SettingsCommandInput))
|
m_MapSettingsCommandContext(m_MapSettingsBackend.NewContext(&m_SettingsCommandInput))
|
||||||
|
|
|
@ -107,9 +107,9 @@ CUi::EPopupMenuFunctionResult CEditor::PopupMenuFile(void *pContext, CUIRect Vie
|
||||||
|
|
||||||
View.HSplitTop(2.0f, nullptr, &View);
|
View.HSplitTop(2.0f, nullptr, &View);
|
||||||
View.HSplitTop(12.0f, &Slot, &View);
|
View.HSplitTop(12.0f, &Slot, &View);
|
||||||
if(pEditor->DoButton_MenuItem(&s_SaveAsButton, "Save As", 0, &Slot, 0, "Saves the current map under a new name (ctrl+shift+s)"))
|
if(pEditor->DoButton_MenuItem(&s_SaveAsButton, pEditor->m_QuickActionSaveAs.Label(), 0, &Slot, 0, pEditor->m_QuickActionSaveAs.Description()))
|
||||||
{
|
{
|
||||||
pEditor->InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save", "maps", true, CEditor::CallbackSaveMap, pEditor);
|
pEditor->m_QuickActionSaveAs.Call();
|
||||||
return CUi::POPUP_CLOSE_CURRENT;
|
return CUi::POPUP_CLOSE_CURRENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,16 +578,9 @@ CUi::EPopupMenuFunctionResult CEditor::PopupGroup(void *pContext, CUIRect View,
|
||||||
// new tile layer
|
// new tile layer
|
||||||
View.HSplitBottom(5.0f, &View, nullptr);
|
View.HSplitBottom(5.0f, &View, nullptr);
|
||||||
View.HSplitBottom(12.0f, &View, &Button);
|
View.HSplitBottom(12.0f, &View, &Button);
|
||||||
static int s_NewTileLayerButton = 0;
|
if(pEditor->DoButton_Editor(&pEditor->m_QuickActionAddTileLayer, pEditor->m_QuickActionAddTileLayer.Label(), 0, &Button, 0, pEditor->m_QuickActionAddTileLayer.Description()))
|
||||||
if(pEditor->DoButton_Editor(&s_NewTileLayerButton, "Add tile layer", 0, &Button, 0, "Creates a new tile layer"))
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<CLayer> pTileLayer = std::make_shared<CLayerTiles>(pEditor, pEditor->m_Map.m_pGameLayer->m_Width, pEditor->m_Map.m_pGameLayer->m_Height);
|
pEditor->m_QuickActionAddTileLayer.Call();
|
||||||
pTileLayer->m_pEditor = pEditor;
|
|
||||||
pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->AddLayer(pTileLayer);
|
|
||||||
int LayerIndex = pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->m_vpLayers.size() - 1;
|
|
||||||
pEditor->SelectLayer(LayerIndex);
|
|
||||||
pEditor->m_Map.m_vpGroups[pEditor->m_SelectedGroup]->m_Collapse = false;
|
|
||||||
pEditor->m_EditorHistory.RecordAction(std::make_shared<CEditorActionAddLayer>(pEditor, pEditor->m_SelectedGroup, LayerIndex));
|
|
||||||
return CUi::POPUP_CLOSE_CURRENT;
|
return CUi::POPUP_CLOSE_CURRENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
169
src/game/editor/prompt.cpp
Normal file
169
src/game/editor/prompt.cpp
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
#include <engine/keys.h>
|
||||||
|
#include <game/client/ui_listbox.h>
|
||||||
|
#include <game/editor/quick_action.h>
|
||||||
|
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
|
#include "prompt.h"
|
||||||
|
|
||||||
|
bool FuzzyMatch(const char *pHaystack, const char *pNeedle)
|
||||||
|
{
|
||||||
|
if(!pNeedle || !pNeedle[0])
|
||||||
|
return false;
|
||||||
|
char aBuf[2] = {0};
|
||||||
|
const char *pHit = pHaystack;
|
||||||
|
int NeedleLen = str_length(pNeedle);
|
||||||
|
for(int i = 0; i < NeedleLen; i++)
|
||||||
|
{
|
||||||
|
if(!pHit)
|
||||||
|
return false;
|
||||||
|
aBuf[0] = pNeedle[i];
|
||||||
|
pHit = str_find_nocase(pHit, aBuf);
|
||||||
|
if(pHit)
|
||||||
|
pHit++;
|
||||||
|
}
|
||||||
|
return pHit;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPrompt::IsActive()
|
||||||
|
{
|
||||||
|
return CEditorComponent::IsActive() || Editor()->m_Dialog == DIALOG_QUICK_PROMPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrompt::SetActive()
|
||||||
|
{
|
||||||
|
Editor()->m_Dialog = DIALOG_QUICK_PROMPT;
|
||||||
|
CEditorComponent::SetActive();
|
||||||
|
|
||||||
|
Ui()->SetActiveItem(&m_PromptInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrompt::SetInactive()
|
||||||
|
{
|
||||||
|
m_ResetFilterResults = true;
|
||||||
|
m_PromptInput.Clear();
|
||||||
|
if(Editor()->m_Dialog == DIALOG_QUICK_PROMPT)
|
||||||
|
Editor()->m_Dialog = DIALOG_NONE;
|
||||||
|
CEditorComponent::SetInactive();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CPrompt::OnInput(const IInput::CEvent &Event)
|
||||||
|
{
|
||||||
|
if(Input()->ModifierIsPressed() && Input()->KeyIsPressed(KEY_P))
|
||||||
|
{
|
||||||
|
SetActive();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrompt::OnInit(CEditor *pEditor)
|
||||||
|
{
|
||||||
|
CEditorComponent::OnInit(pEditor);
|
||||||
|
|
||||||
|
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description) m_vQuickActions.emplace_back(&Editor()->m_QuickAction##name);
|
||||||
|
#include <game/editor/quick_actions.h>
|
||||||
|
#undef REGISTER_QUICK_ACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPrompt::OnRender(CUIRect _)
|
||||||
|
{
|
||||||
|
if(!IsActive())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(Ui()->ConsumeHotkey(CUi::HOTKEY_ESCAPE))
|
||||||
|
{
|
||||||
|
SetInactive();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CListBox s_ListBox;
|
||||||
|
CUIRect Prompt, PromptBox;
|
||||||
|
CUIRect Suggestions;
|
||||||
|
|
||||||
|
Ui()->MapScreen();
|
||||||
|
CUIRect Overlay = *Ui()->Screen();
|
||||||
|
|
||||||
|
Overlay.Draw(ColorRGBA(0, 0, 0, 0.33f), IGraphics::CORNER_NONE, 0.0f);
|
||||||
|
CUIRect Background;
|
||||||
|
Overlay.VMargin(150.0f, &Background);
|
||||||
|
Background.HMargin(50.0f, &Background);
|
||||||
|
Background.Draw(ColorRGBA(0, 0, 0, 0.80f), IGraphics::CORNER_ALL, 5.0f);
|
||||||
|
|
||||||
|
Background.Margin(10.0f, &Prompt);
|
||||||
|
|
||||||
|
Prompt.VSplitMid(nullptr, &PromptBox);
|
||||||
|
|
||||||
|
Prompt.HSplitTop(16.0f, &PromptBox, &Suggestions);
|
||||||
|
PromptBox.Draw(ColorRGBA(0, 0, 0, 0.75f), IGraphics::CORNER_ALL, 2.0f);
|
||||||
|
Suggestions.y += 6.0f;
|
||||||
|
|
||||||
|
if(Ui()->DoClearableEditBox(&m_PromptInput, &PromptBox, 10.0f) || m_ResetFilterResults)
|
||||||
|
{
|
||||||
|
m_PromptSelectedIndex = 0;
|
||||||
|
m_vpFilteredPromptList.clear();
|
||||||
|
if(m_ResetFilterResults && m_pLastAction)
|
||||||
|
{
|
||||||
|
m_vpFilteredPromptList.push_back(m_pLastAction);
|
||||||
|
}
|
||||||
|
for(auto *pQuickAction : m_vQuickActions)
|
||||||
|
{
|
||||||
|
if(pQuickAction->Disabled())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(m_PromptInput.IsEmpty() || FuzzyMatch(pQuickAction->Label(), m_PromptInput.GetString()))
|
||||||
|
{
|
||||||
|
bool Skip = false;
|
||||||
|
if(m_ResetFilterResults)
|
||||||
|
if(pQuickAction == m_pLastAction)
|
||||||
|
Skip = true;
|
||||||
|
if(!Skip)
|
||||||
|
m_vpFilteredPromptList.push_back(pQuickAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_ResetFilterResults = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_ListBox.SetActive(!Ui()->IsPopupOpen());
|
||||||
|
s_ListBox.DoStart(15.0f, m_vpFilteredPromptList.size(), 1, 5, m_PromptSelectedIndex, &Suggestions, false);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < m_vpFilteredPromptList.size(); i++)
|
||||||
|
{
|
||||||
|
const CListboxItem Item = s_ListBox.DoNextItem(m_vpFilteredPromptList[i], m_PromptSelectedIndex >= 0 && (size_t)m_PromptSelectedIndex == i);
|
||||||
|
if(!Item.m_Visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CUIRect LabelColumn, DescColumn;
|
||||||
|
Item.m_Rect.VSplitLeft(5.0f, nullptr, &LabelColumn);
|
||||||
|
LabelColumn.VSplitLeft(100.0f, &LabelColumn, &DescColumn);
|
||||||
|
LabelColumn.VSplitRight(5.0f, &LabelColumn, nullptr);
|
||||||
|
|
||||||
|
SLabelProperties Props;
|
||||||
|
Props.m_MaxWidth = LabelColumn.w;
|
||||||
|
Props.m_EllipsisAtEnd = true;
|
||||||
|
Ui()->DoLabel(&LabelColumn, m_vpFilteredPromptList[i]->Label(), 10.0f, TEXTALIGN_ML, Props);
|
||||||
|
|
||||||
|
Props.m_MaxWidth = DescColumn.w;
|
||||||
|
ColorRGBA DescColor = TextRender()->DefaultTextColor();
|
||||||
|
DescColor.a = Item.m_Selected ? 1.0f : 0.8f;
|
||||||
|
TextRender()->TextColor(DescColor);
|
||||||
|
Ui()->DoLabel(&DescColumn, m_vpFilteredPromptList[i]->Description(), 10.0f, TEXTALIGN_MR, Props);
|
||||||
|
TextRender()->TextColor(TextRender()->DefaultTextColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
const int NewSelected = s_ListBox.DoEnd();
|
||||||
|
if(m_PromptSelectedIndex != NewSelected)
|
||||||
|
{
|
||||||
|
m_PromptSelectedIndex = NewSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(s_ListBox.WasItemActivated())
|
||||||
|
{
|
||||||
|
if(m_PromptSelectedIndex >= 0)
|
||||||
|
{
|
||||||
|
const CQuickAction *pBtn = m_vpFilteredPromptList[m_PromptSelectedIndex];
|
||||||
|
SetInactive();
|
||||||
|
pBtn->Call();
|
||||||
|
m_pLastAction = pBtn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
src/game/editor/prompt.h
Normal file
29
src/game/editor/prompt.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef GAME_EDITOR_PROMPT_H
|
||||||
|
#define GAME_EDITOR_PROMPT_H
|
||||||
|
|
||||||
|
#include <game/client/lineinput.h>
|
||||||
|
#include <game/client/ui_rect.h>
|
||||||
|
#include <game/editor/quick_action.h>
|
||||||
|
|
||||||
|
#include "component.h"
|
||||||
|
|
||||||
|
class CPrompt : public CEditorComponent
|
||||||
|
{
|
||||||
|
bool m_ResetFilterResults = true;
|
||||||
|
const CQuickAction *m_pLastAction = nullptr;
|
||||||
|
int m_PromptSelectedIndex = -1;
|
||||||
|
|
||||||
|
std::vector<const CQuickAction *> m_vpFilteredPromptList;
|
||||||
|
std::vector<CQuickAction *> m_vQuickActions;
|
||||||
|
CLineInputBuffered<512> m_PromptInput;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void OnInit(CEditor *pEditor) override;
|
||||||
|
bool OnInput(const IInput::CEvent &Event) override;
|
||||||
|
void OnRender(CUIRect _) override;
|
||||||
|
bool IsActive();
|
||||||
|
void SetActive();
|
||||||
|
void SetInactive();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
58
src/game/editor/quick_action.h
Normal file
58
src/game/editor/quick_action.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
#ifndef GAME_EDITOR_QUICK_ACTION_H
|
||||||
|
#define GAME_EDITOR_QUICK_ACTION_H
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
typedef std::function<void()> FButtonClickCallback;
|
||||||
|
typedef std::function<bool()> FButtonDisabledCallback;
|
||||||
|
typedef std::function<bool()> FButtonActiveCallback;
|
||||||
|
typedef std::function<int()> FButtonColorCallback;
|
||||||
|
|
||||||
|
class CQuickAction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const char *m_pLabel;
|
||||||
|
const char *m_pDescription;
|
||||||
|
|
||||||
|
FButtonClickCallback m_pfnCallback;
|
||||||
|
FButtonDisabledCallback m_pfnDisabledCallback;
|
||||||
|
FButtonActiveCallback m_pfnActiveCallback;
|
||||||
|
FButtonColorCallback m_pfnColorCallback;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CQuickAction(
|
||||||
|
const char *pLabel,
|
||||||
|
const char *pDescription,
|
||||||
|
FButtonClickCallback pfnCallback,
|
||||||
|
FButtonDisabledCallback pfnDisabledCallback,
|
||||||
|
FButtonActiveCallback pfnActiveCallback,
|
||||||
|
FButtonColorCallback pfnColorCallback) :
|
||||||
|
m_pLabel(pLabel),
|
||||||
|
m_pDescription(pDescription),
|
||||||
|
m_pfnCallback(std::move(pfnCallback)),
|
||||||
|
m_pfnDisabledCallback(std::move(pfnDisabledCallback)),
|
||||||
|
m_pfnActiveCallback(std::move(pfnActiveCallback)),
|
||||||
|
m_pfnColorCallback(std::move(pfnColorCallback))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// code to run when the action is triggered
|
||||||
|
void Call() const { m_pfnCallback(); }
|
||||||
|
|
||||||
|
// bool that indicates if the action can be performed not or not
|
||||||
|
bool Disabled() { return m_pfnDisabledCallback(); }
|
||||||
|
|
||||||
|
// bool that indicates if the action is currently running
|
||||||
|
// only applies to actions that can be turned on or off like proof borders
|
||||||
|
bool Active() { return m_pfnActiveCallback(); }
|
||||||
|
|
||||||
|
// color "enum" that represents the state of the quick actions button
|
||||||
|
// used as Checked argument for DoButton_Editor()
|
||||||
|
int Color() { return m_pfnColorCallback(); }
|
||||||
|
|
||||||
|
const char *Label() const { return m_pLabel; }
|
||||||
|
const char *Description() const { return m_pDescription; }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
55
src/game/editor/quick_actions.cpp
Normal file
55
src/game/editor/quick_actions.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#include <game/mapitems.h>
|
||||||
|
|
||||||
|
#include "editor.h"
|
||||||
|
|
||||||
|
#include "editor_actions.h"
|
||||||
|
|
||||||
|
void CEditor::AddGroup()
|
||||||
|
{
|
||||||
|
m_Map.NewGroup();
|
||||||
|
m_SelectedGroup = m_Map.m_vpGroups.size() - 1;
|
||||||
|
m_EditorHistory.RecordAction(std::make_shared<CEditorActionGroup>(this, m_SelectedGroup, false));
|
||||||
|
}
|
||||||
|
void CEditor::AddTileLayer()
|
||||||
|
{
|
||||||
|
std::shared_ptr<CLayer> pTileLayer = std::make_shared<CLayerTiles>(this, m_Map.m_pGameLayer->m_Width, m_Map.m_pGameLayer->m_Height);
|
||||||
|
pTileLayer->m_pEditor = this;
|
||||||
|
m_Map.m_vpGroups[m_SelectedGroup]->AddLayer(pTileLayer);
|
||||||
|
int LayerIndex = m_Map.m_vpGroups[m_SelectedGroup]->m_vpLayers.size() - 1;
|
||||||
|
SelectLayer(LayerIndex);
|
||||||
|
m_Map.m_vpGroups[m_SelectedGroup]->m_Collapse = false;
|
||||||
|
m_EditorHistory.RecordAction(std::make_shared<CEditorActionAddLayer>(this, m_SelectedGroup, LayerIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CEditor::IsNonGameTileLayerSelected() const
|
||||||
|
{
|
||||||
|
std::shared_ptr<CLayer> pLayer = GetSelectedLayer(0);
|
||||||
|
if(!pLayer)
|
||||||
|
return false;
|
||||||
|
if(pLayer->m_Type != LAYERTYPE_TILES)
|
||||||
|
return false;
|
||||||
|
if(
|
||||||
|
pLayer == m_Map.m_pGameLayer ||
|
||||||
|
pLayer == m_Map.m_pFrontLayer ||
|
||||||
|
pLayer == m_Map.m_pSwitchLayer ||
|
||||||
|
pLayer == m_Map.m_pTeleLayer ||
|
||||||
|
pLayer == m_Map.m_pSpeedupLayer ||
|
||||||
|
pLayer == m_Map.m_pTuneLayer)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CEditor::LayerSelectImage()
|
||||||
|
{
|
||||||
|
if(!IsNonGameTileLayerSelected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::shared_ptr<CLayer> pLayer = GetSelectedLayer(0);
|
||||||
|
std::shared_ptr<CLayerTiles> pTiles = std::static_pointer_cast<CLayerTiles>(pLayer);
|
||||||
|
|
||||||
|
static SLayerPopupContext s_LayerPopupContext = {};
|
||||||
|
s_LayerPopupContext.m_pEditor = this;
|
||||||
|
Ui()->DoPopupMenu(&s_LayerPopupContext, Ui()->MouseX(), Ui()->MouseY(), 120, 270, &s_LayerPopupContext, PopupLayer);
|
||||||
|
PopupSelectImageInvoke(pTiles->m_Image, Ui()->MouseX(), Ui()->MouseY());
|
||||||
|
}
|
58
src/game/editor/quick_actions.h
Normal file
58
src/game/editor/quick_actions.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// This file can be included several times.
|
||||||
|
|
||||||
|
#ifndef REGISTER_QUICK_ACTION
|
||||||
|
#define REGISTER_QUICK_ACTION(name, text, callback, disabled, active, button_color, description)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALWAYS_FALSE []() -> bool { return false; }
|
||||||
|
#define DEFAULT_BTN []() -> int { return -1; }
|
||||||
|
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
AddGroup, "Add group", [&]() { AddGroup(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Adds a new group")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
Refocus, "Refocus", [&]() { MapView()->Focus(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "[HOME] Restore map focus")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
Proof,
|
||||||
|
"Proof",
|
||||||
|
[&]() { MapView()->ProofMode()->Toggle(); },
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
[&]() -> bool { return MapView()->ProofMode()->IsEnabled(); },
|
||||||
|
DEFAULT_BTN,
|
||||||
|
"Toggles proof borders. These borders represent the area that a player can see with default zoom.")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
AddTileLayer, "Add tile layer", [&]() { AddTileLayer(); }, ALWAYS_FALSE, ALWAYS_FALSE, DEFAULT_BTN, "Creates a new tile layer.")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
SaveAs,
|
||||||
|
"Save As",
|
||||||
|
[&]() { InvokeFileDialog(IStorage::TYPE_SAVE, FILETYPE_MAP, "Save map", "Save As", "maps", true, CEditor::CallbackSaveMap, this); },
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
DEFAULT_BTN,
|
||||||
|
"Saves the current map under a new name (ctrl+shift+s)")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
Envelopes,
|
||||||
|
"Envelopes",
|
||||||
|
[&]() { m_ActiveExtraEditor = m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES ? EXTRAEDITOR_NONE : EXTRAEDITOR_ENVELOPES; },
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
[&]() -> int { return m_ShowPicker ? -1 : m_ActiveExtraEditor == EXTRAEDITOR_ENVELOPES; },
|
||||||
|
"Toggles the envelope editor.")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
AddImage,
|
||||||
|
"Add Image",
|
||||||
|
[&]() { InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Add Image", "Add", "mapres", false, AddImage, this); },
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
DEFAULT_BTN,
|
||||||
|
"Load a new image to use in the map")
|
||||||
|
REGISTER_QUICK_ACTION(
|
||||||
|
LayerPropAddImage,
|
||||||
|
"Layer: Add Image",
|
||||||
|
[&]() { LayerSelectImage(); },
|
||||||
|
[&]() -> bool { return !IsNonGameTileLayerSelected(); },
|
||||||
|
ALWAYS_FALSE,
|
||||||
|
DEFAULT_BTN,
|
||||||
|
"Pick mapres image for currently selected layer")
|
||||||
|
|
||||||
|
#undef ALWAYS_FALSE
|
||||||
|
#undef DEFAULT_BTN
|
Loading…
Reference in a new issue