Atlas: Vaguely usable object placement code. Bug fixes.
This was SVN commit r3186.
This commit is contained in:
parent
0a252de08c
commit
547293ee49
@ -216,6 +216,23 @@ CVector3D CCamera::GetWorldCoordinates( int px, int py )
|
||||
return( origin + dir * ( ( 50.0f - origin.Y ) / dir.Y ) );
|
||||
}
|
||||
|
||||
CVector3D CCamera::GetWorldCoordinates(int px, int py, float h)
|
||||
{
|
||||
CPlane plane;
|
||||
plane.Set(CVector3D(0.f, 1.f, 0.f), CVector3D(0.f, h, 0.f)); // upwards normal, passes through h
|
||||
|
||||
CVector3D origin, dir, delta, currentTarget;
|
||||
|
||||
BuildCameraRay(px, py, origin, dir);
|
||||
|
||||
if (plane.FindRayIntersection(origin, dir, ¤tTarget))
|
||||
return currentTarget;
|
||||
|
||||
// No intersection with the infinite plane - nothing sensible can be returned,
|
||||
// so just choose an arbitrary point on the plane
|
||||
return CVector3D(0.f, h, 0.f);
|
||||
}
|
||||
|
||||
CVector3D CCamera::GetFocus()
|
||||
{
|
||||
// Basically the same as GetWorldCoordinates
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
extern int g_mouse_x, g_mouse_y;
|
||||
|
||||
//view port
|
||||
// view port
|
||||
struct SViewPort
|
||||
{
|
||||
unsigned int m_X;
|
||||
@ -34,22 +34,22 @@ class CCamera
|
||||
CCamera ();
|
||||
~CCamera ();
|
||||
|
||||
//Methods for projection
|
||||
// Methods for projection
|
||||
void SetProjection (CMatrix3D *proj) { m_ProjMat = *proj; }
|
||||
void SetProjection (float nearp, float farp, float fov);
|
||||
void SetProjectionTile (int tiles, int tile_x, int tile_y);
|
||||
CMatrix3D GetProjection () { return m_ProjMat; }
|
||||
|
||||
//Updates the frustum planes. Should be called
|
||||
//everytime the view or projection matrices are
|
||||
//altered.
|
||||
// Updates the frustum planes. Should be called
|
||||
// everytime the view or projection matrices are
|
||||
// altered.
|
||||
void UpdateFrustum ();
|
||||
CFrustum GetFrustum () { return m_ViewFrustum; }
|
||||
|
||||
void SetViewPort (SViewPort *viewport);
|
||||
SViewPort GetViewPort () { return m_ViewPort; }
|
||||
|
||||
//getters
|
||||
// getters
|
||||
float GetNearPlane() const { return m_NearPlane; }
|
||||
float GetFarPlane() const { return m_FarPlane; }
|
||||
float GetFOV() const { return m_FOV; }
|
||||
@ -62,40 +62,42 @@ class CCamera
|
||||
|
||||
// Build a ray passing through the screen coordinate (px, py) and the camera
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BuildCameraRay: calculate origin and ray direction of a ray through
|
||||
// the pixel (px,py) on the screen
|
||||
void BuildCameraRay( int px, int py, CVector3D& origin, CVector3D& dir );
|
||||
// BuildCameraRay: as previous, using global mouse position
|
||||
void BuildCameraRay( CVector3D& origin, CVector3D& dir )
|
||||
// BuildCameraRay: calculate origin and ray direction of a ray through
|
||||
// the pixel (px,py) on the screen
|
||||
void BuildCameraRay(int px, int py, CVector3D& origin, CVector3D& dir);
|
||||
// BuildCameraRay: as previous, using global mouse position
|
||||
void BuildCameraRay(CVector3D& origin, CVector3D& dir)
|
||||
{
|
||||
BuildCameraRay( g_mouse_x, g_mouse_y, origin, dir );
|
||||
BuildCameraRay(g_mouse_x, g_mouse_y, origin, dir);
|
||||
}
|
||||
|
||||
// General helpers that seem to fit here
|
||||
// General helpers that seem to fit here
|
||||
|
||||
// Get the screen-space coordinates corresponding to a given world-space position
|
||||
void GetScreenCoordinates( const CVector3D& world, float& x, float& y );
|
||||
// Get the screen-space coordinates corresponding to a given world-space position
|
||||
void GetScreenCoordinates(const CVector3D& world, float& x, float& y);
|
||||
|
||||
// Get the point on the terrain corresponding to pixel (px,py) (or the mouse coordinates)
|
||||
CVector3D GetWorldCoordinates( int px, int py );
|
||||
CVector3D GetWorldCoordinates() { return( GetWorldCoordinates( g_mouse_x, g_mouse_y ) ); }
|
||||
// Get the point on the terrain the camera is pointing towards
|
||||
// Get the point on the terrain corresponding to pixel (px,py) (or the mouse coordinates)
|
||||
CVector3D GetWorldCoordinates(int px, int py);
|
||||
CVector3D GetWorldCoordinates() { return GetWorldCoordinates(g_mouse_x, g_mouse_y); }
|
||||
// Get the point on the plane at height h corresponding to pixel (px,py)
|
||||
CVector3D GetWorldCoordinates(int px, int py, float h);
|
||||
// Get the point on the terrain the camera is pointing towards
|
||||
CVector3D GetFocus();
|
||||
|
||||
// Build an orientation matrix from camera position, camera focus point, and up-vector
|
||||
void LookAt( const CVector3D& camera, const CVector3D& orientation, const CVector3D& up );
|
||||
void LookAt(const CVector3D& camera, const CVector3D& orientation, const CVector3D& up);
|
||||
|
||||
// Build an orientation matrix from camera position, camera orientation, and up-vector
|
||||
void LookAlong( CVector3D camera, CVector3D focus, CVector3D up );
|
||||
void LookAlong(CVector3D camera, CVector3D focus, CVector3D up);
|
||||
|
||||
public:
|
||||
//This is the orientation matrix. The inverse of this
|
||||
//is the view matrix
|
||||
// This is the orientation matrix. The inverse of this
|
||||
// is the view matrix
|
||||
CMatrix3D m_Orientation;
|
||||
|
||||
private:
|
||||
//keep the projection matrix private
|
||||
//so we can't fiddle with it.
|
||||
// keep the projection matrix private
|
||||
// so we can't fiddle with it.
|
||||
CMatrix3D m_ProjMat;
|
||||
|
||||
float m_NearPlane;
|
||||
|
@ -181,8 +181,11 @@ void CEntityManager::renderAll()
|
||||
|
||||
void CEntityManager::destroy( u16 handle )
|
||||
{
|
||||
m_reaper.push_back( m_entities[handle].m_entity );
|
||||
m_entities[handle].m_entity->me.m_handle = INVALID_HANDLE;
|
||||
if (m_entities[handle].m_entity->me.m_handle != INVALID_HANDLE)
|
||||
{
|
||||
m_reaper.push_back( m_entities[handle].m_entity );
|
||||
m_entities[handle].m_entity->me.m_handle = INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool CEntityManager::m_extant = false;
|
||||
|
@ -65,7 +65,7 @@ void CSimulation::Update(double frameTime)
|
||||
{
|
||||
m_DeltaTime += frameTime;
|
||||
|
||||
if( m_DeltaTime >= 0.0 )
|
||||
if( m_DeltaTime >= 0.0 && frameTime )
|
||||
{
|
||||
PROFILE( "simulation turn" );
|
||||
// A new simulation frame is required.
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
int Initialize(CGameAttributes *pGameAttributes);
|
||||
|
||||
// Perform all CSimulation updates for the specified elapsed time.
|
||||
// (If frameTime=0, no simulation updates are done, but the graphics
|
||||
// are interpolated.)
|
||||
void Update(double frameTime);
|
||||
|
||||
// Calculate the message mask of a message to be queued
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "Buttons/ActionButton.h"
|
||||
#include "General/Datafile.h"
|
||||
#include "ScenarioEditor/Tools/Common/Tools.h"
|
||||
|
||||
#include "GameInterface/Messages.h"
|
||||
|
||||
@ -18,6 +19,12 @@ static void LoadMap(void*)
|
||||
{
|
||||
// TODO: Work when the map is not in .../maps/scenarios/
|
||||
std::wstring map = dlg.GetFilename().c_str();
|
||||
|
||||
// Deactivate tools, so they don't carry forwards into the new CWorld
|
||||
// and crash.
|
||||
SetCurrentTool(_T(""));
|
||||
// TODO: clear the undo buffer, etc
|
||||
|
||||
POST_MESSAGE(LoadMap(map));
|
||||
}
|
||||
|
||||
|
@ -53,8 +53,9 @@ void ObjectSidebar::OnFirstDisplay()
|
||||
qry.Post();
|
||||
for (std::vector<AtlasMessage::sEntitiesListItem>::iterator it = qry.entities.begin(); it != qry.entities.end(); ++it)
|
||||
{
|
||||
wxString id = it->id.c_str();
|
||||
wxString name = it->name.c_str();
|
||||
m_ObjectListBox->Append(name, new wxStringClientData(name));
|
||||
m_ObjectListBox->Append(name, new wxStringClientData(id));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ bool WorldCommand::Merge(AtlasWindowCommand* p)
|
||||
if (! prev)
|
||||
return false;
|
||||
|
||||
if (m_Command->GetType() != prev->m_Command->GetType()) // comparing char* pointers, because they're unique-per-class constants
|
||||
if (m_Command->GetName() != prev->m_Command->GetName()) // comparing char* pointers, because they're unique-per-class constants
|
||||
return false;
|
||||
|
||||
if (! m_Command->IsMergeable())
|
||||
|
@ -14,7 +14,7 @@ class PlaceObject : public StateDrivenTool<PlaceObject>
|
||||
DECLARE_DYNAMIC_CLASS(PlaceObject);
|
||||
|
||||
Position m_ScreenPos, m_ObjPos, m_Target;
|
||||
wxString m_ObjectName;
|
||||
wxString m_ObjectID;
|
||||
|
||||
public:
|
||||
PlaceObject()
|
||||
@ -22,21 +22,24 @@ public:
|
||||
SetState(&Waiting);
|
||||
}
|
||||
|
||||
void SendPreviewCommand()
|
||||
void SendObjectMsg(bool preview)
|
||||
{
|
||||
int dragDistSq =
|
||||
(m_ScreenPos.type1.x-m_Target.type1.x)*(m_ScreenPos.type1.x-m_Target.type1.x)
|
||||
+ (m_ScreenPos.type1.y-m_Target.type1.y)*(m_ScreenPos.type1.y-m_Target.type1.y);
|
||||
bool useTarget = (dragDistSq >= 8*8);
|
||||
POST_MESSAGE(EntityPreview(m_ObjectName.c_str(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
||||
bool useTarget = (dragDistSq >= 16*16);
|
||||
if (preview)
|
||||
POST_MESSAGE(EntityPreview(m_ObjectID.c_str(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
||||
else
|
||||
POST_COMMAND(CreateEntity, (m_ObjectID.c_str(), m_ObjPos, useTarget, m_Target, g_DefaultAngle));
|
||||
}
|
||||
|
||||
virtual void Init(void* initData)
|
||||
{
|
||||
wxASSERT(initData);
|
||||
wxString& name = *static_cast<wxString*>(initData);
|
||||
m_ObjectName = name;
|
||||
SendPreviewCommand();
|
||||
wxString& id = *static_cast<wxString*>(initData);
|
||||
m_ObjectID = id;
|
||||
SendObjectMsg(true);
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
@ -45,54 +48,65 @@ public:
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
m_ObjectName = _T("");
|
||||
SendPreviewCommand();
|
||||
m_ObjectID = _T("");
|
||||
SendObjectMsg(true);
|
||||
}
|
||||
|
||||
/*
|
||||
Object placement:
|
||||
* Select unit from list
|
||||
* Move mouse around screen; preview of unit follows mouse
|
||||
* Left mouse down -> remember position, fix preview to point
|
||||
* Mouse move -> if moved > 8px, rotate unit to face mouse; else default orientation
|
||||
* Left mouse release -> finalise placement of object on map
|
||||
Object placement:
|
||||
* Select unit from list
|
||||
* Move mouse around screen; preview of unit follows mouse
|
||||
* Left mouse down -> remember position, fix preview to point
|
||||
* Mouse move -> if moved > [limit], rotate unit to face mouse; else default orientation
|
||||
* Left mouse release -> finalise placement of object on map
|
||||
|
||||
* Scroll wheel -> rotate default orientation
|
||||
* Scroll wheel -> rotate default orientation
|
||||
|
||||
* Escape -> cancel placement tool
|
||||
* Escape -> cancel placement tool
|
||||
|
||||
TOOD: what happens if somebody saves while the preview is active?
|
||||
TOOD: what happens if somebody saves while the preview is active?
|
||||
*/
|
||||
|
||||
bool OnMouseOverride(wxMouseEvent& evt)
|
||||
bool OnMouseOverride(wxMouseEvent& WXUNUSED(evt))
|
||||
{
|
||||
if (evt.GetWheelRotation())
|
||||
// This used to let the scroll-wheel rotate units, but that overrides
|
||||
// the camera zoom and makes navigation very awkward, so it doesn't
|
||||
// any more.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnKeyOverride(wxKeyEvent& evt, KeyEventType dir)
|
||||
{
|
||||
switch (dir)
|
||||
{
|
||||
float speed = M_PI/36.f;
|
||||
case KEY_CHAR:
|
||||
if (evt.GetKeyCode() == WXK_ESCAPE)
|
||||
{
|
||||
SetState(&Disabled);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RotateTick(float dt)
|
||||
{
|
||||
int dir = 0;
|
||||
if (wxGetKeyState(WXK_NEXT)) ++dir; // page-down key
|
||||
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;
|
||||
g_DefaultAngle += (evt.GetWheelRotation() * speed / evt.GetWheelDelta());
|
||||
SendPreviewCommand();
|
||||
return true;
|
||||
g_DefaultAngle += (dir * dt * speed);
|
||||
SendObjectMsg(true);
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnKeyOverride(wxKeyEvent& evt, KeyEventType dir)
|
||||
{
|
||||
if (dir == KEY_CHAR && evt.GetKeyCode() == WXK_ESCAPE)
|
||||
{
|
||||
SetState(&Disabled);
|
||||
return true;
|
||||
}
|
||||
// TODO: arrow keys for rotation?
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -105,7 +119,7 @@ public:
|
||||
else if (evt.LeftDown())
|
||||
{
|
||||
obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target = Position(evt.GetPosition());
|
||||
obj->SendPreviewCommand();
|
||||
obj->SendObjectMsg(true);
|
||||
obj->m_ObjPos = Position::Unchanged(); // make sure object is stationary even if the camera moves
|
||||
SET_STATE(Placing);
|
||||
return true;
|
||||
@ -113,7 +127,7 @@ public:
|
||||
else if (evt.Moving())
|
||||
{
|
||||
obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target = Position(evt.GetPosition());
|
||||
obj->SendPreviewCommand();
|
||||
obj->SendObjectMsg(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -123,6 +137,10 @@ public:
|
||||
{
|
||||
return obj->OnKeyOverride(evt, dir);
|
||||
}
|
||||
void OnTick(PlaceObject* obj, float dt)
|
||||
{
|
||||
obj->RotateTick(dt);
|
||||
}
|
||||
}
|
||||
Waiting;
|
||||
|
||||
@ -135,16 +153,18 @@ public:
|
||||
else if (evt.LeftUp())
|
||||
{
|
||||
obj->m_Target = Position(evt.GetPosition());
|
||||
// TODO: createobject command, so you can actually place an object
|
||||
// Create the actual object
|
||||
obj->SendObjectMsg(false);
|
||||
// Go back to preview mode
|
||||
SET_STATE(Waiting);
|
||||
obj->m_ObjPos = obj->m_ScreenPos = obj->m_Target;
|
||||
obj->SendPreviewCommand();
|
||||
obj->SendObjectMsg(true);
|
||||
return true;
|
||||
}
|
||||
else if (evt.Moving())
|
||||
else if (evt.Dragging())
|
||||
{
|
||||
obj->m_Target = Position(evt.GetPosition());
|
||||
obj->SendPreviewCommand();
|
||||
obj->SendObjectMsg(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@ -154,6 +174,10 @@ public:
|
||||
{
|
||||
return obj->OnKeyOverride(evt, dir);
|
||||
}
|
||||
void OnTick(PlaceObject* obj, float dt)
|
||||
{
|
||||
obj->RotateTick(dt);
|
||||
}
|
||||
}
|
||||
Placing;
|
||||
};
|
||||
|
@ -14,8 +14,10 @@
|
||||
#include "lib/timer.h"
|
||||
#include "lib/res/file/vfs.h"
|
||||
#include "ps/CLogger.h"
|
||||
|
||||
#include "ps/GameSetup/GameSetup.h" // Render()
|
||||
#include "ps/GameSetup/GameSetup.h"
|
||||
#include "ps/Game.h"
|
||||
#include "simulation/Simulation.h"
|
||||
#include "simulation/EntityManager.h"
|
||||
|
||||
using namespace AtlasMessage;
|
||||
|
||||
@ -75,6 +77,7 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
|
||||
state.argv = argv;
|
||||
state.running = true;
|
||||
state.rendering = false;
|
||||
state.worldloaded = false;
|
||||
state.glContext = NULL;
|
||||
|
||||
double last_activity = get_time();
|
||||
@ -168,7 +171,15 @@ bool BeginAtlas(int argc, char* argv[], void* dll)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Do per-frame processing:
|
||||
|
||||
vfs_reload_changed_files();
|
||||
|
||||
if (state.worldloaded)
|
||||
{
|
||||
g_EntityManager.updateAll(0);
|
||||
g_Game->GetSimulation()->Update(0.0);
|
||||
}
|
||||
|
||||
if (state.rendering)
|
||||
{
|
||||
|
@ -9,6 +9,7 @@ struct GameLoopState
|
||||
char** argv;
|
||||
bool running;
|
||||
bool rendering;
|
||||
bool worldloaded;
|
||||
const void* glContext;
|
||||
float frameLength; // smoothed to avoid large jumps
|
||||
|
||||
|
@ -108,6 +108,6 @@ BEGIN_COMMAND(AlterElevation)
|
||||
prev->m_TerrainDelta.OverlayWith(m_TerrainDelta);
|
||||
}
|
||||
|
||||
END_COMMAND(AlterElevation);
|
||||
END_COMMAND(AlterElevation)
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "MessageHandler.h"
|
||||
#include "../GameLoop.h"
|
||||
|
||||
#include "graphics/Patch.h"
|
||||
#include "graphics/TextureManager.h"
|
||||
@ -30,6 +31,8 @@ static void InitGame(std::wstring map)
|
||||
|
||||
// Initialise the game:
|
||||
g_Game = new CGame();
|
||||
|
||||
g_GameLoop->worldloaded = true;
|
||||
}
|
||||
|
||||
static void StartGame()
|
||||
|
@ -1,12 +1,18 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "MessageHandler.h"
|
||||
#include "../CommandProc.h"
|
||||
|
||||
#include "simulation/BaseEntityCollection.h"
|
||||
#include "simulation/EntityManager.h"
|
||||
#include "graphics/Unit.h"
|
||||
#include "graphics/UnitManager.h"
|
||||
#include "graphics/Model.h"
|
||||
#include "maths/Matrix3D.h"
|
||||
#include "ps/CLogger.h"
|
||||
#include "ps/Game.h"
|
||||
|
||||
#define LOG_CATEGORY "editor"
|
||||
|
||||
namespace AtlasMessage {
|
||||
|
||||
@ -16,19 +22,28 @@ QUERYHANDLER(GetEntitiesList)
|
||||
g_EntityTemplateCollection.getBaseEntityNames(names);
|
||||
for (std::vector<CStrW>::iterator it = names.begin(); it != names.end(); ++it)
|
||||
{
|
||||
//CBaseEntity* baseent = g_EntityTemplateCollection.getTemplate(*it);
|
||||
sEntitiesListItem e;
|
||||
e.name = *it;
|
||||
e.id = *it;
|
||||
e.name = *it; //baseent->m_Tag
|
||||
msg->entities.push_back(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static CUnit* g_PreviewUnit = NULL;
|
||||
static CStrW g_PreviewUnitName;
|
||||
static CStrW g_PreviewUnitID;
|
||||
|
||||
static CVector3D GetUnitPos(const Position& pos)
|
||||
{
|
||||
static CVector3D vec;
|
||||
pos.GetWorldSpace(vec, vec); // if msg->pos is 'Unchanged', use the previous pos
|
||||
return vec;
|
||||
}
|
||||
|
||||
MESSAGEHANDLER(EntityPreview)
|
||||
{
|
||||
if (msg->name != g_PreviewUnitName)
|
||||
if (msg->id != g_PreviewUnitID)
|
||||
{
|
||||
// Delete old unit
|
||||
if (g_PreviewUnit)
|
||||
@ -38,11 +53,11 @@ MESSAGEHANDLER(EntityPreview)
|
||||
g_PreviewUnit = NULL;
|
||||
}
|
||||
|
||||
if (msg->name.length())
|
||||
if (msg->id.length())
|
||||
{
|
||||
// Create new unit
|
||||
CBaseEntity* base = g_EntityTemplateCollection.getTemplate(msg->name);
|
||||
if (base)
|
||||
CBaseEntity* base = g_EntityTemplateCollection.getTemplate(msg->id);
|
||||
if (base) // (ignore errors)
|
||||
{
|
||||
g_PreviewUnit = g_UnitMan.CreateUnit(base->m_actorName, 0);
|
||||
// TODO: set player (for colour)
|
||||
@ -50,24 +65,25 @@ MESSAGEHANDLER(EntityPreview)
|
||||
}
|
||||
|
||||
}
|
||||
g_PreviewUnitName = msg->name;
|
||||
g_PreviewUnitID = msg->id;
|
||||
}
|
||||
|
||||
// Position/orient unit
|
||||
if (g_PreviewUnit)
|
||||
{
|
||||
static CVector3D pos;
|
||||
msg->pos.GetWorldSpace(pos, pos); // if msg->pos is 'Unchanged', use the previous pos
|
||||
CVector3D pos = GetUnitPos(msg->pos);
|
||||
|
||||
float s, c;
|
||||
/*
|
||||
|
||||
if (msg->usetarget)
|
||||
{
|
||||
// TODO
|
||||
s=1; c=0;
|
||||
CVector3D target;
|
||||
msg->target.GetWorldSpace(target, pos.Y);
|
||||
CVector2D dir(target.X-pos.X, target.Z-pos.Z);
|
||||
dir = dir.normalize();
|
||||
s = dir.x;
|
||||
c = dir.y;
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
s = sin(msg->angle);
|
||||
c = cos(msg->angle);
|
||||
@ -80,8 +96,68 @@ MESSAGEHANDLER(EntityPreview)
|
||||
m._41 = 0.0f; m._42 = 0.0f; m._43 = 0.0f; m._44 = 1.0f;
|
||||
g_PreviewUnit->GetModel()->SetTransform(m);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BEGIN_COMMAND(CreateEntity)
|
||||
|
||||
HEntity m_Entity;
|
||||
CVector3D m_Pos;
|
||||
float m_Angle;
|
||||
|
||||
void Construct()
|
||||
{
|
||||
}
|
||||
void Destruct()
|
||||
{
|
||||
}
|
||||
|
||||
void Do()
|
||||
{
|
||||
m_Pos = GetUnitPos(d->pos);
|
||||
|
||||
if (d->usetarget)
|
||||
{
|
||||
CVector3D target;
|
||||
d->target.GetWorldSpace(target, m_Pos.Y);
|
||||
CVector2D dir(target.X-m_Pos.X, target.Z-m_Pos.Z);
|
||||
m_Angle = atan2(dir.x, dir.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Angle = d->angle;
|
||||
}
|
||||
|
||||
Redo();
|
||||
}
|
||||
|
||||
void Redo()
|
||||
{
|
||||
CBaseEntity* base = g_EntityTemplateCollection.getTemplate(d->id);
|
||||
if (! base)
|
||||
LOG(ERROR, LOG_CATEGORY, "Failed to load entity template '%ls'", d->id.c_str());
|
||||
else
|
||||
{
|
||||
HEntity ent = g_EntityManager.create(base, m_Pos, m_Angle);
|
||||
|
||||
if (! ent)
|
||||
LOG(ERROR, LOG_CATEGORY, "Failed to create entity of type '%ls'", d->id.c_str());
|
||||
else
|
||||
{
|
||||
// TODO: player ID
|
||||
ent->SetPlayer(g_Game->GetLocalPlayer());
|
||||
|
||||
m_Entity = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Undo()
|
||||
{
|
||||
m_Entity->kill();
|
||||
m_Entity = HEntity();
|
||||
}
|
||||
|
||||
END_COMMAND(CreateEntity)
|
||||
|
||||
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ BEGIN_COMMAND(PaintTerrain)
|
||||
prev->m_TerrainDelta.OverlayWith(m_TerrainDelta);
|
||||
}
|
||||
|
||||
END_COMMAND(PaintTerrain);
|
||||
END_COMMAND(PaintTerrain)
|
||||
|
||||
|
||||
}
|
||||
|
@ -89,6 +89,7 @@ QUERY(GetTerrainGroupPreviews,
|
||||
|
||||
struct sEntitiesListItem
|
||||
{
|
||||
std::wstring id;
|
||||
std::wstring name;
|
||||
// ...
|
||||
};
|
||||
@ -98,13 +99,22 @@ QUERY(GetEntitiesList,
|
||||
);
|
||||
|
||||
MESSAGE(EntityPreview,
|
||||
((std::wstring, name)) // or empty string => disable
|
||||
((std::wstring, id)) // or empty string => disable
|
||||
((Position, pos))
|
||||
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
||||
((Position, target))
|
||||
((float, angle))
|
||||
);
|
||||
|
||||
COMMAND(CreateEntity, NOMERGE,
|
||||
((std::wstring, id))
|
||||
((Position, pos))
|
||||
((bool, usetarget)) // true => use 'target' for orientation; false => use 'angle'
|
||||
((Position, target))
|
||||
((float, angle))
|
||||
);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QUERY(Exit,,); // no inputs nor outputs
|
||||
|
@ -37,6 +37,7 @@ 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;
|
||||
void GetScreenSpace(float& x, float& y) const;
|
||||
};
|
||||
@ -55,8 +56,8 @@ struct IMessage
|
||||
|
||||
#define MESSAGESTRUCT(t) \
|
||||
struct m##t : public IMessage { \
|
||||
const char* GetName() const { return #t; } \
|
||||
Type GetType() const { return IMessage::Message; } \
|
||||
virtual const char* GetName() const { return #t; } \
|
||||
virtual Type GetType() const { return IMessage::Message; } \
|
||||
private: \
|
||||
const m##t& operator=(const m##t&); \
|
||||
public:
|
||||
|
@ -30,6 +30,19 @@ void AtlasMessage::Position::GetWorldSpace(CVector3D& vec) const
|
||||
}
|
||||
}
|
||||
|
||||
void AtlasMessage::Position::GetWorldSpace(CVector3D& vec, float h) const
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 1:
|
||||
vec = g_Game->GetView()->GetCamera()->GetWorldCoordinates(type1.x, type1.y, h);
|
||||
break;
|
||||
|
||||
default:
|
||||
GetWorldSpace(vec);
|
||||
}
|
||||
}
|
||||
|
||||
void AtlasMessage::Position::GetWorldSpace(CVector3D& vec, const CVector3D& prev) const
|
||||
{
|
||||
switch (type)
|
||||
@ -37,6 +50,7 @@ void AtlasMessage::Position::GetWorldSpace(CVector3D& vec, const CVector3D& prev
|
||||
case 2:
|
||||
vec = prev;
|
||||
break;
|
||||
|
||||
default:
|
||||
GetWorldSpace(vec);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user