创建新类(继承GuiTSCtrl)
此类用于显示场景,可以指定特定的中心位置,使用鼠标左键拖动进行旋转,使用鼠标右键拖动或鼠标滚轮实现场景缩放,双击选中物体。中心位置为球的中心点,照相机的位置是球面上的任意点。
1)gameNewTSCtrl.h文件如下
#ifndef
_GAMENEWTSCTRL_H_
#define
_GAMENEWTSCTRL_H_
#ifndef
_DGL_H_
#include
"dgl/dgl.h"
#endif
#ifndef
_GAME_H_
#include
"game/game.h"
#endif
#ifndef
_GUITSCONTROL_H_
#include
"gui/core/guiTSControl.h"
#endif
class
ProjectileData;
class
GameBase;
by mfw 2008-5-22
class
GameNewTSCtrl : public GuiTSCtrl
{
private
:
typedef GuiTSCtrl Parent;
protected
:
enum MouseState
{
None,
Rotating,
Zooming
};
MouseState mMouseState;
bool mZoom;
bool mSpin;
Point3F mCameraPos;
MatrixF mCameraMatrix;
EulerF mCameraRot;
Point3F mOrbitPos;
F32 mMinOrbitDist;
F32 mOrbitDist;
Point2I mLastMousePoint;
// by mfw 2008-5-26
F32 mCameraPosOffsetX;
F32 mCameraPosOffsetY;
F32 mCameraPosOffsetZ;
F32 mOrbitDistOffset;
public
:
GameNewTSCtrl();
bool processCameraQuery(CameraQuery *query);
void renderWorld(const RectI &updateRect);
void onMouseMove(const GuiEvent &evt);
void onRender(Point2I offset, const RectI &updateRect);
public
: //by mfw
bool onWake();
void onMouseUp( const GuiEvent &event );
void onMouseDragged( const GuiEvent &event );
void onRightMouseDown( const GuiEvent &event );
void onRightMouseUp( const GuiEvent &event );
void onRightMouseDragged( const GuiEvent &event );
bool onMouseWheelDown(const GuiEvent &event);
bool onMouseWheelUp(const GuiEvent &event);
void setMouseOptions( bool zoom, bool spin );
void setCamera(Point3F posCenter, F32 radius);
void setCameraPosOffset(F32 offsetX, F32 offsetY, F32 offsetZ);
void setOrbitDisOffset(F32 offset);
void setOrbitDis(F32 offset);
void setCameraVec(F32 x, F32 y, F32 z);
void onMouseDown(const GuiEvent &evt); //left-mouse click
Point3F getMouse3DVec() {return mMouse3DVec;};
Point3F getMouse3DPos() {return mMouse3DPos;};
Point3F getCameraVec() {return mCameraRot;};
Point3F getOrbitPos() {return mOrbitPos;};
Point3F mMouse3DVec;
Point3F mMouse3DPos; //
DECLARE_CONOBJECT(GameNewTSCtrl);
public
:
static void consoleInit();
};
//
#endif
2)gameNewTSCtrl.cc文件如下:
#include
"game/gameNewTSCtrl.h"
#include
"console/consoleTypes.h"
#include
"game/projectile.h"
#include
"game/gameBase.h"
#include
"game/gameConnection.h"
#include
"game/shapeBase.h"
//---------------------------------------------------------------------------
// Debug stuff:
extern
Point3F newlineTestStart = Point3F(0, 0, 0);
extern
Point3F newlineTestEnd = Point3F(0, 1000, 0);
extern
Point3F newlineTestIntersect = Point3F(0, 0, 0);
extern
bool gnewSnapLine = false;
//by mfw 2008-5-22///
//----------------------------------------------------------------------------
// Class: GameNewTSCtrl
//----------------------------------------------------------------------------
static
const F32 newMaxOrbitDist = 50.0f;
static
const S32 newMaxAnimations = 6;
IMPLEMENT_CONOBJECT(GameNewTSCtrl);
GameNewTSCtrl::GameNewTSCtrl()
{
mActive = true;
mMouseState = None;
// Can zoom and spin by default
mZoom = true;
mSpin = true;
mLastMousePoint.set( 0, 0 );
mCameraPosOffsetX = 0;
mCameraPosOffsetY = 0;
mCameraPosOffsetZ = 0;
mOrbitDistOffset = 0.2;
mOrbitDist = 2.5f;
}
// Script function handling for "setObject"
ConsoleMethod( GameNewTSCtrl, setCameraPos, void, 4, 4, "(Point3F pos, float radius)" )
{
Point3F pos;
int numArgsRead = dSscanf(argv[2], "%g %g %g", &pos.x, &pos.y, &pos.z);
if (numArgsRead != 3)
{
Con::printf("%s() - invalid start point.", argv[0]);
return;
}
GameNewTSCtrl* view = static_cast<GameNewTSCtrl*>( object );
view->setCamera(pos, dAtof(argv[3]));
}
ConsoleMethod( GameNewTSCtrl, setCameraPosOffset, void, 5, 5, "(float offsetX, float offsetY,float offsetZ)" )
{
GameNewTSCtrl* view = static_cast<GameNewTSCtrl*>( object );
view->setCameraPosOffset(dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]));
}
ConsoleMethod( GameNewTSCtrl, setOrbitDisOffset, void, 3, 3, "(float offset)" )
{
GameNewTSCtrl* view = static_cast<GameNewTSCtrl*>( object );
view->setOrbitDisOffset(dAtof(argv[2]));
}
ConsoleMethod( GameNewTSCtrl, setOrbitDis, void, 3, 3, "(float offset)" )
{
GameNewTSCtrl* view = static_cast<GameNewTSCtrl*>( object );
view->setOrbitDis(dAtof(argv[2]));
}
ConsoleMethod( GameNewTSCtrl, setCameraVec, void, 5, 5, "(float x, float y,float z)" )
{
GameNewTSCtrl* view = static_cast<GameNewTSCtrl*>( object );
view->setCameraVec(dAtof(argv[2]), dAtof(argv[3]), dAtof(argv[4]));
}
//---------------------------------------------------------------------------
bool
GameNewTSCtrl::processCameraQuery(CameraQuery *camq)
{
// GameUpdateCameraFov();
// return GameProcessCameraQuery(camq);
mOrbitDist = ( mOrbitDist < mMinOrbitDist ) ? mMinOrbitDist : ( ( mOrbitDist > newMaxOrbitDist ) ? newMaxOrbitDist : mOrbitDist );
// Adjust the camera so that we are still facing the model:
Point3F vec;
MatrixF xRot, zRot;
//by mfw 2008-5-26
限制旋转角度,不让漏出地面以下的部分
if(mCameraRot.x < 0)
mCameraRot.x = 0;
if(mCameraRot.x > 3.14)
mCameraRot.x = 3.14;
if(mCameraPosOffsetX != 0)
{
mOrbitPos.x += mCameraPosOffsetX*sin(mCameraRot.z + 1.57);
mOrbitPos.y += mCameraPosOffsetX*cos(mCameraRot.z + 1.57);
}
if(mCameraPosOffsetY != 0)
{
mOrbitPos.x += mCameraPosOffsetY*sin(mCameraRot.z);
mOrbitPos.y += mCameraPosOffsetY*cos(mCameraRot.z);
}
if(mCameraPosOffsetZ != 0)
{
mOrbitPos.z += mCameraPosOffsetZ;
}
if(mOrbitPos.z < 0)
mOrbitPos.z = 0.01;
xRot.set( EulerF( mCameraRot.x, 0, 0 ) );
zRot.set( EulerF( 0, 0, mCameraRot.z ) );
mCameraMatrix.mul( zRot, xRot );
mCameraMatrix.getColumn( 1, &vec );
vec *= mOrbitDist;
mCameraPos = mOrbitPos - vec;
camq->nearPlane = 0.1;
camq->farPlane = 2100.0;
camq->fov = 3.1415 / 3.5;
mCameraMatrix.setColumn( 3, mCameraPos );
camq->cameraMatrix = mCameraMatrix;
return true;
}
//---------------------------------------------------------------------------
void
GameNewTSCtrl::renderWorld(const RectI &updateRect)
{
GameRenderWorld();
dglSetClipRect(updateRect);
}
//---------------------------------------------------------------------------
void
GameNewTSCtrl::onMouseMove(const GuiEvent &evt)
{
if(gnewSnapLine)
return;
MatrixF mat;
Point3F vel;
if ( GameGetCameraTransform(&mat, &vel) )
{
Point3F pos;
mat.getColumn(3,&pos);
const Point3F screenPoint(evt.mousePoint.x, evt.mousePoint.y, -1);
Point3F worldPoint;
pos = mCameraPos;
if (unproject(screenPoint, &worldPoint))
{
Point3F vec = worldPoint - pos;
newlineTestStart = pos;
vec.normalizeSafe();
newlineTestEnd = pos + vec * 1000;
//by mfw
mMouse3DPos = pos;
mMouse3DVec = worldPoint - pos;
mMouse3DVec.normalizeSafe();
S32 lbutton = (evt.modifier > 0) ? 1:0;
Con::executef(this, 2, "onMouseMove",Con::getIntArg(lbutton));
//
}
}
}
void
GameNewTSCtrl::onRender(Point2I offset, const RectI &updateRect)
{
// check if should bother with a render
GameConnection * con = GameConnection::getConnectionToServer();
bool skipRender = !con || (con->getWhiteOut() >= 1.f) || (con->getDamageFlash() >= 1.f) || (con->getBlackOut() >= 1.f);
if(!skipRender)
Parent::onRender(offset, updateRect);
dglSetViewport(updateRect);
CameraQuery camq = mLastCameraQuery;
if(GameProcessCameraQuery(&camq))
GameRenderFilters(camq);
// Draw controls after so they aren't affected by the filters. (If we're doing that.)
if(!skipRender && !mApplyFilterToChildren)
Parent::renderChildControls(offset, updateRect);}
// by mfw
void
GameNewTSCtrl::onMouseDown(const GuiEvent &evt)
{
MatrixF mat;
Point3F vel;
if ( GameGetCameraTransform(&mat, &vel) )
{
//get the camera position
Point3F pos;
mat.getColumn(3,&pos);
pos = mCameraPos;
//take our mouse coordinates and create (x,y,z) screen coordinates
Point3F screenPoint(evt.mousePoint.x, evt.mousePoint.y, -1);
//take our screen coordinates and get the corresponding
//world coordinates (this is what unproject does for us)
Point3F worldPoint;
if (unproject(screenPoint, &worldPoint))
{
mMouse3DPos = pos;
//create a vector that points from our starting point (the
//camera position) and heads towards our point we have chosen
//in the world
mMouse3DVec = worldPoint - pos;
mMouse3DVec.normalizeSafe();
//call client script handler
if(evt.mouseClickCount > 1)
Con::executef(this, 1, "onMouseDown");
}
}
if ( !mActive || !mVisible || !mAwake || !mSpin )
return;
mMouseState = Rotating;
mLastMousePoint = evt.mousePoint;
mouseLock();
}
static
const char* cGetMouse3DVec(SimObject *ptr, S32 argc, const char **argv)
{
GameNewTSCtrl* obj = static_cast<GameNewTSCtrl*>(ptr);
char* retBuffer = Con::getReturnBuffer(256);
const Point3F &vec = obj->getMouse3DVec();
dSprintf(retBuffer, 256, "%g %g %g", vec.x, vec.y, vec.z);
return retBuffer;
}
static
const char* cGetMouse3DPos(SimObject *ptr, S32 argc, const char **argv)
{
GameNewTSCtrl* obj = static_cast<GameNewTSCtrl*>(ptr);
char* retBuffer = Con::getReturnBuffer(256);
const Point3F &pos = obj->getMouse3DPos();
dSprintf(retBuffer, 256, "%g %g %g", pos.x, pos.y, pos.z);
return retBuffer;
}
static
const char* cGetCameraVec(SimObject *ptr, S32 argc, const char **argv)
{
GameNewTSCtrl* obj = static_cast<GameNewTSCtrl*>(ptr);
char* retBuffer = Con::getReturnBuffer(256);
const Point3F &pos = obj->getCameraVec();
dSprintf(retBuffer, 256, "%g %g %g", pos.x, pos.y, pos.z);
return retBuffer;
}
static
const char* cGetOrbitPos(SimObject *ptr, S32 argc, const char **argv)
{
GameNewTSCtrl* obj = static_cast<GameNewTSCtrl*>(ptr);
char* retBuffer = Con::getReturnBuffer(256);
const Point3F &pos = obj->getOrbitPos();
dSprintf(retBuffer, 256, "%g %g %g", pos.x, pos.y, pos.z);
return retBuffer;
}
void
GameNewTSCtrl::consoleInit()
{
Con::addCommand("GameNewTSCtrl", "getMouse3DVec", cGetMouse3DVec, "GameNewTSCtrl.getMouse3DVec();", 2, 2);
Con::addCommand("GameNewTSCtrl", "getMouse3DPos", cGetMouse3DPos, "GameNewTSCtrl.getMouse3DPos();", 2, 2);
Con::addCommand("GameNewTSCtrl", "getCameraVec", cGetCameraVec, "GameNewTSCtrl.getCameraVec();", 2, 2);
Con::addCommand("GameNewTSCtrl", "getOrbitPos", cGetOrbitPos, "GameNewTSCtrl.getOrbitPos();", 2, 2);
}
bool
GameNewTSCtrl::onWake()
{
if ( !Parent::onWake() )
return( false );
mCameraMatrix.identity();
mCameraRot.set( 0.4, 0, 0.5 );
mCameraPos.set( 0, 1.75, 1.25 );
mCameraMatrix.setColumn( 3, mCameraPos );
return( true );
}
// Function to determine the ways the mouse can interact with the gui object
void
GameNewTSCtrl::setMouseOptions( bool zoom, bool spin )
{
mZoom = zoom;
mSpin = spin;
}
// Mouse is up, unlock mouse input
void
GameNewTSCtrl::onMouseUp( const GuiEvent &/*event*/ )
{
mouseUnlock();
mMouseState = None;
Con::executef(this, 1, "onMouseUp");
}
// If mouse is dragged, adjust camera position accordingly. Makes model rotate
void
GameNewTSCtrl::onMouseDragged( const GuiEvent &event )
{
if ( mMouseState != Rotating )
return;
Point2I delta = event.mousePoint - mLastMousePoint;
mLastMousePoint = event.mousePoint;
mCameraRot.x += ( delta.y * 0.01 );
mCameraRot.z += ( delta.x * 0.01 );
}
// Right mouse is down, lock mouse input and get the mouse pointer coordinates and set mode to zoom
void
GameNewTSCtrl::onRightMouseDown( const GuiEvent &event )
{
if ( !mActive || !mVisible || !mAwake || !mZoom )
return;
mMouseState = Zooming;
mLastMousePoint = event.mousePoint;
mouseLock();
}
// Right mouse is up, unlock mouse input
void
GameNewTSCtrl::onRightMouseUp( const GuiEvent &/*event*/ )
{
mouseUnlock();
mMouseState = None;
}
// If mouse is dragged, adjust camera position accordingly. Makes model zoom
void
GameNewTSCtrl::onRightMouseDragged( const GuiEvent &event )
{
if ( mMouseState != Zooming )
return;
S32 delta = event.mousePoint.y - mLastMousePoint.y;
mLastMousePoint = event.mousePoint;
mOrbitDist += ( delta * 0.01 );
}
//
bool
GameNewTSCtrl::onMouseWheelDown(const GuiEvent &event)
{
mOrbitDist += mOrbitDistOffset;
return true;
}
bool
GameNewTSCtrl::onMouseWheelUp(const GuiEvent &event)
{
mOrbitDist -= mOrbitDistOffset;
return true;
}
//
//-----------------------------------------------------------
void
GameNewTSCtrl::setCamera(Point3F posCenter, F32 radius)
{
// Initialize camera values:
mOrbitPos = posCenter;
if(radius != 0)
{
mMinOrbitDist = radius;
mOrbitDist = mMinOrbitDist + 7;
}
}
void
GameNewTSCtrl::setCameraPosOffset(F32 offsetX, F32 offsetY, F32 offsetZ)
{
mCameraPosOffsetX = offsetX;
mCameraPosOffsetY = offsetY;
mCameraPosOffsetZ = offsetZ;
}
void
GameNewTSCtrl::setOrbitDisOffset(F32 offset)
{
mOrbitDistOffset =offset;
}
void
GameNewTSCtrl::setOrbitDis(F32 offset)
{
mOrbitDist =offset;
}
void
GameNewTSCtrl::setCameraVec(F32 x, F32 y, F32 z)
{
mCameraRot.x = x;
mCameraRot.y = y;
mCameraRot.z = z;
}
//
//--------------------------------------------------------------------------
ConsoleFunction( snapToggle, void, 1, 1, "()" )
{
gnewSnapLine = !gnewSnapLine;
}
//
3)使用方法与GameTSCtrl类似,如下列代码
new GameNewTSCtrl
(playerInterface)
function
playerInterface
::
onWake(
%this
)
{
$caremaTargetPos
=
"23.8848 -408.508 1.017"
;
playerInterface
.
setCameraPos(
$caremaTargetPos
,
0.5
);
$enableDirectInput
=
"1"
;
activateDirectInput
();
}