1
0
forked from 0ad/0ad

Fix #56 (add unit-following camera mode (press 'F')), based on patch from markelov.

Remove obsolete IsNewSimulation function.

This was SVN commit r8190.
This commit is contained in:
Ykkrosh 2010-09-26 23:05:25 +00:00
parent 9bdbc3906f
commit 82691683cb
10 changed files with 108 additions and 7 deletions

View File

@ -113,6 +113,7 @@ hotkey.archive.abort = "Alt+F4" ; Prematurely terminate the archive builder
; > CAMERA SETTINGS
hotkey.camera.reset = "H" ; Reset camera rotation to default.
hotkey.camera.follow = "F" ; Follow the first unit in the selection
hotkey.camera.reset.origin = "Ctrl+H" ; Reset camera to origin.
hotkey.camera.zoom.in = Plus, Equals, NumPlus ; Zoom camera in.
hotkey.camera.zoom.out = Minus, NumMinus ; Zoom camera out.

View File

@ -759,3 +759,22 @@ function performCommand(entity, commandName)
}
}
}
// Set the camera to follow the given unit
function setCameraFollow(entity)
{
// Follow the given entity if it's a unit
if (entity)
{
var entState = GetEntityState(entity);
if (entState && isUnit(entState))
{
Engine.CameraFollow(entity);
return;
}
}
// Otherwise stop following
Engine.CameraFollow(0);
}

View File

@ -62,6 +62,11 @@
<object hotkey="killUnit">
<action on="Press">performCommand(g_Selection.toList()[0], "delete");</action>
</object>
<!-- camera.follow mode - follow the first unit in the selection -->
<object hotkey="camera.follow">
<action on="Press">setCameraFollow(g_Selection.toList()[0]);</action>
</object>
<!-- ================================ ================================ -->
<!-- Developer / Debug items -->

View File

