mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 01:58:19 +00:00
Merge #6067
6067: Implement smooth zoom for editor r=heinrich5991 a=Robyt3 Port the smooth zoom code from the ingame camera to the editor with some minor adjustments. The smooth zoom animation time can be adjusted with the existing `cl_smooth_zoom_time` config variable. Closes #2525. ## Checklist - [X] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [X] Tested in combination with possibly related configuration options: `cl_smooth_zoom_time`, `cl_limit_max_zoom_level` and `ed_zoom_target` - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
commit
d94a8ef399
|
@ -969,10 +969,7 @@ void CEditor::DoToolbar(CUIRect ToolBar)
|
|||
static int s_ZoomOutButton = 0;
|
||||
if(DoButton_FontIcon(&s_ZoomOutButton, "-", 0, &Button, 0, "[NumPad-] Zoom out", IGraphics::CORNER_L))
|
||||
{
|
||||
if(m_ZoomLevel + 50 > 2000)
|
||||
m_ZoomLevel = 2000;
|
||||
else
|
||||
m_ZoomLevel += 50;
|
||||
ChangeZoom(50.0f);
|
||||
}
|
||||
|
||||
TB_Top.VSplitLeft(25.0f, &Button, &TB_Top);
|
||||
|
@ -981,17 +978,14 @@ void CEditor::DoToolbar(CUIRect ToolBar)
|
|||
{
|
||||
m_EditorOffsetX = 0;
|
||||
m_EditorOffsetY = 0;
|
||||
m_ZoomLevel = 100;
|
||||
SetZoom(100.0f);
|
||||
}
|
||||
|
||||
TB_Top.VSplitLeft(20.0f, &Button, &TB_Top);
|
||||
static int s_ZoomInButton = 0;
|
||||
if(DoButton_FontIcon(&s_ZoomInButton, "+", 0, &Button, 0, "[NumPad+] Zoom in", IGraphics::CORNER_R))
|
||||
{
|
||||
if(m_ZoomLevel - 50 < 10)
|
||||
m_ZoomLevel = 10;
|
||||
else
|
||||
m_ZoomLevel -= 50;
|
||||
ChangeZoom(-50.0f);
|
||||
}
|
||||
|
||||
TB_Top.VSplitLeft(5.0f, nullptr, &TB_Top);
|
||||
|
@ -2401,7 +2395,7 @@ void CEditor::DoMapEditor(CUIRect View)
|
|||
}
|
||||
|
||||
CLayerTiles *pT = static_cast<CLayerTiles *>(GetSelectedLayerType(0, LAYERTYPE_TILES));
|
||||
if(m_ShowTileInfo && pT && pT->m_Visible && m_ZoomLevel <= 300)
|
||||
if(m_ShowTileInfo && pT && pT->m_Visible && m_Zoom <= 300.0f)
|
||||
{
|
||||
GetSelectedGroup()->MapScreen();
|
||||
pT->ShowInfo();
|
||||
|
@ -5719,7 +5713,7 @@ void CEditor::RenderMenubar(CUIRect MenuBar)
|
|||
char aTimeStr[6];
|
||||
str_timestamp_format(aTimeStr, sizeof(aTimeStr), "%H:%M");
|
||||
|
||||
str_format(aBuf, sizeof(aBuf), "X: %i, Y: %i, Z: %i, A: %.1f, G: %i %s", (int)UI()->MouseWorldX() / 32, (int)UI()->MouseWorldY() / 32, m_ZoomLevel, m_AnimateSpeed, m_GridFactor, aTimeStr);
|
||||
str_format(aBuf, sizeof(aBuf), "X: %i, Y: %i, Z: %.1f, A: %.1f, G: %i %s", (int)UI()->MouseWorldX() / 32, (int)UI()->MouseWorldY() / 32, m_Zoom, m_AnimateSpeed, m_GridFactor, aTimeStr);
|
||||
UI()->DoLabel(&Info, aBuf, 10.0f, TEXTALIGN_RIGHT);
|
||||
|
||||
static int s_CloseButton = 0;
|
||||
|
@ -5784,14 +5778,14 @@ void CEditor::Render()
|
|||
|
||||
// do zooming
|
||||
if(Input()->KeyPress(KEY_KP_MINUS) && m_Dialog == DIALOG_NONE && m_EditBoxActive == 0)
|
||||
m_ZoomLevel += 50;
|
||||
ChangeZoom(50.0f);
|
||||
if(Input()->KeyPress(KEY_KP_PLUS) && m_Dialog == DIALOG_NONE && m_EditBoxActive == 0)
|
||||
m_ZoomLevel -= 50;
|
||||
ChangeZoom(-50.0f);
|
||||
if(Input()->KeyPress(KEY_KP_MULTIPLY) && m_Dialog == DIALOG_NONE && m_EditBoxActive == 0)
|
||||
{
|
||||
m_EditorOffsetX = 0;
|
||||
m_EditorOffsetY = 0;
|
||||
m_ZoomLevel = 100;
|
||||
SetZoom(100.0f);
|
||||
}
|
||||
|
||||
for(int i = KEY_1; i <= KEY_0; i++)
|
||||
|
@ -6024,25 +6018,13 @@ void CEditor::Render()
|
|||
|
||||
if(m_Dialog == DIALOG_NONE && !m_MouseInsidePopup && UI()->MouseInside(&View))
|
||||
{
|
||||
// Determines in which direction to zoom.
|
||||
int Zoom = 0;
|
||||
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP))
|
||||
Zoom--;
|
||||
if(Input()->KeyPress(KEY_MOUSE_WHEEL_DOWN))
|
||||
Zoom++;
|
||||
|
||||
if(Zoom != 0)
|
||||
{
|
||||
float OldLevel = m_ZoomLevel;
|
||||
m_ZoomLevel = maximum(m_ZoomLevel + Zoom * 20, 10);
|
||||
if(g_Config.m_ClLimitMaxZoomLevel)
|
||||
m_ZoomLevel = minimum(m_ZoomLevel, 2000);
|
||||
if(g_Config.m_EdZoomTarget)
|
||||
ZoomMouseTarget((float)m_ZoomLevel / OldLevel);
|
||||
}
|
||||
ChangeZoom(20.0f);
|
||||
if(Input()->KeyPress(KEY_MOUSE_WHEEL_UP))
|
||||
ChangeZoom(-20.0f);
|
||||
}
|
||||
|
||||
m_WorldZoom = m_ZoomLevel / 100.0f;
|
||||
UpdateZoom();
|
||||
|
||||
if(m_GuiActive)
|
||||
RenderStatusbar(StatusBar);
|
||||
|
@ -6116,8 +6098,9 @@ void CEditor::Reset(bool CreateDefault)
|
|||
m_EditorOffsetX = 0.0f;
|
||||
m_EditorOffsetY = 0.0f;
|
||||
|
||||
m_Zoom = 200.0f;
|
||||
m_Zooming = false;
|
||||
m_WorldZoom = 1.0f;
|
||||
m_ZoomLevel = 200;
|
||||
|
||||
m_MouseDeltaX = 0;
|
||||
m_MouseDeltaY = 0;
|
||||
|
@ -6134,20 +6117,46 @@ void CEditor::Reset(bool CreateDefault)
|
|||
|
||||
int CEditor::GetLineDistance() const
|
||||
{
|
||||
int LineDistance = 512;
|
||||
if(m_Zoom <= 100.0f)
|
||||
return 16;
|
||||
else if(m_Zoom <= 250.0f)
|
||||
return 32;
|
||||
else if(m_Zoom <= 450.0f)
|
||||
return 64;
|
||||
else if(m_Zoom <= 850.0f)
|
||||
return 128;
|
||||
else if(m_Zoom <= 1550.0f)
|
||||
return 256;
|
||||
else
|
||||
return 512;
|
||||
}
|
||||
|
||||
if(m_ZoomLevel <= 100)
|
||||
LineDistance = 16;
|
||||
else if(m_ZoomLevel <= 250)
|
||||
LineDistance = 32;
|
||||
else if(m_ZoomLevel <= 450)
|
||||
LineDistance = 64;
|
||||
else if(m_ZoomLevel <= 850)
|
||||
LineDistance = 128;
|
||||
else if(m_ZoomLevel <= 1550)
|
||||
LineDistance = 256;
|
||||
void CEditor::SetZoom(float Target)
|
||||
{
|
||||
Target = clamp(Target, MinZoomLevel(), MaxZoomLevel());
|
||||
|
||||
return LineDistance;
|
||||
const float Now = Client()->LocalTime();
|
||||
float Current = m_Zoom;
|
||||
float Derivative = 0.0f;
|
||||
if(m_Zooming)
|
||||
{
|
||||
const float Progress = ZoomProgress(Now);
|
||||
Current = m_ZoomSmoothing.Evaluate(Progress);
|
||||
Derivative = m_ZoomSmoothing.Derivative(Progress);
|
||||
}
|
||||
|
||||
m_ZoomSmoothingTarget = Target;
|
||||
m_ZoomSmoothing = CCubicBezier::With(Current, Derivative, 0.0f, m_ZoomSmoothingTarget);
|
||||
m_ZoomSmoothingStart = Now;
|
||||
m_ZoomSmoothingEnd = Now + g_Config.m_ClSmoothZoomTime / 1000.0f;
|
||||
|
||||
m_Zooming = true;
|
||||
}
|
||||
|
||||
void CEditor::ChangeZoom(float Amount)
|
||||
{
|
||||
const float CurrentTarget = m_Zooming ? m_ZoomSmoothingTarget : m_Zoom;
|
||||
SetZoom(CurrentTarget + Amount);
|
||||
}
|
||||
|
||||
void CEditor::ZoomMouseTarget(float ZoomFactor)
|
||||
|
@ -6166,8 +6175,46 @@ void CEditor::ZoomMouseTarget(float ZoomFactor)
|
|||
float Mwy = aPoints[1] + WorldHeight * (UI()->MouseY() / UI()->Screen()->h);
|
||||
|
||||
// adjust camera
|
||||
m_WorldOffsetX += (Mwx - m_WorldOffsetX) * (1 - ZoomFactor);
|
||||
m_WorldOffsetY += (Mwy - m_WorldOffsetY) * (1 - ZoomFactor);
|
||||
m_WorldOffsetX += (Mwx - m_WorldOffsetX) * (1.0f - ZoomFactor);
|
||||
m_WorldOffsetY += (Mwy - m_WorldOffsetY) * (1.0f - ZoomFactor);
|
||||
}
|
||||
|
||||
void CEditor::UpdateZoom()
|
||||
{
|
||||
if(m_Zooming)
|
||||
{
|
||||
const float Time = Client()->LocalTime();
|
||||
const float OldLevel = m_Zoom;
|
||||
if(Time >= m_ZoomSmoothingEnd)
|
||||
{
|
||||
m_Zoom = m_ZoomSmoothingTarget;
|
||||
m_Zooming = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Zoom = m_ZoomSmoothing.Evaluate(ZoomProgress(Time));
|
||||
}
|
||||
m_Zoom = clamp(m_Zoom, MinZoomLevel(), MaxZoomLevel());
|
||||
if(g_Config.m_EdZoomTarget)
|
||||
ZoomMouseTarget(m_Zoom / OldLevel);
|
||||
}
|
||||
|
||||
m_WorldZoom = m_Zoom / 100.0f;
|
||||
}
|
||||
|
||||
float CEditor::MinZoomLevel() const
|
||||
{
|
||||
return 10.0f;
|
||||
}
|
||||
|
||||
float CEditor::MaxZoomLevel() const
|
||||
{
|
||||
return g_Config.m_ClLimitMaxZoomLevel ? 2000.0f : std::numeric_limits<float>::max();
|
||||
}
|
||||
|
||||
float CEditor::ZoomProgress(float CurrentTime) const
|
||||
{
|
||||
return (CurrentTime - m_ZoomSmoothingStart) / (m_ZoomSmoothingEnd - m_ZoomSmoothingStart);
|
||||
}
|
||||
|
||||
void CEditor::Goto(float X, float Y)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifndef GAME_EDITOR_EDITOR_H
|
||||
#define GAME_EDITOR_EDITOR_H
|
||||
|
||||
#include <base/bezier.h>
|
||||
#include <base/system.h>
|
||||
|
||||
#include <game/client/render.h>
|
||||
|
@ -800,8 +801,10 @@ public:
|
|||
m_EditorOffsetX = 0.0f;
|
||||
m_EditorOffsetY = 0.0f;
|
||||
|
||||
m_Zoom = 200.0f;
|
||||
m_Zooming = false;
|
||||
m_WorldZoom = 1.0f;
|
||||
m_ZoomLevel = 200;
|
||||
|
||||
m_LockMouse = false;
|
||||
m_ShowMousePointer = true;
|
||||
m_MouseDeltaX = 0;
|
||||
|
@ -984,8 +987,16 @@ public:
|
|||
float m_WorldOffsetY;
|
||||
float m_EditorOffsetX;
|
||||
float m_EditorOffsetY;
|
||||
|
||||
// Zooming
|
||||
CCubicBezier m_ZoomSmoothing;
|
||||
float m_ZoomSmoothingStart;
|
||||
float m_ZoomSmoothingEnd;
|
||||
bool m_Zooming;
|
||||
float m_Zoom;
|
||||
float m_ZoomSmoothingTarget;
|
||||
float m_WorldZoom;
|
||||
int m_ZoomLevel;
|
||||
|
||||
bool m_LockMouse;
|
||||
bool m_ShowMousePointer;
|
||||
bool m_GuiActive;
|
||||
|
@ -1274,7 +1285,15 @@ public:
|
|||
static const char *Explain(int ExplanationID, int Tile, int Layer);
|
||||
|
||||
int GetLineDistance() const;
|
||||
|
||||
// Zooming
|
||||
void SetZoom(float Target);
|
||||
void ChangeZoom(float Amount);
|
||||
void ZoomMouseTarget(float ZoomFactor);
|
||||
void UpdateZoom();
|
||||
float ZoomProgress(float CurrentTime) const;
|
||||
float MinZoomLevel() const;
|
||||
float MaxZoomLevel() const;
|
||||
|
||||
static ColorHSVA ms_PickerColor;
|
||||
static int ms_SVPicker;
|
||||
|
|
Loading…
Reference in a new issue