//----------------------------------------------------------------------------- // Torque Game Engine // Copyright (C) GarageGames.com, Inc. //----------------------------------------------------------------------------- #include "gui/core/guiCanvas.h" #include "game/guiPlayerView.h" #include "console/consoleTypes.h" static const F32 MaxOrbitDist = 5.0f; static const S32 MaxAnimations = 6; IMPLEMENT_CONOBJECT( GuiPlayerView ); //------------------------------------------------------------------------------ GuiPlayerView::GuiPlayerView() : GuiTSCtrl() { mActive = true; mMouseState = None; mModel = NULL; mWeapon = NULL; mLastMousePoint.set( 0, 0 ); lastRenderTime = 0; runThread = 0; wNode = -1; pNode = -1; mAnimationSeq = 0; } //------------------------------------------------------------------------------ GuiPlayerView::~GuiPlayerView() { if ( mModel ) { delete mModel; mModel = NULL; } if ( mWeapon ) { delete mWeapon; mWeapon = NULL; } } //------------------------------------------------------------------------------ ConsoleMethod( GuiPlayerView, setModel, void, 4, 4, "playerView.setModel( raceGender, skin )" ) { argc; object->setPlayerModel( argv[2], argv[3] ); } ConsoleMethod( GuiPlayerView, setSeq, void, 3, 3, "playerView.setSeq( index )" ) { argc; object->setPlayerSeq( dAtoi(argv[2]) ); } //------------------------------------------------------------------------------ bool GuiPlayerView::onWake() { if ( !Parent::onWake() ) return( false ); mCameraMatrix.identity(); mCameraRot.set( 0, 0, 3.9 ); mCameraPos.set( 0, 1.75, 1.25 ); mCameraMatrix.setColumn( 3, mCameraPos ); mOrbitPos.set( 0, 0, 0 ); mOrbitDist = 3.5f; return( true ); } //------------------------------------------------------------------------------ void GuiPlayerView::onMouseDown( const GuiEvent &event ) { if ( !mActive || !mVisible || !mAwake ) return; mMouseState = Rotating; mLastMousePoint = event.mousePoint; mouseLock(); } //------------------------------------------------------------------------------ void GuiPlayerView::onMouseUp( const GuiEvent &/*event*/ ) { mouseUnlock(); mMouseState = None; } //------------------------------------------------------------------------------ void GuiPlayerView::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 ); } //------------------------------------------------------------------------------ void GuiPlayerView::onRightMouseDown( const GuiEvent &event ) { mMouseState = Zooming; mLastMousePoint = event.mousePoint; mouseLock(); } //------------------------------------------------------------------------------ void GuiPlayerView::onRightMouseUp( const GuiEvent &/*event*/ ) { mouseUnlock(); mMouseState = None; } //------------------------------------------------------------------------------ void GuiPlayerView::onRightMouseDragged( const GuiEvent &event ) { if ( mMouseState != Zooming ) return; S32 delta = event.mousePoint.y - mLastMousePoint.y; mLastMousePoint = event.mousePoint; mOrbitDist += ( delta * 0.01 ); } void GuiPlayerView::setPlayerSeq( S32 index ) { if( index > MaxAnimations || index < 0 ) return; mAnimationSeq = index; } //------------------------------------------------------------------------------ void GuiPlayerView::setPlayerModel( const char* shape, const char* skin ) { // Stuff random rotation values in... mCameraRot.z = gRandGen.randF(-4.14, -1); if ( mModel ) { delete mModel; mModel = NULL; } if ( mWeapon ) { delete mWeapon; mWeapon = NULL; } runThread = 0; Resource hShape = ResourceManager->load( shape); if ( !bool( hShape ) ) return; mModel = new TSShapeInstance( hShape, true ); AssertFatal( mModel, "ERROR! Failed to load warrior model!" ); // Set the skin: if ( !mModel->ownMaterialList() ) mModel->cloneMaterialList(); TSMaterialList* materialList = mModel->getMaterialList(); for ( U32 i = 0; i < materialList->mMaterialNames.size(); i++ ) { const char* name = materialList->mMaterialNames[i]; if ( !name ) continue; const U32 len = dStrlen( name ); AssertISV( len < 200, "GuiPlayerView::setPlayerModel - Skin name exceeds maximum length!" ); if ( len < 6 ) continue; const char* replace = dStrstr( name, "base." ); if ( !replace ) continue; char newName[256]; dStrncpy( newName, name, replace - name ); newName[replace - name] = 0; dStrcat( newName, skin ); dStrcat( newName, "." ); dStrcat( newName, replace + 5 ); TextureHandle test = TextureHandle( newName, MeshTexture, false ); if ( test.getGLName() ) materialList->mMaterials[i] = test; else materialList->mMaterials[i] = TextureHandle( name, MeshTexture, false ); } // Initialize camera values: mOrbitPos = mModel->getShape()->center; mMinOrbitDist = mModel->getShape()->radius; // // initialize run thread // S32 sequence = hShape->findSequence("dummyRun"); // // if( sequence != -1 ) // { // runThread = mModel->addThread(); // mModel->setPos( runThread, 0 ); // mModel->setTimeScale( runThread, 1 ); // mModel->setSequence( runThread, sequence, 0 ); // } // create a weapon for this dude Resource wShape; if( dStrcmp( shape, "heavy_male") == 0 || dStrcmp( shape, "bioderm_heavy") == 0 || dStrcmp( shape, "heavy_female") == 0 ) { wShape = ResourceManager->load( "shapes/weapon_mortar.dts" ); } else if( dStrcmp( shape, "medium_male") == 0 || dStrcmp( shape, "bioderm_medium") == 0 || dStrcmp( shape, "medium_female") == 0 ) { wShape = ResourceManager->load( "shapes/weapon_plasma.dts" ); } else { wShape = ResourceManager->load( "shapes/weapon_disc.dts" ); } if ( !bool( wShape ) ) return; pNode = hShape->findNode("mount0"); wNode = wShape->findNode("mountPoint"); mWeapon = new TSShapeInstance( wShape, true ); AssertFatal( mWeapon, "ERROR! Failed to load Weapon Model!" ); // the first time recording lastRenderTime = Platform::getVirtualMilliseconds(); } void GuiPlayerView::getWeaponTransform( MatrixF *mat ) { MatrixF weapTrans = mWeapon->mNodeTransforms[wNode]; Point3F weapOffset = -weapTrans.getPosition(); MatrixF modelTrans = mModel->mNodeTransforms[pNode]; modelTrans.mulP( weapOffset ); modelTrans.setPosition( weapOffset ); *mat = modelTrans; } //------------------------------------------------------------------------------ bool GuiPlayerView::processCameraQuery( CameraQuery* query ) { // Make sure the orbit distance is within the acceptable range: mOrbitDist = ( mOrbitDist < mMinOrbitDist ) ? mMinOrbitDist : ( ( mOrbitDist > MaxOrbitDist ) ? MaxOrbitDist : mOrbitDist ); // Adjust the camera so that we are still facing the model: Point3F vec; MatrixF xRot, zRot; 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; query->nearPlane = 0.1; query->farPlane = 2100.0; query->fov = 3.1415 / 3.5; mCameraMatrix.setColumn( 3, mCameraPos ); query->cameraMatrix = mCameraMatrix; return( true ); } //------------------------------------------------------------------------------ void GuiPlayerView::renderWorld( const RectI &updateRect ) { if ( !(bool)mModel /* || !(bool)mWeapon */) return; S32 time = Platform::getVirtualMilliseconds(); S32 dt = time - lastRenderTime; lastRenderTime = time; glClear( GL_DEPTH_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glEnable( GL_DEPTH_TEST ); glDepthFunc( GL_LEQUAL ); // animate and render in a run pose F32 fdt = dt; // mModel->advanceTime( fdt/1000.f, runThread ); mModel->animate(); mModel->render(); // render a weapon, if we have one if(mWeapon) { MatrixF mat; getWeaponTransform( &mat ); glPushMatrix(); dglMultMatrix( &mat ); mWeapon->render(); glPopMatrix(); } glDisable( GL_DEPTH_TEST ); dglSetClipRect( updateRect ); dglSetCanonicalState(); } void GuiPlayerView::onMouseEnter(const GuiEvent & event) { Con::executef(this, 1, "onMouseEnter"); } void GuiPlayerView::onMouseLeave(const GuiEvent & event) { Con::executef(this, 1, "onMouseLeave"); }