mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-08-15 14:43:32 -07:00
Modernize Brush in Atlas
Use dynamic event bindings allowing to bind all events in all sort of ways. Addionally no need for subclassing wx widgets. Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
This commit is contained in:
parent
7ee476928b
commit
32b9713781
5 changed files with 64 additions and 108 deletions
|
|
@ -44,7 +44,7 @@ static Brush* g_Brush_CurrentlyActive = NULL; // only one brush can be active at
|
|||
const float Brush::STRENGTH_MULTIPLIER = 1024.f;
|
||||
|
||||
Brush::Brush()
|
||||
: m_Shape(CIRCLE), m_Size(4), m_Strength(1.f), m_IsActive(false)
|
||||
: m_Shape(Shape::CIRCLE), m_Size(4), m_Strength(1.f), m_IsActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -76,9 +76,9 @@ int Brush::GetWidth() const
|
|||
{
|
||||
switch (m_Shape)
|
||||
{
|
||||
case CIRCLE:
|
||||
case Shape::CIRCLE:
|
||||
return m_Size;
|
||||
case SQUARE:
|
||||
case Shape::SQUARE:
|
||||
return m_Size;
|
||||
default:
|
||||
wxFAIL;
|
||||
|
|
@ -108,7 +108,7 @@ std::vector<float> Brush::GetData() const
|
|||
|
||||
switch (m_Shape)
|
||||
{
|
||||
case CIRCLE:
|
||||
case Shape::CIRCLE:
|
||||
{
|
||||
int i = 0;
|
||||
// All calculations are done in units of half-tiles, since that
|
||||
|
|
@ -131,7 +131,7 @@ std::vector<float> Brush::GetData() const
|
|||
break;
|
||||
}
|
||||
|
||||
case SQUARE:
|
||||
case Shape::SQUARE:
|
||||
{
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; ++y)
|
||||
|
|
@ -144,6 +144,17 @@ std::vector<float> Brush::GetData() const
|
|||
return data;
|
||||
}
|
||||
|
||||
int Brush::GetSize() const
|
||||
{
|
||||
return m_Size;
|
||||
}
|
||||
|
||||
void Brush::SetSize(int size)
|
||||
{
|
||||
m_Size = size;
|
||||
Send();
|
||||
}
|
||||
|
||||
float Brush::GetStrength() const
|
||||
{
|
||||
return m_Strength;
|
||||
|
|
@ -152,115 +163,54 @@ float Brush::GetStrength() const
|
|||
void Brush::SetStrength(float strength)
|
||||
{
|
||||
m_Strength = strength;
|
||||
Send();
|
||||
}
|
||||
|
||||
void Brush::SetCircle(int size)
|
||||
void Brush::SetShape(Shape shape)
|
||||
{
|
||||
m_Shape = CIRCLE;
|
||||
m_Size = size;
|
||||
m_Shape = shape;
|
||||
Send();
|
||||
}
|
||||
|
||||
void Brush::SetSquare(int size)
|
||||
{
|
||||
m_Shape = SQUARE;
|
||||
m_Size = size;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BrushShapeCtrl : public wxRadioBox
|
||||
{
|
||||
public:
|
||||
BrushShapeCtrl(wxWindow* parent, wxArrayString& shapes, Brush& brush)
|
||||
: wxRadioBox(parent, wxID_ANY, _("Shape"), wxDefaultPosition, wxDefaultSize, shapes, 0, wxRA_SPECIFY_ROWS),
|
||||
m_Brush(brush)
|
||||
{
|
||||
SetSelection(m_Brush.m_Shape);
|
||||
}
|
||||
|
||||
private:
|
||||
Brush& m_Brush;
|
||||
|
||||
void OnChange(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_Brush.m_Shape = (Brush::BrushShape)GetSelection();
|
||||
m_Brush.Send();
|
||||
}
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
BEGIN_EVENT_TABLE(BrushShapeCtrl, wxRadioBox)
|
||||
EVT_RADIOBOX(wxID_ANY, BrushShapeCtrl::OnChange)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
class BrushSizeCtrl: public wxSpinCtrl
|
||||
{
|
||||
public:
|
||||
BrushSizeCtrl(wxWindow* parent, Brush& brush)
|
||||
: wxSpinCtrl(parent, wxID_ANY, wxString::Format(_T("%d"), brush.m_Size), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100, brush.m_Size),
|
||||
m_Brush(brush)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Brush& m_Brush;
|
||||
|
||||
void OnChange(wxSpinEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_Brush.m_Size = GetValue();
|
||||
m_Brush.Send();
|
||||
}
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
BEGIN_EVENT_TABLE(BrushSizeCtrl, wxSpinCtrl)
|
||||
EVT_SPINCTRL(wxID_ANY, BrushSizeCtrl::OnChange)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
class BrushStrengthCtrl : public wxSpinCtrl
|
||||
{
|
||||
public:
|
||||
BrushStrengthCtrl(wxWindow* parent, Brush& brush)
|
||||
: wxSpinCtrl(parent, wxID_ANY, wxString::Format(_T("%d"), (int)(10.f*brush.m_Strength)), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100, (int)(10.f*brush.m_Strength)),
|
||||
m_Brush(brush)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Brush& m_Brush;
|
||||
|
||||
void OnChange(wxSpinEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_Brush.m_Strength = GetValue()/10.f;
|
||||
m_Brush.Send();
|
||||
}
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
BEGIN_EVENT_TABLE(BrushStrengthCtrl, wxSpinCtrl)
|
||||
EVT_SPINCTRL(wxID_ANY, BrushStrengthCtrl::OnChange)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
void Brush::CreateUI(wxWindow* parent, wxSizer* sizer)
|
||||
{
|
||||
wxArrayString shapes; // Must match order of BrushShape enum
|
||||
// Must match order of Brush::Shape enum
|
||||
wxArrayString shapes;
|
||||
shapes.Add(_("Circle"));
|
||||
shapes.Add(_("Square"));
|
||||
|
||||
// TODO (maybe): get rid of the extra static box, by not using wxRadioBox
|
||||
sizer->Add(new BrushShapeCtrl(parent, shapes, *this), wxSizerFlags().Expand().Border(wxALL, 5));
|
||||
auto* brushShapeCtrl = new wxRadioBox(parent, wxID_ANY, _("Shape"), wxDefaultPosition, wxDefaultSize, shapes, 0, wxRA_SPECIFY_ROWS);
|
||||
brushShapeCtrl->Bind(wxEVT_RADIOBOX, [this, brushShapeCtrl](auto&){ SetShape(static_cast<Shape>(brushShapeCtrl->GetSelection())); });
|
||||
sizer->Add(brushShapeCtrl, wxSizerFlags().Expand().Border(wxALL, 5));
|
||||
|
||||
sizer->AddSpacer(5);
|
||||
|
||||
// TODO: These are yucky
|
||||
auto* brushSizeLabel = new wxStaticText(parent, wxID_ANY, _("Size"));
|
||||
auto* brushSizeCtrl = new wxSpinCtrl(parent, wxID_ANY,
|
||||
wxString::Format(_T("%d"), GetSize()),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,
|
||||
0, 100, GetSize());
|
||||
auto burshSizeSetter = [this, brushSizeCtrl](auto&){ SetSize(brushSizeCtrl->GetValue()); };
|
||||
brushSizeCtrl->Bind(wxEVT_SPINCTRL, burshSizeSetter);
|
||||
|
||||
auto* brushStrengthLabel = new wxStaticText(parent, wxID_ANY, _("Strength"));
|
||||
auto* brushStrengthCtrl = new wxSpinCtrl(parent, wxID_ANY,
|
||||
wxString::Format(_T("%d"), static_cast<int>(10.f * GetStrength())),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS | wxTE_PROCESS_ENTER,
|
||||
0, 100, static_cast<int>(10.f * GetStrength()));
|
||||
auto burshStrenghtSetter = [this, brushStrengthCtrl](auto&){ SetStrength(brushStrengthCtrl->GetValue() / 10.f); };
|
||||
brushStrengthCtrl->Bind(wxEVT_SPINCTRL, burshStrenghtSetter);
|
||||
|
||||
wxFlexGridSizer* spinnerSizer = new wxFlexGridSizer(2, 5, 5);
|
||||
spinnerSizer->AddGrowableCol(1);
|
||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Size")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(new BrushSizeCtrl(parent, *this), wxSizerFlags().Expand());
|
||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Strength")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(new BrushStrengthCtrl(parent, *this), wxSizerFlags().Expand());
|
||||
|
||||
spinnerSizer->Add(brushSizeLabel, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(brushSizeCtrl, wxSizerFlags().Expand());
|
||||
spinnerSizer->Add(brushStrengthLabel, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
||||
spinnerSizer->Add(brushStrengthCtrl, wxSizerFlags().Expand());
|
||||
|
||||
sizer->Add(spinnerSizer, wxSizerFlags().Expand().Border(wxALL, 5));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2025 Wildfire Games.
|
||||
/* Copyright (C) 2026 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
|
|
@ -29,6 +29,8 @@ class Brush
|
|||
friend class BrushSizeCtrl;
|
||||
friend class BrushStrengthCtrl;
|
||||
public:
|
||||
enum class Shape { CIRCLE = 0, SQUARE};
|
||||
|
||||
Brush();
|
||||
~Brush();
|
||||
|
||||
|
|
@ -38,8 +40,10 @@ public:
|
|||
int GetHeight() const;
|
||||
std::vector<float> GetData() const;
|
||||
|
||||
void SetCircle(int size);
|
||||
void SetSquare(int size);
|
||||
void SetShape(Shape shape);
|
||||
|
||||
int GetSize() const;
|
||||
void SetSize(int size);
|
||||
|
||||
float GetStrength() const;
|
||||
void SetStrength(float strength);
|
||||
|
|
@ -54,8 +58,7 @@ private:
|
|||
// If active, send SetBrush message to the game
|
||||
void Send();
|
||||
|
||||
enum BrushShape { CIRCLE = 0, SQUARE};
|
||||
BrushShape m_Shape;
|
||||
Shape m_Shape;
|
||||
int m_Size;
|
||||
float m_Strength;
|
||||
bool m_IsActive;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ class FillTerrain : public StateDrivenTool<FillTerrain>
|
|||
public:
|
||||
FillTerrain()
|
||||
{
|
||||
m_Brush.SetSquare(2);
|
||||
m_Brush.SetShape(Brush::Shape::SQUARE);
|
||||
m_Brush.SetSize(2);
|
||||
SetState(&Waiting);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,8 @@ public:
|
|||
{
|
||||
SetState(&Waiting);
|
||||
|
||||
m_EyedropperBrush.SetSquare(2);
|
||||
m_EyedropperBrush.SetShape(Brush::Shape::SQUARE);
|
||||
m_EyedropperBrush.SetSize(2);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@ class ReplaceTerrain : public StateDrivenTool<ReplaceTerrain>
|
|||
public:
|
||||
ReplaceTerrain()
|
||||
{
|
||||
m_Brush.SetSquare(2);
|
||||
m_Brush.SetShape(Brush::Shape::SQUARE);
|
||||
m_Brush.SetSize(2);
|
||||
SetState(&Waiting);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue