forked from mirrors/0ad
More reliable texture blending. Resource unloading. Minor fixes.
This was SVN commit r3106.
This commit is contained in:
@@ -301,10 +301,8 @@ void CGameView::RenderNoCull()
|
||||
|
||||
void CGameView::UnloadResources()
|
||||
{
|
||||
// Should probably do something like:
|
||||
// g_TexMan.UnloadTerrainTextures();
|
||||
// g_ObjMan.UnloadObjects();
|
||||
|
||||
g_ObjMan.UnloadObjects();
|
||||
g_TexMan.UnloadTerrainTextures();
|
||||
g_Renderer.UnloadAlphaMaps();
|
||||
g_Renderer.UnloadWaterTextures();
|
||||
}
|
||||
|
||||
@@ -37,19 +37,7 @@ template<typename T, typename S> static void delete_pair_2nd(std::pair<T,S> v) {
|
||||
|
||||
CObjectManager::~CObjectManager()
|
||||
{
|
||||
for (size_t i = 0; i < m_ObjectTypes.size(); i++) {
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_Objects.begin(),
|
||||
m_ObjectTypes[i].m_Objects.end(),
|
||||
delete_pair_2nd<ObjectKey, CObjectEntry*>
|
||||
);
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_ObjectBases.begin(),
|
||||
m_ObjectTypes[i].m_ObjectBases.end(),
|
||||
delete_pair_2nd<CStr, CObjectBase*>
|
||||
);
|
||||
}
|
||||
delete m_SelectedThing;
|
||||
UnloadObjects();
|
||||
}
|
||||
|
||||
|
||||
@@ -176,6 +164,26 @@ int CObjectManager::LoadObjects()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CObjectManager::UnloadObjects()
|
||||
{
|
||||
for (size_t i = 0; i < m_ObjectTypes.size(); i++) {
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_Objects.begin(),
|
||||
m_ObjectTypes[i].m_Objects.end(),
|
||||
delete_pair_2nd<ObjectKey, CObjectEntry*>
|
||||
);
|
||||
std::for_each(
|
||||
m_ObjectTypes[i].m_ObjectBases.begin(),
|
||||
m_ObjectTypes[i].m_ObjectBases.end(),
|
||||
delete_pair_2nd<CStr, CObjectBase*>
|
||||
);
|
||||
}
|
||||
m_ObjectTypes.clear();
|
||||
|
||||
delete m_SelectedThing;
|
||||
m_SelectedThing = NULL;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// For ScEd:
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
~CObjectManager();
|
||||
|
||||
int LoadObjects();
|
||||
void UnloadObjects();
|
||||
|
||||
void AddObjectType(const char* name);
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ float CTerrain::FlattenArea(float x0,float x1,float z0,float z1)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CTerrain::MakeDirty(int x0, int z0, int x1, int z1)
|
||||
void CTerrain::MakeDirty(int x0, int z0, int x1, int z1, int dirtyFlags)
|
||||
{
|
||||
// flag vertex data as dirty for affected patches, and rebuild bounds of these patches
|
||||
int px0 = clamp((x0/PATCH_SIZE)-1, 0, (int)m_MapSizePatches);
|
||||
@@ -408,19 +408,21 @@ void CTerrain::MakeDirty(int x0, int z0, int x1, int z1)
|
||||
for (int j = pz0; j < pz1; j++) {
|
||||
for (int i = px0; i < px1; i++) {
|
||||
CPatch* patch = GetPatch(i,j);
|
||||
patch->CalcBounds();
|
||||
patch->SetDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
if (dirtyFlags & RENDERDATA_UPDATE_VERTICES)
|
||||
patch->CalcBounds();
|
||||
patch->SetDirty(dirtyFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTerrain::MakeDirty()
|
||||
void CTerrain::MakeDirty(int dirtyFlags)
|
||||
{
|
||||
for (u32 j = 0; j < m_MapSizePatches; j++) {
|
||||
for (u32 i = 0; i < m_MapSizePatches; i++) {
|
||||
CPatch* patch = GetPatch(i,j);
|
||||
patch->CalcBounds();
|
||||
patch->SetDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
if (dirtyFlags & RENDERDATA_UPDATE_VERTICES)
|
||||
patch->CalcBounds();
|
||||
patch->SetDirty(dirtyFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,9 +77,9 @@ public:
|
||||
float FlattenArea(float x0,float x1,float z0,float z1);
|
||||
|
||||
// mark a specific square of tiles as dirty - use this after modifying the heightmap
|
||||
void MakeDirty(int x0, int z0, int x1, int z1);
|
||||
void MakeDirty(int x0, int z0, int x1, int z1, int dirtyFlags);
|
||||
// mark the entire map as dirty
|
||||
void MakeDirty();
|
||||
void MakeDirty(int dirtyFlags);
|
||||
|
||||
private:
|
||||
// delete any data allocated by this terrain
|
||||
|
||||
@@ -28,16 +28,24 @@ CTextureManager::CTextureManager():
|
||||
|
||||
CTextureManager::~CTextureManager()
|
||||
{
|
||||
for (size_t i=0;i<m_TextureEntries.size();i++) {
|
||||
UnloadTerrainTextures();
|
||||
}
|
||||
|
||||
void CTextureManager::UnloadTerrainTextures()
|
||||
{
|
||||
for (size_t i=0; i < m_TextureEntries.size(); i++)
|
||||
delete m_TextureEntries[i];
|
||||
}
|
||||
|
||||
TerrainGroupMap::iterator it=m_TerrainGroups.begin();
|
||||
m_TextureEntries.clear();
|
||||
|
||||
TerrainGroupMap::iterator it = m_TerrainGroups.begin();
|
||||
while (it != m_TerrainGroups.end())
|
||||
{
|
||||
delete it->second;
|
||||
++it;
|
||||
}
|
||||
m_TerrainGroups.clear();
|
||||
|
||||
m_LastGroupIndex = 0;
|
||||
}
|
||||
|
||||
CTextureEntry* CTextureManager::FindTexture(CStr tag)
|
||||
|
||||
@@ -83,6 +83,8 @@ public:
|
||||
// Find all XML's in the directory (with subdirs) and try to load them as
|
||||
// terrain XML's
|
||||
int LoadTerrainTextures();
|
||||
|
||||
void UnloadTerrainTextures();
|
||||
|
||||
CTextureEntry* FindTexture(CStr tag);
|
||||
CTextureEntry* FindTexture(Handle handle);
|
||||
|
||||
@@ -86,6 +86,7 @@ void CPatchRData::BuildBlends()
|
||||
m_BlendIndices.clear();
|
||||
m_BlendSplats.clear();
|
||||
m_BlendVertices.clear();
|
||||
m_BlendVertexIndices.clear();
|
||||
|
||||
// get index of this patch (unused)
|
||||
//int px=m_Patch->m_X;
|
||||
@@ -110,7 +111,7 @@ void CPatchRData::BuildBlends()
|
||||
for (int m=-1;m<=1;m++) {
|
||||
for (int k=-1;k<=1;k++) {
|
||||
CMiniPatch* nmp=terrain->GetTile(gx+k,gz+m);
|
||||
if (nmp) {
|
||||
if (nmp && nmp->Tex1 != mp->Tex1) {
|
||||
if (nmp->Tex1Priority>mp->Tex1Priority || (nmp->Tex1Priority==mp->Tex1Priority && nmp->Tex1>mp->Tex1)) {
|
||||
STex tex;
|
||||
tex.m_Handle=nmp->Tex1;
|
||||
|
||||
@@ -601,7 +601,7 @@ void TransparentRenderModifier::PrepareTexture(uint UNUSED(pass), CTexture* text
|
||||
|
||||
void TransparentRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model))
|
||||
{
|
||||
// No per-model setup nececssary
|
||||
// No per-model setup necessary
|
||||
}
|
||||
|
||||
|
||||
@@ -654,5 +654,5 @@ void TransparentShadowRenderModifier::PrepareTexture(uint UNUSED(pass), CTexture
|
||||
|
||||
void TransparentShadowRenderModifier::PrepareModel(uint UNUSED(pass), CModel* UNUSED(model))
|
||||
{
|
||||
// No per-model setup nececssary
|
||||
// No per-model setup necessary
|
||||
}
|
||||
|
||||
@@ -28,6 +28,19 @@ static void LoadMap(void*)
|
||||
// TODO: Make this a non-undoable command
|
||||
}
|
||||
|
||||
static void SaveMap(void*)
|
||||
{
|
||||
wxFileDialog dlg (NULL, wxFileSelectorPromptStr, Datafile::GetDataDirectory()+_T("/mods/official/maps/scenarios"),
|
||||
_T(""), _T("PMP files (*.pmp)|*.pmp|All files (*.*)|*.*"), wxSAVE|wxOVERWRITE_PROMPT);
|
||||
|
||||
if (dlg.ShowModal() == wxID_OK)
|
||||
{
|
||||
// TODO: Work when the map is not in .../maps/scenarios/
|
||||
std::wstring map = dlg.GetFilename().c_str();
|
||||
POST_MESSAGE(SaveMap(map));
|
||||
}
|
||||
}
|
||||
|
||||
static void GenerateMap(void*)
|
||||
{
|
||||
POST_MESSAGE(GenerateMap(9));
|
||||
@@ -56,6 +69,7 @@ MapSidebar::MapSidebar(wxWindow* parent)
|
||||
// TODO: Intercept arrow keys and send them to the GL window
|
||||
|
||||
m_MainSizer->Add(new ActionButton(this, _T("Load existing map"), &LoadMap, NULL));
|
||||
m_MainSizer->Add(new ActionButton(this, _T("Save map"), &SaveMap, NULL));
|
||||
m_MainSizer->Add(new ActionButton(this, _T("Generate empty map"), &GenerateMap, NULL));
|
||||
|
||||
{
|
||||
|
||||
@@ -52,20 +52,25 @@ class TextureNotebookPage : public wxPanel
|
||||
{
|
||||
public:
|
||||
TextureNotebookPage(wxWindow* parent, const wxString& name)
|
||||
: wxPanel(parent, wxID_ANY), m_Name(name), m_Loaded(false)
|
||||
: wxPanel(parent, wxID_ANY), m_Name(name), m_ListCtrl(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
void OnDisplay()
|
||||
{
|
||||
if (m_Loaded)
|
||||
if (m_ListCtrl)
|
||||
{
|
||||
int sel = m_ListCtrl->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);
|
||||
if (sel != -1)
|
||||
SetSelection(m_ListCtrl->GetItemData(sel));
|
||||
return;
|
||||
}
|
||||
|
||||
m_TextureNames.Clear();
|
||||
|
||||
wxSizer* sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxListCtrl* list = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ICON | wxLC_SINGLE_SEL | wxLC_AUTOARRANGE);
|
||||
m_ListCtrl = new wxListCtrl(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLC_ICON | wxLC_SINGLE_SEL | wxLC_AUTOARRANGE);
|
||||
|
||||
const int imageWidth = 64;
|
||||
const int imageHeight = 32;
|
||||
@@ -93,25 +98,29 @@ public:
|
||||
item.SetId(i);
|
||||
item.SetImage(i);
|
||||
|
||||
list->InsertItem(item);
|
||||
m_ListCtrl->InsertItem(item);
|
||||
++i;
|
||||
}
|
||||
list->AssignImageList(imglist, wxIMAGE_LIST_NORMAL);
|
||||
m_ListCtrl->AssignImageList(imglist, wxIMAGE_LIST_NORMAL);
|
||||
|
||||
sizer->Add(list, wxSizerFlags().Expand().Proportion(1));
|
||||
sizer->Add(m_ListCtrl, wxSizerFlags().Expand().Proportion(1));
|
||||
SetSizer(sizer);
|
||||
Layout(); // required to make things size correctly
|
||||
|
||||
m_Loaded = true;
|
||||
}
|
||||
|
||||
void OnSelect(wxListEvent& evt)
|
||||
{
|
||||
g_SelectedTexture = m_TextureNames[evt.GetData()];
|
||||
SetSelection(evt.GetData());
|
||||
}
|
||||
|
||||
void SetSelection(int n)
|
||||
{
|
||||
if (n >= 0 && n < (int)m_TextureNames.GetCount())
|
||||
g_SelectedTexture = m_TextureNames[n];
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_Loaded;
|
||||
wxListCtrl* m_ListCtrl;
|
||||
wxString m_Name;
|
||||
wxArrayString m_TextureNames;
|
||||
|
||||
|
||||
@@ -63,6 +63,7 @@ MESSAGEHANDLER(Scroll)
|
||||
g_Game->GetView()->GetCamera()->BuildCameraRay(x, y, origin, dir);
|
||||
dir *= targetDistance;
|
||||
camera.Translate(targetPos - dir - origin);
|
||||
g_Game->GetView()->GetCamera()->UpdateFrustum();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -115,6 +116,7 @@ MESSAGEHANDLER(RotateAround)
|
||||
camera._21 = 0.f; // (_21 = Y component returned by GetLeft())
|
||||
|
||||
camera.Translate(focusPos + offset);
|
||||
g_Game->GetView()->GetCamera()->UpdateFrustum();
|
||||
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
|
||||
@@ -88,19 +88,19 @@ BEGIN_COMMAND(AlterElevation)
|
||||
m_TerrainDelta.RaiseVertex(x0+dx, y0+dy, amount*b);
|
||||
}
|
||||
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H);
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H, RENDERDATA_UPDATE_VERTICES);
|
||||
}
|
||||
|
||||
void Undo()
|
||||
{
|
||||
m_TerrainDelta.Undo();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
}
|
||||
|
||||
void Redo()
|
||||
{
|
||||
m_TerrainDelta.Redo();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(RENDERDATA_UPDATE_VERTICES);
|
||||
}
|
||||
|
||||
void MergeWithSelf(cAlterElevation* prev)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "graphics/Patch.h"
|
||||
#include "graphics/TextureManager.h"
|
||||
#include "graphics/TextureEntry.h"
|
||||
#include "graphics/MapWriter.h"
|
||||
#include "ps/Game.h"
|
||||
#include "ps/GameAttributes.h"
|
||||
#include "ps/Loader.h"
|
||||
@@ -96,4 +97,10 @@ MESSAGEHANDLER(LoadMap)
|
||||
StartGame();
|
||||
}
|
||||
|
||||
MESSAGEHANDLER(SaveMap)
|
||||
{
|
||||
CMapWriter writer;
|
||||
writer.SaveMap(CStr(L"maps/scenarios/" + msg->filename), g_Game->GetWorld()->GetTerrain(), &g_LightEnv, g_Game->GetWorld()->GetUnitManager());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,43 +115,19 @@ BEGIN_COMMAND(PaintTerrain)
|
||||
if ((unsigned)x >= m_VertsPerSide-1 || (unsigned)y >= m_VertsPerSide-1)
|
||||
return;
|
||||
|
||||
set(x,y, TerrainTile(tex, priority == ePaintTerrainPriority::HIGH ? 1 : -1));
|
||||
/* (TODO: fix all this)
|
||||
// Priority system: If the new tile should have a high priority,
|
||||
// set it to one plus the maximum priority of all surrounding tiles
|
||||
// TODO: the blending system is broken when adjacent tiles have
|
||||
// the same priority but different textures
|
||||
int greatestSame = 0;
|
||||
int greatestDiff = 0;
|
||||
// (so that it's definitely the highest).
|
||||
// Similar for low priority.
|
||||
int greatest = 0;
|
||||
int scale = (priority == ePaintTerrainPriority::HIGH ? +1 : -1);
|
||||
CMiniPatch* tile;
|
||||
#define TILE(dx, dy) \
|
||||
tile = m_Terrain->GetTile(x dx, y dy); \
|
||||
if (tile) { \
|
||||
if (tile->Tex1 == tex && tile->Tex1Priority*scale > greatestSame) \
|
||||
greatestSame = tile->Tex1Priority*scale; \
|
||||
else if (tile->Tex1 != tex && tile->Tex1Priority*scale > greatestDiff) \
|
||||
greatestDiff = tile->Tex1Priority*scale; \
|
||||
}
|
||||
#define TILE(dx, dy) tile = m_Terrain->GetTile(x dx, y dy); if (tile && tile->Tex1Priority*scale > greatest) greatest = tile->Tex1Priority*scale;
|
||||
TILE(-1, -1) TILE(+0, -1) TILE(+1, -1)
|
||||
TILE(-1, +0) TILE(+1, +0)
|
||||
TILE(-1, +1) TILE(+0, +1) TILE(+1, +1)
|
||||
#undef TILE
|
||||
// If the greatest priority is of the same texture as this one,
|
||||
// give this one the same priority (to minimise confusion in the
|
||||
// blending system)
|
||||
if (greatestSame > greatestDiff)
|
||||
{
|
||||
tile = m_Terrain->GetTile(x,y);
|
||||
// Don't bother updating tiles that are exactly the same
|
||||
// (e.g. when dragging big brushes around)
|
||||
if (tile->Tex1 != tex || tile->Tex1Priority != greatestSame)
|
||||
set(x,y, TerrainTile(tex, greatestSame*scale));
|
||||
}
|
||||
// Set this texture to have a priority greater than the surrounding ones
|
||||
else
|
||||
set(x,y, TerrainTile(tex, (greatestDiff+1)*scale));
|
||||
*/
|
||||
set(x,y, TerrainTile(tex, (greatest+1)*scale));
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -204,19 +180,19 @@ BEGIN_COMMAND(PaintTerrain)
|
||||
m_TerrainDelta.PaintTile(x0+dx, y0+dy, texture, d->priority);
|
||||
}
|
||||
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H);
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(x0, y0, x0+g_CurrentBrush.m_W, y0+g_CurrentBrush.m_H, RENDERDATA_UPDATE_INDICES);
|
||||
}
|
||||
|
||||
void Undo()
|
||||
{
|
||||
m_TerrainDelta.Undo();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(RENDERDATA_UPDATE_INDICES);
|
||||
}
|
||||
|
||||
void Redo()
|
||||
{
|
||||
m_TerrainDelta.Redo();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty();
|
||||
g_Game->GetWorld()->GetTerrain()->MakeDirty(RENDERDATA_UPDATE_INDICES);
|
||||
}
|
||||
|
||||
void MergeWithSelf(cPaintTerrain* prev)
|
||||
|
||||
@@ -66,5 +66,8 @@ bool InputProcessor::ProcessInput(GameLoopState* state)
|
||||
moved = true;
|
||||
}
|
||||
|
||||
if (moved)
|
||||
camera->UpdateFrustum();
|
||||
|
||||
return moved;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ MESSAGE(LoadMap,
|
||||
((std::wstring, filename))
|
||||
);
|
||||
|
||||
MESSAGE(SaveMap,
|
||||
((std::wstring, filename))
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MESSAGE(RenderStyle,
|
||||
|
||||
Reference in New Issue
Block a user