# Added tool for viewing models and animations outside the game.

Atlas: Added ActorViewer. Moved GL canvas into separate class for shared
use. Disabled message-handling callback while blocked on the game, and
stopped creating dialog boxes inside the game thread in order to avoid
deadlocks (hopefully). Support multiple Views (for independent sets of
camera/update/render code). Recalculate territory boundaries when
necessary. Changed default list of animations to match those currently
used by actors.
# Tidied up more code.
Moved some more #includes out of .h files, to minimise unnecessary
compilation.
MathUtil: Deleted unused/unuseful macros (M_PI (use PI instead), M_PI_2
(use PI/2), MAX3, ABS (use abs)).
ObjectManager: Removed some ScEd-specific things.
Unit: Moved creation out of UnitManager, so units can be created without
adding to the manager. Changed CStr8 to the more conventional CStr.
app_hooks: Removed warning for setting multiple times.
win: Restored SEH catcher.
GameSetup, GameView: Removed RenderNoCull, because it doesn't seem to do
what it says it does ("force renderer to load everything") since we're
loading-on-demand most stuff and it doesn't seem especially useful since
we'd prefer to minimise loading times (but feel free to correct me if
I'm wrong). (And because it crashes when things need to be initialised
in a different order, so it's easier to remove than to understand and
fix it.)
PatchRData, Renderer: Work sensibly when there's no game (hence no LOS
manager, water, etc).
LOSManager: Use entity position instead of actor position when possible.
TerritoryManager: Allow delayed recalculations (so Atlas can issue lots
of move+recalculate commands per frame).
Cinematic: Non-pointer wxTimer, so it doesn't leak and doesn't have to
be deleted manually.

This was SVN commit r4261.
This commit is contained in:
Ykkrosh 2006-08-28 17:36:42 +00:00
parent 5205944dce
commit 35e91718c5
85 changed files with 1665 additions and 733 deletions

View File

@ -25,21 +25,20 @@
</attachpoints>
<animations>
<item> Attack </item>
<item> AttackA </item>
<item> AttackB </item>
<item> AttackC </item>
<item> Death </item>
<item> DeathA </item>
<item> DeathB </item>
<item> Idle </item>
<item> IdleA </item>
<item> IdleB </item>
<item> IdleC </item>
<item> Run </item>
<item> Special </item>
<item> Walk </item>
<item> Pack </item>
<item>attack1 </item>
<item>attack2 </item>
<item>build </item>
<item>corpse </item>
<item>death </item>
<item>gather_fruit</item>
<item>gather_grain</item>
<item>gather_stone</item>
<item>gather_wood </item>
<item>idle </item>
<item>melee </item>
<item>run </item>
<item>walk </item>
</animations>
<playercolours>

View File

@ -0,0 +1 @@
pyrogenesis.exe -editor -actorviewer

View File

@ -484,9 +484,11 @@ function setup_atlas_packages()
setup_atlas_package("AtlasUI", "dll",
{ -- src
"ActorEditor",
"ActorViewer",
"ArchiveViewer",
"ColourTester",
"CustomControls/Buttons",
"CustomControls/Canvas",
"CustomControls/ColourDialog",
"CustomControls/DraggableListCtrl",
"CustomControls/EditableListCtrl",

View File

@ -303,32 +303,6 @@ void CGameView::SubmitModelRecursive(CModel* model)
}
}
void CGameView::RenderNoCull()
{
CUnitManager *pUnitMan=m_pWorld->GetUnitManager();
CTerrain *pTerrain=m_pWorld->GetTerrain();
if (m_LockCullCamera == false)
m_CullCamera = m_ViewCamera;
g_Renderer.SetCamera(m_ViewCamera, m_CullCamera);
CheckLightEnv();
uint i,j;
const std::vector<CUnit*>& units=pUnitMan->GetUnits();
for (i=0;i<units.size();++i) {
SubmitModelRecursive(units[i]->GetModel());
}
u32 patchesPerSide=pTerrain->GetPatchesPerSide();
for (j=0; j<patchesPerSide; j++) {
for (i=0; i<patchesPerSide; i++) {
CPatch* patch=pTerrain->GetPatch(i,j);
g_Renderer.Submit(patch);
}
}
}
static void MarkUpdateColorRecursive(CModel* model)
{
model->SetDirty(RENDERDATA_UPDATE_COLOR);

View File

@ -141,10 +141,6 @@ public:
void CameraLock(CVector3D Trans, bool smooth=true);
void CameraLock(float x, float y, float z, bool smooth=true);
// RenderNoCull: render absolutely everything to a blank frame to force
// renderer to load required assets
void RenderNoCull();
// Camera Control Functions (used by input handler)
void ResetCamera();
void ResetCameraOrientation();

View File

@ -1,31 +1,31 @@
#include "precompiled.h"
#include "MapReader.h"
#include "lib/types.h"
#include "UnitManager.h"
#include "Unit.h"
#include "ps/Game.h"
#include "ObjectManager.h"
#include "simulation/Entity.h"
#include "simulation/EntityTemplate.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/EntityManager.h"
#include "ps/CLogger.h"
#include "maths/MathUtil.h"
#include "Camera.h"
#include "graphics/Patch.h"
#include "graphics/Camera.h"
#include "graphics/GameView.h"
#include "renderer/WaterManager.h"
#include "renderer/SkyManager.h"
#include "Model.h"
#include "Terrain.h"
#include "TextureManager.h"
#include "TextureEntry.h"
#include "graphics/Model.h"
#include "graphics/ObjectManager.h"
#include "graphics/Patch.h"
#include "graphics/Terrain.h"
#include "graphics/TextureEntry.h"
#include "graphics/TextureManager.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
#include "lib/timer.h"
#include "lib/types.h"
#include "maths/MathUtil.h"
#include "ps/CLogger.h"
#include "ps/Game.h"
#include "ps/Loader.h"
#include "ps/LoaderThunks.h"
#include "ps/xml/Xeromyces.h"
#include "renderer/SkyManager.h"
#include "renderer/WaterManager.h"
#include "simulation/Entity.h"
#include "simulation/EntityManager.h"
#include "simulation/EntityTemplate.h"
#include "simulation/EntityTemplateCollection.h"
#define LOG_CATEGORY "graphics"

View File

@ -237,7 +237,7 @@ void CMapWriter::WriteXML(const char* filename,
CVector3D in = pCamera->m_Orientation.GetIn();
// Convert to spherical coordinates
float rotation = atan2(in.X, in.Z);
float declination = atan2(sqrt(in.X*in.X + in.Z*in.Z), in.Y) - M_PI_2;
float declination = atan2(sqrt(in.X*in.X + in.Z*in.Z), in.Y) - PI/2;
{
XML_Element("Rotation");

View File

@ -29,7 +29,7 @@ bool operator< (const CObjectManager::ObjectKey& a, const CObjectManager::Object
return a.ActorVariation < b.ActorVariation;
}
CObjectManager::CObjectManager() : m_SelectedThing(NULL)
CObjectManager::CObjectManager()
{
m_ObjectTypes.reserve(32);
}
@ -158,6 +158,10 @@ void CObjectManager::DeleteObject(CObjectEntry* entry)
int CObjectManager::LoadObjects()
{
// This is kind of useless - it should probably be removed,
// and UnloadObject moved into the destructor, and singletonness
// removed if we still want to unload the object manager and reuse it
// again later.
AddObjectType("");
return 0;
}
@ -177,9 +181,6 @@ void CObjectManager::UnloadObjects()
);
}
m_ObjectTypes.clear();
delete m_SelectedThing;
m_SelectedThing = NULL;
}

View File

@ -14,16 +14,6 @@ class CMatrix3D;
// access to sole CObjectManager object
#define g_ObjMan CObjectManager::GetSingleton()
// Slight hack, to allow ScEd to place either entities or objects
class CObjectThing
{
public:
virtual ~CObjectThing() {}
virtual void Create(CMatrix3D& transform, int playerID)=0;
virtual void SetTransform(CMatrix3D& transform)=0;
virtual CObjectEntry* GetObjectEntry()=0;
};
///////////////////////////////////////////////////////////////////////////////////////////
// CObjectManager: manager class for all possible actor types
class CObjectManager : public Singleton<CObjectManager>
@ -51,7 +41,6 @@ public:
};
public:
CObjectThing* m_SelectedThing;
// constructor, destructor
CObjectManager();
@ -68,8 +57,8 @@ public:
CObjectBase* FindObjectBase(const char* objname);
CObjectEntry* FindObjectVariation(const char* objname, const std::vector<std::set<CStr8> >& selections);
CObjectEntry* FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStr8> >& selections);
CObjectEntry* FindObjectVariation(const char* objname, const std::vector<std::set<CStr> >& selections);
CObjectEntry* FindObjectVariation(CObjectBase* base, const std::vector<std::set<CStr> >& selections);
// Get all names, quite slowly. (Intended only for ScEd.)
void GetAllObjectNames(std::vector<CStr>& names);

View File

