1
0
forked from 0ad/0ad

ScEd: Added unit deletion. Made zoom less frustrating. Let >2 players work.

Fixed random actor props.

This was SVN commit r2109.
This commit is contained in:
Ykkrosh 2005-04-03 05:02:00 +00:00
parent a948e4687b
commit 6a0b5fa0ab
17 changed files with 250 additions and 134 deletions

View File

@ -17,6 +17,7 @@
#include "SkeletonAnimManager.h"
#include "MeshManager.h"
#include "lib/res/ogl_tex.h"
#include "lib/res/h_mgr.h"
#include "ps/CLogger.h"
#define LOG_CATEGORY "graphics"
@ -366,6 +367,7 @@ CModel* CModel::Clone() const
clone->m_ObjectBounds=m_ObjectBounds;
clone->InitModel(m_pModelDef);
clone->SetTexture(m_Texture);
if (m_Texture.GetHandle()) h_add_ref(m_Texture.GetHandle());
clone->SetMaterial(m_Material);
clone->SetAnimation(m_Anim);
clone->SetPlayerID(m_PlayerID);

View File

@ -2,6 +2,7 @@
#include "ObjectBase.h"
#include "ObjectManager.h"
#include "Xeromyces.h"
#include "CLogger.h"
@ -352,9 +353,41 @@ void CObjectBase::CalculateVariation(std::set<CStr>& strings, variation_key& cho
}
}
assert(randNum < 0); // which should always happen; otherwise it
// wouldn't have chosen any of the variants.
assert(randNum < 0);
// This should always happen; otherwise it
// wouldn't have chosen any of the variants.
}
assert(choices.size() == m_Variants.size());
// Also, make choices for all props:
// Work out which props have been chosen
std::map<CStr, CStr> chosenProps;
CObjectBase::variation_key::const_iterator choice_it = choices.begin();
for (std::vector<std::vector<CObjectBase::Variant> >::iterator grp = m_Variants.begin();
grp != m_Variants.end();
++grp)
{
CObjectBase::Variant& var (grp->at(*(choice_it++)));
for (std::vector<CObjectBase::Prop>::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it)
{
chosenProps[it->m_PropPointName] = it->m_ModelName;
}
}
// Load each prop, and call CalculateVariation on them:
for (std::map<CStr, CStr>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
{
CObjectBase* prop = g_ObjMan.FindObjectBase(it->second);
if (prop)
{
variation_key propChoices;
prop->CalculateVariation(strings, propChoices);
choices.insert(choices.end(), propChoices.begin(), propChoices.end());
}
}
// (TODO: This seems rather fragile, e.g. if props fail to load)
}

View File