@ -52,6 +52,7 @@
#include "scripting/ScriptableObject.h"
#include "simulation/LOSManager.h"
#include "simulation2/Simulation2.h"
#include "simulation2/components/ICmpPosition.h"
extern int g_xres, g_yres;
@ -157,6 +158,7 @@ public:
LockCullCamera(false),
ConstrainCamera(true),
Culling(true),
FollowEntity(INVALID_ENTITY),
// Dummy values (these will be filled in by the config file)
ViewScrollSpeed(0),
@ -235,6 +237,11 @@ public:
CCinemaManager TrackManager;
/**
* Entity for the camera to follow, or INVALID_ENTITY if none.
*/
entity_id_t FollowEntity;
////////////////////////////////////////
// Settings
float ViewScrollSpeed;
@ -574,7 +581,7 @@ void CGameView::Update(float DeltaTime)
// TODO: this is probably not an ideal place for this, it should probably go
// in a CCmpWaterManager or some such thing (once such a thing exists)
if (!g_Game->m_Paused)
if (!m->Game->m_Paused)
g_Renderer.GetWaterManager()->m_WaterTexTimer += DeltaTime;
if (m->TrackManager.IsActive() && m->TrackManager.IsPlaying())
@ -639,6 +646,9 @@ void CGameView::Update(float DeltaTime)
if (moveRightward || moveForward)
{
// Break out of following mode when the user starts scrolling
m->FollowEntity = INVALID_ENTITY;
float s = sin(m->RotateY.GetSmoothedValue());
float c = cos(m->RotateY.GetSmoothedValue());
m->PosX.AddSmoothly(c * moveRightward);
@ -647,6 +657,37 @@ void CGameView::Update(float DeltaTime)
m->PosZ.AddSmoothly(c * moveForward);
}
if (m->FollowEntity)
{
CmpPtr<ICmpPosition> cmpPosition(*(m->Game->GetSimulation2()), m->FollowEntity);
if (!cmpPosition.null() && cmpPosition->IsInWorld())
{
// Get the most recent interpolated position
float frameOffset = m->Game->GetSimulation2()->GetLastFrameOffset();
CVector3D pos = cmpPosition->GetInterpolatedTransform(frameOffset, false).GetTranslation();
// move the camera after unit
// use smoothed values of rotation around X and Y, since we need to hold user's rotation done
// in this function above
CCamera targetCam = m->ViewCamera;
targetCam.m_Orientation.SetIdentity();
targetCam.m_Orientation.RotateX(m->RotateX.GetSmoothedValue());
targetCam.m_Orientation.RotateY(m->RotateY.GetSmoothedValue());
targetCam.m_Orientation.Translate(m->PosX.GetValue(), m->PosY.GetValue(), m->PosZ.GetValue());
CVector3D pivot = targetCam.GetFocus();
CVector3D delta = pos - pivot;
m->PosX.AddSmoothly(delta.X);
m->PosY.AddSmoothly(delta.Y);
m->PosZ.AddSmoothly(delta.Z);
}
else
{
// The unit disappeared (died or garrisoned etc), so stop following it
m->FollowEntity = INVALID_ENTITY;
}
}
if (hotkeys[HOTKEY_CAMERA_ZOOM_IN])
m->Zoom.AddSmoothly(m->ViewZoomSpeed * DeltaTime);
if (hotkeys[HOTKEY_CAMERA_ZOOM_OUT])
@ -785,6 +826,9 @@ void CGameView::MoveCameraTarget(const CVector3D& target)
m->PosZ.SetValueSmoothly(delta.Z + m->PosZ.GetValue());
ClampDistance(m, false);
// Break out of following mode so the camera really moves to the target
m->FollowEntity = INVALID_ENTITY;
}
void CGameView::ResetCameraTarget(const CVector3D& target)
@ -803,6 +847,9 @@ void CGameView::ResetCameraTarget(const CVector3D& target)
SetupCameraMatrix(m, &m->ViewCamera.m_Orientation);
m->ViewCamera.UpdateFrustum();
// Break out of following mode so the camera really moves to the target
m->FollowEntity = INVALID_ENTITY;
}
void CGameView::ResetCameraAngleZoom()
@ -824,6 +871,11 @@ void CGameView::ResetCameraAngleZoom()
m->RotateY.SetValueSmoothly(DEGTORAD(m->ViewRotateYDefault));
}
void CGameView::CameraFollow(entity_id_t entity)
{
m->FollowEntity = entity;
}
InReaction game_view_handler(const SDL_Event_* ev)
{
// put any events that must be processed even if inactive here

View File

@ -23,6 +23,7 @@ extern float g_MaxZoomHeight; //note: Max terrain height is this minus YMinOffs
extern float g_YMinOffset;
#include "renderer/Scene.h"
#include "simulation2/system/Entity.h"
#include "lib/input.h" // InReaction - can't forward-declare enum
@ -85,6 +86,7 @@ public:
void MoveCameraTarget(const CVector3D& target);
void ResetCameraTarget(const CVector3D& target);
void ResetCameraAngleZoom();
void CameraFollow(entity_id_t entity);
CCamera *GetCamera();
CCinemaManager* GetCinema();

View File

@ -73,11 +73,6 @@ void PopGuiPage(void* UNUSED(cbdata))
g_GUI->PopPage();
}
bool IsNewSimulation(void* UNUSED(cbdata))
{
return true; // XXX: delete this function
}
CScriptVal GuiInterfaceCall(void* cbdata, std::wstring name, CScriptVal data)
{
CGUIManager* guiManager = static_cast<CGUIManager*> (cbdata);
@ -317,6 +312,16 @@ void SetRevealMap(void* UNUSED(cbdata), bool enabled)
cmpRangeManager->SetLosRevealAll(enabled);
}
/**
* Start / stop camera following mode
* @param entityid unit id to follow. If zero, stop following mode
*/
void CameraFollow(void* UNUSED(cbdata), entity_id_t entityid)
{
if (g_Game && g_Game->GetView())
g_Game->GetView()->CameraFollow(entityid);
}
} // namespace
void GuiScriptingInit(ScriptInterface& scriptInterface)
@ -328,7 +333,6 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<void, &PopGuiPage>("PopGuiPage");
// Simulation<->GUI interface functions:
scriptInterface.RegisterFunction<bool, &IsNewSimulation>("IsNewSimulation");
scriptInterface.RegisterFunction<CScriptVal, std::wstring, CScriptVal, &GuiInterfaceCall>("GuiInterfaceCall");
scriptInterface.RegisterFunction<void, CScriptVal, &PostNetworkCommand>("PostNetworkCommand");
@ -357,4 +361,5 @@ void GuiScriptingInit(ScriptInterface& scriptInterface)
scriptInterface.RegisterFunction<bool, &AtlasIsAvailable>("AtlasIsAvailable");
scriptInterface.RegisterFunction<CScriptVal, std::wstring, &LoadMapData>("LoadMapData");
scriptInterface.RegisterFunction<void, bool, &SetRevealMap>("SetRevealMap");
scriptInterface.RegisterFunction<void, entity_id_t, &CameraFollow>("CameraFollow");
}

