Atlas: more flexible brushes

This was SVN commit r2868.
This commit is contained in:
Ykkrosh 2005-10-08 03:55:21 +00:00
parent 29d6f420fd
commit 8bc8bcb740
14 changed files with 301 additions and 13 deletions

View File

@ -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++) {

View File

@ -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

View File

@ -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>

View 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>

View File

@ -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);

View File

@ -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__

View File

@ -4,4 +4,4 @@ class MapSidebar : public Sidebar
{
public:
MapSidebar(wxWindow* parent);
};
};

View File

@ -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);
}
}

View File

@ -0,0 +1,7 @@
#include "../Common/Sidebar.h"
class TerrainSidebar : public Sidebar
{
public:
TerrainSidebar(wxWindow* parent);
};

View File

@ -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*)

View File

@ -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;

View File

@ -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__

View File

@ -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);

View File

@ -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()