@ -7,18 +7,37 @@
#include "SkeletonAnim.h"
#include "SkeletonAnimDef.h"
CUnit::CUnit(CObjectEntry* object, CEntity* entity, const std::set<CStr8>& actorSelections)
CUnit::CUnit(CObjectEntry* object, CEntity* entity, const std::set<CStr>& actorSelections)
: m_Object(object), m_Model(object->m_Model->Clone()), m_Entity(entity),
m_ID(-1), m_ActorSelections(actorSelections)
{
}
CUnit::~CUnit()
{
delete m_Model;
}
CUnit* CUnit::Create(const CStr& actorName, CEntity* entity, const std::set<CStr>& selections)
{
CObjectBase* base = g_ObjMan.FindObjectBase(actorName);
if (! base)
return NULL;
std::set<CStr> actorSelections = base->CalculateRandomVariation(selections);
std::vector<std::set<CStr> > selectionsVec;
selectionsVec.push_back(actorSelections);
CObjectEntry* obj = g_ObjMan.FindObjectVariation(base, selectionsVec);
if (! obj)
return NULL;
return new CUnit(obj, entity, actorSelections);
}
void CUnit::ShowAmmunition()
{
if (!m_Object->m_AmmunitionModel || !m_Object->m_AmmunitionPoint)
@ -115,9 +134,9 @@ void CUnit::SetPlayerID(int id)
m_Model->SetPlayerID(m_PlayerID);
}
void CUnit::SetEntitySelection(const CStrW& selection)
void CUnit::SetEntitySelection(const CStr& selection)
{
CStrW selection_lc = selection.LowerCase();
CStr selection_lc = selection.LowerCase();
// If we've already selected this, don't do anything
if (m_EntitySelections.find(selection_lc) != m_EntitySelections.end())
@ -130,7 +149,7 @@ void CUnit::SetEntitySelection(const CStrW& selection)
ReloadObject();
}
void CUnit::SetActorSelections(const std::set<CStr8>& selections)
void CUnit::SetActorSelections(const std::set<CStr>& selections)
{
m_ActorSelections = selections;
ReloadObject();
@ -138,7 +157,7 @@ void CUnit::SetActorSelections(const std::set<CStr8>& selections)
void CUnit::ReloadObject()
{
std::vector<std::set<CStr8> > selections;
std::vector<std::set<CStr> > selections;
// TODO: push world selections (seasons, etc) (and reload whenever they're changed)
selections.push_back(m_EntitySelections);
selections.push_back(m_ActorSelections);

View File

@ -3,24 +3,31 @@
#include <set>
#include "ps/CStr.h"
class CModel;
class CObjectEntry;
class CEntity;
class CSkeletonAnim;
class CStr8;
class CStrW;
/////////////////////////////////////////////////////////////////////////////////////////////
// CUnit: simple "actor" definition - defines a sole object within the world
class CUnit
{
private:
// Private constructor. Needs complete list of selections for the variation.
CUnit(CObjectEntry* object, CEntity* entity, const std::set<CStr>& actorSelections);
public:
CUnit(CObjectEntry* object, CEntity* entity, const std::set<CStr8>& actorSelections);
// Attempt to create a unit with the given actor, attached to an entity
// (or NULL), with a set of suggested selections (with the rest being randomised).
// Returns NULL on failure.
static CUnit* Create(const CStr& actorName, CEntity* entity, const std::set<CStr>& selections);
// destructor
~CUnit();
// get unit's template object; never NULL
CObjectEntry* GetObject() { return m_Object; }
// get unit's model data; never NULL
@ -34,19 +41,20 @@ public:
// Sets the animation a random one matching 'name'. If none is found,
// sets to idle instead. Applies recursively to props.
bool SetRandomAnimation(const CStr8& name, bool once = false, float speed = 0.0f);
// SetEntitySelection(name) should typically be used before this.
bool SetRandomAnimation(const CStr& name, bool once = false, float speed = 0.0f);
// Returns a random animation matching 'name'. If none is found,
// returns idle instead.
CSkeletonAnim* GetRandomAnimation(const CStr8& name);
CSkeletonAnim* GetRandomAnimation(const CStr& name);
// Sets the entity-selection, and updates the unit to use the new
// actor variation.
void SetEntitySelection(const CStrW& selection);
void SetEntitySelection(const CStr& selection);
// Returns whether the currently active animation is one of the ones
// matching 'name'.
bool IsPlayingAnimation(const CStr8& name);
bool IsPlayingAnimation(const CStr& name);
// Set player ID of this unit
void SetPlayerID(int id);
@ -57,9 +65,9 @@ public:
int GetID() const { return m_ID; }
void SetID(int id) { m_ID = id; }
const std::set<CStr8>& GetActorSelections() const { return m_ActorSelections; }
const std::set<CStr>& GetActorSelections() const { return m_ActorSelections; }
void SetActorSelections(const std::set<CStr8>& selections);
void SetActorSelections(const std::set<CStr>& selections);
private:
// object from which unit was created
@ -76,9 +84,9 @@ private:
int m_ID;
// actor-level selections for this unit
std::set<CStr8> m_ActorSelections;
std::set<CStr> m_ActorSelections;
// entity-level selections for this unit
std::set<CStr8> m_EntitySelections;
std::set<CStr> m_EntitySelections;
void ReloadObject();
};

View File

@ -19,7 +19,6 @@
#include "ObjectEntry.h"
#include "simulation/Entity.h"
#include "simulation/LOSManager.h"
#include "simulation/TerritoryManager.h"
extern CConsole* g_Console;
@ -127,22 +126,8 @@ CUnit* CUnitManager::PickUnit(const CVector3D& origin, const CVector3D& dir) con
// CreateUnit: create a new unit and add it to the world
CUnit* CUnitManager::CreateUnit(const CStr& actorName, CEntity* entity, const std::set<CStr8>& selections)
{
CObjectBase* base = g_ObjMan.FindObjectBase(actorName);
if (! base)
return NULL;
std::set<CStr8> actorSelections = base->CalculateRandomVariation(selections);
std::vector<std::set<CStr8> > selectionsVec;
selectionsVec.push_back(actorSelections);
CObjectEntry* obj = g_ObjMan.FindObjectVariation(base, selectionsVec);
if (! obj)
return NULL;
CUnit* unit = new CUnit(obj, entity, actorSelections);
CUnit* unit = CUnit::Create(actorName, entity, selections);
if (unit)
AddUnit(unit);
return unit;
}

View File

@ -41,7 +41,7 @@ public:
void DeleteAll();
// creates a new unit and adds it to the world
CUnit* CreateUnit(const CStr& actorName, CEntity* entity, const std::set<CStr8>& selections);
CUnit* CreateUnit(const CStr& actorName, CEntity* entity, const std::set<CStr>& selections);
// return the units
const std::vector<CUnit*>& GetUnits() const { return m_Units; }

View File

@ -157,7 +157,6 @@ static AppHooks ah =
void app_hooks_update(AppHooks* ah_)
{
debug_assert(ah_);
ONCE_NOT(debug_warn("app hooks already set"));
// override members in <ah> if they are non-zero in <ah_>
// (otherwise, we stick with the defaults set above)

View File

@ -1394,7 +1394,7 @@ static float fade_factor_exponential(float t)
static float fade_factor_s_curve(float t)
{
// cosine curve
float y = cos(t*M_PI + M_PI);
float y = cos(t*PI + PI);
// map [-1,1] to [0,1]
return (y + 1.0f) / 2.0f;
}

View File

@ -327,7 +327,7 @@ static inline void pre_libc_init()
static int SEH_wrapped_entry()
{
int ret;
//__try
__try
{
pre_libc_init();
#ifdef USE_WINMAIN
@ -336,7 +336,7 @@ static int SEH_wrapped_entry()
ret = mainCRTStartup(); // calls _cinit and then our main
#endif
}
//__except(wdbg_exception_filter(GetExceptionInformation()))
__except(wdbg_exception_filter(GetExceptionInformation()))
{
ret = -1;
}

View File

@ -357,6 +357,9 @@ void kill_mainloop()
int main(int argc, char* argv[])
{
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(7864);
// see discussion at declaration of win_pre_main_init.
#if OS_WIN
win_pre_main_init();

View File

@ -5,24 +5,14 @@
#define PI 3.14159265358979323846f
#endif
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#endif
#define DEGTORAD(a) ((a) * (PI/180.0f))
#define RADTODEG(a) ((a) * (180.0f/PI))
#define SQR(x) ((x) * (x))
#define MAX3(a,b,c) ( MAX (MAX(a,b), c) )
#define ABS(a) ((a > 0) ? (a) : (-a))
template <typename T>
T Interpolate(T& a, T& b, float l)
{
return( a + ( b - a ) * l );
return a + (b - a) * l;
}
template <typename T>
@ -35,11 +25,11 @@ inline T clamp(T value, T min, T max)
static inline int RoundUpToPowerOf2(int x)
{
if ((x & (x-1))==0) return x;
if ((x & (x-1)) == 0)
return x;
int d = x;
while (d & (d-1)) {
while (d & (d-1))
d &= (d-1);
}
return d << 1;
}

View File

@ -31,7 +31,7 @@ Noise2D::Noise2D(int f)
grads[i] = new CVector2D_Maths[freq];
for(int j=0; j<freq; j++)
{
float a = randFloat() * 2 * M_PI;
float a = randFloat() * 2 * PI;
grads[i][j] = CVector2D_Maths(cos(a), sin(a));
}
}

View File

@ -14,49 +14,54 @@
#include "lib/res/graphics/tex.h"
#include "lib/res/graphics/cursor.h"
#include "ps/CConsole.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/Font.h"
#include "ps/Game.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/Interact.h"
#include "ps/Loader.h"
#include "ps/Overlay.h"
#include "ps/Profile.h"
#include "ps/ProfileViewer.h"
#include "ps/Loader.h"
#include "ps/Font.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
#include "ps/Interact.h"
#include "ps/Hotkey.h"
#include "ps/ConfigDB.h"
#include "ps/CLogger.h"
#include "ps/i18n.h"
#include "ps/Overlay.h"
#include "ps/StringConvert.h"
#include "ps/Globals.h"
#include "ps/Util.h"
#include "ps/i18n.h"
#include "graphics/ParticleEngine.h"
#include "graphics/MapReader.h"
#include "graphics/Terrain.h"
#include "graphics/TextureManager.h"
#include "graphics/ObjectManager.h"
#include "graphics/SkeletonAnimManager.h"
#include "graphics/GameView.h"
#include "graphics/LightEnv.h"
#include "graphics/Model.h"
#include "graphics/UnitManager.h"
#include "graphics/MapReader.h"
#include "graphics/MaterialManager.h"
#include "graphics/MeshManager.h"
#include "graphics/GameView.h"
#include "graphics/Model.h"
#include "graphics/ObjectManager.h"
#include "graphics/ParticleEngine.h"
#include "graphics/SkeletonAnimManager.h"
#include "graphics/Terrain.h"
#include "graphics/TextureManager.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
#include "renderer/Renderer.h"
#include "renderer/VertexBufferManager.h"
#include "maths/MathUtil.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/FormationCollection.h"
#include "simulation/TechnologyCollection.h"
#include "simulation/Entity.h"
#include "simulation/EntityHandles.h"
#include "simulation/EntityManager.h"
#include "simulation/EntityTemplate.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/EventHandlers.h"
#include "simulation/FormationCollection.h"
#include "simulation/FormationManager.h"
#include "simulation/TerritoryManager.h"
#include "simulation/PathfindEngine.h"
#include "simulation/Scheduler.h"
#include "simulation/Projectile.h"
#include "simulation/Scheduler.h"
#include "simulation/TechnologyCollection.h"
#include "scripting/ScriptableComplex.inl"
#include "scripting/ScriptingHost.h"
@ -266,22 +271,6 @@ void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task)
/////////////////////////////////////////////////////////////////////////////////////////////
// RenderNoCull: render absolutely everything to a blank frame to force renderer
// to load required assets
static void RenderNoCull()
{
g_Renderer.BeginFrame();
if (g_Game)
g_Game->GetView()->RenderNoCull();
g_Renderer.FlushFrame();
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
g_Renderer.EndFrame();
}
void Render()
{
MICROLOG(L"begin frame");
@ -389,12 +378,6 @@ void Render()
g_Game->GetView()->GetCinema()->DrawAllSplines();
PROFILE_END( "render cinematic splines" );
}
else
{
PROFILE_START( "flush frame" );
g_Renderer.FlushFrame();
PROFILE_END( "flush frame" );
}
oglCheck();
@ -898,9 +881,6 @@ void Init(int argc, char* argv[], uint flags)
// add all debug_printf "tags" that we are interested in:
debug_filter_add("TIMER");
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(187);
// Query CPU capabilities, possibly set some CPU-dependent flags
cpu_init();
@ -1004,7 +984,13 @@ void Init(int argc, char* argv[], uint flags)
}
// (must come after SetVideoMode, since it calls oglInit)
const char* missing = oglHaveExtensions(0, "GL_ARB_multitexture", "GL_EXT_draw_range_elements", "GL_ARB_texture_env_combine", "GL_ARB_texture_env_dot3", "GL_ARB_texture_env_crossbar", 0);
const char* missing = oglHaveExtensions(0,
"GL_ARB_multitexture",
"GL_EXT_draw_range_elements",
"GL_ARB_texture_env_combine",
"GL_ARB_texture_env_dot3",
"GL_ARB_texture_env_crossbar",
0);
if(missing)
{
wchar_t buf[500];
@ -1079,27 +1065,20 @@ void Init(int argc, char* argv[], uint flags)
}
#endif
{
TIMER("Init_renderblank");
MICROLOG(L"render blank");
// render everything to a blank frame to force renderer to load everything
RenderNoCull();
}
if (g_FixedFrameTiming) {
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
CCamera &camera = *g_Game->GetView()->GetCamera();
#if 0 // TOPDOWN
g_Camera.SetProjection(1.0f,10000.0f,DEGTORAD(90));
g_Camera.m_Orientation.SetIdentity();
g_Camera.m_Orientation.RotateX(DEGTORAD(90));
g_Camera.m_Orientation.Translate(CELL_SIZE*250*0.5, 250, CELL_SIZE*250*0.5);
camera.SetProjection(1.0f,10000.0f,DEGTORAD(90));
camera.m_Orientation.SetIdentity();
camera.m_Orientation.RotateX(DEGTORAD(90));
camera.m_Orientation.Translate(CELL_SIZE*250*0.5, 250, CELL_SIZE*250*0.5);
#else // std view
g_Camera.SetProjection(1.0f,10000.0f,DEGTORAD(20));
g_Camera.m_Orientation.SetXRotation(DEGTORAD(30));
g_Camera.m_Orientation.RotateY(DEGTORAD(-45));
g_Camera.m_Orientation.Translate(350, 350, -275);
camera.SetProjection(1.0f,10000.0f,DEGTORAD(20));
camera.m_Orientation.SetXRotation(DEGTORAD(30));
camera.m_Orientation.RotateY(DEGTORAD(-45));
camera.m_Orientation.Translate(350, 350, -275);
#endif
g_Camera.UpdateFrustum();
camera.UpdateFrustum();
}
if (g_AutostartMap.Length())

View File

@ -15,6 +15,7 @@ extern void GUI_DisplayLoadProgress(int percent, const wchar_t* pending_task);
extern void Render();
extern void RenderActor();
extern void Shutdown();

View File

@ -2,9 +2,6 @@
#include "Interact.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
#include "ps/Hotkey.h"
#include "graphics/GameView.h"
#include "graphics/HFTracer.h"
#include "graphics/Model.h"
@ -18,22 +15,27 @@
#include "lib/res/graphics/unifont.h"
#include "lib/timer.h"
#include "maths/MathUtil.h"
#include "ps/Globals.h"
#include "network/NetMessage.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
#include "ps/Globals.h"
#include "ps/Hotkey.h"
#include "ps/Player.h"
#include "ps/VFSUtil.h"
#include "ps/World.h"
#include "renderer/Renderer.h"
#include "scripting/GameEvents.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/BoundingObjects.h"
#include "simulation/Collision.h"
#include "simulation/Entity.h"
#include "simulation/EntityFormation.h"
#include "simulation/EntityManager.h"
#include "simulation/EntityTemplate.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/EventHandlers.h"
#include "simulation/FormationManager.h"
#include "simulation/TerritoryManager.h"
#include "simulation/Simulation.h"
#include "simulation/TerritoryManager.h"
#include "ps/CLogger.h"
#define LOG_CATEGORY "world"
@ -1294,7 +1296,7 @@ InReaction interactInputHandler( const SDL_Event_* ev )
{
int deltax = ev->ev.motion.x - button_down_x;
int deltay = ev->ev.motion.y - button_down_y;
if( ABS( deltax ) > 2 || ABS( deltay ) > 2 )
if( abs( deltax ) > 2 || abs( deltay ) > 2 )
g_Mouseover.startBandbox( button_down_x, button_down_y );
}
break;
@ -1384,9 +1386,9 @@ bool CBuildingPlacer::activate(CStrW& templateName)
void CBuildingPlacer::mousePressed()
{
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
CCamera &camera=*g_Game->GetView()->GetCamera();
if( m_template->m_socket == L"" )
clickPos = g_Camera.GetWorldCoordinates();
clickPos = camera.GetWorldCoordinates();
m_clicked = true;
}
@ -1430,8 +1432,8 @@ void CBuildingPlacer::update( float timeStep )
{
// Rotate object
m_timeSinceClick += timeStep;
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
CVector3D mousePos = g_Camera.GetWorldCoordinates();
CCamera &camera = *g_Game->GetView()->GetCamera();
CVector3D mousePos = camera.GetWorldCoordinates();
CVector3D dif = mousePos - clickPos;
float x = dif.X, z = dif.Z;
if(x*x + z*z < 3*3) {
@ -1454,8 +1456,8 @@ void CBuildingPlacer::update( float timeStep )
}
else
{
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
pos = g_Camera.GetWorldCoordinates();
CCamera &camera = *g_Game->GetView()->GetCamera();
pos = camera.GetWorldCoordinates();
}
bool onSocket = false;

View File

@ -288,7 +288,6 @@ void initKeyNameMap()
SKeycodeMapping* it = keycodeMapping;
while( it->keycode != 0 )
{
debug_printf("adding key %s\n", it->keyname);
keymap.insert( std::pair<CStr,int>( CStr( it->keyname ).LowerCase(), it->keycode ) );
if( it->altkeyname )
keymap.insert( std::pair<CStr,int>( CStr( it->altkeyname ).LowerCase(), it->keycode ) );

View File

@ -412,9 +412,12 @@ void CPatchRData::Update()
CTerrain* terrain=m_Patch->m_Parent;
int mapSize=terrain->GetVerticesPerSide();
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
int vsize=PATCH_SIZE+1;
if (g_Game)
{
CLOSManager* losMgr = g_Game->GetWorld()->GetLOSManager();
// this is very similar to BuildVertices(), but just for color
for (int j=0;j<vsize;j++) {
for (int i=0;i<vsize;i++) {
@ -444,6 +447,19 @@ void CPatchRData::Update()
m_Vertices[v].m_LOSColor = losMod;
}
}
}
else
{
for (int j = 0; j < vsize; ++j)
{
for (int i = 0; i < vsize; ++i)
{
int v = (j*vsize)+i;
m_Vertices[v].m_LOSColor = SColor4ub(255, 255, 255, 255);
}
}
}
// upload base vertices into their vertex buffer
m_VBBase->m_Owner->UpdateChunkVertices(m_VBBase,m_Vertices);

View File

@ -705,9 +705,6 @@ void CRenderer::SetFastPlayerColor(bool fast)
// BeginFrame: signal frame start
void CRenderer::BeginFrame()
{
if(!g_Game || !g_Game->IsGameStarted())
return;
// bump frame counter
m_FrameCounter++;
@ -1158,9 +1155,6 @@ void CRenderer::RenderRefractions()
// FlushFrame: force rendering of any batched objects
void CRenderer::FlushFrame()
{
if(!g_Game || !g_Game->IsGameStarted())
return;
oglCheck();
// Prepare model renderers
@ -1178,7 +1172,8 @@ void CRenderer::FlushFrame()
m->terrainRenderer->PrepareForRendering();
PROFILE_END("prepare terrain");
if (m_Options.m_Shadows) {
if (m_Options.m_Shadows)
{
MICROLOG(L"render shadows");
RenderShadowMap();
}
@ -1227,7 +1222,7 @@ void CRenderer::FlushFrame()
oglCheck();
// render water
if (m_WaterManager->m_RenderWater)
if (m_WaterManager->m_RenderWater && g_Game)
{
MICROLOG(L"render water");
m->terrainRenderer->RenderWater();
@ -1247,7 +1242,6 @@ void CRenderer::FlushFrame()
// on all the time, so it might not be worth worrying about.
}
// Clean up texture blend mode so particles and other things render OK
// (really this should be cleaned up by whoever set it)
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
@ -1284,9 +1278,6 @@ void CRenderer::FlushFrame()
// EndFrame: signal frame end
void CRenderer::EndFrame()
{
if(!g_Game || !g_Game->IsGameStarted())
return;
g_Renderer.SetTexture(0,0);
static bool once=false;

View File

@ -205,7 +205,7 @@ void SkyManager::RenderSky()
// Rotate so that the "left" face, which contains the brightest part of each
// skymap, is in the direction of the sun from our light environment
glRotatef( 90.0f + g_Renderer.GetLightEnv().GetRotation()*180.0f/M_PI, 0.0f, 1.0f, 0.0f );
glRotatef( 90.0f + RADTODEG(g_Renderer.GetLightEnv().GetRotation()), 0.0f, 1.0f, 0.0f );
// Distance to draw the faces at
const float D = 2000.0;

View File

@ -132,7 +132,7 @@ void TerrainRenderer::EndFrame()
// Query if patches have been submitted this frame
bool TerrainRenderer::HaveSubmissions()
{
return m->visiblePatches.size() > 0;
return !m->visiblePatches.empty();
}

View File

@ -40,6 +40,7 @@
#include "simulation/EntityFormation.h"
#include "simulation/EntityHandles.h"
#include "simulation/EntityManager.h"
#include "simulation/EntityTemplate.h"
#include "simulation/FormationManager.h"
#include "simulation/LOSManager.h"
#include "simulation/Scheduler.h"

View File

@ -14,15 +14,15 @@ before, 30+ files had to be recompiled because they #included Entity.h
which #includes ScriptableComplex.h.
*/
#ifndef SCRIPTABLE_COMPLEX_INCLUDED
#define SCRIPTABLE_COMPLEX_INCLUDED
#include "scripting/ScriptingHost.h"
#include "simulation/ScriptObject.h"
#include "JSConversions.h"
#include <set>
#ifndef SCRIPTABLE_COMPLEX_INCLUDED
#define SCRIPTABLE_COMPLEX_INCLUDED
class IJSComplex;
class IJSComplexProperty
@ -285,5 +285,3 @@ extern void* jscomplexproperty_suballoc();
extern void jscomplexproperty_suballoc_free(IJSComplexProperty* p);
#endif

View File

@ -52,6 +52,7 @@ linker won't find the definitions of these functions. Right now this is only
#ifndef SCRIPTABLE_COMPLEX_INL_INCLUDED
#define SCRIPTABLE_COMPLEX_INL_INCLUDED
#include "ScriptableComplex.h"
//-----------------------------------------------------------------------------
// CJSComplexPropertyAccessor

View File

@ -3,6 +3,7 @@
#include "Collision.h"
#include "Entity.h"
#include "EntityManager.h"
#include "EntityTemplate.h"
#include <float.h>

View File

@ -1,36 +1,36 @@
// Last modified: May 15 2004, Mark Thompson (mark@wildfiregames.com)
#include "precompiled.h"
#include "ps/Profile.h"
#include "Entity.h"
#include "EntityManager.h"
#include "EntityTemplateCollection.h"
#include "graphics/Unit.h"
#include "Aura.h"
#include "ProductionQueue.h"
#include "renderer/Renderer.h"
#include "graphics/Model.h"
#include "graphics/Terrain.h"
#include "ps/Interact.h"
#include "Collision.h"
#include "PathfindEngine.h"
#include "ps/Game.h"
#include "maths/scripting/JSInterface_Vector3D.h"
#include "maths/MathUtil.h"
#include "ps/CConsole.h"
#include "renderer/WaterManager.h"
#include "EntityFormation.h"
#include "FormationManager.h"
#include "TerritoryManager.h"
#include "Formation.h"
#include "TechnologyCollection.h"
#include "graphics/GameView.h"
#include "graphics/Model.h"
#include "graphics/Sprite.h"
#include "graphics/Terrain.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
#include "maths/MathUtil.h"
#include "maths/scripting/JSInterface_Vector3D.h"
#include "ps/CConsole.h"
#include "ps/Game.h"
#include "ps/Interact.h"
#include "ps/Profile.h"
#include "renderer/Renderer.h"
#include "renderer/WaterManager.h"
#include "scripting/ScriptableComplex.inl"
#include "Aura.h"
#include "Collision.h"
#include "Entity.h"
#include "EntityFormation.h"
#include "EntityManager.h"
#include "EntityTemplate.h"
#include "EntityTemplateCollection.h"
#include "EventHandlers.h"
#include "Formation.h"
#include "FormationManager.h"
#include "PathfindEngine.h"
#include "ProductionQueue.h"
#include "TechnologyCollection.h"
#include "TerritoryManager.h"
extern CConsole* g_Console;
extern int g_xres, g_yres;
@ -467,7 +467,7 @@ void CEntity::update( size_t timestep )
{
if( ( m_lastState != -1 ) || !m_actor->GetModel()->GetAnimation() )
{
m_actor->SetEntitySelection( L"idle" );
m_actor->SetEntitySelection( "idle" );
m_actor->SetRandomAnimation( "idle" );
}
}
@ -1167,14 +1167,14 @@ void CEntity::renderAuras()
CVector2D CEntity::getScreenCoords( float height )
{
CCamera &g_Camera=*g_Game->GetView()->GetCamera();
CCamera &camera = *g_Game->GetView()->GetCamera();
float sx, sy;
CVector3D above;
above.X = m_position.X;
above.Z = m_position.Z;
above.Y = getAnchorLevel(m_position.X, m_position.Z) + height;
g_Camera.GetScreenCoordinates(above, sx, sy);
camera.GetScreenCoordinates(above, sx, sy);
return CVector2D( sx, sy );
}
@ -1399,14 +1399,14 @@ void CEntity::renderRank()
if( g_Selection.m_unitUITextures.find( m_rankName ) == g_Selection.m_unitUITextures.end() )
return;
CCamera *g_Camera=g_Game->GetView()->GetCamera();
CCamera *camera = g_Game->GetView()->GetCamera();
float sx, sy;
CVector3D above;
above.X = m_position.X;
above.Z = m_position.Z;
above.Y = getAnchorLevel(m_position.X, m_position.Z) + m_base->m_rankHeight;
g_Camera->GetScreenCoordinates(above, sx, sy);
camera->GetScreenCoordinates(above, sx, sy);
int size = m_base->m_rankWidth/2;
float x1 = sx + m_base->m_healthBarSize/2;
@ -1853,7 +1853,7 @@ bool CEntity::Kill( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(arg
if( m_actor )
{
m_actor->SetEntitySelection( L"death" );
m_actor->SetEntitySelection( "death" );
m_actor->SetRandomAnimation( "death", true );
}

View File

@ -38,13 +38,8 @@
#include "scripting/DOMEvent.h"
#include "scripting/ScriptCustomTypes.h"
// JW: must be pulled in because CEntity no longer mirrors CEntityTemplate exactly.
// some fields have been moved out of CEntity and are accessed via m_base,
// so CEntityTemplate must be fully defined.
#include "EntityTemplate.h"
class CAura;
//class CEntityTemplate; // see comment above
class CEntityTemplate;
class CBoundingObject;
class CPlayer;
class CProductionQueue;

View File

@ -3,6 +3,7 @@
#include "EntityManager.h"
#include "EntityTemplateCollection.h"
#include "EntityTemplate.h"
#include "ps/ConfigDB.h"
#include "ps/Profile.h"
#include "graphics/Terrain.h"

View File

@ -24,10 +24,11 @@
#include "EntityMessage.h"
#include "ps/Game.h"
#include "ps/World.h"
#include "ps/CStr.h"
#include "maths/Vector3D.h"
class CEntityTemplate;
class CPlayer;
class CStrW;
#define MAX_HANDLES 4096

View File

@ -4,6 +4,7 @@
#include "Entity.h"
#include "EntityTemplate.h"
#include "EventHandlers.h"
#include "graphics/Model.h"
#include "graphics/ObjectEntry.h"
#include "graphics/SkeletonAnim.h"
@ -406,7 +407,7 @@ bool CEntity::processContactActionNoPathing( CEntityOrder* current, size_t times
popOrder();
entf_clear(ENTF_IS_RUNNING);
entf_clear(ENTF_SHOULD_RUN);
m_actor->SetEntitySelection( L"idle" );
m_actor->SetEntitySelection( "idle" );
m_actor->SetRandomAnimation( "idle" );
return( false );
}

View File

@ -4,7 +4,6 @@
#define ENTITY_SUPPORT_INCLUDED
#include "EntityHandles.h"
#include "ScriptObject.h"
class CEntityManager;

View File

@ -21,13 +21,14 @@
#include "graphics/ObjectEntry.h"
#include "scripting/ScriptableComplex.h"
#include "scripting/DOMEvent.h"
#include "BoundingObjects.h"
#include "EventHandlers.h"
#include "EntitySupport.h"
#include "ScriptObject.h"
#include "ps/XML/Xeromyces.h"
class CPlayer;
class CXeromyces;
class XMBElement;
class CEntityTemplate : public CJSComplex<CEntityTemplate>, public IEventTarget
{

View File

@ -1,6 +1,7 @@
#include "precompiled.h"
#include "EntityTemplateCollection.h"
#include "EntityTemplate.h"
#include "graphics/ObjectManager.h"
#include "graphics/Model.h"
#include "ps/CLogger.h"

View File

@ -20,16 +20,18 @@
#include <map>
#include "ps/CStr.h"
#include "ps/Singleton.h"
#include "graphics/ObjectEntry.h"
#include "EntityTemplate.h"
#include "ps/Game.h"
#define g_EntityTemplateCollection CEntityTemplateCollection::GetSingleton()
class CPlayer;
class CEntityTemplate;
class CEntityTemplateCollection : public Singleton<CEntityTemplateCollection>
{
// TODO: PS_MAX_PLAYERS doesn't seem to be an upper limit -
// "This may be overridden by system.cfg ("max_players")"
// - so we shouldn't use it here
static const uint NULL_PLAYER = (PS_MAX_PLAYERS+1);
typedef STL_HASH_MAP<CStrW, CEntityTemplate*, CStrW_hash_compare> TemplateMap;

View File

@ -7,6 +7,7 @@
#include "graphics/Terrain.h"
#include "Entity.h"
#include "EntityManager.h"
#include "EntityTemplate.h"
#include "graphics/Unit.h"
#include "maths/Bound.h"
#include "graphics/Model.h"
@ -209,7 +210,16 @@ ELOSStatus CLOSManager::GetStatus(float fx, float fz, CPlayer* player)
EUnitLOSStatus CLOSManager::GetUnitStatus(CUnit* unit, CPlayer* player)
{
CVector3D centre = unit->GetModel()->GetTransform().GetTranslation();
CVector3D centre;
// For entities, we must use the simulation position so that we stay synchronised
// (because the output of this function will presumably affect AI)
CEntity* entity = unit->GetEntity();
if (entity)
centre = entity->m_position;
else
centre = unit->GetModel()->GetTransform().GetTranslation();
ELOSStatus status = GetStatus(centre.X, centre.Z, player);
if(status & LOS_VISIBLE)
@ -217,7 +227,7 @@ EUnitLOSStatus CLOSManager::GetUnitStatus(CUnit* unit, CPlayer* player)
if(status & LOS_EXPLORED)
{
if(unit->GetEntity() == 0 || unit->GetEntity()->m_base->m_visionPermanent)
if(!entity || entity->m_base->m_visionPermanent)
{
// both actors (which are usually for decoration) and units with the
// permanent flag should be remembered

View File

@ -4,6 +4,7 @@
#include "EntityOrders.h"
#include "Entity.h"
#include "EntityTemplate.h"
#include "PathfindEngine.h"

View File

@ -15,12 +15,12 @@
#include "lib/timer.h"
#include "lib/ogl.h"
#include "EntityManager.h"
using namespace std;
#include "EntityTemplate.h"
CTerritoryManager::CTerritoryManager()
{
m_TerritoryMatrix = 0;
m_DelayedRecalculate = false;
}
CTerritoryManager::~CTerritoryManager()
@ -129,6 +129,14 @@ void CTerritoryManager::Recalculate()
}
}
void CTerritoryManager::DelayedRecalculate()
{
// This is useful particularly for Atlas, which wants to recalculate
// the boundaries as you move an object around but which doesn't want
// to waste time recalculating multiple times per frame
m_DelayedRecalculate = true;
}
CTerritory* CTerritoryManager::GetTerritory(int x, int z)
{
debug_assert( (uint) x < m_TilesPerSide && (uint) z < m_TilesPerSide );
@ -209,6 +217,12 @@ void CTerritoryManager::CalculateBoundary( std::vector<CEntity*>& centres, size_
}
void CTerritoryManager::renderTerritories()
{
if (m_DelayedRecalculate)
{
Recalculate();
m_DelayedRecalculate = false;
}
const CTerrain* pTerrain = g_Game->GetWorld()->GetTerrain();
CFrustum frustum = g_Game->GetView()->GetCamera()->GetFrustum();
std::vector<CTerritory*>::iterator terr=m_Territories.begin();
@ -218,6 +232,9 @@ void CTerritoryManager::renderTerritories()
for ( ; terr != m_Territories.end(); ++terr )
{
if ((*terr)->boundary.empty())
continue;
std::vector<CVector2D>::iterator it=(*terr)->boundary.begin()+1;
//const SPlayerColour& col = (*terr)->owner->GetColour();
//glColor3f(col.r, col.g, col.b);

View File

@ -10,10 +10,6 @@
#ifndef TERRITORY_MANAGER_INCLUDED
#define TERRITORY_MANAGER_INCLUDED
#include "ps/Singleton.h"
#include "ps/Game.h"
#include "ps/World.h"
#include "ps/Player.h"
#include "ps/Vector2D.h"
#include "EntityHandles.h"
@ -39,6 +35,7 @@ class CTerritoryManager
CTerritory*** m_TerritoryMatrix; // m_TerritoryMatrix[x][z] points to the territory for tile (x, z)
uint m_TilesPerSide;
bool m_DelayedRecalculate;
public:
CTerritoryManager();
@ -46,6 +43,7 @@ public:
void Initialize(); // initialize, called after the game is fully loaded
void Recalculate(); // recalculate the territory boundaries
void DelayedRecalculate(); // recalculate the territory boundaries when next rendered
void renderTerritories();
CTerritory* GetTerritory(int x, int z); // get the territory to which the given tile belongs
CTerritory* GetTerritory(float x, float z); // get the territory to which the given world-space point belongs

View File

@ -0,0 +1,299 @@
#include "stdafx.h"
#include "ActorViewer.h"
#include "wx/treectrl.h"
#include "General/Datafile.h"
#include "ScenarioEditor/Tools/Common/Tools.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "ScenarioEditor/Sections/Environment/LightControl.h"
#include "GameInterface/Messages.h"
#include "CustomControls/Canvas/Canvas.h"
#include "CustomControls/SnapSplitterWindow/SnapSplitterWindow.h"
using namespace AtlasMessage;
//////////////////////////////////////////////////////////////////////////
class ActorCanvas : public Canvas
{
public:
ActorCanvas(wxWindow* parent, int* attribList)
: Canvas(parent, attribList, wxBORDER_SUNKEN),
m_Distance(20.f), m_Angle(0.f), m_LastIsValid(false)
{
}
void PostLookAt()
{
POST_MESSAGE(LookAt, (eRenderView::ACTOR,
Position(m_Distance*sin(m_Angle), m_Distance/2.f, m_Distance*cos(m_Angle)),
Position(0, 0, 0)));
}
protected:
virtual void HandleMouseEvent(wxMouseEvent& evt)
{
bool camera_changed = false;
if (evt.GetWheelRotation())
{
float speed = -1.f * ScenarioEditor::GetSpeedModifier();
m_Distance += evt.GetWheelRotation() * speed / evt.GetWheelDelta();
camera_changed = true;
}
if (evt.ButtonDown(wxMOUSE_BTN_LEFT))
{
m_LastX = evt.GetX();
m_LastY = evt.GetY();
m_LastIsValid = true;
}
else if (evt.Dragging() && evt.ButtonIsDown(wxMOUSE_BTN_LEFT) && m_LastIsValid)
{
int dx = evt.GetX() - m_LastX;
int dy = evt.GetY() - m_LastY;
m_LastX = evt.GetX();
m_LastY = evt.GetY();
m_Angle += dx * M_PI/256.f * ScenarioEditor::GetSpeedModifier();
m_Distance += dy / 8.f * ScenarioEditor::GetSpeedModifier();
camera_changed = true;
}
else if (evt.ButtonUp(wxMOUSE_BTN_ANY))
{
// In some situations (e.g. double-clicking the title bar to
// maximise the window) we get a dragging event without the matching
// buttondown; so disallow dragging when there was a buttonup since
// the last buttondown.
// (TODO: does this affect the scenario editor too?)
m_LastIsValid = false;
}
m_Distance = std::max(m_Distance, 1/64.f); // don't let people fly through the origin
if (camera_changed)
PostLookAt();
}
private:
float m_Distance;
float m_Angle;
int m_LastX, m_LastY;
bool m_LastIsValid;
};
//////////////////////////////////////////////////////////////////////////
class StringTreeItemData : public wxTreeItemData
{
public:
StringTreeItemData(const wxString& string) : m_String(string) {}
wxString m_String;
};
enum
{
ID_Actors,
ID_Animations,
ID_Play,
ID_Pause,
ID_Slow,
};
BEGIN_EVENT_TABLE(ActorViewer, wxFrame)
EVT_CLOSE(ActorViewer::OnClose)
EVT_TREE_SEL_CHANGED(ID_Actors, ActorViewer::OnTreeSelection)
EVT_COMBOBOX(ID_Animations, ActorViewer::OnAnimationSelection)
EVT_TEXT_ENTER(ID_Animations, ActorViewer::OnAnimationSelection)
EVT_BUTTON(ID_Play, ActorViewer::OnSpeedButton)
EVT_BUTTON(ID_Pause, ActorViewer::OnSpeedButton)
EVT_BUTTON(ID_Slow, ActorViewer::OnSpeedButton)
END_EVENT_TABLE()
static void SendToGame(const AtlasMessage::sEnvironmentSettings& settings)
{
POST_COMMAND(SetEnvironmentSettings, (settings));
}
ActorViewer::ActorViewer(wxWindow* parent)
: wxFrame(parent, wxID_ANY, _("Actor Viewer"), wxDefaultPosition, wxSize(800, 600)),
m_CurrentSpeed(0.f)
{
SetIcon(wxIcon(_T("ICON_ActorEditor")));
SnapSplitterWindow* splitter = new SnapSplitterWindow(this, 0);
splitter->SetDefaultSashPosition(250);
wxPanel* sidePanel = new wxPanel(splitter);
// TODO: don't have this duplicated from ScenarioEditor.cpp
int glAttribList[] = {
WX_GL_RGBA,
WX_GL_DOUBLEBUFFER,
WX_GL_DEPTH_SIZE, 24,
WX_GL_BUFFER_SIZE, 24,
WX_GL_MIN_ALPHA, 8,
0
};
ActorCanvas* canvas = new ActorCanvas(splitter, glAttribList);
splitter->SplitVertically(sidePanel, canvas);
wglMakeCurrent(NULL, NULL);
POST_MESSAGE(SetContext, (canvas->GetContext()));
POST_MESSAGE(Init, ());
canvas->InitSize();
canvas->PostLookAt();
//////////////////////////////////////////////////////////////////////////
// Construct a tree containing all the available actors
qGetObjectsList qry;
qry.Post();
std::vector<sObjectsListItem> objects = *qry.objects;
m_TreeCtrl = new wxTreeCtrl(sidePanel, ID_Actors);
wxTreeItemId root = m_TreeCtrl->AddRoot(_("Actors"));
std::map<std::wstring, wxTreeItemId> treeEntries;
wxRegEx stripDirs (_T("^([^/]+)/"), wxRE_ADVANCED); // the non-empty string up to the first slash
for (std::vector<sObjectsListItem>::iterator it = objects.begin(); it != objects.end(); ++it)
{
if (it->type != 1)
continue;
wxString name = it->name.c_str();
// Loop through the directory components of the name, stripping them
// off and search down the tree hierarchy
wxString path = _T("");
wxTreeItemId treeItem = root;
while (stripDirs.Matches(name))
{
wxString dir = stripDirs.GetMatch(name, 1);
path += dir + _T("/");
// If we've got 'path' in the tree already, use it
std::map<std::wstring, wxTreeItemId>::iterator entry = treeEntries.find(path.c_str());
if (entry != treeEntries.end())
{
treeItem = entry->second;
}
else
{
// Add this new path into the tree
treeItem = m_TreeCtrl->AppendItem(treeItem, dir);
treeEntries.insert(std::make_pair(path, treeItem));
}
// Remove the leading directory name from the full filename
stripDirs.Replace(&name, _T(""));
}
m_TreeCtrl->AppendItem(treeItem, name, -1, -1, new StringTreeItemData(it->name.c_str()));
}
m_TreeCtrl->Expand(root);
wxArrayString animations;
AtObj animationsList (Datafile::ReadList("animations"));
for (AtIter it = animationsList["item"]; it.defined(); ++it)
animations.Add(it);
m_AnimationBox = new wxComboBox(sidePanel, ID_Animations, _T("Idle"), wxDefaultPosition, wxDefaultSize, animations);
m_EnvironmentSettings.sunelevation = 45 * M_PI/180;
m_EnvironmentSettings.sunrotation = 315 * M_PI/180;
m_EnvironmentSettings.suncolour = Colour(255, 255, 255);
m_EnvironmentSettings.terraincolour = Colour(164, 164, 164);
m_EnvironmentSettings.unitcolour = Colour(164, 164, 164);
LightControl* lightControl = new LightControl(sidePanel, wxSize(100, 100), m_EnvironmentSettings);
m_Conn = m_EnvironmentSettings.RegisterObserver(0, &SendToGame);
SendToGame(m_EnvironmentSettings);
wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
wxSizer* bottomSizer = new wxBoxSizer(wxHORIZONTAL);
wxSizer* bottomRightSizer = new wxBoxSizer(wxVERTICAL);
wxSizer* playButtonSizer = new wxBoxSizer(wxHORIZONTAL);
mainSizer->Add(m_TreeCtrl, wxSizerFlags().Expand().Proportion(1));
mainSizer->Add(bottomSizer, wxSizerFlags().Expand());
bottomSizer->Add(lightControl, wxSizerFlags().Border(wxRIGHT, 5));
bottomSizer->Add(bottomRightSizer, wxSizerFlags().Proportion(1));
playButtonSizer->Add(new wxButton(sidePanel, ID_Play, _("Play")), wxSizerFlags().Proportion(1));
playButtonSizer->Add(new wxButton(sidePanel, ID_Pause, _("Pause")), wxSizerFlags().Proportion(1));
playButtonSizer->Add(new wxButton(sidePanel, ID_Slow, _("Slow")), wxSizerFlags().Proportion(1));
bottomRightSizer->Add(m_AnimationBox, wxSizerFlags().Expand());
bottomRightSizer->Add(playButtonSizer, wxSizerFlags().Expand());
sidePanel->SetSizer(mainSizer);
//////////////////////////////////////////////////////////////////////////
// Start by displaying the default non-existent actor
m_CurrentActor = _T("structures/fndn_1x1.xml");
SetActorView();
POST_MESSAGE(RenderEnable, (eRenderView::ACTOR));
}
void ActorViewer::OnClose(wxCloseEvent& WXUNUSED(event))
{
POST_MESSAGE(Shutdown, ());
AtlasMessage::qExit().Post();
// blocks until engine has noticed the message, so we won't be
// destroying the GLCanvas while it's still rendering
Destroy();
}
void ActorViewer::SetActorView()
{
POST_MESSAGE(SetActorViewer, (m_CurrentActor.c_str(), m_AnimationBox->GetValue().c_str(), m_CurrentSpeed));
}
void ActorViewer::OnTreeSelection(wxTreeEvent& event)
{
wxTreeItemData* data = m_TreeCtrl->GetItemData(event.GetItem());
if (! data)
return;
m_CurrentActor = static_cast<StringTreeItemData*>(data)->m_String;
SetActorView();
}
void ActorViewer::OnAnimationSelection(wxCommandEvent& WXUNUSED(event))
{
SetActorView();
}
void ActorViewer::OnSpeedButton(wxCommandEvent& event)
{
if (event.GetId() == ID_Play)
m_CurrentSpeed = 1.f;
else if (event.GetId() == ID_Pause)
m_CurrentSpeed = 0.f;
else if (event.GetId() == ID_Slow)
m_CurrentSpeed = 0.1f;
else
{
wxLogDebug(_T("Invalid OnSpeedButton (%d)"), event.GetId());
m_CurrentSpeed = 1.f;
}
SetActorView();
}

View File

@ -0,0 +1,29 @@
#include "Windows/AtlasWindow.h"
#include "GameInterface/Messages.h"
#include "General/Observable.h"
class wxTreeCtrl;
class ActorViewer : public wxFrame
{
public:
ActorViewer(wxWindow* parent);
private:
void SetActorView();
void OnClose(wxCloseEvent& event);
void OnTreeSelection(wxTreeEvent& event);
void OnAnimationSelection(wxCommandEvent& event);
void OnSpeedButton(wxCommandEvent& event);
wxTreeCtrl* m_TreeCtrl;
wxComboBox* m_AnimationBox;
wxString m_CurrentActor;
float m_CurrentSpeed;
Observable<AtlasMessage::sEnvironmentSettings> m_EnvironmentSettings;
ObservableScopedConnection m_Conn;
DECLARE_EVENT_TABLE();
};

View File

@ -0,0 +1,88 @@
#include "stdafx.h"
#include "Canvas.h"
#include "GameInterface/Messages.h"
#include "ScenarioEditor/tools/Common/Tools.h"
Canvas::Canvas(wxWindow* parent, int* attribList, long style)
: wxGLCanvas(parent, -1, wxDefaultPosition, wxDefaultSize, style, _T("GLCanvas"), attribList),
m_SuppressResize(true),
m_LastMousePos(-1, -1), m_MouseCaptured(false)
{
}
void Canvas::OnResize(wxSizeEvent&)
{
// Be careful not to send 'resize' messages to the game before we've
// told it that this canvas exists
if (! m_SuppressResize)
POST_MESSAGE(ResizeScreen, (GetClientSize().GetWidth(), GetClientSize().GetHeight()));
// TODO: fix flashing
}
void Canvas::InitSize()
{
m_SuppressResize = false;
SetSize(320, 240);
}
void Canvas::OnMouseCapture(wxMouseCaptureChangedEvent& WXUNUSED(evt))
{
if (m_MouseCaptured)
{
// unexpected loss of capture (i.e. not through ReleaseMouse)
m_MouseCaptured = false;
// (Note that this can be made to happen easily, by alt-tabbing away,
// and mouse events will be missed; so it is never guaranteed that e.g.
// two LeftDown events will be separated by a LeftUp.)
}
}
void Canvas::OnMouse(wxMouseEvent& evt)
{
// Capture on button-down, so we can respond even when the mouse
// moves off the window
if (!m_MouseCaptured && evt.ButtonDown())
{
m_MouseCaptured = true;
CaptureMouse();
}
// Un-capture when all buttons are up
else if (m_MouseCaptured && evt.ButtonUp() &&
! (evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_MIDDLE) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT))
)
{
m_MouseCaptured = false;
ReleaseMouse();
}
// Set focus when clicking
if (evt.ButtonDown())
SetFocus();
// Reject motion events if the mouse has not actually moved
if (evt.Moving() || evt.Dragging())
{
if (m_LastMousePos == evt.GetPosition())
return;
m_LastMousePos = evt.GetPosition();
}
HandleMouseEvent(evt);
}
BEGIN_EVENT_TABLE(Canvas, wxGLCanvas)
EVT_SIZE(Canvas::OnResize)
EVT_LEFT_DOWN (Canvas::OnMouse)
EVT_LEFT_UP (Canvas::OnMouse)
EVT_RIGHT_DOWN (Canvas::OnMouse)
EVT_RIGHT_UP (Canvas::OnMouse)
EVT_MIDDLE_DOWN(Canvas::OnMouse)
EVT_MIDDLE_UP (Canvas::OnMouse)
EVT_MOUSEWHEEL (Canvas::OnMouse)
EVT_MOTION (Canvas::OnMouse)
EVT_MOUSE_CAPTURE_CHANGED(Canvas::OnMouseCapture)
END_EVENT_TABLE()

View File

@ -0,0 +1,24 @@
#include "wx/glcanvas.h"
class Canvas : public wxGLCanvas
{
public:
Canvas(wxWindow* parent, int* attribList, long style);
void InitSize();
protected:
virtual void HandleMouseEvent(wxMouseEvent& evt) = 0;
private:
void OnResize(wxSizeEvent&);
void OnMouseCapture(wxMouseCaptureChangedEvent& evt);
void OnMouse(wxMouseEvent& evt);
bool m_SuppressResize;
wxPoint m_LastMousePos;
bool m_MouseCaptured;
DECLARE_EVENT_TABLE();
};

View File

@ -1,5 +1,8 @@
#include "stdafx.h"
/* Disabled (and should be removed if it turns out to be unnecessary)
- see MessagePasserImpl.cpp for information
#include "AtlasEventLoop.h"
AtlasEventLoop::AtlasEventLoop()
@ -36,3 +39,4 @@ bool AtlasEventLoop::Dispatch()
return wxEventLoop::Dispatch();
}
*/

View File

@ -1,6 +1,9 @@
#ifndef ATLASEVENTLOOP_H__
#define ATLASEVENTLOOP_H__
/* Disabled (and should be removed if it turns out to be unnecessary)
- see MessagePasserImpl.cpp for information
#include "wx/evtloop.h"
struct tagMSG;
@ -21,4 +24,6 @@ public:
virtual bool Dispatch();
};
*/
#endif // ATLASEVENTLOOP_H__

View File

@ -5,6 +5,7 @@
#include <boost/bind.hpp>
typedef boost::signals::connection ObservableConnection;
typedef boost::signals::scoped_connection ObservableScopedConnection;
template <typename T> class Observable : public T
{

View File

@ -5,11 +5,13 @@
#include "General/AtlasEventLoop.h"
#include "General/Datafile.h"
#include "ActorEditor/ActorEditor.h"
#include "ColourTester/ColourTester.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "FileConverter/FileConverter.h"
#include "ActorViewer/ActorViewer.h"
#include "ArchiveViewer/ArchiveViewer.h"
#include "ColourTester/ColourTester.h"
#include "FileConverter/FileConverter.h"
#include "ScenarioEditor/ScenarioEditor.h"
#include "GameInterface/MessagePasser.h"
@ -26,7 +28,7 @@ ATLASDLLIMPEXP void* ShareableMalloc(size_t n)
}
ATLASDLLIMPEXP void ShareableFree(void* p)
{
return free(p);
free(p);
}
// Define the function pointers that we'll use when calling those functions.
// (The game loads the addresses of the above functions, then does the same.)
@ -72,16 +74,30 @@ ATLASDLLIMPEXP void Atlas_SetMessagePasser(MessagePasser* passer)
g_MessagePasser = passer;
}
ATLASDLLIMPEXP void Atlas_StartWindow(wchar_t* type)
ATLASDLLIMPEXP void Atlas_StartWindow(const wchar_t* type)
{
g_InitialWindowType = type;
wxEntry(g_Module);
}
ATLASDLLIMPEXP void Atlas_DisplayError(const wchar_t* text, unsigned int WXUNUSED(flags))
{
// This is called from the game thread.
// wxLog appears to be thread-safe, so that's okay.
wxLogError(L"%s", text);
class wxDLLApp : public wxApp
// TODO: wait for user response (if possible) before returning,
// and return their status (break/continue/debug/etc), but only in
// cases where we're certain it won't deadlock (i.e. the UI event loop
// is still running and won't block before showing the dialog to the user)
// and where it matters (i.e. errors, not warnings (unless they're going to
// turn into errors after continuing))
}
class AtlasDLLApp : public wxApp
{
public:
virtual bool OnInit()
{
if (! wxIsDebuggerRunning())
@ -99,10 +115,11 @@ public:
wxFrame* frame;
#define MAYBE(t) if (g_InitialWindowType == _T(#t)) frame = new t(NULL); else
MAYBE(ActorEditor)
MAYBE(ColourTester)
MAYBE(ScenarioEditor)
MAYBE(FileConverter)
MAYBE(ActorViewer)
MAYBE(ArchiveViewer)
MAYBE(ColourTester)
MAYBE(FileConverter)
MAYBE(ScenarioEditor)
#undef MAYBE
// else
{
@ -188,6 +205,8 @@ public:
}
}
/* Disabled (and should be removed if it turns out to be unnecessary)
- see MessagePasserImpl.cpp for information
virtual int MainLoop()
{
// Override the default MainLoop so that we can provide our own event loop
@ -201,6 +220,8 @@ public:
m_mainLoop = old;
return ret;
}
*/
};
IMPLEMENT_APP_NO_MAIN(wxDLLApp)
IMPLEMENT_APP_NO_MAIN(AtlasDLLApp)

View File

@ -3,9 +3,11 @@
namespace AtlasMessage { class MessagePasser; }
ATLASDLLIMPEXP void Atlas_SetMessagePasser(AtlasMessage::MessagePasser*);
ATLASDLLIMPEXP void Atlas_StartWindow(wchar_t* type);
ATLASDLLIMPEXP void Atlas_StartWindow(const wchar_t* type);
ATLASDLLIMPEXP void Atlas_GLSetCurrent(void* context);
ATLASDLLIMPEXP void Atlas_GLSwapBuffers(void* context);
ATLASDLLIMPEXP void Atlas_NotifyEndOfFrame();
ATLASDLLIMPEXP void Atlas_DisplayError(const wchar_t* text, unsigned int flags);

View File

@ -2,7 +2,6 @@
#include "ScenarioEditor.h"
#include "wx/glcanvas.h"
#include "wx/evtloop.h"
#include "wx/tooltip.h"
#include "wx/image.h"
@ -11,84 +10,74 @@
#include "General/AtlasEventLoop.h"
#include "General/Datafile.h"
#include "SnapSplitterWindow/SnapSplitterWindow.h"
#include "HighResTimer/HighResTimer.h"
#include "Buttons/ToolButton.h"
#include "CustomControls/Canvas/Canvas.h"
#include "GameInterface/MessagePasser.h"
#include "GameInterface/Messages.h"
#include "tools/Common/Tools.h"
// #define UI_ONLY
static HighResTimer g_Timer;
using namespace AtlasMessage;
//////////////////////////////////////////////////////////////////////////
// TODO: move into another file
class Canvas : public wxGLCanvas
// GL functions exported from DLL, and called by game (in a separate
// thread to the standard wx one)
ATLASDLLIMPEXP void Atlas_GLSetCurrent(void* context)
{
((wxGLContext*)context)->SetCurrent();
}
ATLASDLLIMPEXP void Atlas_GLSwapBuffers(void* context)
{
((wxGLContext*)context)->SwapBuffers();
}
//////////////////////////////////////////////////////////////////////////
class GameCanvas : public Canvas
{
public:
Canvas(wxWindow* parent, int* attribList)
: wxGLCanvas(parent, -1, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS, _T("GLCanvas"), attribList),
m_SuppressResize(true),
m_MouseState(NONE), m_LastMouseState(NONE), m_MouseCaptured(false),
m_LastMousePos(-1, -1)
GameCanvas(wxWindow* parent, int* attribList)
: Canvas(parent, attribList, wxWANTS_CHARS),
m_MouseState(NONE), m_LastMouseState(NONE)
{
}
void OnResize(wxSizeEvent&)
{
#ifndef UI_ONLY
// Be careful not to send 'resize' messages to the game before we've
// told it that this canvas exists
if (! m_SuppressResize)
POST_MESSAGE(ResizeScreen, (GetClientSize().GetWidth(), GetClientSize().GetHeight()));
// TODO: fix flashing
#endif // UI_ONLY
}
void InitSize()
{
m_SuppressResize = false;
SetSize(320, 240);
}
private:
bool KeyScroll(wxKeyEvent& evt, bool enable)
{
#ifndef UI_ONLY
int dir;
switch (evt.GetKeyCode())
{
case WXK_LEFT: dir = AtlasMessage::eScrollConstantDir::LEFT; break;
case WXK_RIGHT: dir = AtlasMessage::eScrollConstantDir::RIGHT; break;
case WXK_UP: dir = AtlasMessage::eScrollConstantDir::FORWARDS; break;
case WXK_DOWN: dir = AtlasMessage::eScrollConstantDir::BACKWARDS; break;
case WXK_LEFT: dir = eScrollConstantDir::LEFT; break;
case WXK_RIGHT: dir = eScrollConstantDir::RIGHT; break;
case WXK_UP: dir = eScrollConstantDir::FORWARDS; break;
case WXK_DOWN: dir = eScrollConstantDir::BACKWARDS; break;
case WXK_SHIFT: case WXK_CONTROL: dir = -1; break;
default: return false;
}
float speed = 120.f;
if (wxGetKeyState(WXK_SHIFT) && wxGetKeyState(WXK_CONTROL))
speed /= 64.f;
else if (wxGetKeyState(WXK_CONTROL))
speed /= 4.f;
else if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
float speed = 120.f * ScenarioEditor::GetSpeedModifier();
if (dir == -1) // changed modifier keys - update all currently-scrolling directions
{
if (wxGetKeyState(WXK_LEFT)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::LEFT, speed));
if (wxGetKeyState(WXK_RIGHT)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::RIGHT, speed));
if (wxGetKeyState(WXK_UP)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::FORWARDS, speed));
if (wxGetKeyState(WXK_DOWN)) POST_MESSAGE(ScrollConstant, (AtlasMessage::eScrollConstantDir::BACKWARDS, speed));
if (wxGetKeyState(WXK_LEFT)) POST_MESSAGE(ScrollConstant, (eRenderView::GAME, eScrollConstantDir::LEFT, speed));
if (wxGetKeyState(WXK_RIGHT)) POST_MESSAGE(ScrollConstant, (eRenderView::GAME, eScrollConstantDir::RIGHT, speed));
if (wxGetKeyState(WXK_UP)) POST_MESSAGE(ScrollConstant, (eRenderView::GAME, eScrollConstantDir::FORWARDS, speed));
if (wxGetKeyState(WXK_DOWN)) POST_MESSAGE(ScrollConstant, (eRenderView::GAME, eScrollConstantDir::BACKWARDS, speed));
}
else
{
POST_MESSAGE(ScrollConstant, (dir, enable ? speed : 0.0f));
POST_MESSAGE(ScrollConstant, (eRenderView::GAME, dir, enable ? speed : 0.0f));
}
#endif // UI_ONLY
return true;
}
@ -135,47 +124,14 @@ public:
float speed = 16.f;
if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
POST_MESSAGE(SmoothZoom, (speed*dir));
POST_MESSAGE(SmoothZoom, (eRenderView::GAME, speed*dir));
}
else
evt.Skip();
}
void OnMouseCapture(wxMouseCaptureChangedEvent& WXUNUSED(evt))
virtual void HandleMouseEvent(wxMouseEvent& evt)
{
if (m_MouseCaptured)
{
// unexpected loss of capture (i.e. not through ReleaseMouse)
m_MouseCaptured = false;
// (Note that this can be made to happen easily, by alt-tabbing away,
// and mouse events will be missed; so it is never guaranteed that e.g.
// two LeftDown events will be separated by a LeftUp.)
}
}
void OnMouse(wxMouseEvent& evt)
{
// Capture on button-down, so we can respond even when the mouse
// moves off the window
if (!m_MouseCaptured && evt.ButtonDown())
{
m_MouseCaptured = true;
CaptureMouse();
}
// Un-capture when all buttons are up
else if (m_MouseCaptured && evt.ButtonUp() &&
! (evt.ButtonIsDown(wxMOUSE_BTN_LEFT) || evt.ButtonIsDown(wxMOUSE_BTN_MIDDLE) || evt.ButtonIsDown(wxMOUSE_BTN_RIGHT))
)
{
m_MouseCaptured = false;
ReleaseMouse();
}
// Set focus when clicking
if (evt.ButtonDown())
SetFocus();
// TODO or at least to think about: When using other controls in the
// editor, it's annoying that keyboard/scrollwheel no longer navigate
@ -188,16 +144,6 @@ public:
if (evt.Moving())
SetFocus();
// Reject motion events if the mouse has not actually moved
if (evt.Moving() || evt.Dragging())
{
if (m_LastMousePos == evt.GetPosition())
return;
m_LastMousePos = evt.GetPosition();
}
#ifndef UI_ONLY
if (GetCurrentTool().OnMouse(evt))
{
// Mouse event has been handled by the tool, so don't try
@ -209,15 +155,8 @@ public:
if (evt.GetWheelRotation())
{
float speed = 16.f;
if (wxGetKeyState(WXK_SHIFT) && wxGetKeyState(WXK_CONTROL))
speed /= 64.f;
else if (wxGetKeyState(WXK_CONTROL))
speed /= 4.f;
else if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
POST_MESSAGE(SmoothZoom, (evt.GetWheelRotation() * speed / evt.GetWheelDelta()));
float speed = 16.f * ScenarioEditor::GetSpeedModifier();
POST_MESSAGE(SmoothZoom, (eRenderView::GAME, evt.GetWheelRotation() * speed / evt.GetWheelDelta()));
}
else
{
@ -236,8 +175,8 @@ public:
switch (m_MouseState)
{
case NONE: break;
case SCROLL: POST_MESSAGE(Scroll, (AtlasMessage::eScrollType::FROM, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (AtlasMessage::eRotateAroundType::FROM, evt.GetPosition())); break;
case SCROLL: POST_MESSAGE(Scroll, (eRenderView::GAME, eScrollType::FROM, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (eRenderView::GAME, eRotateAroundType::FROM, evt.GetPosition())); break;
default: wxFAIL;
}
m_LastMouseState = m_MouseState;
@ -247,59 +186,28 @@ public:
switch (m_MouseState)
{
case NONE: break;
case SCROLL: POST_MESSAGE(Scroll, (AtlasMessage::eScrollType::TO, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (AtlasMessage::eRotateAroundType::TO, evt.GetPosition())); break;
case SCROLL: POST_MESSAGE(Scroll, (eRenderView::GAME, eScrollType::TO, evt.GetPosition())); break;
case ROTATEAROUND: POST_MESSAGE(RotateAround, (eRenderView::GAME, eRotateAroundType::TO, evt.GetPosition())); break;
default: wxFAIL;
}
}
}
#endif // UI_ONLY
}
private:
bool m_SuppressResize;
enum { NONE, SCROLL, ROTATEAROUND };
int m_MouseState, m_LastMouseState;
bool m_MouseCaptured;
wxPoint m_LastMousePos;
DECLARE_EVENT_TABLE();
};
BEGIN_EVENT_TABLE(Canvas, wxGLCanvas)
EVT_SIZE (Canvas::OnResize)
EVT_KEY_DOWN (Canvas::OnKeyDown)
EVT_KEY_UP (Canvas::OnKeyUp)
EVT_CHAR (Canvas::OnChar)
EVT_LEFT_DOWN (Canvas::OnMouse)
EVT_LEFT_UP (Canvas::OnMouse)
EVT_RIGHT_DOWN (Canvas::OnMouse)
EVT_RIGHT_UP (Canvas::OnMouse)
EVT_MIDDLE_DOWN(Canvas::OnMouse)
EVT_MIDDLE_UP (Canvas::OnMouse)
EVT_MOUSEWHEEL (Canvas::OnMouse)
EVT_MOTION (Canvas::OnMouse)
EVT_MOUSE_CAPTURE_CHANGED(Canvas::OnMouseCapture)
BEGIN_EVENT_TABLE(GameCanvas, Canvas)
EVT_KEY_DOWN(GameCanvas::OnKeyDown)
EVT_KEY_UP(GameCanvas::OnKeyUp)
EVT_CHAR(GameCanvas::OnChar)
END_EVENT_TABLE()
// GL functions exported from DLL, and called by game (in a separate
// thread to the standard wx one)
ATLASDLLIMPEXP void Atlas_GLSetCurrent(void* context)
{
((wxGLContext*)context)->SetCurrent();
}
ATLASDLLIMPEXP void Atlas_GLSwapBuffers(void* context)
{
((wxGLContext*)context)->SwapBuffers();
}
//////////////////////////////////////////////////////////////////////////
volatile bool g_FrameHasEnded;
// Called from game thread
ATLASDLLIMPEXP void Atlas_NotifyEndOfFrame()
@ -434,7 +342,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
WX_GL_MIN_ALPHA, 8, // alpha bits
0
};
Canvas* canvas = new Canvas(m_SectionLayout.GetCanvasParent(), glAttribList);
Canvas* canvas = new GameCanvas(m_SectionLayout.GetCanvasParent(), glAttribList);
m_SectionLayout.SetCanvas(canvas);
// The canvas' context gets made current on creation; but it can only be
// current for one thread at a time, and it needs to be current for the
@ -447,7 +355,6 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
// Send setup messages to game engine:
#ifndef UI_ONLY
POST_MESSAGE(SetContext, (canvas->GetContext()));
POST_MESSAGE(Init, ());
@ -458,8 +365,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
// a valid map loaded)
POST_MESSAGE(GenerateMap, (9));
POST_MESSAGE(RenderEnable, (true));
#endif
POST_MESSAGE(RenderEnable, (eRenderView::GAME));
// Set up a timer to make sure tool-updates happen frequently (in addition
// to the idle handler (which makes them happen more frequently if there's nothing
@ -468,16 +374,26 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
m_Timer.Start(20);
}
float ScenarioEditor::GetSpeedModifier()
{
if (wxGetKeyState(WXK_SHIFT) && wxGetKeyState(WXK_CONTROL))
return 1.f/64.f;
else if (wxGetKeyState(WXK_CONTROL))
return 1.f/4.f;
else if (wxGetKeyState(WXK_SHIFT))
return 4.f;
else
return 1.f;
}
void ScenarioEditor::OnClose(wxCloseEvent&)
{
SetCurrentTool(_T(""));
#ifndef UI_ONLY
POST_MESSAGE(Shutdown, ());
#endif
AtlasMessage::qExit().Post();
qExit().Post();
// blocks until engine has noticed the message, so we won't be
// destroying the GLCanvas while it's still rendering
@ -553,7 +469,7 @@ void ScenarioEditor::OnOpen(wxCommandEvent& WXUNUSED(event))
SetOpenFilename(dlg.GetFilename());
// Wait for it to load, while the wxBusyInfo is telling the user that we're doing that
AtlasMessage::qPing qry;
qPing qry;
qry.Post();
}
@ -576,7 +492,7 @@ void ScenarioEditor::OnSave(wxCommandEvent& event)
POST_MESSAGE(SaveMap, (map));
// Wait for it to finish saving
AtlasMessage::qPing qry;
qPing qry;
qry.Post();
}
}
@ -599,7 +515,7 @@ void ScenarioEditor::OnSaveAs(wxCommandEvent& WXUNUSED(event))
SetOpenFilename(dlg.GetFilename());
// Wait for it to finish saving
AtlasMessage::qPing qry;
qPing qry;
qry.Post();
}
}
@ -631,7 +547,7 @@ void ScenarioEditor::OnScreenshot(wxCommandEvent& WXUNUSED(event))
//////////////////////////////////////////////////////////////////////////
AtlasMessage::Position::Position(const wxPoint& pt)
Position::Position(const wxPoint& pt)
: type(1)
{
type1.x = pt.x;
@ -640,6 +556,8 @@ AtlasMessage::Position::Position(const wxPoint& pt)
//////////////////////////////////////////////////////////////////////////
/* Disabled (and should be removed if it turns out to be unnecessary)
- see MessagePasserImpl.cpp for information
static void QueryCallback()
{
@ -670,6 +588,14 @@ static void QueryCallback()
AtlasEventLoop* evtLoop = (AtlasEventLoop*)wxEventLoop::GetActive();
// evtLoop might be NULL, particularly if we're still initialising windows
// and haven't got into the normal event loop yet. But we'd have to process
// messages anyway, to avoid the deadlocks that this is for. So, don't bother
// with that and just crash instead.
// (Maybe it could be solved better by constructing/finding an event loop
// object here and setting it as the global one, assuming it's not overwritten
// later by wx.)
while (evtLoop->Pending())
{
// Based on src/msw/evtloop.cpp's wxEventLoop::Dispatch()
@ -712,8 +638,9 @@ static void QueryCallback()
}
}
}
void AtlasMessage::QueryMessage::Post()
*/
void QueryMessage::Post()
{
g_MessagePasser->Query(this, &QueryCallback);
// g_MessagePasser->Query(this, &QueryCallback);
g_MessagePasser->Query(this, NULL);
}

View File

@ -27,6 +27,8 @@ public:
static AtlasWindowCommandProc& GetCommandProc();
static float GetSpeedModifier();
private:
wxTimer m_Timer;

View File

@ -729,7 +729,7 @@ public:
m_Sizer->Add(m_Track, 0);
m_Sizer->Add(m_Path, 0);
m_Timer = new wxTimer(this, wxID_ANY);
m_Timer.SetOwner(this);
}
void Update()
{
@ -744,7 +744,7 @@ public:
void PrepareTimers()
{
m_OldTime = m_NewTime = m_HighResTimer.GetTime();
m_Timer->Start(10);
m_Timer.Start(10);
}
void Reset()
{
@ -754,7 +754,7 @@ public:
float m_OldTime;
float m_NewTime;
wxTimer* m_Timer;
wxTimer m_Timer;
private:
TrackSlider* m_Track;
HighResTimer m_HighResTimer;
@ -771,7 +771,7 @@ END_EVENT_TABLE()
void TrackSlider::OnScroll(wxScrollEvent& WXUNUSED(event))
{
//Move path and send movement message
m_Sidebar->m_SliderBox->m_Timer->Stop();
m_Sidebar->m_SliderBox->m_Timer.Stop();
if ( m_Sidebar->m_SelectedTrack < 0 || m_Sidebar->m_SelectedPath < 0 )
{
SetValue(0);
@ -792,7 +792,7 @@ void TrackSlider::OnScroll(wxScrollEvent& WXUNUSED(event))
}
void PathSlider::OnScroll(wxScrollEvent& WXUNUSED(event))
{
m_Sidebar->m_SliderBox->m_Timer->Stop();
m_Sidebar->m_SliderBox->m_Timer.Stop();
if ( m_Sidebar->m_SelectedTrack < 0 || m_Sidebar->m_SelectedPath < 0 )
{
SetValue(0);
@ -834,7 +834,7 @@ void TrackSlider::Update(float interval)
if ( move == range && m_Sidebar->m_Playing )
{
m_Parent->m_Timer->Stop();
m_Parent->m_Timer.Stop();
SetValue(0);
m_Path->SetValue(0);
m_Sidebar->GotoNode(0);
@ -859,7 +859,7 @@ public:
{
if ( m_Parent->m_SelectedTrack < 0 )
return;
m_Parent->m_SliderBox->m_Timer->Stop();
m_Parent->m_SliderBox->m_Timer.Stop();
m_Parent->m_Playing = false;
std::wstring name=*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name;
@ -894,7 +894,7 @@ public:
{
if ( m_Parent->m_SelectedTrack < 0 || m_Parent->m_SelectedPath < 0)
return;
m_Parent->m_SliderBox->m_Timer->Stop();
m_Parent->m_SliderBox->m_Timer.Stop();
m_Parent->m_Playing = false;
m_Parent->m_AbsoluteTime = m_Parent->m_TimeElapsed = 0.0f;
m_Parent->SelectPath(0);
@ -910,7 +910,7 @@ public:
{
if ( m_Parent->m_SelectedTrack < 0 )
return;
m_Parent->m_SliderBox->m_Timer->Stop();
m_Parent->m_SliderBox->m_Timer.Stop();
m_Parent->m_SliderBox->PrepareTimers();
POST_MESSAGE(CinemaEvent,
@ -925,7 +925,7 @@ public:
{
if ( m_Parent->m_SelectedTrack < 0 )
return;
m_Parent->m_SliderBox->m_Timer->Stop();
m_Parent->m_SliderBox->m_Timer.Stop();
m_Parent->m_SliderBox->Reset();
//m_Parent->m_NodeList->Thaw();
m_Parent->m_Playing = false;
@ -939,7 +939,7 @@ public:
//void OnForward(wxCommandEvent& event)
void OnNext(wxCommandEvent& WXUNUSED(event))
{
m_Parent->m_SliderBox->m_Timer->Stop();
m_Parent->m_SliderBox->m_Timer.Stop();
m_Parent->m_Playing = false;
std::wstring name=*m_Parent->m_Tracks[m_Parent->m_SelectedTrack].name;
sCinemaPath path = m_Parent->GetCurrentPath();

View File

@ -60,18 +60,13 @@ public:
Add(m_Slider);
}
~VariableSliderBox()
{
m_Conn.disconnect();
}
void OnSettingsChange(const AtlasMessage::sEnvironmentSettings& WXUNUSED(env))
{
m_Slider->UpdateFromVar();
}
private:
ObservableConnection m_Conn;
ObservableScopedConnection m_Conn;
VariableSlider* m_Slider;
};
@ -122,11 +117,6 @@ public:
Add(m_Combo);
}
~VariableListBox()
{
m_Conn.disconnect();
}
void SetChoices(const std::vector<std::wstring>& choices)
{
wxArrayString choices_arraystr;
@ -145,7 +135,7 @@ public:
}
private:
ObservableConnection m_Conn;
ObservableScopedConnection m_Conn;
VariableCombo* m_Combo;
};
@ -210,18 +200,13 @@ public:
Add(m_Button);
}
~VariableColourBox()
{
m_Conn.disconnect();
}
void OnSettingsChange(const AtlasMessage::sEnvironmentSettings& WXUNUSED(env))
{
m_Button->UpdateDisplay();
}
private:
ObservableConnection m_Conn;
ObservableScopedConnection m_Conn;
VariableColourButton* m_Button;
};
@ -240,7 +225,7 @@ EnvironmentSidebar::EnvironmentSidebar(wxWindow* sidebarContainer, wxWindow* bot
m_MainSizer->Add(new VariableSliderBox(this, _("Water waviness"), g_EnvironmentSettings.waterwaviness, 0, 10.f));
m_MainSizer->Add(new VariableSliderBox(this, _("Sun rotation"), g_EnvironmentSettings.sunrotation, -M_PI, M_PI));
m_MainSizer->Add(new VariableSliderBox(this, _("Sun elevation"), g_EnvironmentSettings.sunelevation, -M_PI/2, M_PI/2));
m_MainSizer->Add(new LightControl(this, g_EnvironmentSettings));
m_MainSizer->Add(new LightControl(this, wxSize(150, 150), g_EnvironmentSettings));
m_MainSizer->Add(m_SkyList = new VariableListBox(this, _("Sky set"), g_EnvironmentSettings.skyset));
m_MainSizer->Add(new VariableColourBox(this, _("Sun colour"), g_EnvironmentSettings.suncolour));
m_MainSizer->Add(new VariableColourBox(this, _("Terrain ambient colour"), g_EnvironmentSettings.terraincolour));

View File

@ -14,5 +14,5 @@ protected:
private:
VariableListBox* m_SkyList;
ObservableConnection m_Conn;
ObservableScopedConnection m_Conn;
};

View File

@ -8,13 +8,13 @@ class LightSphere : public wxControl
{
public:
LightSphere(wxWindow* parent, LightControl* lightControl)
: wxControl(parent, wxID_ANY, wxDefaultPosition, wxSize(150, 150)),
LightSphere(wxWindow* parent, const wxSize& size, LightControl* lightControl)
: wxControl(parent, wxID_ANY, wxDefaultPosition, size),
m_LightControl(lightControl)
{
}
void OnPaint(wxPaintEvent& event)
void OnPaint(wxPaintEvent& WXUNUSED(event))
{
// Draw a lit 3D sphere:
@ -87,9 +87,16 @@ public:
float mz2 = 1 - mx*mx - my*my;
if (mz2 >= 0.f)
{
float mz = sqrt(mz2);
//float mz = sqrt(mz2);
//phi = asin(mz);
// ^^ That's giving the height of the sphere at that point, so it's
// matching the point the user clicked on - but that's quite inconvenient
// when you want to move the sun near the horizon. So just make up
// some formula that gives a slightly nicer-feeling result:
phi = asin(mz2*mz2);
theta = -atan2(mx, my);
phi = asin(mz);
}
else
{
@ -114,12 +121,16 @@ BEGIN_EVENT_TABLE(LightSphere, wxControl)
EVT_LEFT_DOWN(LightSphere::OnMouse)
END_EVENT_TABLE()
LightControl::LightControl(wxWindow* parent, Observable<AtlasMessage::sEnvironmentSettings>& environment)
LightControl::LightControl(wxWindow* parent, const wxSize& size, Observable<AtlasMessage::sEnvironmentSettings>& environment)
: wxPanel(parent), m_Environment(environment)
{
m_Sphere = new LightSphere(this, this);
wxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->SetMinSize(size);
m_Sphere = new LightSphere(this, size, this);
m_Sphere->theta = environment.sunrotation;
m_Sphere->phi = environment.sunelevation;
sizer->Add(m_Sphere, wxSizerFlags().Expand().Proportion(1));
SetSizer(sizer);
m_Conn = environment.RegisterObserver(0, &LightControl::OnSettingsChange, this);
}

View File

@ -10,7 +10,7 @@ class LightSphere;
class LightControl : public wxPanel
{
public:
LightControl(wxWindow* parent, Observable<AtlasMessage::sEnvironmentSettings>& environment);
LightControl(wxWindow* parent, const wxSize& size, Observable<AtlasMessage::sEnvironmentSettings>& environment);
~LightControl();
void OnSettingsChange(const AtlasMessage::sEnvironmentSettings& settings);

View File

@ -99,13 +99,7 @@ public:
if (wxGetKeyState(WXK_PRIOR)) --dir; // page-up key
if (dir)
{
float speed = M_PI/2.f; // radians per second
if (wxGetKeyState(WXK_SHIFT) && wxGetKeyState(WXK_CONTROL))
speed /= 64.f;
else if (wxGetKeyState(WXK_CONTROL))
speed /= 4.f;
else if (wxGetKeyState(WXK_SHIFT))
speed *= 4.f;
float speed = M_PI/2.f * ScenarioEditor::GetSpeedModifier(); // radians per second
g_DefaultAngle += (dir * dt * speed);
SendObjectMsg(true);
}

View File

@ -0,0 +1,190 @@
#include "precompiled.h"
#include "ActorViewer.h"
#include "View.h"
#include "graphics/Model.h"
#include "graphics/ObjectManager.h"
#include "graphics/Patch.h"
#include "graphics/Terrain.h"
#include "graphics/TextureEntry.h"
#include "graphics/TextureManager.h"
#include "graphics/Unit.h"
#include "graphics/UnitManager.h"
#include "maths/MathUtil.h"
#include "ps/GameSetup/Config.h"
#include "renderer/Renderer.h"
#include "renderer/SkyManager.h"
struct ActorViewerImpl
{
CUnit* Unit;
CStrW CurrentUnitID;
CStrW CurrentUnitAnim;
float CurrentSpeed;
CTerrain Terrain;
};
ActorViewer::ActorViewer()
: m(*new ActorViewerImpl())
{
m.Unit = NULL;
// Set up the renderer
g_TexMan.LoadTerrainTextures();
g_ObjMan.LoadObjects();
g_Renderer.LoadAlphaMaps();
// (TODO: should these be unloaded properly some time? and what should
// happen if we want the actor viewer and scenario editor loaded at
// the same time?)
// Create a tiny empty piece of terrain, just so we can put shadows
// on it without having to think too hard
m.Terrain.Initialize(1, NULL);
CTextureEntry* tex = g_TexMan.FindTexture("whiteness");
if (tex)
{
CPatch* patch = m.Terrain.GetPatch(0, 0);
for (int i = 0; i < PATCH_SIZE; ++i)
{
for (int j = 0; j < PATCH_SIZE; ++j)
{
CMiniPatch& mp = patch->m_MiniPatches[i][j];
mp.Tex1 = tex->GetHandle();
mp.Tex1Priority = 0;
}
}
}
}
ActorViewer::~ActorViewer()
{
delete m.Unit;
delete &m;
}
void ActorViewer::SetActor(const CStrW& id, const CStrW& animation)
{
bool needsAnimReload = false;
if (! m.Unit || id != m.CurrentUnitID)
{
delete m.Unit;
m.Unit = NULL;
// If there's no actor to display, return with nothing loaded
if (id.empty())
return;
m.Unit = CUnit::Create((CStr)id, NULL, std::set<CStr>());
if (! m.Unit)
return;
float angle = PI;
float s = sin(angle);
float c = cos(angle);
CMatrix3D mat;
mat._11 = -c; mat._12 = 0.0f; mat._13 = -s; mat._14 = CELL_SIZE * PATCH_SIZE/2;
mat._21 = 0.0f; mat._22 = 1.0f; mat._23 = 0.0f; mat._24 = 0.0f;
mat._31 = s; mat._32 = 0.0f; mat._33 = -c; mat._34 = CELL_SIZE * PATCH_SIZE/2;
mat._41 = 0.0f; mat._42 = 0.0f; mat._43 = 0.0f; mat._44 = 1.0f;
m.Unit->GetModel()->SetTransform(mat);
m.Unit->GetModel()->ValidatePosition();
needsAnimReload = true;
}
if (animation != m.CurrentUnitAnim)
needsAnimReload = true;
if (needsAnimReload)
{
CStr anim = ((CStr)animation).LowerCase();
float speed;
// TODO: this is just copied from template_unit.xml and isn't the
// same for all units. But we don't know anything about entities here,
// so what to do?
if (anim == "walk")
speed = 7.f;
else if (anim == "run")
speed = 12.f;
else
speed = 0.f;
m.CurrentSpeed = speed;
m.Unit->SetEntitySelection(anim);
m.Unit->SetRandomAnimation(anim, false, speed);
}
m.CurrentUnitID = id;
m.CurrentUnitAnim = animation;
}
// TODO: don't have this duplicated from GameView
void SubmitModelRecursive(CModel* model)
{
g_Renderer.Submit(model);
const std::vector<CModel::Prop>& props = model->GetProps();
for (size_t i = 0; i < props.size(); ++i)
SubmitModelRecursive(props[i].m_Model);
}
void ActorViewer::Render()
{
m.Terrain.MakeDirty(RENDERDATA_UPDATE_COLOR);
g_Renderer.SetClearColor(0xFFFFFFFFu);
g_Renderer.BeginFrame();
// Find the centre of the interesting region, in the middle of the patch
// and half way up the model (assuming there is one)
CVector3D centre;
if (m.Unit)
m.Unit->GetModel()->GetBounds().GetCentre(centre);
else
centre.Y = 0.f;
centre.X = centre.Z = CELL_SIZE * PATCH_SIZE/2;
CCamera camera = View::GetView_Actor()->GetCamera();
camera.m_Orientation.Translate(centre.X, centre.Y, centre.Z);
camera.UpdateFrustum();
g_Renderer.SetCamera(camera, camera);
g_Renderer.Submit(m.Terrain.GetPatch(0, 0));
if (m.Unit)
SubmitModelRecursive(m.Unit->GetModel());
g_Renderer.FlushFrame();
g_Renderer.EndFrame();
oglCheck();
}
void ActorViewer::Update(float dt)
{
if (m.Unit)
{
m.Unit->GetModel()->Update(dt);
// Move the model by speed*dt forwards
CMatrix3D mat = m.Unit->GetModel()->GetTransform();
float z = mat.GetTranslation().Z;
z -= m.CurrentSpeed*dt;
// Wrap at the edges, so it doesn't run off into the horizon
if (z < CELL_SIZE*PATCH_SIZE * 0.4f)
z = CELL_SIZE*PATCH_SIZE * 0.6f;
mat.Translate(0.f, 0.f, z - mat.GetTranslation().Z);
m.Unit->GetModel()->SetTransform(mat);
m.Unit->GetModel()->ValidatePosition();
}
}

View File

@ -0,0 +1,22 @@
#ifndef ACTORVIEWER_H__
#define ACTORVIEWER_H__
struct ActorViewerImpl;
class ActorViewer
{
public:
ActorViewer();
~ActorViewer();
void SetActor(const CStrW& id, const CStrW& animation);
void Render();
void Update(float dt);
private:
ActorViewerImpl& m;
NO_COPY_CTOR(ActorViewer);
};
#endif // ACTORVIEWER_H__

View File

@ -1,3 +1,6 @@
#ifndef BRUSHES_H__
#define BRUSHES_H__
#include "maths/Vector3D.h"
class TerrainOverlay;
@ -33,3 +36,5 @@ private:
extern Brush g_CurrentBrush;
}
#endif // BRUSHES_H__

View File

@ -1,3 +1,6 @@
#ifndef COMMANDPROC_H__
#define COMMANDPROC_H__
#include <string>
#include <list>
#include <map>
@ -162,3 +165,5 @@ The following macros convert that into:
}
#endif // COMMANDPROC_H__

View File

@ -5,44 +5,33 @@
#include "MessagePasserImpl.h"
#include "Messages.h"
#include "SharedMemory.h"
#include "Brushes.h"
#include "Handlers/MessageHandler.h"
#include "ActorViewer.h"
#include "View.h"
#include "InputProcessor.h"
#include "lib/app_hooks.h"
#include "lib/sdl.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "lib/res/file/vfs.h"
#include "ps/CLogger.h"
#include "ps/GameSetup/GameSetup.h"
#include "ps/Game.h"
#include "ps/World.h"
#include "simulation/Simulation.h"
#include "simulation/EntityManager.h"
using namespace AtlasMessage;
namespace AtlasMessage
{
extern void AtlasRenderSelection();
extern void RegisterHandlers();
}
void AtlasRender()
{
Render();
AtlasRenderSelection();
}
// Loaded from DLL:
void (*Atlas_StartWindow)(wchar_t* type);
void (*Atlas_StartWindow)(const wchar_t* type);
void (*Atlas_SetMessagePasser)(MessagePasser*);
void (*Atlas_GLSetCurrent)(void* context);
void (*Atlas_GLSwapBuffers)(void* context);
void (*Atlas_NotifyEndOfFrame)();
void (*Atlas_DisplayError)(const wchar_t* text, unsigned int flags);
namespace AtlasMessage
{
void* (*ShareableMallocFptr)(size_t);
@ -60,13 +49,33 @@ static GameLoopState state;
GameLoopState* g_GameLoop = &state;
static void* LaunchWindow(void*)
static void* LaunchWindow(void* data)
{
const wchar_t* windowName = reinterpret_cast<const wchar_t*>(data);
debug_set_thread_name("atlas_window");
Atlas_StartWindow(L"ScenarioEditor");
Atlas_StartWindow(windowName);
return NULL;
}
// Work out which Atlas window to launch, given the command-line arguments
static const wchar_t* FindWindowName(int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "-actorviewer") == 0)
return L"ActorViewer";
}
return L"ScenarioEditor";
}
static ErrorReaction AtlasDisplayError(const wchar_t* text, uint flags)
{
// TODO: after Atlas has been unloaded, don't do this
Atlas_DisplayError(text, flags);
return ER_CONTINUE;
}
bool BeginAtlas(int argc, char* argv[], void* dll)
{
@ -77,6 +86,7 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
GET(Atlas_GLSetCurrent);
GET(Atlas_GLSwapBuffers);
GET(Atlas_NotifyEndOfFrame);
GET(Atlas_DisplayError);
#undef GET
#define GET(x) *(void**)&x##Fptr = dlsym(dll, #x); debug_assert(x##Fptr); if (! x##Fptr) return false;
GET(ShareableMalloc);
@ -90,14 +100,19 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
RegisterHandlers();
// Create a new thread, and launch the Atlas window inside that thread
pthread_t gameThread;
pthread_create(&gameThread, NULL, LaunchWindow, NULL);
const wchar_t* windowName = FindWindowName(argc, argv);
pthread_t uiThread;
pthread_create(&uiThread, NULL, LaunchWindow, reinterpret_cast<void*>(const_cast<wchar_t*>(windowName)));
// Override ah_display_error to pass all errors to the Atlas UI
AppHooks hooks = {0};
hooks.display_error = AtlasDisplayError;
app_hooks_update(&hooks);
state.argc = argc;
state.argv = argv;
state.running = true;
state.rendering = false;
state.worldloaded = false;
state.view = View::GetView_None();
state.glContext = NULL;
double last_activity = get_time();
@ -108,13 +123,13 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
//////////////////////////////////////////////////////////////////////////
// (TODO: Work out why these things have to be in this order (to avoid
// jumps when starting to move, etc)
// jumps when starting to move, etc))
// Calculate frame length
{
const double time = get_time();
double time = get_time();
static double last_time = time;
const float length = (float)(time-last_time);
float length = (float)(time-last_time);
last_time = time;
debug_assert(length >= 0.0f);
// TODO: filter out big jumps, e.g. when having done a lot of slow
@ -181,17 +196,9 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
vfs_reload_changed_files();
if (state.worldloaded)
{
g_EntityManager.updateAll(0);
g_Game->GetSimulation()->Update(0.0);
}
state.view->Update(state.frameLength);
if (state.rendering)
{
AtlasRender();
Atlas_GLSwapBuffers((void*)state.glContext);
}
state.view->Render();
double time = get_time();
if (recent_activity)
@ -199,13 +206,14 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
// Be nice to the processor (by sleeping lots) if we're not doing anything
// useful, and nice to the user (by just yielding to other threads) if we are
bool yield = time - last_activity > 0.5;
if ( state.worldloaded )
{
if ( g_Game->GetView()->GetCinema()->IsPlaying() )
g_Game->GetView()->GetCinema()->Update(state.frameLength);
bool yield = (time - last_activity > 0.5);
// But make sure we aren't doing anything interesting right now, where
// the user wants to see the screen updating even though they're not
// interacting with it
if (state.view->WantsHighFramerate())
yield = false;
}
if (yield) // if there was no recent activity...
{
double sleepUntil = time + 0.5; // only redraw at 2fps
@ -231,7 +239,11 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
// TODO: delete all remaining messages, to avoid memory leak warnings
pthread_join(gameThread, NULL);
// Wait for the UI to exit
pthread_join(uiThread, NULL);
// Clean up
View::DestroyViews();
exit(0);
}

View File

@ -3,13 +3,16 @@
extern void (*Atlas_GLSetCurrent)(void* context);
class View;
struct GameLoopState
{
int argc;
char** argv;
bool running;
bool rendering;
bool worldloaded;
bool running; // whether the Atlas game loop is still running
View* view; // current 'view' (controls updates, rendering, etc)
const void* glContext;
float frameLength; // smoothed to avoid large jumps

View File

@ -14,7 +14,7 @@ MESSAGEHANDLER(Brush)
MESSAGEHANDLER(BrushPreview)
{
g_CurrentBrush.SetRenderEnabled(msg->enable);
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
g_CurrentBrush.m_Centre = msg->pos->GetWorldSpace();
}
}

View File

@ -2,6 +2,7 @@
#include "MessageHandler.h"
#include "../GameLoop.h"
#include "../View.h"
#include "maths/Vector3D.h"
#include "maths/Quaternion.h"
@ -18,6 +19,7 @@ MESSAGEHANDLER(ScrollConstant)
{
if (g_Game->GetView()->GetCinema()->IsPlaying())
return;
if (msg->dir < 0 || msg->dir > 3)
{
debug_warn("ScrollConstant: invalid direction");
@ -28,10 +30,14 @@ MESSAGEHANDLER(ScrollConstant)
}
}
// TODO: change all these g_Game->...GetCamera() bits to use the current View's
// camera instead.
MESSAGEHANDLER(Scroll)
{
if ( g_Game->GetView()->GetCinema()->IsPlaying() )
if (g_Game->GetView()->GetCinema()->IsPlaying()) // TODO: do this better (probably a separate View class for cinematics)
return;
static CVector3D targetPos;
static float targetDistance = 0.f;
@ -57,7 +63,7 @@ MESSAGEHANDLER(Scroll)
if (msg->type == eScrollType::FROM)
{
msg->pos->GetWorldSpace(targetPos);
targetPos = msg->pos->GetWorldSpace();
targetDistance = (targetPos - camera.GetTranslation()).GetLength();
}
else if (msg->type == eScrollType::TO)
@ -81,6 +87,7 @@ MESSAGEHANDLER(SmoothZoom)
{
if (g_Game->GetView()->GetCinema()->IsPlaying())
return;
g_GameLoop->input.zoomDelta += msg->amount;
}
@ -88,6 +95,7 @@ MESSAGEHANDLER(RotateAround)
{
if (g_Game->GetView()->GetCinema()->IsPlaying())
return;
static CVector3D focusPos;
static float lastX = 0.f, lastY = 0.f;
@ -96,7 +104,7 @@ MESSAGEHANDLER(RotateAround)
if (msg->type == eRotateAroundType::FROM)
{
msg->pos->GetScreenSpace(lastX, lastY); // get mouse position
msg->pos->GetWorldSpace(focusPos); // get point on terrain under mouse
focusPos = msg->pos->GetWorldSpace(); // get point on terrain under mouse
}
else if (msg->type == eRotateAroundType::TO)
{
@ -136,5 +144,33 @@ MESSAGEHANDLER(RotateAround)
}
}
MESSAGEHANDLER(LookAt)
{
// TODO: different view depending on
CCamera& camera = View::GetView_Actor()->GetCamera();
CVector3D tgt = msg->target->GetWorldSpace();
CVector3D eye = msg->pos->GetWorldSpace();
tgt.Y = -tgt.Y; // ??? why is this needed?
eye.Y = -eye.Y; // ???
// Based on http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/glu/lookat.html
CVector3D f = tgt - eye;
f.Normalize();
CVector3D s = f.Cross(CVector3D(0, 1, 0));
CVector3D u = s.Cross(f);
CMatrix3D M (
s[0], s[1], s[2], 0,
u[0], u[1], u[2], 0,
-f[0], -f[1], -f[2], 0,
0, 0, 0, 1
);
M.GetTranspose(camera.m_Orientation);
camera.m_Orientation.Translate(-eye);
camera.UpdateFrustum();
}
}

View File

@ -102,7 +102,7 @@ BEGIN_COMMAND(AlterElevation)
}
static CVector3D previousPosition;
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
g_CurrentBrush.m_Centre = msg->pos->GetWorldSpace(previousPosition);
previousPosition = g_CurrentBrush.m_Centre;
int x0, y0;
@ -158,7 +158,7 @@ BEGIN_COMMAND(FlattenElevation)
int amount = (int)msg->amount;
static CVector3D previousPosition;
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre, previousPosition);
g_CurrentBrush.m_Centre = msg->pos->GetWorldSpace(previousPosition);
previousPosition = g_CurrentBrush.m_Centre;
int xc, yc;

View File

@ -50,7 +50,10 @@ void SetSettings(const sEnvironmentSettings& s)
g_LightEnv.SetRotation(s.sunrotation);
g_LightEnv.SetElevation(s.sunelevation);
g_Renderer.GetSkyManager()->SetSkySet(*s.skyset);
CStrW skySet = *s.skyset;
if (skySet.length() == 0)
skySet = L"default";
g_Renderer.GetSkyManager()->SetSkySet(skySet);
#define COLOUR(A, B) B = RGBColor(A->r/255.f, A->g/255.f, A->b/255.f)
COLOUR(s.suncolour, g_LightEnv.m_SunColor);

View File

@ -3,6 +3,8 @@
#include "MessageHandler.h"
#include "../GameLoop.h"
#include "../CommandProc.h"
#include "../ActorViewer.h"
#include "../View.h"
#include "renderer/Renderer.h"
#include "graphics/GameView.h"
@ -15,10 +17,8 @@
#include "ps/GameSetup/Config.h"
#include "ps/GameSetup/GameSetup.h"
namespace AtlasMessage {
MESSAGEHANDLER(Init)
{
UNUSED2(msg);
@ -45,9 +45,10 @@ MESSAGEHANDLER(Shutdown)
// we kill the EntityManager
GetCommandProc().Destroy();
Shutdown();
View::DestroyViews();
g_GameLoop->view = View::GetView_None();
g_GameLoop->rendering = false;
Shutdown();
}
@ -60,7 +61,16 @@ QUERYHANDLER(Exit)
MESSAGEHANDLER(RenderEnable)
{
g_GameLoop->rendering = msg->enabled;
if (msg->view == eRenderView::NONE) g_GameLoop->view = View::GetView_None();
else if (msg->view == eRenderView::GAME) g_GameLoop->view = View::GetView_Game();
else if (msg->view == eRenderView::ACTOR) g_GameLoop->view = View::GetView_Actor();
else debug_warn("Invalid view type");
}
MESSAGEHANDLER(SetActorViewer)
{
View::GetView_Actor()->SetSpeedMultiplier(msg->speed);
View::GetView_Actor()->GetActorViewer().SetActor(*msg->id, *msg->animation);
}
//////////////////////////////////////////////////////////////////////////
@ -81,18 +91,9 @@ MESSAGEHANDLER(ResizeScreen)
SViewPort vp = { 0, 0, g_xres, g_yres };
if (g_Game)
{
g_Game->GetView()->GetCamera()->SetViewPort(&vp);
g_Game->GetView()->GetCamera()->SetProjection (1, 5000, DEGTORAD(20));
}
g_Renderer.SetViewport(vp);
g_Renderer.Resize(g_xres, g_yres);
if (g_Game)
g_Game->GetView()->GetCamera()->UpdateFrustum();
g_GUI.UpdateResolution();
g_Console->UpdateScreenSize(g_xres, g_yres);

View File

@ -35,8 +35,6 @@ static void InitGame(std::wstring map)
// Initialise the game:
g_Game = new CGame();
g_GameLoop->worldloaded = true;
}
static void StartGame()

View File

@ -7,6 +7,7 @@
#include "graphics/GameView.h"
#include "graphics/Model.h"
#include "graphics/ObjectEntry.h"
#include "graphics/ObjectManager.h"
#include "graphics/Terrain.h"
#include "graphics/Unit.h"
@ -18,8 +19,10 @@
#include "ps/Game.h"
#include "ps/World.h"
#include "simulation/EntityTemplateCollection.h"
#include "simulation/EntityTemplate.h"
#include "simulation/Entity.h"
#include "simulation/EntityManager.h"
#include "simulation/TerritoryManager.h"
#define LOG_CATEGORY "editor"
@ -214,7 +217,7 @@ static float flt_minus_epsilon(float f)
static CVector3D GetUnitPos(const Position& pos)
{
static CVector3D vec;
pos.GetWorldSpace(vec, vec); // if msg->pos is 'Unchanged', use the previous pos
vec = pos.GetWorldSpace(vec); // if msg->pos is 'Unchanged', use the previous pos
float xOnMap = clamp(vec.X, 0.f, flt_minus_epsilon((g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide()-1)*CELL_SIZE));
float zOnMap = clamp(vec.Z, 0.f, flt_minus_epsilon((g_Game->GetWorld()->GetTerrain()->GetVerticesPerSide()-1)*CELL_SIZE));
@ -296,8 +299,7 @@ MESSAGEHANDLER(ObjectPreview)
if (msg->usetarget)
{
// Aim from pos towards msg->target
CVector3D target;
msg->target->GetWorldSpace(target, pos.Y);
CVector3D target = msg->target->GetWorldSpace(pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
dir = dir.normalize();
s = dir.x;
@ -337,8 +339,7 @@ BEGIN_COMMAND(CreateObject)
if (msg->usetarget)
{
// Aim from m_Pos towards msg->target
CVector3D target;
msg->target->GetWorldSpace(target, m_Pos.Y);
CVector3D target = msg->target->GetWorldSpace(m_Pos.Y);
CVector2D dir(target.X-m_Pos.X, target.Z-m_Pos.Z);
m_Angle = atan2(dir.x, dir.y);
}
@ -388,6 +389,9 @@ BEGIN_COMMAND(CreateObject)
{
ent->SetPlayer(g_Game->GetPlayer(m_Player));
ent->m_actor->SetID(m_ID);
if (ent->m_base->m_isTerritoryCentre)
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
}
}
}
@ -424,7 +428,14 @@ BEGIN_COMMAND(CreateObject)
if (unit)
{
if (unit->GetEntity())
{
bool wasTerritoryCentre = unit->GetEntity()->m_base->m_isTerritoryCentre;
unit->GetEntity()->kill();
if (wasTerritoryCentre)
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
}
else
{
g_UnitMan.RemoveUnit(unit);
@ -504,6 +515,9 @@ BEGIN_COMMAND(MoveObject)
if (unit->GetEntity())
{
unit->GetEntity()->m_position = pos;
if (unit->GetEntity()->m_base->m_isTerritoryCentre)
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
}
else
{
@ -549,8 +563,7 @@ BEGIN_COMMAND(RotateObject)
if (msg->usetarget)
{
CVector3D& pos = unit->GetEntity()->m_position;
CVector3D target;
msg->target->GetWorldSpace(target, pos.Y);
CVector3D target = msg->target->GetWorldSpace(pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
m_AngleNew = atan2(dir.x, dir.y);
}
@ -568,8 +581,7 @@ BEGIN_COMMAND(RotateObject)
float s, c;
if (msg->usetarget)
{
CVector3D target;
msg->target->GetWorldSpace(target, pos.Y);
CVector3D target = msg->target->GetWorldSpace(pos.Y);
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
dir = dir.normalize();
s = dir.x;
@ -660,6 +672,10 @@ BEGIN_COMMAND(DeleteObject)
{
// HACK: I don't know the proper way of undoably deleting entities...
unit->GetEntity()->entf_set(ENTF_DESTROYED);
// TODO: territories don't ignore DESTROYED entities
if (unit->GetEntity()->m_base->m_isTerritoryCentre)
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
}
g_UnitMan.RemoveUnit(unit);
@ -669,8 +685,13 @@ BEGIN_COMMAND(DeleteObject)
void Undo()
{
if (m_UnitInLimbo->GetEntity())
{
m_UnitInLimbo->GetEntity()->entf_clear(ENTF_DESTROYED);
if (m_UnitInLimbo->GetEntity()->m_base->m_isTerritoryCentre)
g_Game->GetWorld()->GetTerritoryManager()->DelayedRecalculate();
}
g_UnitMan.AddUnit(m_UnitInLimbo);
m_UnitInLimbo = NULL;
}

View File

@ -163,7 +163,7 @@ BEGIN_COMMAND(PaintTerrain)
void Do()
{
msg->pos->GetWorldSpace(g_CurrentBrush.m_Centre);
g_CurrentBrush.m_Centre = msg->pos->GetWorldSpace();
int x0, y0;
g_CurrentBrush.GetBottomLeft(x0, y0);

View File

@ -1,3 +1,6 @@
#ifndef INPUTPROCESSOR_H__
#define INPUTPROCESSOR_H__
#include "GameLoop.h"
class InputProcessor
@ -6,3 +9,5 @@ public:
// Returns true if the camera has moved
bool ProcessInput(GameLoopState* state);
};
#endif // INPUTPROCESSOR_H__

View File

@ -43,12 +43,13 @@ IMessage* MessagePasserImpl::Retrieve()
m_Mutex.Unlock();
// if (m_Trace && msg) debug_printf("%8.3f retrieved message: %s\n", get_time(), msg->GetType());
if (m_Trace && msg)
debug_printf("%8.3f retrieved message: %s\n", get_time(), msg->GetName());
return msg;
}
void MessagePasserImpl::Query(QueryMessage* qry, void(*timeoutCallback)())
void MessagePasserImpl::Query(QueryMessage* qry, void(* UNUSED(timeoutCallback) )())
{
debug_assert(qry);
debug_assert(qry->GetType() == IMessage::Query);
@ -74,32 +75,49 @@ void MessagePasserImpl::Query(QueryMessage* qry, void(*timeoutCallback)())
// Wait until the query handler has handled the query and called sem_post:
// At least on Win32, it is necessary for the UI thread to run its event
// loop to avoid deadlocking the system (particularly when the game
// tries to show a dialog box); so timeoutCallback is called whenever we
// think it's necessary for that to happen.
#if OS_WIN
// On Win32, use MsgWaitForMultipleObjects, which waits on the semaphore
// but is also interrupted by incoming Windows-messages.
while (0 != (err = sem_msgwait_np(&sem)))
#else
// TODO: On non-Win32, I have no idea whether the same problem exists; but
// it might do, so call the callback every few seconds just in case it helps.
struct timespec abs_timeout;
clock_gettime(CLOCK_REALTIME, &abs_timeout);
abs_timeout.tv_sec += 2;
while (0 != (err = sem_timedwait(&sem, &abs_timeout)))
#endif
// The following code was necessary to avoid deadlock, but it still breaks
// in some cases (e.g. when Atlas issues a query before its event loop starts
// running) and doesn't seem to be the simplest possible solution.
// So currently we're trying to not do anything like that at all, and
// just stop the game making windows (which is what seems (from experience) to
// deadlock things) by overriding ah_display_error. Hopefully it'll work like
// that, and the redundant code below/elsewhere can be removed, but it's
// left in here in case it needs to be reinserted in the future to make it
// work.
// (See http://www.wildfiregames.com/forum/index.php?s=&showtopic=10236&view=findpost&p=174617)
// // At least on Win32, it is necessary for the UI thread to run its event
// // loop to avoid deadlocking the system (particularly when the game
// // tries to show a dialog box); so timeoutCallback is called whenever we
// // think it's necessary for that to happen.
//
// #if OS_WIN
// // On Win32, use MsgWaitForMultipleObjects, which waits on the semaphore
// // but is also interrupted by incoming Windows-messages.
// // while (0 != (err = sem_msgwait_np(&sem)))
//
// while (0 != (err = sem_wait(&sem)))
// #else
// // TODO: On non-Win32, I have no idea whether the same problem exists; but
// // it might do, so call the callback every few seconds just in case it helps.
// struct timespec abs_timeout;
// clock_gettime(CLOCK_REALTIME, &abs_timeout);
// abs_timeout.tv_sec += 2;
// while (0 != (err = sem_timedwait(&sem, &abs_timeout)))
// #endif
while (0 != (err = sem_wait(&sem)))
{
// If timed out, call callback and try again
if (errno == ETIMEDOUT)
timeoutCallback();
// if (errno == ETIMEDOUT)
// timeoutCallback();
// else
// Keep retrying while EINTR, but other errors are probably fatal
else if (errno != EINTR)
if (errno != EINTR)
{
debug_warn("Semaphore wait failed");
return; // (leak the semaphore)
return; // (leaks the semaphore)
}
}

View File

@ -13,8 +13,11 @@ MESSAGE(Init, );
MESSAGE(Shutdown, );
struct eRenderView { enum { NONE, GAME, ACTOR }; };
MESSAGE(RenderEnable,
((bool, enabled)));
((int, view)) // eRenderView
);
//////////////////////////////////////////////////////////////////////////
@ -108,7 +111,7 @@ SHAREABLE_STRUCT(sObjectsListItem);
QUERY(GetObjectsList,
, // no inputs
((std::vector<sObjectsListItem>, objects))
((std::vector<sObjectsListItem>, objects)) // sorted by .name
);
struct sObjectSettings
@ -123,6 +126,8 @@ struct sObjectSettings
};
SHAREABLE_STRUCT(sObjectSettings);
// Preview object in the game world - creates a temporary unit at the given
// position, and removes it when the preview is next changed
MESSAGE(ObjectPreview,
((std::wstring, id)) // or empty string => disable
((sObjectSettings, settings))
@ -141,6 +146,13 @@ COMMAND(CreateObject, NOMERGE,
((float, angle))
);
// Set an actor to be previewed on its own (i.e. without the game world).
// (Use RenderEnable to make it visible.)
MESSAGE(SetActorViewer,
((std::wstring, id))
((std::wstring, animation))
((float, speed))
);
//////////////////////////////////////////////////////////////////////////
@ -149,29 +161,38 @@ QUERY(Exit,,); // no inputs nor outputs
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
struct eScrollConstantDir { enum { FORWARDS, BACKWARDS, LEFT, RIGHT }; };
MESSAGE(ScrollConstant,
((int, dir))
((int, view)) // eRenderView
((int, dir)) // eScrollConstantDir
((float, speed)) // set speed 0.0f to stop scrolling
);
struct eScrollType { enum { FROM, TO }; };
MESSAGE(Scroll, // for scrolling by dragging the mouse FROM somewhere TO elsewhere
((int, type))
((int, view)) // eRenderView
((int, type)) // eScrollType
((Position, pos))
);
MESSAGE(SmoothZoom,
((int, view)) // eRenderView
((float, amount))
);
struct eRotateAroundType { enum { FROM, TO }; };
MESSAGE(RotateAround,
((int, type))
((int, view)) // eRenderView
((int, type)) // eRotateAroundType
((Position, pos))
);
MESSAGE(LookAt,
((int, view)) // eRenderView
((Position, pos))
((Position, target))
);
//////////////////////////////////////////////////////////////////////////
struct sEnvironmentSettings
@ -225,16 +246,11 @@ struct ePaintTerrainPriority { enum { HIGH, LOW }; };
COMMAND(PaintTerrain, MERGE,
((Position, pos))
((std::wstring, texture))
((int, priority))
((int, priority)) // ePaintTerrainPriority
);
//////////////////////////////////////////////////////////////////////////
typedef int ObjectID;
FUNCTION(
inline bool ObjectIDIsValid(ObjectID id) { return (id >= 0); }
);
QUERY(PickObject,
((Position, pos))
,
@ -276,64 +292,8 @@ COMMAND(SetObjectSettings, NOMERGE,
//////////////////////////////////////////////////////////////////////////
struct sCinemaSplineNode
{
Shareable<float> x, y, z, t;
public:
sCinemaSplineNode(float px, float py, float pz) : x(px), y(py), z(pz), t(0.0f){}
sCinemaSplineNode() {}
void SetTime(float _t) { t = _t; }
};
SHAREABLE_STRUCT(sCinemaSplineNode);
struct sCinemaPath
{
Shareable<std::vector<AtlasMessage::sCinemaSplineNode> > nodes;
Shareable<float> duration, x, y, z;
Shareable<int> mode, growth, change, style; //change == switch point
sCinemaPath(float rx, float ry, float rz) : x(rx), y(ry), z(rz),
mode(0), style(0), change(0), growth(0), duration(0) {}
sCinemaPath() : x(0), y(0), z(0), mode(0), style(0),
change(0), growth(0), duration(0) {}
AtlasMessage::sCinemaPath operator-(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x - path.x, y - path.y,
z - path.z);
}
AtlasMessage::sCinemaPath operator+(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x + path.x, y + path.y,
z + path.z);
}
};
SHAREABLE_STRUCT(sCinemaPath);
struct sCinemaTrack
{
Shareable<std::wstring> name;
Shareable<float> x, y, z, timescale, duration;
Shareable<std::vector<AtlasMessage::sCinemaPath> > paths;
public:
sCinemaTrack(float rx, float ry, float rz, std::wstring track)
: x(rx), y(ry), z(rz), timescale(1.f), duration(0)
{ name = track; }
sCinemaTrack() : x(0), y(0), z(0), timescale(1.f), duration(0) {}
};
SHAREABLE_STRUCT(sCinemaTrack);
struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH,
IMMEDIATE_TRACK }; };
struct sCameraInfo
{
Shareable<float> pX, pY, pZ, rX, rY, rZ; //position and rotation
};
SHAREABLE_STRUCT(sCameraInfo);
QUERY(GetCinemaTracks,
, //no input
, // no inputs
((std::vector<AtlasMessage::sCinemaTrack> , tracks))
);

View File

@ -165,8 +165,6 @@ const bool NOMERGE = false;
QUERY_WITH_INPUTS) \
(name, in_vals, out_vals)
#define FUNCTION(def) def
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@ -187,7 +185,6 @@ const bool NOMERGE = false;
#undef QUERY_WITHOUT_INPUTS
#undef QUERY_WITH_INPUTS
#undef QUERY
#undef FUNCTION
}

View File

@ -8,52 +8,50 @@
#include "ps/Game.h"
#include "graphics/GameView.h"
void AtlasMessage::Position::GetWorldSpace(CVector3D& vec) const
CVector3D AtlasMessage::Position::GetWorldSpace() const
{
switch (type)
{
case 0:
vec.Set(type0.x, type0.y, type0.z);
return CVector3D(type0.x, type0.y, type0.z);
break;
case 1:
vec = g_Game->GetView()->GetCamera()->GetWorldCoordinates(type1.x, type1.y);
return g_Game->GetView()->GetCamera()->GetWorldCoordinates(type1.x, type1.y);
break;
case 2:
debug_warn("Invalid Position acquisition (unchanged without previous)");
vec.Set(0.f, 0.f, 0.f);
return CVector3D(0.f, 0.f, 0.f);
break;
default:
debug_warn("Invalid Position type");
vec.Set(0.f, 0.f, 0.f);
return CVector3D(0.f, 0.f, 0.f);
}
}
void AtlasMessage::Position::GetWorldSpace(CVector3D& vec, float h) const
CVector3D AtlasMessage::Position::GetWorldSpace(float h) const
{
switch (type)
{
case 1:
vec = g_Game->GetView()->GetCamera()->GetWorldCoordinates(type1.x, type1.y, h);
break;
return g_Game->GetView()->GetCamera()->GetWorldCoordinates(type1.x, type1.y, h);
default:
GetWorldSpace(vec);
return GetWorldSpace();
}
}
void AtlasMessage::Position::GetWorldSpace(CVector3D& vec, const CVector3D& prev) const
CVector3D AtlasMessage::Position::GetWorldSpace(const CVector3D& prev) const
{
switch (type)
{
case 2:
vec = prev;
break;
return prev;
default:
GetWorldSpace(vec);
return GetWorldSpace();
}
}

View File

@ -35,8 +35,6 @@ extern cmdHandlers& GetCmdHandlers();
extern cmdHandler c##name##_create(); \
GetCmdHandlers().insert(std::pair<std::string, cmdHandler>("c"#name, c##name##_create()));
#define FUNCTION(def)
#undef SHAREABLE_STRUCT
#define SHAREABLE_STRUCT(name)

View File

@ -161,7 +161,7 @@ public:
const wrapped_type _Unwrap() const
{
return buf ? wrapped_type(buf, buf+length-1) : wrapped_type();
return (buf && length) ? wrapped_type(buf, buf+length-1) : wrapped_type();
}
const wrapped_type operator*() const
@ -173,7 +173,7 @@ public:
// without constructing a new std::basic_string then calling c_str on that
const C* c_str() const
{
return buf ? buf : (C*)empty_str;
return (buf && length) ? buf : (C*)empty_str;
}
};

View File

@ -39,13 +39,14 @@ struct Position
// Only for use in the game, not the UI.
// Implementations in Misc.cpp.
void GetWorldSpace(CVector3D& vec) const;
void GetWorldSpace(CVector3D& vec, float h) const;
void GetWorldSpace(CVector3D& vec, const CVector3D& prev) const;
CVector3D GetWorldSpace() const;
CVector3D GetWorldSpace(float h) const;
CVector3D GetWorldSpace(const CVector3D& prev) const;
void GetScreenSpace(float& x, float& y) const;
};
SHAREABLE_STRUCT(Position);
struct Colour
{
Colour()
@ -62,6 +63,64 @@ struct Colour
};
SHAREABLE_STRUCT(Colour);
typedef int ObjectID;
inline bool ObjectIDIsValid(ObjectID id) { return (id >= 0); }
struct sCinemaSplineNode
{
Shareable<float> x, y, z, t;
public:
sCinemaSplineNode(float px, float py, float pz) : x(px), y(py), z(pz), t(0.0f) {}
sCinemaSplineNode() {}
void SetTime(float _t) { t = _t; }
};
SHAREABLE_STRUCT(sCinemaSplineNode);
struct sCinemaPath
{
Shareable<std::vector<AtlasMessage::sCinemaSplineNode> > nodes;
Shareable<float> duration, x, y, z;
Shareable<int> mode, growth, change, style; // change == switch point
sCinemaPath(float rx, float ry, float rz) : x(rx), y(ry), z(rz),
mode(0), style(0), change(0), growth(0), duration(0) {}
sCinemaPath() : x(0), y(0), z(0), mode(0), style(0),
change(0), growth(0), duration(0) {}
AtlasMessage::sCinemaPath operator-(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x - path.x, y - path.y, z - path.z);
}
AtlasMessage::sCinemaPath operator+(const AtlasMessage::sCinemaPath& path)
{
return AtlasMessage::sCinemaPath(x + path.x, y + path.y, z + path.z);
}
};
SHAREABLE_STRUCT(sCinemaPath);
struct sCinemaTrack
{
Shareable<std::wstring> name;
Shareable<float> x, y, z, timescale, duration;
Shareable<std::vector<AtlasMessage::sCinemaPath> > paths;
public:
sCinemaTrack(float rx, float ry, float rz, std::wstring track)
: x(rx), y(ry), z(rz), timescale(1.f), duration(0), name(track) {}
sCinemaTrack() : x(0), y(0), z(0), timescale(1.f), duration(0) {}
};
SHAREABLE_STRUCT(sCinemaTrack);
struct eCinemaEventMode { enum { SMOOTH, SELECT, IMMEDIATE_PATH, IMMEDIATE_TRACK }; };
struct sCameraInfo
{
Shareable<float> pX, pY, pZ, rX, rY, rZ; // position and rotation
};
SHAREABLE_STRUCT(sCameraInfo);
}
#endif // SHAREDTYPES_H__

View File

@ -0,0 +1,165 @@
#include "precompiled.h"
#include "View.h"
#include "ActorViewer.h"
#include "GameLoop.h"
#include "ps/Game.h"
#include "ps/GameSetup/GameSetup.h"
#include "simulation/EntityManager.h"
#include "simulation/Simulation.h"
extern void (*Atlas_GLSwapBuffers)(void* context);
extern int g_xres, g_yres;
//////////////////////////////////////////////////////////////////////////
class ViewNone : public View
{
public:
virtual void Update(float) { }
virtual void Render() { }
virtual CCamera& GetCamera() { return dummyCamera; }
virtual bool WantsHighFramerate() { return false; }
private:
CCamera dummyCamera;
};
//////////////////////////////////////////////////////////////////////////
ViewActor::ViewActor()
: m_SpeedMultiplier(1.f), m_ActorViewer(new ActorViewer())
{
}
ViewActor::~ViewActor()
{
delete m_ActorViewer;
}
void ViewActor::Update(float frameLength)
{
m_ActorViewer->Update(frameLength * m_SpeedMultiplier);
}
void ViewActor::Render()
{
SViewPort vp = { 0, 0, g_xres, g_yres };
CCamera& camera = GetCamera();
camera.SetViewPort(&vp);
camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
camera.UpdateFrustum();
m_ActorViewer->Render();
Atlas_GLSwapBuffers((void*)g_GameLoop->glContext);
}
CCamera& ViewActor::GetCamera()
{
return m_Camera;
}
bool ViewActor::WantsHighFramerate()
{
if (m_SpeedMultiplier != 0.f)
return true;
return false;
}
void ViewActor::SetSpeedMultiplier(float speed)
{
m_SpeedMultiplier = speed;
}
ActorViewer& ViewActor::GetActorViewer()
{
return *m_ActorViewer;
}
//////////////////////////////////////////////////////////////////////////
namespace AtlasMessage
{
extern void AtlasRenderSelection();
}
ViewGame::ViewGame()
{
debug_assert(g_Game);
}
void ViewGame::Update(float frameLength)
{
g_EntityManager.updateAll(0);
g_Game->GetSimulation()->Update(0.0);
if (g_Game->GetView()->GetCinema()->IsPlaying())
g_Game->GetView()->GetCinema()->Update(frameLength);
}
void ViewGame::Render()
{
SViewPort vp = { 0, 0, g_xres, g_yres };
CCamera& camera = GetCamera();
camera.SetViewPort(&vp);
camera.SetProjection(CGameView::defaultNear, CGameView::defaultFar, CGameView::defaultFOV);
camera.UpdateFrustum();
::Render();
AtlasMessage::AtlasRenderSelection();
Atlas_GLSwapBuffers((void*)g_GameLoop->glContext);
}
CCamera& ViewGame::GetCamera()
{
return *g_Game->GetView()->GetCamera();
}
bool ViewGame::WantsHighFramerate()
{
if (g_Game->GetView()->GetCinema()->IsPlaying())
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////
ViewNone* view_None = NULL;
ViewGame* view_Game = NULL;
ViewActor* view_Actor = NULL;
View::~View()
{
}
View* View::GetView_None()
{
if (! view_None)
view_None = new ViewNone();
return view_None;
}
ViewGame* View::GetView_Game()
{
if (! view_Game)
view_Game = new ViewGame();
return view_Game;
}
ViewActor* View::GetView_Actor()
{
if (! view_Actor)
view_Actor = new ViewActor();
return view_Actor;
}
void View::DestroyViews()
{
delete view_None; view_None = NULL;
delete view_Game; view_Game = NULL;
delete view_Actor; view_Actor = NULL;
}

View File

@ -0,0 +1,62 @@
#ifndef VIEW_H__
#define VIEW_H__
class ViewGame;
class ViewActor;
class View
{
public:
virtual ~View();
virtual void Update(float frameLength) = 0;
virtual void Render() = 0;
virtual CCamera& GetCamera() = 0;
virtual bool WantsHighFramerate() = 0;
// These always return a valid (not NULL) object
static View* GetView_None();
static ViewGame* GetView_Game();
static ViewActor* GetView_Actor();
// Invalidates any View objects previously returned by this class
static void DestroyViews();
};
//////////////////////////////////////////////////////////////////////////
class ActorViewer;
class ViewGame : public View
{
public:
ViewGame();
virtual void Update(float frameLength);
virtual void Render();
virtual CCamera& GetCamera();
virtual bool WantsHighFramerate();
private:
};
class ViewActor : public View
{
public:
ViewActor();
~ViewActor();
virtual void Update(float frameLength);
virtual void Render();
virtual CCamera& GetCamera();
virtual bool WantsHighFramerate();
void SetSpeedMultiplier(float speed);
ActorViewer& GetActorViewer();
private:
float m_SpeedMultiplier;
CCamera m_Camera;
ActorViewer* m_ActorViewer;
};
#endif // VIEW_H__