From 1af9aa074e7067074cbe14fd501bc42ebb46434e Mon Sep 17 00:00:00 2001 From: Matei Date: Mon, 5 Sep 2005 19:48:28 +0000 Subject: [PATCH] Added initial version of building placement cursor, which can be shown with the startPlacing(templateName) JS function. Also activated depth test for selection outlines so they don't overlap units. This was SVN commit r2667. --- source/main.cpp | 1 + source/ps/GameSetup/GameSetup.cpp | 12 ++++ source/ps/Interact.cpp | 113 +++++++++++++++++++++++++++++- source/ps/Interact.h | 24 +++++++ source/scripting/ScriptGlue.cpp | 28 ++++++++ source/simulation/Entity.cpp | 2 +- 6 files changed, 178 insertions(+), 2 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 9c94096b4b..e00d13b61e 100755 --- a/source/main.cpp +++ b/source/main.cpp @@ -214,6 +214,7 @@ static void Frame() // TODO Where does GameView end and other things begin? g_Mouseover.update( TimeSinceLastFrame ); g_Selection.update(); + g_BuildingPlacer.update( TimeSinceLastFrame ); PROFILE_END( "selection and interaction ui" ); PROFILE_START( "sound update" ); diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 3d527475f6..882b848247 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -244,10 +244,21 @@ void Render() } PROFILE_START( "render selection" ); + glEnable( GL_DEPTH_TEST ); g_Mouseover.renderSelectionOutlines(); g_Selection.renderSelectionOutlines(); + glDisable( GL_DEPTH_TEST ); PROFILE_END( "render selection" ); + PROFILE_START( "render building placement cursor" ); + if( g_BuildingPlacer.m_active ) + { + //glEnable( GL_DEPTH_TEST ); + g_BuildingPlacer.render(); + //glDisable( GL_DEPTH_TEST ); + } + PROFILE_END( "render building placement cursor" ); + glPopAttrib(); } else @@ -790,6 +801,7 @@ void Init(int argc, char* argv[], bool setup_gfx, bool setup_gui) new CPathfindEngine; new CSelectedEntities; new CMouseoverEntities; + new CBuildingPlacer; new CSessionManager; diff --git a/source/ps/Interact.cpp b/source/ps/Interact.cpp index 58cb28e57d..c70e56a0bb 100755 --- a/source/ps/Interact.cpp +++ b/source/ps/Interact.cpp @@ -14,6 +14,7 @@ #include "BoundingObjects.h" #include "Unit.h" #include "Model.h" +#include "simulation/BaseEntityCollection.h" #include "scripting/GameEvents.h" extern CConsole* g_Console; @@ -748,6 +749,12 @@ void MouseButtonUpHandler(const SDL_Event *ev, int clicks) switch( ev->button.button ) { case SDL_BUTTON_LEFT: + if( g_BuildingPlacer.m_active ) + { + g_BuildingPlacer.mouseReleased(); + break; + } + if (customSelectionMode) break; @@ -777,6 +784,12 @@ void MouseButtonUpHandler(const SDL_Event *ev, int clicks) else g_Mouseover.setSelection(); break; + case SDL_BUTTON_RIGHT: + if( g_BuildingPlacer.m_active ) + { + g_BuildingPlacer.cancel(); + break; + } } } @@ -904,11 +917,15 @@ int interactInputHandler( const SDL_Event* ev ) button_down_x = ev->button.x; button_down_y = ev->button.y; button_down_time = get_time(); + if( g_BuildingPlacer.m_active ) + { + g_BuildingPlacer.mousePressed(); + } break; } break; case SDL_MOUSEMOTION: - if( !g_Mouseover.isBandbox() && button_down ) + if( !g_Mouseover.isBandbox() && button_down && !g_BuildingPlacer.m_active ) { int deltax = ev->motion.x - button_down_x; int deltay = ev->motion.y - button_down_y; @@ -953,3 +970,97 @@ void ResetInteraction() { customSelectionMode = false; } + + +bool CBuildingPlacer::activate(CStrW& templateName) +{ + if(m_active) + { + return false; + } + + m_templateName = templateName; + m_active = true; + m_clicked = false; + m_dragged = false; + m_angle = 0; + m_timeSinceClick = 0; + //g_Console->InsertMessage( L"BuildingPlacer: Activated with %ls", m_templateName.c_str() ); + return true; +} + +void CBuildingPlacer::mousePressed() +{ + CCamera &g_Camera=*g_Game->GetView()->GetCamera(); + clickPos = g_Camera.GetWorldCoordinates(); + m_clicked = true; + //g_Console->InsertMessage( L"BuildingPlacer: Clicked (%f, %f, %f)", clickPos.X, clickPos.Y, clickPos.Z ); +} + +void CBuildingPlacer::mouseReleased() +{ + m_active = false; // do it first in case we fail + CBaseEntity* baseEntity = g_EntityTemplateCollection.getTemplate( m_templateName ); + //g_Console->InsertMessage( L"BuildingPlacer: Created %ls at (%f, %f, %f) [%f]", + // m_templateName.c_str(), clickPos.X, clickPos.Y, clickPos.Z, m_angle ); + HEntity ent = g_EntityManager.create( baseEntity, clickPos, m_angle ); + ent->SetPlayer(g_Game->GetLocalPlayer()); +} + +void CBuildingPlacer::cancel() +{ + //g_Console->InsertMessage( L"BuildingPlacer: Cancelled"); + m_active = false; +} + +void CBuildingPlacer::update( float timeStep ) +{ + if(!m_active) + return; + + if(m_clicked) + { + m_timeSinceClick += timeStep; + CCamera &g_Camera=*g_Game->GetView()->GetCamera(); + CVector3D pos = g_Camera.GetWorldCoordinates(); + CVector3D dif = pos - clickPos; + float x = dif.X, z = dif.Z; + if(x*x + z*z < 3*3) { + if(m_dragged || m_timeSinceClick > 0.2f) + { + m_angle += timeStep * PI; + } + } + else + { + m_dragged = true; + m_angle = atan2(x, z); + } + } +} + +void CBuildingPlacer::render() +{ + if(!m_active) + return; + + CVector3D pos; + if(m_clicked) + { + pos = clickPos; + } + else + { + CCamera &g_Camera=*g_Game->GetView()->GetCamera(); + pos = g_Camera.GetWorldCoordinates(); + } + + glBegin(GL_LINE_STRIP); + glColor3f(1,1,1); + glVertex3f(pos.X, pos.Y+6, pos.Z); + glColor3f(1,1,1); + glVertex3f(pos.X, pos.Y, pos.Z); + glColor3f(1,1,1); + glVertex3f(pos.X + 3*sin(m_angle), pos.Y, pos.Z + 3*cos(m_angle)); + glEnd(); +} \ No newline at end of file diff --git a/source/ps/Interact.h b/source/ps/Interact.h index 32ee751ca7..712433e652 100755 --- a/source/ps/Interact.h +++ b/source/ps/Interact.h @@ -113,6 +113,29 @@ struct CMouseoverEntities : public Singleton void stopBandbox(); }; +struct CBuildingPlacer : public Singleton +{ + CBuildingPlacer() + { + m_active = false; + } + + CStrW m_templateName; + bool m_active; + bool m_clicked; + bool m_dragged; + float m_angle; + float m_timeSinceClick; + CVector3D clickPos; + + bool activate( CStrW& templateName ); + void mousePressed(); + void mouseReleased(); + void cancel(); + void update( float timeStep ); + void render(); +}; + bool isMouseoverType( CEntity* ev, void* userdata ); bool isOnScreen( CEntity* ev, void* userdata ); @@ -123,4 +146,5 @@ int interactInputHandler( const SDL_Event* ev ); #define g_Selection CSelectedEntities::GetSingleton() #define g_Mouseover CMouseoverEntities::GetSingleton() +#define g_BuildingPlacer CBuildingPlacer::GetSingleton() diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp index f9390191e2..abe5d89a62 100755 --- a/source/scripting/ScriptGlue.cpp +++ b/source/scripting/ScriptGlue.cpp @@ -741,6 +741,33 @@ JSBool getGlobal( JSContext* cx, JSObject* globalObject, uint argc, jsval* argv, return( JS_TRUE ); } +// Activates the building placement cursor for placing a building. +// params: templateName - the name of the entity to place. +// returns: true if cursor was activated, false if cursor was already active. +JSBool startPlacing( JSContext* cx, JSObject* globalObject, uint argc, jsval* argv, jsval* rval ) +{ + CStrW name; + if(argc == 0) { + name = L"hele_ho"; // save some typing during testing + } + else { + try + { + name = g_ScriptingHost.ValueToUCString( argv[0] ); + } + catch( PSERROR_Scripting_ConversionFailed ) + { + *rval = JSVAL_NULL; + JS_ReportError( cx, "Invalid template name argument" ); + return( JS_TRUE ); + } + } + + *rval = g_BuildingPlacer.activate(name) ? JS_TRUE : JS_FALSE; + + return( JS_TRUE ); +} + //----------------------------------------------------------------------------- // function table @@ -765,6 +792,7 @@ JSFunctionSpec ScriptFunctionTable[] = JS_FUNC(getEntityByHandle, getEntityByHandle, 1) JS_FUNC(getEntityTemplate, getEntityTemplate, 1) JS_FUNC(issueCommand, issueCommand, 2) + JS_FUNC(startPlacing, startPlacing, 1) // Camera JS_FUNC(setCameraTarget, setCameraTarget, 1) diff --git a/source/simulation/Entity.cpp b/source/simulation/Entity.cpp index 3be0dd2d67..fc2cd9cc35 100755 --- a/source/simulation/Entity.cpp +++ b/source/simulation/Entity.cpp @@ -664,7 +664,7 @@ void CEntity::renderSelectionOutline( float alpha ) const SPlayerColour& col = m_player->GetColour(); glColor3f( col.r, col.g, col.b ); } - + glBegin( GL_LINE_LOOP ); CVector3D pos = m_graphics_position;