diff --git a/source/graphics/Model.cpp b/source/graphics/Model.cpp index 9eab92f832..1e56b6b642 100755 --- a/source/graphics/Model.cpp +++ b/source/graphics/Model.cpp @@ -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); diff --git a/source/graphics/ObjectBase.cpp b/source/graphics/ObjectBase.cpp index 2993ecdc4f..df65d60ee6 100644 --- a/source/graphics/ObjectBase.cpp +++ b/source/graphics/ObjectBase.cpp @@ -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& 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 chosenProps; + CObjectBase::variation_key::const_iterator choice_it = choices.begin(); + for (std::vector >::iterator grp = m_Variants.begin(); + grp != m_Variants.end(); + ++grp) + { + CObjectBase::Variant& var (grp->at(*(choice_it++))); + for (std::vector::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::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) } diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index cb2b1d688e..077950fdb8 100755 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -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 chosenProps; + std::map 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 >::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::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it) + chosenProps[it->m_PropPointName] = *it; + + for (std::vector::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::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it) + m_Props.push_back(it->second); + + for (std::map::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;pFindPropPoint((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& units=g_UnitMan.GetUnits(); - for (uint i=0;i& 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& newprops=m_Model->GetProps(); - for (uint j=0;jAddProp(newprops[j].m_Point,newprops[j].m_Model->Clone()); - } + const std::vector& 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& mdlprops=unitmodel->GetProps(); - for (uint j=0;jGetModelDef()==oldmodeldef) { + std::vector& 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 chosenProps; - std::map 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 >::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::iterator it = var.m_Props.begin(); it != var.m_Props.end(); ++it) - chosenProps[it->m_PropPointName] = *it; - - for (std::vector::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::iterator it = chosenProps.begin(); it != chosenProps.end(); ++it) - m_Props.push_back(it->second); - - for (std::map::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 ); } + 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::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* names = (std::vector*)context; @@ -172,13 +189,13 @@ void CObjectManager::GetAllObjectNames(std::vector& 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 diff --git a/source/graphics/ObjectManager.h b/source/graphics/ObjectManager.h index 514ffb5598..91f413d178 100755 --- a/source/graphics/ObjectManager.h +++ b/source/graphics/ObjectManager.h @@ -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& names); diff --git a/source/graphics/Unit.h b/source/graphics/Unit.h index 78e48707a7..f8df0169cf 100755 --- a/source/graphics/Unit.h +++ b/source/graphics/Unit.h @@ -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); } diff --git a/source/lib/sysdep/win/wdbg.cpp b/source/lib/sysdep/win/wdbg.cpp index 4f3cca806e..e6713e3f35 100755 --- a/source/lib/sysdep/win/wdbg.cpp +++ b/source/lib/sysdep/win/wdbg.cpp @@ -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); } diff --git a/source/main.cpp b/source/main.cpp index 1b1fc4fe90..179281ba04 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -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 diff --git a/source/ps/GameAttributes.cpp b/source/ps/GameAttributes.cpp index 60d41e6b66..6528baaf2b 100644 --- a/source/ps/GameAttributes.cpp +++ b/source/ps/GameAttributes.cpp @@ -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 ) diff --git a/source/ps/GameAttributes.h b/source/ps/GameAttributes.h index 92c3dd73c6..0e605dc283 100644 --- a/source/ps/GameAttributes.h +++ b/source/ps/GameAttributes.h @@ -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(); }; diff --git a/source/tools/sced/EditorData.cpp b/source/tools/sced/EditorData.cpp index 3674f93611..cbfb61d4e9 100755 --- a/source/tools/sced/EditorData.cpp +++ b/source/tools/sced/EditorData.cpp @@ -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;iGetModel()->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) { diff --git a/source/tools/sced/NaviCam.cpp b/source/tools/sced/NaviCam.cpp index 054c47d3be..b7ec54419f 100755 --- a/source/tools/sced/NaviCam.cpp +++ b/source/tools/sced/NaviCam.cpp @@ -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 (h1500) { - // 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 (h1500) { +// // 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(); } diff --git a/source/tools/sced/SelectObjectTool.cpp b/source/tools/sced/SelectObjectTool.cpp index 43748ca032..4fd925c98e 100755 --- a/source/tools/sced/SelectObjectTool.cpp +++ b/source/tools/sced/SelectObjectTool.cpp @@ -8,6 +8,7 @@ #include "Renderer.h" #include "UnitManager.h" #include "SelectObjectTool.h" +#include "Entity.h" #include // default tool instance @@ -106,6 +107,19 @@ void CSelectObjectTool::RenderUnitBounds(CUnit* unit) glEnd(); } +///////////////////////////////////////////////////////////////////////////////////////////////// +void CSelectObjectTool::DeleteSelected() +{ + for (std::vector::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 diff --git a/source/tools/sced/SelectObjectTool.h b/source/tools/sced/SelectObjectTool.h index d5d414e3d9..3ecdeb35ec 100755 --- a/source/tools/sced/SelectObjectTool.h +++ b/source/tools/sced/SelectObjectTool.h @@ -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; } diff --git a/source/tools/sced/SmoothElevationTool.cpp b/source/tools/sced/SmoothElevationTool.cpp index 480c9cb4ee..6971ee45f9 100755 --- a/source/tools/sced/SmoothElevationTool.cpp +++ b/source/tools/sced/SmoothElevationTool.cpp @@ -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); diff --git a/source/tools/sced/ui/ScEdView.cpp b/source/tools/sced/ui/ScEdView.cpp index ab822f1be3..59e22ee04d 100755 --- a/source/tools/sced/ui/ScEdView.cpp +++ b/source/tools/sced/ui/ScEdView.cpp @@ -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;