mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-19 22:48:18 +00:00
Refactor editor image list using CScrollRegion
, split method
This commit is contained in:
parent
9f01c6fe66
commit
5dc6c90a50
|
@ -3922,133 +3922,20 @@ void CEditor::SortImages()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CEditor::RenderImages(CUIRect ToolBox, CUIRect View)
|
void CEditor::RenderImagesList(CUIRect ToolBox)
|
||||||
{
|
{
|
||||||
static float s_ScrollValue = 0;
|
const float RowHeight = 12.0f;
|
||||||
float ImagesHeight = 30.0f + 14.0f * m_Map.m_vpImages.size() + 27.0f;
|
|
||||||
float ScrollDifference = ImagesHeight - ToolBox.h;
|
|
||||||
|
|
||||||
if(ImagesHeight > ToolBox.h) // Do we even need a scrollbar?
|
static CScrollRegion s_ScrollRegion;
|
||||||
{
|
vec2 ScrollOffset(0.0f, 0.0f);
|
||||||
CUIRect Scroll;
|
CScrollRegionParams ScrollParams;
|
||||||
ToolBox.VSplitRight(20.0f, &ToolBox, &Scroll);
|
ScrollParams.m_ScrollbarWidth = 10.0f;
|
||||||
s_ScrollValue = UI()->DoScrollbarV(&s_ScrollValue, &Scroll, s_ScrollValue);
|
ScrollParams.m_ScrollbarMargin = 3.0f;
|
||||||
|
ScrollParams.m_ScrollUnit = RowHeight * 5;
|
||||||
if(UI()->MouseInside(&Scroll) || UI()->MouseInside(&ToolBox))
|
s_ScrollRegion.Begin(&ToolBox, &ScrollOffset, &ScrollParams);
|
||||||
{
|
ToolBox.y += ScrollOffset.y;
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool ScrollToSelection = false;
|
||||||
if(Input()->KeyPress(KEY_DOWN) && m_Dialog == DIALOG_NONE)
|
if(Input()->KeyPress(KEY_DOWN) && m_Dialog == DIALOG_NONE)
|
||||||
{
|
{
|
||||||
int OldImage = m_SelectedImage;
|
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)
|
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
|
for(int e = 0; e < 2; e++) // two passes, first embedded, then external
|
||||||
int i = m_SelectedImage;
|
|
||||||
if(i >= 0 && (size_t)i < m_Map.m_vpImages.size())
|
|
||||||
{
|
{
|
||||||
CUIRect r;
|
CUIRect Slot;
|
||||||
View.Margin(10.0f, &r);
|
ToolBox.HSplitTop(RowHeight + 3.0f, &Slot, &ToolBox);
|
||||||
if(r.h < r.w)
|
if(s_ScrollRegion.AddRect(Slot))
|
||||||
r.w = r.h;
|
UI()->DoLabel(&Slot, e == 0 ? "Embedded" : "External", 12.0f, TEXTALIGN_CENTER);
|
||||||
|
|
||||||
|
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
|
else
|
||||||
r.h = r.w;
|
Height = 43;
|
||||||
float Max = (float)(maximum(m_Map.m_vpImages[i]->m_Width, m_Map.m_vpImages[i]->m_Height));
|
UiInvokePopupMenu(&s_PopupImageID, 0, UI()->MouseX(), UI()->MouseY(), 120, Height, PopupImage);
|
||||||
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);
|
}
|
||||||
|
|
||||||
|
// 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_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::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()->BlendNormal();
|
||||||
Graphics()->WrapClamp();
|
Graphics()->WrapClamp();
|
||||||
Graphics()->QuadsBegin();
|
Graphics()->QuadsBegin();
|
||||||
IGraphics::CQuadItem QuadItem(r.x, r.y, r.w, r.h);
|
IGraphics::CQuadItem QuadItem(View.x, View.y, View.w, View.h);
|
||||||
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
Graphics()->QuadsDrawTL(&QuadItem, 1);
|
||||||
Graphics()->QuadsEnd();
|
Graphics()->QuadsEnd();
|
||||||
Graphics()->WrapNormal();
|
Graphics()->WrapNormal();
|
||||||
}
|
}
|
||||||
//if(ImageCur + 27.0f > ImageStopAt)
|
|
||||||
// return;
|
|
||||||
|
|
||||||
CUIRect Slot;
|
void CEditor::RenderSounds(CUIRect ToolBox)
|
||||||
ToolBox.HSplitTop(5.0f, &Slot, &ToolBox);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CEditor::RenderSounds(CUIRect ToolBox, CUIRect View)
|
|
||||||
{
|
{
|
||||||
static float s_ScrollValue = 0;
|
static float s_ScrollValue = 0;
|
||||||
float SoundsHeight = 30.0f + 14.0f * m_Map.m_vpSounds.size() + 27.0f;
|
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)
|
if(m_Mode == MODE_LAYERS)
|
||||||
RenderLayers(ToolBox);
|
RenderLayers(ToolBox);
|
||||||
else if(m_Mode == MODE_IMAGES)
|
else if(m_Mode == MODE_IMAGES)
|
||||||
RenderImages(ToolBox, View);
|
{
|
||||||
|
RenderImagesList(ToolBox);
|
||||||
|
RenderSelectedImage(View);
|
||||||
|
}
|
||||||
else if(m_Mode == MODE_SOUNDS)
|
else if(m_Mode == MODE_SOUNDS)
|
||||||
RenderSounds(ToolBox, View);
|
RenderSounds(ToolBox, View);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1127,7 +1127,8 @@ public:
|
||||||
bool IsEnvelopeUsed(int EnvelopeIndex) const;
|
bool IsEnvelopeUsed(int EnvelopeIndex) const;
|
||||||
|
|
||||||
void RenderLayers(CUIRect LayersBox);
|
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 RenderSounds(CUIRect Toolbox, CUIRect View);
|
||||||
void RenderModebar(CUIRect View);
|
void RenderModebar(CUIRect View);
|
||||||
void RenderStatusbar(CUIRect View);
|
void RenderStatusbar(CUIRect View);
|
||||||
|
|
Loading…
Reference in a new issue