Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions Core/GameEngine/Include/GameClient/View.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
#include "Common/GameType.h"
#include "Common/Snapshot.h"
#include "Lib/BaseType.h"
#include "WW3D2/camera.h"
#include "WW3D2/coltype.h" ///< we don't generally do this, but we need the W3D collision types
#include "WWMath/plane.h"
#include "WWMath/wwmath.h"

#define DEFAULT_VIEW_WIDTH 640
Expand Down Expand Up @@ -120,11 +122,12 @@ class View : public Snapshot
Bool (*callback)( Drawable *draw, void *userData ),
void *userData ) = 0;

/** project the 4 corners of this view into the world and return each point as a parameter,
the world points are at the requested Z */
virtual void getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
/// Project the 4 corners of this view into the world and return each point as a parameter,
/// the world points are at the requested Z. Returns whether all corner view rays intersect
/// with the Z plane.
virtual PlaneClass::IntersectionResType getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
Coord3D *bottomRight, Coord3D *bottomLeft,
Real z );
Real z, ViewportClass viewPort = ViewportClass() );

virtual void setWidth( Int width ) { m_width = width; }
virtual Int getWidth() { return m_width; }
Expand Down Expand Up @@ -238,8 +241,12 @@ class View : public Snapshot

Bool worldToScreen( const Coord3D *w, ICoord2D *s ) { return worldToScreenTriReturn( w, s ) == WTS_INSIDE_FRUSTUM; } ///< Transform world coordinate "w" into screen coordinate "s"
virtual WorldToScreenReturn worldToScreenTriReturn(const Coord3D *w, ICoord2D *s ) = 0; ///< Like worldToScreen(), but with a more informative return value
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) = 0; ///< transform screen coord to a point on the 3D terrain
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) = 0; ///< transform screen point to world point at the specified world Z value

/// Transform screen point to the viewed world position on the 3D terrain. Returns true when intersection exists.
virtual Bool screenToTerrain( const ICoord2D *screen, Coord3D *world ) = 0;

/// Transform screen point to the viewed world position at the specified world Z height. Returns the type of the intersection.
virtual PlaneClass::IntersectionResType screenToWorldAtZ( const ICoord2D *screen, Coord3D *world, Real z ) = 0;

virtual void getLocation ( ViewLocation *location ); ///< write the view's current location in to the view location object
virtual void setLocation ( const ViewLocation *location ); ///< set the view's current location from to the view location object
Expand Down Expand Up @@ -403,8 +410,8 @@ class ViewDummy : public View
{
return WTS_INVALID;
}
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) override {}
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) override {}
virtual Bool screenToTerrain( const ICoord2D *screen, Coord3D *world ) override { return false; }
virtual PlaneClass::IntersectionResType screenToWorldAtZ( const ICoord2D *screen, Coord3D *world, Real z ) override { return PlaneClass::NO_INTERSECTION; }
virtual void drawView() override {}
virtual void updateView() override {}
virtual void stepView() override {}
Expand Down
18 changes: 10 additions & 8 deletions Core/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3900,7 +3900,8 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
// create the message and append arguments for a guard location
GameMessage *newMsg = TheMessageStream->appendMessage( GameMessage::MSG_DO_GUARD_POSITION );
Coord3D pos;
TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos );
if (!TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos ))
break;
newMsg->appendLocationArgument(pos);
newMsg->appendIntegerArgument(GUARDMODE_NORMAL);

Expand All @@ -3918,8 +3919,6 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if (TheGlobalData->m_useAlternateMouse
&& TheMouse->isClick(&m_mouseRightDragAnchor, &m_mouseRightDragLift, m_mouseRightDown, m_mouseRightUp))
{
Bool isPoint = (msg->getArgument(0)->pixelRegion.height() == 0 && msg->getArgument(0)->pixelRegion.width() == 0);

// NOTE: RIGHT_CLICK is not transmitted if AREA_SELECTION or DRAWABLE_PICKED occurs.
// If we see this msg, no object was clicked on, therefore clicked on ground.
// Issue move command to all currently selected objects.
Expand All @@ -3930,9 +3929,11 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage

// translate from screen coordinates to terrain coords
Coord3D pos;
TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos );
if (!TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos ))
break;

const CommandButton *command = TheInGameUI->getGUICommand();
Bool isPoint = (msg->getArgument(0)->pixelRegion.height() == 0 && msg->getArgument(0)->pixelRegion.width() == 0);
Bool controllable = TheInGameUI->areSelectedObjectsControllable()
|| (command && command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT);
if (isPoint && controllable)
Expand Down Expand Up @@ -3971,7 +3972,8 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
// create the message and append arguments for a guard location
GameMessage *newMsg = TheMessageStream->appendMessage( GameMessage::MSG_DO_GUARD_POSITION );
Coord3D pos;
TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos );
if (!TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos ))
break;
newMsg->appendLocationArgument(pos);
newMsg->appendIntegerArgument(GUARDMODE_NORMAL);

Expand All @@ -3985,8 +3987,6 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
}
case GameMessage::MSG_MOUSE_LEFT_CLICK:
{
Bool isPoint = (msg->getArgument(0)->pixelRegion.height() == 0 && msg->getArgument(0)->pixelRegion.width() == 0);

// NOTE: LEFT_CLICK is not transmitted if AREA_SELECTION or DRAWABLE_PICKED occurs.
// If we see this msg, no object was clicked on, therefore clicked on ground.
// Issue move command to all currently selected objects.
Expand All @@ -3997,7 +3997,8 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage

// translate from screen coordinates to terrain coords
Coord3D pos;
TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos );
if( !TheTacticalView->screenToTerrain( &msg->getArgument( 0 )->pixel, &pos ) )
break;

const CommandButton *command = TheInGameUI->getGUICommand();
// maintain this as the list of GUI button initiated commands that fire with left click in alt mouse mode
Expand All @@ -4012,6 +4013,7 @@ GameMessageDisposition CommandTranslator::translateGameMessage(const GameMessage
if ((TheGlobalData->m_useAlternateMouse) && (! isFiringGUICommand))
break;

Bool isPoint = (msg->getArgument(0)->pixelRegion.height() == 0 && msg->getArgument(0)->pixelRegion.width() == 0);
Bool controllable = TheInGameUI->areSelectedObjectsControllable()
|| (command && command->getCommandType() == GUI_COMMAND_SPECIAL_POWER_FROM_SHORTCUT);
if (isPoint && controllable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,20 +141,19 @@ static CommandStatus doFireWeaponCommand( const CommandButton *command, const IC
Coord3D world;

// translate the mouse location into world coords
TheTacticalView->screenToTerrain( mouse, &world );

// create the message and append arguments
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON_AT_LOCATION );
msg->appendIntegerArgument( command->getWeaponSlot() );
msg->appendLocationArgument( world );
msg->appendIntegerArgument( command->getMaxShotsToFire() );

//Also append the object ID (incase weapon doesn't like obstacles on land).
Object *target = validUnderCursor( mouse, command, PICK_TYPE_SELECTABLE );
ObjectID targetID = target ? target->getID() : INVALID_ID;
msg->appendObjectIDArgument( targetID );

if (TheTacticalView->screenToTerrain( mouse, &world ))
{
// create the message and append arguments
msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_WEAPON_AT_LOCATION );
msg->appendIntegerArgument( command->getWeaponSlot() );
msg->appendLocationArgument( world );
msg->appendIntegerArgument( command->getMaxShotsToFire() );

//Also append the object ID (incase weapon doesn't like obstacles on land).
Object *target = validUnderCursor( mouse, command, PICK_TYPE_SELECTABLE );
ObjectID targetID = target ? target->getID() : INVALID_ID;
msg->appendObjectIDArgument( targetID );
}
}
else if( BitIsSet( command->getOptions(), COMMAND_OPTION_NEED_OBJECT_TARGET ) )
{
Expand Down Expand Up @@ -233,7 +232,8 @@ static CommandStatus doGuardCommand( const CommandButton *command, GuardMode gua
if (BitIsSet( command->getOptions(), NEED_TARGET_POS ))
{
// translate the mouse location into world coords
TheTacticalView->screenToTerrain( mouse, &world );
if( !TheTacticalView->screenToTerrain( mouse, &world ) )
return COMMAND_COMPLETE;
}
else
{
Expand Down Expand Up @@ -277,7 +277,8 @@ static CommandStatus doAttackMoveCommand( const CommandButton *command, const IC

// convert mouse point to world coords
Coord3D world;
TheTacticalView->screenToTerrain( mouse, &world );
if( !TheTacticalView->screenToTerrain( mouse, &world ) )
return COMMAND_COMPLETE;

// send the message to set the rally point
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_DO_ATTACKMOVETO );
Expand Down Expand Up @@ -316,7 +317,8 @@ static CommandStatus doSetRallyPointCommand( const CommandButton *command, const

// convert mouse point to world coords
Coord3D world;
TheTacticalView->screenToTerrain( mouse, &world );
if( !TheTacticalView->screenToTerrain( mouse, &world ) )
return COMMAND_COMPLETE;

// send the message to set the rally point
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_SET_RALLY_POINT );
Expand All @@ -339,7 +341,8 @@ static CommandStatus doPlaceBeacon( const CommandButton *command, const ICoord2D

// convert mouse point to world coords
Coord3D world;
TheTacticalView->screenToTerrain( mouse, &world );
if( !TheTacticalView->screenToTerrain( mouse, &world ) )
return COMMAND_COMPLETE;

// send the message to set the rally point
GameMessage *msg = TheMessageStream->appendMessage( GameMessage::MSG_PLACE_BEACON );
Expand Down Expand Up @@ -414,14 +417,15 @@ GameMessageDisposition GUICommandTranslator::translateGameMessage(const GameMess
if (BitIsSet(command->getOptions(), NEED_TARGET_POS)) {
Coord3D worldPos;

TheTacticalView->screenToTerrain(&mouse, &worldPos);

GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_EVACUATE);
msg->appendLocationArgument(worldPos);
if( TheTacticalView->screenToTerrain(&mouse, &worldPos) )
{
GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_EVACUATE);
msg->appendLocationArgument(worldPos);

pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_EVACUATE );
pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), GameMessage::MSG_EVACUATE );

commandStatus = COMMAND_COMPLETE;
commandStatus = COMMAND_COMPLETE;
}
}

break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess
Coord3D world;

// translate mouse position to world position
TheTacticalView->screenToTerrain( &mouse, &world );
if( !TheTacticalView->screenToTerrain( &mouse, &world ) )
{
TheInGameUI->placeBuildAvailable( nullptr, nullptr );
break;
}

//
// placing things causes a dozer to go over and build it ... get the dozer in question
Expand Down Expand Up @@ -163,8 +167,7 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess
if (build && TheInGameUI->isPlacementAnchored())
{
GameMessage *placeMsg;
// Player *player = ThePlayerList->getLocalPlayer();
Coord3D world;
Coord3D worldStart, worldEnd;
Real angle;
ICoord2D anchorStart, anchorEnd;
Bool isLineBuild = TheBuildAssistant->isLineBuildTemplate( build );
Expand All @@ -176,7 +179,12 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess
TheInGameUI->getPlacementPoints( &anchorStart, &anchorEnd );

// translate the screen position of start to world target location
TheTacticalView->screenToTerrain( &anchorStart, &world );
if( !TheTacticalView->screenToTerrain( &anchorStart, &worldStart ) )
break;

if( isLineBuild )
if( !TheTacticalView->screenToTerrain( &anchorEnd, &worldEnd ) )
break;

Object *builderObj = TheGameLogic->findObjectByID( TheInGameUI->getPendingPlaceSourceObjectID() );

Expand Down Expand Up @@ -217,7 +225,7 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess

// check to see if this is a legal location to build something at
LegalBuildCode lbc;
lbc = TheBuildAssistant->isLocationLegalToBuild( &world,
lbc = TheBuildAssistant->isLocationLegalToBuild( &worldStart,
build,
angle,
BuildAssistant::USE_QUICK_PATHFIND |
Expand All @@ -244,7 +252,7 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess
//dozer/worker.
placeMsg = TheMessageStream->appendMessage( GameMessage::MSG_DO_SPECIAL_POWER_AT_LOCATION );
placeMsg->appendIntegerArgument( commandButton->getSpecialPowerTemplate()->getID() ); //The ID of the special power template.
placeMsg->appendLocationArgument( world ); //Position of special to be fired.
placeMsg->appendLocationArgument( worldStart ); //Position of special to be fired.
placeMsg->appendRealArgument( angle ); //Angle of special to be fired.
placeMsg->appendObjectIDArgument( INVALID_ID ); //There is no object in the way.
placeMsg->appendIntegerArgument( commandButton->getOptions() ); //Command button options.
Expand All @@ -268,15 +276,11 @@ GameMessageDisposition PlaceEventTranslator::translateGameMessage(const GameMess
placeMsg = TheMessageStream->appendMessage( GameMessage::MSG_DOZER_CONSTRUCT );

placeMsg->appendIntegerArgument(build->getTemplateID());
placeMsg->appendLocationArgument(world);
placeMsg->appendLocationArgument(worldStart);
placeMsg->appendRealArgument(angle);
if( isLineBuild )
{
Coord3D worldEnd;

TheTacticalView->screenToTerrain( &anchorEnd, &worldEnd );
placeMsg->appendLocationArgument( worldEnd );

}

pickAndPlayUnitVoiceResponse( TheInGameUI->getAllSelectedDrawables(), placeMsg->getType() );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,11 @@ GameMessageDisposition SelectionTranslator::translateGameMessage(const GameMessa
{
Coord3D position;

TheTacticalView->screenToTerrain( &pixel, &position );
mouseoverMessage = TheMessageStream->appendMessage( GameMessage::MSG_MOUSEOVER_LOCATION_HINT );
mouseoverMessage->appendLocationArgument( position );
if( TheTacticalView->screenToTerrain( &pixel, &position ) )
{
mouseoverMessage = TheMessageStream->appendMessage( GameMessage::MSG_MOUSEOVER_LOCATION_HINT );
mouseoverMessage->appendLocationArgument( position );
}
}
}

Expand Down
51 changes: 33 additions & 18 deletions Core/GameEngine/Source/GameClient/View.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,12 @@ Bool View::isUserControlLocked() const
/** project the 4 corners of this view into the world and return each point as a parameter,
the world points are at the requested Z */
//-------------------------------------------------------------------------------------------------
void View::getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
PlaneClass::IntersectionResType View::getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
Coord3D *bottomRight, Coord3D *bottomLeft,
Real z )
Real z, ViewportClass viewPort )
{
// sanity
if( topLeft == nullptr || topRight == nullptr || bottomRight == nullptr || bottomLeft == nullptr)
return;
return PlaneClass::NO_INTERSECTION;

ICoord2D screenTopLeft;
ICoord2D screenTopRight;
Expand All @@ -262,20 +261,36 @@ void View::getScreenCornerWorldPointsAtZ( Coord3D *topLeft, Coord3D *topRight,
// setup the screen coords for the 4 corners of the viewable display
getOrigin( &origin.x, &origin.y );

screenTopLeft.x = origin.x;
screenTopLeft.y = origin.y;
screenTopRight.x = origin.x + viewWidth;
screenTopRight.y = origin.y;
screenBottomRight.x = origin.x + viewWidth;
screenBottomRight.y = origin.y + viewHeight;
screenBottomLeft.x = origin.x;
screenBottomLeft.y = origin.y + viewHeight;

// project
screenToWorldAtZ( &screenTopLeft, topLeft, z );
screenToWorldAtZ( &screenTopRight, topRight, z );
screenToWorldAtZ( &screenBottomRight, bottomRight, z );
screenToWorldAtZ( &screenBottomLeft, bottomLeft, z );
screenTopLeft.x = origin.x + viewWidth * viewPort.Min.X;
screenTopLeft.y = origin.y + viewHeight * viewPort.Min.Y;
screenTopRight.x = origin.x + viewWidth * viewPort.Max.X;
screenTopRight.y = origin.y + viewHeight * viewPort.Min.Y;
screenBottomRight.x = origin.x + viewWidth * viewPort.Max.X;
screenBottomRight.y = origin.y + viewHeight * viewPort.Max.Y;
screenBottomLeft.x = origin.x + viewWidth * viewPort.Min.X;
screenBottomLeft.y = origin.y + viewHeight * viewPort.Max.Y;

PlaneClass::IntersectionResType combinedResult = PlaneClass::INSIDE_SEGMENT;
PlaneClass::IntersectionResType individualResults[4];
individualResults[0] = screenToWorldAtZ( &screenTopLeft, topLeft, z );
individualResults[1] = screenToWorldAtZ( &screenTopRight, topRight, z );
individualResults[2] = screenToWorldAtZ( &screenBottomRight, bottomRight, z );
individualResults[3] = screenToWorldAtZ( &screenBottomLeft, bottomLeft, z );

for( Int i = 0; i < 4; ++i )
{
if( individualResults[i] == PlaneClass::NO_INTERSECTION )
{
combinedResult = PlaneClass::NO_INTERSECTION;
break;
}
if( individualResults[i] == PlaneClass::OUTSIDE_LINE )
{
combinedResult = PlaneClass::OUTSIDE_LINE;
}
}

return combinedResult;
}

// ------------------------------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ class W3DView : public View, public SubsystemInterface
virtual void setFieldOfView( Real angle ) override; ///< Set the horizontal field of view angle

virtual WorldToScreenReturn worldToScreenTriReturn( const Coord3D *w, ICoord2D *s ) override; ///< Transform world coordinate "w" into screen coordinate "s"
virtual void screenToTerrain( const ICoord2D *screen, Coord3D *world ) override; ///< transform screen coord to a point on the 3D terrain
virtual void screenToWorldAtZ( const ICoord2D *s, Coord3D *w, Real z ) override; ///< transform screen point to world point at the specified world Z value
virtual Bool screenToTerrain( const ICoord2D *screen, Coord3D *world ) override;
virtual PlaneClass::IntersectionResType screenToWorldAtZ( const ICoord2D *screen, Coord3D *world, Real z ) override;

CameraClass *get3DCamera() const { return m_3DCamera; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ class WorldHeightMap : public RefCountClass,
Int getXExtent() {return m_width;} ///<number of vertices in x
Int getYExtent() {return m_height;} ///<number of vertices in y

Region2D getDrawRegion2D();

Int getDrawOrgX() {return m_drawOriginX;}
Int getDrawOrgY() {return m_drawOriginY;}

Expand Down
Loading
Loading