Refactor editor image list using CScrollRegion, split method

This commit is contained in:
Robert Müller 2022-08-13 21:30:43 +02:00
parent 9f01c6fe66
commit 5dc6c90a50
2 changed files with 128 additions and 156 deletions

View file

@ -3922,133 +3922,20 @@ void CEditor::SortImages()
}
}
void CEditor::RenderImages(CUIRect ToolBox, CUIRect View)
void CEditor::RenderImagesList(CUIRect ToolBox)
{
static float s_ScrollValue = 0;
float ImagesHeight = 30.0f + 14.0f * m_Map.m_vpImages.size() + 27.0f;
float ScrollDifference = ImagesHeight - ToolBox.h;
const float RowHeight = 12.0f;
if(ImagesHeight > ToolBox.h) // Do we even need a scrollbar?
{
CUIRect Scroll;
ToolBox.VSplitRight(20.0f, &ToolBox, &Scroll);
s_ScrollValue = UI()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue);
if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&ToolBox))
{
int ScrollNum = (int)((ImagesHeight - ToolBox.h) / 14.0f) + 1;
if(ScrollNum > 0)
{
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP))
s_ScrollValue = clamp(s_ScrollValue - 1.0f / ScrollNum, 0.0f, 1.0f);
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN))
s_ScrollValue = clamp(s_ScrollValue + 1.0f / ScrollNum, 0.0f, 1.0f);
}
}
}
float ImageStartAt = ScrollDifference * s_ScrollValue;
if(ImageStartAt < 0.0f)
ImageStartAt = 0.0f;
float ImageStopAt = ImagesHeight - ScrollDifference * (1 - s_ScrollValue);
float ImageCur = 0.0f;
for(int e = 0; e < 2; e++) // two passes, first embedded, then external
{
CUIRect Slot;
if(ImageCur > ImageStopAt)
break;
else if(ImageCur >= ImageStartAt)
{
ToolBox.HSplitTop(15.0f, &Slot, &ToolBox);
if(e == 0)
UI()->DoLabel(&Slot, "Embedded", 12.0f, TEXTALIGN_CENTER);
else
UI()->DoLabel(&Slot, "External", 12.0f, TEXTALIGN_CENTER);
}
ImageCur += 15.0f;
for(int i = 0; i < (int)m_Map.m_vpImages.size(); i++)
{
if((e && !m_Map.m_vpImages[i]->m_External) ||
(!e && m_Map.m_vpImages[i]->m_External))
{
continue;
}
if(ImageCur > ImageStopAt)
break;
else if(ImageCur < ImageStartAt)
{
ImageCur += 14.0f;
continue;
}
ImageCur += 14.0f;
char aBuf[128];
str_copy(aBuf, m_Map.m_vpImages[i]->m_aName, sizeof(aBuf));
ToolBox.HSplitTop(12.0f, &Slot, &ToolBox);
int Selected = m_SelectedImage == i;
const bool ImageUsed = std::any_of(m_Map.m_vpGroups.cbegin(), m_Map.m_vpGroups.cend(), [i](const auto &pGroup) {
return std::any_of(pGroup->m_vpLayers.cbegin(), pGroup->m_vpLayers.cend(), [i](const auto &pLayer) {
if(pLayer->m_Type == LAYERTYPE_QUADS)
return static_cast<CLayerQuads *>(pLayer)->m_Image == i;
else if(pLayer->m_Type == LAYERTYPE_TILES)
return static_cast<CLayerTiles *>(pLayer)->m_Image == i;
return false;
});
});
if(!ImageUsed)
Selected += 2; // Image is unused
if(Selected < 2 && e == 1)
{
if(!IsVanillaImage(m_Map.m_vpImages[i]->m_aName))
{
Selected += 4; // Image should be embedded
}
}
float FontSize = 10.0f;
while(TextRender()->TextWidth(nullptr, FontSize, aBuf, -1, -1.0f) > Slot.w)
FontSize--;
if(int Result = DoButton_Ex(&m_Map.m_vpImages[i], aBuf, Selected, &Slot,
BUTTON_CONTEXT, "Select image.", 0, FontSize))
{
m_SelectedImage = i;
static int s_PopupImageID = 0;
if(Result == 2)
{
CEditorImage *pImg = m_Map.m_vpImages[m_SelectedImage];
int Height;
if(pImg->m_External || IsVanillaImage(pImg->m_aName))
Height = 60;
else
Height = 43;
UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, Height, PopupImage);
}
}
ToolBox.HSplitTop(2.0f, nullptr, &ToolBox);
}
// separator
ToolBox.HSplitTop(5.0f, &Slot, &ToolBox);
ImageCur += 5.0f;
IGraphics::CLineItem LineItem(Slot.x, Slot.y + Slot.h / 2, Slot.x + Slot.w, Slot.y + Slot.h / 2);
Graphics()->TextureClear();
Graphics()->LinesBegin();
Graphics()->LinesDraw(&LineItem, 1);
Graphics()->LinesEnd();
}
static CScrollRegion s_ScrollRegion;
vec2 ScrollOffset(0.0f, 0.0f);
CScrollRegionParams ScrollParams;
ScrollParams.m_ScrollbarWidth = 10.0f;
ScrollParams.m_ScrollbarMargin = 3.0f;
ScrollParams.m_ScrollUnit = RowHeight * 5;
s_ScrollRegion.Begin(&ToolBox, &ScrollOffset, &ScrollParams);
ToolBox.y += ScrollOffset.y;
bool ScrollToSelection = false;
if(Input()->KeyPress(KEY_DOWN) && m_Dialog == DIALOG_NONE)
{
int OldImage = m_SelectedImage;
@ -4072,6 +3959,7 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect View)
}
}
}
ScrollToSelection = OldImage != m_SelectedImage;
}
if(Input()->KeyPress(KEY_UP) && m_Dialog == DIALOG_NONE)
{
@ -4096,44 +3984,124 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect View)
}
}
}
ScrollToSelection = OldImage != m_SelectedImage;
}
// render image
int i = m_SelectedImage;
if(i >= 0 && (size_t)i < m_Map.m_vpImages.size())
for(int e = 0; e < 2; e++) // two passes, first embedded, then external
{
CUIRect r;
View.Margin(10.0f, &r);
if(r.h < r.w)
r.w = r.h;
else
r.h = r.w;
float Max = (float)(maximum(m_Map.m_vpImages[i]->m_Width, m_Map.m_vpImages[i]->m_Height));
r.w *= m_Map.m_vpImages[i]->m_Width / Max;
r.h *= m_Map.m_vpImages[i]->m_Height / Max;
Graphics()->TextureSet(m_Map.m_vpImages[i]->m_Texture);
Graphics()->BlendNormal();
Graphics()->WrapClamp();
Graphics()->QuadsBegin();
IGraphics::CQuadItem QuadItem(r.x, r.y, r.w, r.h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
Graphics()->WrapNormal();
}
//if(ImageCur + 27.0f > ImageStopAt)
// return;
CUIRect Slot;
ToolBox.HSplitTop(RowHeight + 3.0f, &Slot, &ToolBox);
if(s_ScrollRegion.AddRect(Slot))
UI()->DoLabel(&Slot, e == 0 ? "Embedded" : "External", 12.0f, TEXTALIGN_CENTER);
CUIRect Slot;
ToolBox.HSplitTop(5.0f, &Slot, &ToolBox);
for(int i = 0; i < (int)m_Map.m_vpImages.size(); i++)
{
if((e && !m_Map.m_vpImages[i]->m_External) ||
(!e && m_Map.m_vpImages[i]->m_External))
{
continue;
}
ToolBox.HSplitTop(RowHeight + 2.0f, &Slot, &ToolBox);
int Selected = m_SelectedImage == i;
if(!s_ScrollRegion.AddRect(Slot, Selected && ScrollToSelection))
continue;
Slot.HSplitTop(RowHeight, &Slot, nullptr);
const bool ImageUsed = std::any_of(m_Map.m_vpGroups.cbegin(), m_Map.m_vpGroups.cend(), [i](const auto &pGroup) {
return std::any_of(pGroup->m_vpLayers.cbegin(), pGroup->m_vpLayers.cend(), [i](const auto &pLayer) {
if(pLayer->m_Type == LAYERTYPE_QUADS)
return static_cast<CLayerQuads *>(pLayer)->m_Image == i;
else if(pLayer->m_Type == LAYERTYPE_TILES)
return static_cast<CLayerTiles *>(pLayer)->m_Image == i;
return false;
});
});
if(!ImageUsed)
Selected += 2; // Image is unused
if(Selected < 2 && e == 1)
{
if(!IsVanillaImage(m_Map.m_vpImages[i]->m_aName))
{
Selected += 4; // Image should be embedded
}
}
float FontSize = 10.0f;
while(TextRender()->TextWidth(nullptr, FontSize, m_Map.m_vpImages[i]->m_aName, -1, -1.0f) > Slot.w)
FontSize--;
if(int Result = DoButton_Ex(&m_Map.m_vpImages[i], m_Map.m_vpImages[i]->m_aName, Selected, &Slot,
BUTTON_CONTEXT, "Select image.", IGraphics::CORNER_ALL, FontSize))
{
m_SelectedImage = i;
static int s_PopupImageID = 0;
if(Result == 2)
{
CEditorImage *pImg = m_Map.m_vpImages[m_SelectedImage];
int Height;
if(pImg->m_External || IsVanillaImage(pImg->m_aName))
Height = 60;
else
Height = 43;
UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, Height, PopupImage);
}
}
}
// separator
ToolBox.HSplitTop(5.0f, &Slot, &ToolBox);
if(s_ScrollRegion.AddRect(Slot))
{
IGraphics::CLineItem LineItem(Slot.x, Slot.y + Slot.h / 2, Slot.x + Slot.w, Slot.y + Slot.h / 2);
Graphics()->TextureClear();
Graphics()->LinesBegin();
Graphics()->LinesDraw(&LineItem, 1);
Graphics()->LinesEnd();
}
}
// new image
static int s_NewImageButton = 0;
ToolBox.HSplitTop(12.0f, &Slot, &ToolBox);
if(DoButton_Editor(&s_NewImageButton, "Add", 0, &Slot, 0, "Load a new image to use in the map"))
InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Add Image", "Add", "mapres", "", AddImage, this);
static int s_AddImageButton = 0;
CUIRect AddImageButton;
ToolBox.HSplitTop(5.0f + RowHeight + 1.0f, &AddImageButton, &ToolBox);
if(s_ScrollRegion.AddRect(AddImageButton))
{
AddImageButton.HSplitTop(5.0f, nullptr, &AddImageButton);
AddImageButton.HSplitTop(RowHeight, &AddImageButton, nullptr);
if(DoButton_Editor(&s_AddImageButton, "Add", 0, &AddImageButton, 0, "Load a new image to use in the map"))
InvokeFileDialog(IStorage::TYPE_ALL, FILETYPE_IMG, "Add Image", "Add", "mapres", "", AddImage, this);
}
s_ScrollRegion.End();
}
void CEditor::RenderSounds(CUIRect ToolBox, CUIRect View)
void CEditor::RenderSelectedImage(CUIRect View)
{
if(m_SelectedImage < 0 || (size_t)m_SelectedImage >= m_Map.m_vpImages.size())
return;
View.Margin(10.0f, &View);
if(View.h < View.w)
View.w = View.h;
else
View.h = View.w;
float Max = maximum<float>(m_Map.m_vpImages[m_SelectedImage]->m_Width, m_Map.m_vpImages[m_SelectedImage]->m_Height);
View.w *= m_Map.m_vpImages[m_SelectedImage]->m_Width / Max;
View.h *= m_Map.m_vpImages[m_SelectedImage]->m_Height / Max;
Graphics()->TextureSet(m_Map.m_vpImages[m_SelectedImage]->m_Texture);
Graphics()->BlendNormal();
Graphics()->WrapClamp();
Graphics()->QuadsBegin();
IGraphics::CQuadItem QuadItem(View.x, View.y, View.w, View.h);
Graphics()->QuadsDrawTL(&QuadItem, 1);
Graphics()->QuadsEnd();
Graphics()->WrapNormal();
}
void CEditor::RenderSounds(CUIRect ToolBox)
{
static float s_ScrollValue = 0;
float SoundsHeight = 30.0f + 14.0f * m_Map.m_vpSounds.size() + 27.0f;
@ -5902,7 +5870,10 @@ void CEditor::Render()
if(m_Mode == MODE_LAYERS)
RenderLayers(ToolBox);
else if(m_Mode == MODE_IMAGES)
RenderImages(ToolBox, View);
{
RenderImagesList(ToolBox);
RenderSelectedImage(View);
}
else if(m_Mode == MODE_SOUNDS)
RenderSounds(ToolBox, View);
}

View file

@ -1127,7 +1127,8 @@ public:
bool IsEnvelopeUsed(int EnvelopeIndex) const;
void RenderLayers(CUIRect LayersBox);
void RenderImages(CUIRect Toolbox, CUIRect View);
void RenderImagesList(CUIRect Toolbox);
void RenderSelectedImage(CUIRect View);
void RenderSounds(CUIRect Toolbox, CUIRect View);
void RenderModebar(CUIRect View);
void RenderStatusbar(CUIRect View);