@ -40,20 +40,68 @@ CObjectEntry::~CObjectEntry()
delete m_Model;
}
bool CObjectEntry::BuildModel()
bool CObjectEntry::BuildRandomVariant(CObjectBase::variation_key& vars, CObjectBase::variation_key::iterator& vars_it)
{
// check we've enough data to consider building the object
if (m_ModelName.Length()==0 || m_TextureName.Length()==0) {
return false;
CStr chosenTexture;
CStr chosenModel;
std::map<CStr, CObjectBase::Prop> chosenProps;
std::map<CStr, CObjectBase::Anim> chosenAnims;
// For each group in m_Base->m_Variants, take whichever variant is specified
// by 'vars', and then store its data into the 'chosen' variables. If data
// is specified more than once, the last value overrides all previous ones.
for (std::vector<std::vector<CObjectBase::Variant> >::iterator grp = m_Base->m_Variants.begin();
grp != m_Base->m_Variants.end();
++grp)
{
if (vars_it == vars.end())
{
debug_warn("BuildRandomVariant is using too many vars");
return false;
}
// Get the correct variant
CObjectBase::Variant& var (grp->at(*(vars_it++)));
// Apply its data:
if (var.m_TextureFilename.Length())
chosenTexture = var.m_TextureFilename;
if (var.m_ModelFilename.Length())
chosenModel = var.m_ModelFilename;
for (std::vector<CObjectBase::Prop>::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it)
chosenProps[it->m_PropPointName] = *it;
for (std::vector<CObjectBase::Anim>::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it)
chosenAnims[it->m_AnimName] = *it;
}
// Copy the chosen data onto this model:
m_TextureName = chosenTexture;
m_ModelName = chosenModel;
for (std::map<CStr, CObjectBase::Prop>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
m_Props.push_back(it->second);
for (std::map<CStr, CObjectBase::Anim>::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it)
m_Animations.push_back(it->second);
// Build the model:
// get the root directory of this object
CStr dirname=g_ObjMan.m_ObjectTypes[m_Type].m_Name;
CStr dirname = g_ObjMan.m_ObjectTypes[m_Type].m_Name;
// remember the old model so we can replace any models using it later on
CModelDefPtr oldmodeldef=m_Model ? m_Model->GetModelDef() : CModelDefPtr();
CModelDefPtr oldmodeldef = m_Model ? m_Model->GetModelDef() : CModelDefPtr();
const char* modelfilename = m_ModelName.c_str();
const char* modelfilename = m_ModelName;
// try and create a model
CModelDefPtr modeldef (g_MeshManager.GetMesh(modelfilename));
@ -65,7 +113,7 @@ bool CObjectEntry::BuildModel()
// delete old model, create new
delete m_Model;
m_Model=new CModel;
m_Model = new CModel;
m_Model->SetTexture((const char*) m_TextureName);
m_Model->SetMaterial(g_MaterialManager.LoadMaterial(m_Base->m_Material));
m_Model->InitModel(modeldef);
@ -74,12 +122,12 @@ bool CObjectEntry::BuildModel()
m_Model->CalcObjectBounds();
// load animations
for (uint t = 0; t < m_Animations.size(); t++)
for (size_t t = 0; t < m_Animations.size(); t++)
{
if (m_Animations[t].m_FileName.Length() > 0)
{
const char* animfilename = m_Animations[t].m_FileName.c_str();
m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename,m_Animations[t].m_Speed);
const char* animfilename = m_Animations[t].m_FileName;
m_Animations[t].m_AnimData = m_Model->BuildAnimation(animfilename, m_Animations[t].m_Speed);
CStr AnimNameLC = m_Animations[t].m_AnimName.LowerCase();
@ -103,7 +151,7 @@ bool CObjectEntry::BuildModel()
else
{
// FIXME, RC - don't store invalid animations (possible?)
m_Animations[t].m_AnimData=0;
m_Animations[t].m_AnimData = NULL;
}
}
// start up idling
@ -111,117 +159,92 @@ bool CObjectEntry::BuildModel()
LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", modelfilename);
// build props - TODO, RC - need to fix up bounds here
for (uint p=0;p<m_Props.size();p++) {
const CObjectBase::Prop& prop=m_Props[p];
SPropPoint* proppoint=modeldef->FindPropPoint((const char*) prop.m_PropPointName);
if (proppoint) {
CObjectEntry* oe=g_ObjMan.FindObject(prop.m_ModelName);
if (oe) {
// try and build model if we haven't already got it
if (!oe->m_Model) oe->BuildModel();
if (oe->m_Model) {
CModel* propmodel=oe->m_Model->Clone();
m_Model->AddProp(proppoint,propmodel);
if (oe->m_WalkAnim) propmodel->SetAnimation(oe->m_WalkAnim);
} else {
LOG(ERROR, LOG_CATEGORY, "Failed to build prop model \"%s\" on actor \"%s\"", (const char*)prop.m_ModelName, (const char*)m_Base->m_ShortName);
}
// TODO: Make sure random variations get handled correctly when a prop fails
for (size_t p = 0; p < m_Props.size(); p++)
{
const CObjectBase::Prop& prop = m_Props[p];
SPropPoint* proppoint = modeldef->FindPropPoint((const char*) prop.m_PropPointName);
if (proppoint)
{
CObjectEntry* oe = g_ObjMan.FindObjectVariation(prop.m_ModelName, vars, vars_it);
if (oe)
{
CModel* propmodel = oe->m_Model->Clone();
m_Model->AddProp(proppoint, propmodel);
if (oe->m_WalkAnim)
propmodel->SetAnimation(oe->m_WalkAnim);
}
} else {
else
{
LOG(ERROR, LOG_CATEGORY, "Failed to build prop model \"%s\" on actor \"%s\"", (const char*)prop.m_ModelName, (const char*)m_Base->m_ShortName);
}
}
else
{
LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)prop.m_PropPointName, modelfilename, (const char*)prop.m_ModelName);
}
}
// setup flags
if (m_Base->m_Properties.m_CastShadows) {
if (m_Base->m_Properties.m_CastShadows)
{
m_Model->SetFlags(m_Model->GetFlags()|MODELFLAG_CASTSHADOWS);
}
// replace any units using old model to now use new model; also reprop models, if necessary
// FIXME, RC - ugh, doesn't recurse correctly through props
const std::vector<CUnit*>& units=g_UnitMan.GetUnits();
for (uint i=0;i<units.size();++i) {
/*
// (PT: Removed this, since I'm not entirely sure what it's useful for, and it
// gets a bit confusing with randomised actors)
const std::vector<CUnit*>& units = g_UnitMan.GetUnits();
for (size_t i = 0; i < units.size(); ++i)
{
CModel* unitmodel=units[i]->GetModel();
if (unitmodel->GetModelDef()==oldmodeldef) {
if (unitmodel->GetModelDef() == oldmodeldef)
{
unitmodel->InitModel(m_Model->GetModelDef());
unitmodel->SetFlags(m_Model->GetFlags());
const std::vector<CModel::Prop>& newprops=m_Model->GetProps();
for (uint j=0;j<newprops.size();j++) {
unitmodel->AddProp(newprops[j].m_Point,newprops[j].m_Model->Clone());
}
const std::vector<CModel::Prop>& newprops = m_Model->GetProps();
for (size_t j = 0; j < newprops.size(); j++)
unitmodel->AddProp(newprops[j].m_Point, newprops[j].m_Model->Clone());
}
std::vector<CModel::Prop>& mdlprops=unitmodel->GetProps();
for (uint j=0;j<mdlprops.size();j++) {
CModel::Prop& prop=mdlprops[j];
if (prop.m_Model) {
if (prop.m_Model->GetModelDef()==oldmodeldef) {
std::vector<CModel::Prop>& mdlprops = unitmodel->GetProps();
for (size_t j = 0; j < mdlprops.size(); j++)
{
CModel::Prop& prop = mdlprops[j];
if (prop.m_Model)
{
if (prop.m_Model->GetModelDef() == oldmodeldef)
{
delete prop.m_Model;
prop.m_Model=m_Model->Clone();
prop.m_Model = m_Model->Clone();
}
}
}
}
*/
return true;
}
void CObjectEntry::ApplyRandomVariant(CObjectBase::variation_key& vars)
CSkeletonAnim* CObjectEntry::GetNamedAnimation(CStr animationName)
{
CStr chosenTexture;
CStr chosenModel;
std::map<CStr, CObjectBase::Prop> chosenProps;
std::map<CStr, CObjectBase::Anim> chosenAnims;
for (size_t t = 0; t < m_Animations.size(); t++)
if (m_Animations[t].m_AnimName == animationName)
return m_Animations[t].m_AnimData;
CObjectBase::variation_key::const_iterator vars_it = vars.begin();
for (std::vector<std::vector<CObjectBase::Variant> >::iterator grp = m_Base->m_Variants.begin();
grp != m_Base->m_Variants.end();
++grp)
{
CObjectBase::Variant& var (grp->at(*(vars_it++)));
if (var.m_TextureFilename.Length())
chosenTexture = var.m_TextureFilename;
if (var.m_ModelFilename.Length())
chosenModel = var.m_ModelFilename;
for (std::vector<CObjectBase::Prop>::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it)
chosenProps[it->m_PropPointName] = *it;
for (std::vector<CObjectBase::Anim>::iterator it = var.m_Anims.begin(); it != var.m_Anims.end(); ++it)
chosenAnims[it->m_AnimName] = *it;
}
m_TextureName = chosenTexture;
m_ModelName = chosenModel;
for (std::map<CStr, CObjectBase::Prop>::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it)
m_Props.push_back(it->second);
for (std::map<CStr, CObjectBase::Anim>::iterator it = chosenAnims.begin(); it != chosenAnims.end(); ++it)
m_Animations.push_back(it->second);
}
CSkeletonAnim* CObjectEntry::GetNamedAnimation( CStr animationName )
{
for( uint t = 0; t < m_Animations.size(); t++ )
{
if( m_Animations[t].m_AnimName == animationName )
return( m_Animations[t].m_AnimData );
}
return( NULL );
return NULL;
}
CObjectBase::Prop* CObjectEntry::FindProp(const char* proppointname)
{
for (size_t i=0;i<m_Props.size();i++) {
if (strcmp(proppointname,m_Props[i].m_PropPointName)==0) return &m_Props[i];
}
for (size_t i = 0; i < m_Props.size(); i++)
if (strcmp(proppointname, m_Props[i].m_PropPointName) == 0)
return &m_Props[i];
return 0;
return NULL;
}

View File

@ -14,11 +14,9 @@ public:
CObjectEntry(int type, CObjectBase* base);
~CObjectEntry();
bool BuildModel();
bool BuildRandomVariant(CObjectBase::variation_key& vars, CObjectBase::variation_key::iterator& vars_it);
void ApplyRandomVariant(CObjectBase::variation_key& var);
// base actor. Contains all the things that don't change between
// Base actor. Contains all the things that don't change between
// different variations of the actor.
CObjectBase* m_Base;

View File

@ -49,6 +49,7 @@ CObjectManager::~CObjectManager()
delete_pair_2nd<CStr, CObjectBase*>
);
}
delete m_SelectedThing;
}
@ -81,7 +82,7 @@ CObjectBase* CObjectManager::FindObjectBase(const char* objectname)
delete obj;
}
LOG(ERROR, LOG_CATEGORY, "CObjectManager::FindObject(): Cannot find object '%s'", objectname);
LOG(ERROR, LOG_CATEGORY, "CObjectManager::FindObjectBase(): Cannot find object '%s'", objectname);
return 0;
}
@ -100,9 +101,24 @@ CObjectEntry* CObjectManager::FindObject(const char* objname)
CObjectBase::variation_key var;
base->CalculateVariation(choices, var);
return FindObjectVariation(base, var, var.begin());
}
CObjectEntry* CObjectManager::FindObjectVariation(const char* objname, CObjectBase::variation_key vars, CObjectBase::variation_key::iterator& vars_it)
{
CObjectBase* base = FindObjectBase(objname);
if (! base)
return NULL;
return FindObjectVariation(base, vars, vars_it);
}
CObjectEntry* CObjectManager::FindObjectVariation(CObjectBase* base, CObjectBase::variation_key vars, CObjectBase::variation_key::iterator& vars_it)
{
// Look to see whether this particular variation has already been loaded
ObjectKey key (CStr(objname), var);
ObjectKey key (base->m_Name, vars);
std::map<ObjectKey, CObjectEntry*>::iterator it = m_ObjectTypes[0].m_Objects.find(key);
if (it != m_ObjectTypes[0].m_Objects.end())
@ -110,11 +126,9 @@ CObjectEntry* CObjectManager::FindObject(const char* objname)
// If it hasn't been loaded, load it now
CObjectEntry* obj = new CObjectEntry(0, base); // TODO: type ???
CObjectEntry* obj = new CObjectEntry(0, base); // TODO: type ?
obj->ApplyRandomVariant(var);
if (! obj->BuildModel())
if (! obj->BuildRandomVariant(vars, vars_it))
{
DeleteObject(obj);
return NULL;
@ -161,6 +175,9 @@ void CObjectManager::LoadObjects()
}
//////////////////////////////////////////////////////////////////////////
// For ScEd:
static void GetObjectThunk(const char* path, const vfsDirEnt* ent, void* context)
{
std::vector<CStr>* names = (std::vector<CStr>*)context;
@ -172,13 +189,13 @@ void CObjectManager::GetAllObjectNames(std::vector<CStr>& names)
VFSUtil::EnumDirEnts("art/actors/", "*.xml", true, GetObjectThunk, &names);
}
struct CObjectThing_Entity : public CObjectThing
{
CObjectThing_Entity(CBaseEntity* b) : base(b) {}
CObjectThing_Entity(CBaseEntity* b) : base(b), obj(g_ObjMan.FindObject((CStr)b->m_actorName)), ent(NULL) {}
~CObjectThing_Entity() {}
CBaseEntity* base;
CEntity* ent;
CObjectEntry* obj;
void Create(CMatrix3D& transform, int playerID)
{
CVector3D orient = transform.GetIn();
@ -191,7 +208,7 @@ struct CObjectThing_Entity : public CObjectThing
CVector3D orient = transform.GetIn();
CVector3D position = transform.GetTranslation();
// This is quite yucky, but nothing else seems to actually work:
// This looks quite yucky, but nothing else seems to actually work:
ent->m_position =
ent->m_position_previous =
ent->m_graphics_position = position;
@ -203,7 +220,7 @@ struct CObjectThing_Entity : public CObjectThing
}
CObjectEntry* GetObjectEntry()
{
return g_ObjMan.FindObject((CStr)base->m_actorName);
return obj;
}
};
struct CObjectThing_Object : public CObjectThing

View File

@ -7,7 +7,6 @@
#include "CStr.h"
#include "ObjectBase.h"
class CObjectBase;
class CObjectEntry;
class CBaseEntity;
class CMatrix3D;
@ -68,6 +67,9 @@ public:
CObjectBase* FindObjectBase(const char* objname);
CObjectEntry* FindObjectVariation(const char* objname, CObjectBase::variation_key vars, CObjectBase::variation_key::iterator& vars_it);
CObjectEntry* FindObjectVariation(CObjectBase* base, CObjectBase::variation_key vars, CObjectBase::variation_key::iterator& vars_it);
// Get all names, quite slowly. (Intended only for ScEd.)
void GetAllObjectNames(std::vector<CStr>& names);

View File

@ -13,10 +13,10 @@ class CUnit
{
public:
// constructor - unit invalid without a model and object
CUnit(CObjectEntry* object,CModel* model) : m_Object(object), m_Model(model), m_Entity( NULL ) {
CUnit(CObjectEntry* object,CModel* model) : m_Object(object), m_Model(model), m_Entity(NULL) {
assert(object && model);
}
CUnit(CObjectEntry* object,CModel* model, CEntity* entity) : m_Object(object), m_Model(model), m_Entity( entity ) {
CUnit(CObjectEntry* object,CModel* model, CEntity* entity) : m_Object(object), m_Model(model), m_Entity(entity) {
assert(object && model);
}

View File

@ -1236,6 +1236,12 @@ int debug_assert_failed(const char* file, int line, const char* expr)
out(L"Assertion failed in %hs, line %d: \"%hs\"\r\n", file, line, expr);
dump_stack(1); // skip this function's frame
#if defined(SCED) && !(defined(NDEBUG)||defined(TESTING))
// ScEd keeps running while the dialog is showing, and tends to crash before
// there's a chance to read the assert message. So, just break immediately.
debug_break();
#endif
return dialog(ASSERT);
}

View File

@ -1446,13 +1446,9 @@ int main(int argc, char* argv[])
MICROLOG(L"Init");
Init(argc, argv, true);
// Do some limited tests to ensure things aren't broken
#ifndef NDEBUG
{
extern void PerformTests();
PerformTests();
}
#endif
// Optionally, do some simple tests to ensure things aren't broken
// extern void PerformTests();
// PerformTests();
while(!quit)
{
@ -1472,6 +1468,8 @@ int main(int argc, char* argv[])
void ScEd_Init()
{
new CProfileManager;
g_Quickstart = true;
Init(0, NULL, false);
@ -1480,6 +1478,8 @@ void ScEd_Init()
void ScEd_Shutdown()
{
Shutdown();
delete &g_Profiler;
}
#endif // SCED

View File

@ -132,6 +132,11 @@ void CPlayerSlot::AssignToSessionID(int id)
SetAssignment(SLOT_SESSION, NULL, id);
}
void CPlayerSlot::AssignLocal()
{
AssignToSessionID(1);
}
namespace PlayerSlotArray_JS
{
JSBool GetProperty( JSContext* cx, JSObject* obj, jsval id, jsval* vp )

View File

@ -95,7 +95,10 @@ public:
// Reset any assignment the slot might have before and mark the slot as free
void AssignOpen();
// Assign to the local player in SP or Server Player in MP
void AssignLocal();
// TODO This will wait until there actually is AI to set up
// void AssignAI();
};

View File

@ -165,6 +165,9 @@ bool CEditorData::Init()
// Set attributes for the game
g_GameAttributes.m_MapFile = L""; // start without a map
for (int i=1; i<8; ++i)
g_GameAttributes.GetSlot(i)->AssignLocal();
// Set up the actual game
g_Game = new CGame();
PSRETURN ret = g_Game->StartGame(&g_GameAttributes);
@ -603,9 +606,9 @@ void CEditorData::UpdateWorld(float time)
for (uint i=0;i<units.size();++i) {
units[i]->GetModel()->Update(time);
}
if (m_Mode==TEST_MODE) {
g_EntityManager.updateAll( time );
}
// if (m_Mode==TEST_MODE) {
// g_EntityManager.updateAll( time );
// }
} else {
// CObjectEntry* selobject=g_ObjMan.GetSelectedObject();
// if (selobject && selobject->m_Model) {

View File

@ -22,18 +22,21 @@ void CNaviCam::OnMouseWheelScroll(u32 flags,int px,int py,float dir)
float factor=dir*dir;
if (dir<0) factor=-factor;
// check we're not going to zoom into the terrain, or too far out into space
float h=m_Camera.m_Orientation.GetTranslation().Y+forward.Y*factor*m_CameraZoom;
float minh=65536*HEIGHT_SCALE*1.05f;
if (h<minh || h>1500) {
// yup, we will; don't move anywhere (do clamped move instead, at some point)
} else {
// do a full move
m_CameraZoom-=(factor)*0.1f;
if (m_CameraZoom<0.01f) m_CameraZoom=0.01f;
m_Camera.m_Orientation.Translate(forward*(factor*m_CameraZoom));
}
// // check we're not going to zoom into the terrain, or too far out into space
// float h=m_Camera.m_Orientation.GetTranslation().Y+forward.Y*factor*m_CameraZoom;
// float minh=65536*HEIGHT_SCALE*1.05f;
//
// if (h<minh || h>1500) {
// // yup, we will; don't move anywhere (do clamped move instead, at some point)
// } else {
// // do a full move
// m_CameraZoom-=(factor)*0.1f;
// if (m_CameraZoom<0.1f) m_CameraZoom=0.01f;
// m_Camera.m_Orientation.Translate(forward*(factor*m_CameraZoom));
// }
m_Camera.m_Orientation.Translate(forward*(factor*2.5f));
g_EditorData.OnCameraChanged();
}

View File

@ -8,6 +8,7 @@
#include "Renderer.h"
#include "UnitManager.h"
#include "SelectObjectTool.h"
#include "Entity.h"
#include <algorithm>
// default tool instance
@ -106,6 +107,19 @@ void CSelectObjectTool::RenderUnitBounds(CUnit* unit)
glEnd();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
void CSelectObjectTool::DeleteSelected()
{
for (std::vector<CUnit*>::iterator iter = m_SelectedUnits.begin(); iter != m_SelectedUnits.end(); ++iter)
{
if ((*iter)->GetEntity())
(*iter)->GetEntity()->kill();
else
g_UnitMan.DeleteUnit(*iter);
}
m_SelectedUnits.clear();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// GetFirstEntity: return the entity of the first selected object

View File

@ -26,6 +26,8 @@ public:
// (TODO: less hackiness, for the whole player-selection system)
CEntity* GetFirstEntity();
void DeleteSelected();
// get the default select object instance
static CSelectObjectTool* GetTool() { return &m_SelectObjectTool; }

View File

@ -21,6 +21,7 @@ void CSmoothElevationTool::SmoothSelection()
double curtime=1000*get_time();
double elapsed=(curtime-m_LastTriggerTime);
if (elapsed > 1000.0) elapsed = 1000.0;
while (elapsed>=m_SmoothPower) {
CSmoothElevationCommand* smoothCmd=new CSmoothElevationCommand(MAX_SMOOTH_POWER,m_BrushSize,m_SelectionCentre);
g_CmdMan.Execute(smoothCmd);

View File

@ -17,6 +17,7 @@
#include "ogl.h"
#undef _IGNORE_WGL_H_
#include "SelectObjectTool.h"
#include "Game.h"
#include "res/vfs.h"
@ -572,6 +573,9 @@ BOOL CScEdView::PreTranslateMessage(MSG* pMsg)
if (GetAsyncKeyState(VK_CONTROL))
mainfrm->OnEditRedo();
break;
case VK_DELETE:
CSelectObjectTool::GetTool()->DeleteSelected();
break;
}
}
return 1;