View File

@ -74,6 +74,7 @@ static SHotkeyInfo hotkeyInfo[] =
{ HOTKEY_WIREFRAME, "wireframe", SDLK_w, 0 },
{ HOTKEY_TOGGLEFULLSCREEN, "togglefullscreen", 0, 0 },
{ HOTKEY_CAMERA_RESET, "camera.reset", 0, 0 },
{ HOTKEY_CAMERA_FOLLOW, "camera.follow", 0, 0 },
{ HOTKEY_CAMERA_ZOOM_IN, "camera.zoom.in", SDLK_PLUS, SDLK_KP_PLUS },
{ HOTKEY_CAMERA_ZOOM_OUT, "camera.zoom.out", SDLK_MINUS, SDLK_KP_MINUS },
{ HOTKEY_CAMERA_ZOOM_WHEEL_IN, "camera.zoom.wheel.in", MOUSE_WHEELUP, 0 },

View File

@ -55,6 +55,7 @@ enum
HOTKEY_WIREFRAME,
HOTKEY_TOGGLEFULLSCREEN,
HOTKEY_CAMERA_RESET,
HOTKEY_CAMERA_FOLLOW,
HOTKEY_CAMERA_ZOOM_IN,
HOTKEY_CAMERA_ZOOM_OUT,
HOTKEY_CAMERA_ZOOM_WHEEL_IN,

View File

@ -83,6 +83,7 @@ public:
m_ComponentManager.ResetState();
m_DeltaTime = 0.0;
m_LastFrameOffset = 0.0f;
m_TurnNumber = 0;
CParamNode noParam;
@ -133,6 +134,7 @@ public:
CSimContext m_SimContext;
CComponentManager m_ComponentManager;
double m_DeltaTime;
float m_LastFrameOffset;
std::wstring m_StartupScript;
CScriptValRooted m_MapSettings;
@ -245,6 +247,8 @@ bool CSimulation2Impl::Update(int turnLength, const std::vector<SimulationComman
void CSimulation2Impl::Interpolate(float frameLength, float frameOffset)
{
m_LastFrameOffset = frameOffset;
CMessageInterpolate msg(frameLength, frameOffset);
m_ComponentManager.BroadcastMessage(msg);
}
@ -376,6 +380,11 @@ void CSimulation2::RenderSubmit(SceneCollector& collector, const CFrustum& frust
m->m_ComponentManager.BroadcastMessage(msg);
}
float CSimulation2::GetLastFrameOffset() const
{
return m->m_LastFrameOffset;
}
bool CSimulation2::LoadScripts(const VfsPath& path)
{
return m->LoadScripts(path);

View File

@ -114,6 +114,12 @@ public:
void Interpolate(float frameLength, float frameOffset);
void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling);
/**
* Returns the last frame offset passed to Interpolate(), i.e. the offset corresponding
* to the currently-rendered scene.
*/
float GetLastFrameOffset() const;
/**
* Construct a new entity and add it to the world.
* @param templateName see ICmpTemplateManager for syntax