Atlas: more flexible brushes
This was SVN commit r2868.
This commit is contained in:
parent
29d6f420fd
commit
8bc8bcb740
@ -236,7 +236,7 @@ void CTerrain::Resize(u32 size)
|
||||
|
||||
// now copy over rows of data
|
||||
u32 j;
|
||||
u16* src=m_Heightmap;
|
||||
u16* src=m_Heightmap;
|
||||
u16* dst=newHeightmap;
|
||||
u32 copysize=newMapSize>m_MapSize ? m_MapSize : newMapSize;
|
||||
for (j=0;j<copysize;j++) {
|
||||
|
@ -58,6 +58,7 @@ Global
|
||||
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Testing.ActiveCfg = Release|Win32
|
||||
{228B468D-3C2E-45BF-9833-C626E1A35B04}.Testing.Build.0 = Release|Win32
|
||||
{E859DDC0-224A-41F6-B09F-E320EC8DDA35}.Debug.ActiveCfg = Debug|Win32
|
||||
{E859DDC0-224A-41F6-B09F-E320EC8DDA35}.Debug.Build.0 = Debug|Win32
|
||||
{E859DDC0-224A-41F6-B09F-E320EC8DDA35}.Release.ActiveCfg = Release|Win32
|
||||
{E859DDC0-224A-41F6-B09F-E320EC8DDA35}.Release.Build.0 = Release|Win32
|
||||
{E859DDC0-224A-41F6-B09F-E320EC8DDA35}.Testing.ActiveCfg = Debug|Win32
|
||||
|
@ -358,6 +358,16 @@
|
||||
RelativePath=".\ScenarioEditor\Sections\Common\Sidebar.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Terrain"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\ScenarioEditor\Sections\Terrain\Terrain.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScenarioEditor\Sections\Terrain\Terrain.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Tools"
|
||||
@ -368,6 +378,12 @@
|
||||
<Filter
|
||||
Name="Common"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\ScenarioEditor\Tools\Common\Brushes.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScenarioEditor\Tools\Common\Brushes.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ScenarioEditor\Tools\Common\Tools.cpp">
|
||||
</File>
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "wx/regex.h"
|
||||
#include "wx/image.h"
|
||||
#include "wx/splitter.h"
|
||||
#include "wx/spinctrl.h"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
#include "Sections/Map/Map.h"
|
||||
#include "Sections/Terrain/Terrain.h"
|
||||
|
||||
#include "tools/Common/Tools.h"
|
||||
|
||||
@ -270,6 +271,8 @@ AtlasWindowCommandProc& ScenarioEditor::GetCommandProc() { return g_CommandProc;
|
||||
ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
: wxFrame(parent, wxID_ANY, _("Atlas - Scenario Editor"), wxDefaultPosition, wxSize(1024, 768))
|
||||
{
|
||||
// wxLog::SetTraceMask(wxTraceMessages);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
|
||||
@ -334,7 +337,11 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
|
||||
// Set up sidebars:
|
||||
|
||||
Sidebar* sidebar = new MapSidebar(splitter);
|
||||
// TODO: wxWidgets bug (http://sourceforge.net/tracker/index.php?func=detail&aid=1298803&group_id=9863&atid=109863)
|
||||
// - pressing menu keys (e.g. alt+f) with notebook tab focussed causes application to freeze
|
||||
wxNotebook* sidebar = new wxNotebook(splitter, wxID_ANY);
|
||||
sidebar->AddPage(new MapSidebar(sidebar), _("Map"), false);
|
||||
sidebar->AddPage(new TerrainSidebar(sidebar), _("Terrain"), false);
|
||||
|
||||
// Build layout:
|
||||
|
||||
@ -360,7 +367,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
|
||||
USE_TOOL(AlterElevation);
|
||||
|
||||
// Set up a timer to make sure tool-updates happen frequently (in addition
|
||||
// to the idle handler (which makes then happen more frequently if there's nothing
|
||||
// to the idle handler (which makes them happen more frequently if there's nothing
|
||||
// else to do))
|
||||
m_Timer.SetOwner(this);
|
||||
m_Timer.Start(20);
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef SIDEBAR_H__
|
||||
#define SIDEBAR_H__
|
||||
|
||||
class Sidebar : public wxPanel
|
||||
{
|
||||
public:
|
||||
@ -6,3 +9,5 @@ public:
|
||||
protected:
|
||||
wxSizer* m_MainSizer; // vertical box sizer
|
||||
};
|
||||
|
||||
#endif // SIDEBAR_H__
|
||||
|
@ -4,4 +4,4 @@ class MapSidebar : public Sidebar
|
||||
{
|
||||
public:
|
||||
MapSidebar(wxWindow* parent);
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,35 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Terrain.h"
|
||||
|
||||
#include "ActionButton.h"
|
||||
#include "Datafile.h"
|
||||
#include "ScenarioEditor/Tools/Common/Brushes.h"
|
||||
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
#include "wx/spinctrl.h"
|
||||
|
||||
TerrainSidebar::TerrainSidebar(wxWindow* parent)
|
||||
: Sidebar(parent)
|
||||
{
|
||||
// TODO: Less ugliness
|
||||
// TODO: Intercept arrow keys and send them to the GL window
|
||||
|
||||
m_MainSizer->Add(new wxStaticText(this, wxID_ANY, _T("TODO: Make this much less ugly\n")));
|
||||
|
||||
{
|
||||
wxSizer* sizer = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Elevation tools"));
|
||||
sizer->Add(new wxButton(this, wxID_ANY, _("Modify"), wxDefaultPosition, wxSize(50,20)));
|
||||
sizer->Add(new wxButton(this, wxID_ANY, _("Smooth"), wxDefaultPosition, wxSize(50,20)));
|
||||
sizer->Add(new wxButton(this, wxID_ANY, _("Sample"), wxDefaultPosition, wxSize(50,20)));
|
||||
m_MainSizer->Add(sizer);
|
||||
}
|
||||
|
||||
{
|
||||
wxSizer* sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Brush"));
|
||||
g_Brush_Elevation.CreateUI(this, sizer);
|
||||
m_MainSizer->Add(sizer);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
#include "../Common/Sidebar.h"
|
||||
|
||||
class TerrainSidebar : public Sidebar
|
||||
{
|
||||
public:
|
||||
TerrainSidebar(wxWindow* parent);
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Common/Tools.h"
|
||||
|
||||
#include "Common/Brushes.h"
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
using AtlasMessage::Position;
|
||||
@ -22,10 +22,7 @@ public:
|
||||
|
||||
void OnEnable(AlterElevation*)
|
||||
{
|
||||
int w = 2, h = 3;
|
||||
float* data = new float[w*h];
|
||||
for (int i = 0; i < w*h; ++i) data[i] = 1.f;
|
||||
POST_COMMAND(SetBrush(w, h, data));
|
||||
g_Brush_Elevation.MakeActive();
|
||||
}
|
||||
|
||||
void OnDisable(AlterElevation*)
|
||||
|
@ -0,0 +1,172 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "Brushes.h"
|
||||
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
Brush::Brush()
|
||||
: m_BrushShape(SQUARE), m_BrushSize(4), m_IsActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
Brush::~Brush()
|
||||
{
|
||||
}
|
||||
|
||||
int Brush::GetWidth()
|
||||
{
|
||||
switch (m_BrushShape)
|
||||
{
|
||||
case CIRCLE:
|
||||
return m_BrushSize*2 + 1;
|
||||
case SQUARE:
|
||||
return m_BrushSize;
|
||||
default:
|
||||
wxFAIL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int Brush::GetHeight()
|
||||
{
|
||||
switch (m_BrushShape)
|
||||
{
|
||||
case CIRCLE:
|
||||
return m_BrushSize*2 + 1;
|
||||
case SQUARE:
|
||||
return m_BrushSize;
|
||||
default:
|
||||
wxFAIL;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
float* Brush::GetNewedData()
|
||||
{
|
||||
int width = GetWidth();
|
||||
int height = GetHeight();
|
||||
|
||||
float* data = new float[width*height];
|
||||
|
||||
switch (m_BrushShape)
|
||||
{
|
||||
case CIRCLE:
|
||||
{
|
||||
int i = 0;
|
||||
for (int y = -m_BrushSize; y <= m_BrushSize; ++y)
|
||||
{
|
||||
for (int x = -m_BrushSize; x <= m_BrushSize; ++x)
|
||||
{
|
||||
// TODO: proper circle rasterization, with variable smoothness etc
|
||||
if (x*x + y*y <= m_BrushSize*m_BrushSize - 4)
|
||||
data[i++] = 1.f;
|
||||
else if (x*x + y*y <= m_BrushSize*m_BrushSize)
|
||||
data[i++] = 0.5f;
|
||||
else
|
||||
data[i++] = 0.f;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SQUARE:
|
||||
{
|
||||
int i = 0;
|
||||
for (int y = 0; y < height; ++y)
|
||||
for (int x = 0; x < width; ++x)
|
||||
data[i++] = 1.f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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_BrushShape);
|
||||
}
|
||||
|
||||
private:
|
||||
Brush& m_Brush;
|
||||
|
||||
void OnChange(wxCommandEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_Brush.m_BrushShape = (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_BrushSize), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 50, brush.m_BrushSize),
|
||||
m_Brush(brush)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
Brush& m_Brush;
|
||||
|
||||
void OnChange(wxSpinEvent& WXUNUSED(evt))
|
||||
{
|
||||
m_Brush.m_BrushSize = GetValue();
|
||||
m_Brush.Send();
|
||||
}
|
||||
|
||||
DECLARE_EVENT_TABLE();
|
||||
};
|
||||
BEGIN_EVENT_TABLE(BrushSizeCtrl, wxSpinCtrl)
|
||||
EVT_SPINCTRL(wxID_ANY, BrushSizeCtrl::OnChange)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
|
||||
void Brush::CreateUI(wxWindow* parent, wxSizer* sizer)
|
||||
{
|
||||
wxArrayString shapes; // Must match order of BrushShape enum
|
||||
shapes.Add(_("Square"));
|
||||
shapes.Add(_("Circle"));
|
||||
// TODO (maybe): get rid of the extra static box, by not using wxRadioBox
|
||||
sizer->Add(new BrushShapeCtrl(parent, shapes, *this));
|
||||
|
||||
wxSizer* spinnerSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
spinnerSizer->Add(new wxStaticText(parent, wxID_ANY, _("Size")));
|
||||
spinnerSizer->Add(new BrushSizeCtrl(parent, *this));
|
||||
sizer->Add(spinnerSizer);
|
||||
}
|
||||
|
||||
void Brush::MakeActive()
|
||||
{
|
||||
if (g_Brush_CurrentlyActive)
|
||||
g_Brush_CurrentlyActive->m_IsActive = false;
|
||||
|
||||
g_Brush_CurrentlyActive = this;
|
||||
m_IsActive = true;
|
||||
|
||||
Send();
|
||||
}
|
||||
|
||||
void Brush::Send()
|
||||
{
|
||||
if (m_IsActive)
|
||||
POST_COMMAND(SetBrush(GetWidth(), GetHeight(), GetNewedData()));
|
||||
}
|
||||
|
||||
|
||||
Brush g_Brush_Elevation;
|
||||
Brush* g_Brush_CurrentlyActive = NULL;
|
@ -0,0 +1,39 @@
|
||||
#ifndef BRUSHES_H__
|
||||
#define BRUSHES_H__
|
||||
|
||||
class BrushShapeCtrl;
|
||||
class BrushSizeCtrl;
|
||||
|
||||
class Brush
|
||||
{
|
||||
friend class BrushShapeCtrl;
|
||||
friend class BrushSizeCtrl;
|
||||
public:
|
||||
Brush();
|
||||
~Brush();
|
||||
|
||||
int GetWidth();
|
||||
int GetHeight();
|
||||
float* GetNewedData(); // freshly allocated via new[]
|
||||
|
||||
void CreateUI(wxWindow* parent, wxSizer* sizer);
|
||||
|
||||
// Set this brush to be active - sends SetBrush message now, and also
|
||||
// whenever the brush is altered (until a different one is activated).
|
||||
void MakeActive();
|
||||
|
||||
private:
|
||||
// If active, send SetBrush message to the game
|
||||
void Send();
|
||||
|
||||
enum BrushShape { SQUARE = 0, CIRCLE };
|
||||
BrushShape m_BrushShape;
|
||||
int m_BrushSize;
|
||||
bool m_IsActive;
|
||||
};
|
||||
|
||||
extern Brush g_Brush_Elevation;
|
||||
|
||||
extern Brush* g_Brush_CurrentlyActive;
|
||||
|
||||
#endif // BRUSHES_H__
|
@ -5,6 +5,7 @@
|
||||
#include "ps/Game.h"
|
||||
#include "graphics/Terrain.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "maths/MathUtil.h"
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
@ -22,6 +23,8 @@ void Brush::SetData(int w, int h, const float* data)
|
||||
{
|
||||
m_W = w;
|
||||
m_H = h;
|
||||
|
||||
delete[] m_Data;
|
||||
m_Data = data;
|
||||
}
|
||||
|
||||
@ -52,7 +55,6 @@ void Brush::Render()
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
glColor3f(0.f, 1.f, 0.f);
|
||||
|
||||
int x0, y0;
|
||||
GetBottomRight(x0, y0);
|
||||
@ -63,6 +65,8 @@ void Brush::Render()
|
||||
{
|
||||
for (int dx = 0; dx < m_W; ++dx)
|
||||
{
|
||||
glColor3f(0.f, clamp(m_Data[dx + dy*m_W], 0.f, 1.f), 0.f);
|
||||
|
||||
CVector3D pos;
|
||||
terrain->CalcPosition(x0+dx, y0+dy, pos);
|
||||
glVertex3f(pos.X, pos.Y, pos.Z);
|
||||
|
@ -54,10 +54,14 @@ BEGIN_COMMAND(AlterElevation)
|
||||
g_CurrentBrush.GetBottomRight(x0, y0);
|
||||
for (int dy = 0; dy < g_CurrentBrush.m_H; ++dy)
|
||||
for (int dx = 0; dx < g_CurrentBrush.m_W; ++dx)
|
||||
if (g_CurrentBrush.Get(dx, dy)) // TODO: variable raise amount?
|
||||
terrain->RaiseVertex(x0+dx, y0+dy, amount);
|
||||
{
|
||||
// TODO: proper variable raise amount (store floats in terrain delta array?)
|
||||
float b = g_CurrentBrush.Get(dx, dy);
|
||||
if (b)
|
||||
terrain->RaiseVertex(x0+dx, y0+dy, amount*b);
|
||||
}
|
||||
|
||||
terrain->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W-1, y0+g_CurrentBrush.m_H-1);
|
||||
terrain->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H);
|
||||
}
|
||||
|
||||
void Undo()
|
||||
|
Loading…
Reference in New Issue
Block a user