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;
|
const float Brush::STRENGTH_MULTIPLIER = 1024.f;
|
||||||
|
|
||||||
Brush::Brush()
|
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)
|
switch (m_Shape)
|
||||||
{
|
{
|
||||||
case CIRCLE:
|
case Shape::CIRCLE:
|
||||||
return m_Size;
|
return m_Size;
|
||||||
case SQUARE:
|
case Shape::SQUARE:
|
||||||
return m_Size;
|
return m_Size;
|
||||||
default:
|
default:
|
||||||
wxFAIL;
|
wxFAIL;
|
||||||
|
|
@ -108,7 +108,7 @@ std::vector<float> Brush::GetData() const
|
||||||
|
|
||||||
switch (m_Shape)
|
switch (m_Shape)
|
||||||
{
|
{
|
||||||
case CIRCLE:
|
case Shape::CIRCLE:
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// All calculations are done in units of half-tiles, since that
|
// All calculations are done in units of half-tiles, since that
|
||||||
|
|
@ -131,7 +131,7 @@ std::vector<float> Brush::GetData() const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQUARE:
|
case Shape::SQUARE:
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (int y = 0; y < height; ++y)
|
for (int y = 0; y < height; ++y)
|
||||||
|
|
@ -144,6 +144,17 @@ std::vector<float> Brush::GetData() const
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Brush::GetSize() const
|
||||||
|
{
|
||||||
|
return m_Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Brush::SetSize(int size)
|
||||||
|
{
|
||||||
|
m_Size = size;
|
||||||
|
Send();
|
||||||
|
}
|
||||||
|
|
||||||
float Brush::GetStrength() const
|
float Brush::GetStrength() const
|
||||||
{
|
{
|
||||||
return m_Strength;
|
return m_Strength;
|
||||||
|
|
@ -152,115 +163,54 @@ float Brush::GetStrength() const
|
||||||
void Brush::SetStrength(float strength)
|
void Brush::SetStrength(float strength)
|
||||||
{
|
{
|
||||||
m_Strength = strength;
|
m_Strength = strength;
|
||||||
|
Send();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Brush::SetCircle(int size)
|
void Brush::SetShape(Shape shape)
|
||||||
{
|
{
|
||||||
m_Shape = CIRCLE;
|
m_Shape = shape;
|
||||||
m_Size = size;
|
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)
|
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(_("Circle"));
|
||||||
shapes.Add(_("Square"));
|
shapes.Add(_("Square"));
|
||||||
|
|
||||||
// TODO (maybe): get rid of the extra static box, by not using wxRadioBox
|
// 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);
|
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);
|
wxFlexGridSizer* spinnerSizer = new wxFlexGridSizer(2, 5, 5);
|
||||||
spinnerSizer->AddGrowableCol(1);
|
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(brushSizeLabel, wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
||||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Strength")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL|wxALIGN_RIGHT));
|
spinnerSizer->Add(brushSizeCtrl, wxSizerFlags().Expand());
|
||||||
spinnerSizer->Add(new BrushStrengthCtrl(parent, *this), 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));
|
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.
|
* This file is part of 0 A.D.
|
||||||
*
|
*
|
||||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||||
|
|
@ -29,6 +29,8 @@ class Brush
|
||||||
friend class BrushSizeCtrl;
|
friend class BrushSizeCtrl;
|
||||||
friend class BrushStrengthCtrl;
|
friend class BrushStrengthCtrl;
|
||||||
public:
|
public:
|
||||||
|
enum class Shape { CIRCLE = 0, SQUARE};
|
||||||
|
|
||||||
Brush();
|
Brush();
|
||||||
~Brush();
|
~Brush();
|
||||||
|
|
||||||
|
|
@ -38,8 +40,10 @@ public:
|
||||||
int GetHeight() const;
|
int GetHeight() const;
|
||||||
std::vector<float> GetData() const;
|
std::vector<float> GetData() const;
|
||||||
|
|
||||||
void SetCircle(int size);
|
void SetShape(Shape shape);
|
||||||
void SetSquare(int size);
|
|
||||||
|
int GetSize() const;
|
||||||
|
void SetSize(int size);
|
||||||
|
|
||||||
float GetStrength() const;
|
float GetStrength() const;
|
||||||
void SetStrength(float strength);
|
void SetStrength(float strength);
|
||||||
|
|
@ -54,8 +58,7 @@ private:
|
||||||
// If active, send SetBrush message to the game
|
// If active, send SetBrush message to the game
|
||||||
void Send();
|
void Send();
|
||||||
|
|
||||||
enum BrushShape { CIRCLE = 0, SQUARE};
|
Shape m_Shape;
|
||||||
BrushShape m_Shape;
|
|
||||||
int m_Size;
|
int m_Size;
|
||||||
float m_Strength;
|
float m_Strength;
|
||||||
bool m_IsActive;
|
bool m_IsActive;
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ class FillTerrain : public StateDrivenTool<FillTerrain>
|
||||||
public:
|
public:
|
||||||
FillTerrain()
|
FillTerrain()
|
||||||
{
|
{
|
||||||
m_Brush.SetSquare(2);
|
m_Brush.SetShape(Brush::Shape::SQUARE);
|
||||||
|
m_Brush.SetSize(2);
|
||||||
SetState(&Waiting);
|
SetState(&Waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,8 @@ public:
|
||||||
{
|
{
|
||||||
SetState(&Waiting);
|
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:
|
public:
|
||||||
ReplaceTerrain()
|
ReplaceTerrain()
|
||||||
{
|
{
|
||||||
m_Brush.SetSquare(2);
|
m_Brush.SetShape(Brush::Shape::SQUARE);
|
||||||
|
m_Brush.SetSize(2);
|
||||||
SetState(&Waiting);
|
SetState(&Waiting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue