mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Pick objects by cursor (#1296)
* Initial Commit * Move GetRayFrom2DPosition to los.cpp * Quick formatting * Reogranize conversions a bit * Update ViewHandler.cpp * Remove unued temp variables * Update Changes.txt --------- Co-authored-by: Sezz <sezzary@outlook.com>
This commit is contained in:
parent
dacc2c8f6a
commit
14fa1d39aa
11 changed files with 96 additions and 32 deletions
|
@ -32,8 +32,9 @@ Version 1.3
|
|||
Lua API changes:
|
||||
* Add Lara:GetInteractedMoveable() which returns currently interacted moveable by Lara.
|
||||
* Add Moveable:SetStatus() to set the current status of the moveable.
|
||||
* Add View:GetCameraPosition(), View:GetCameraTarget() and View:GetCameraRoom() functions.
|
||||
* Add Room:GetColor() to get room's ambient light color.
|
||||
* Add Util.PickMoveableByDisplayPosition() and Util.PickStaticByDisplayPosition() functions.
|
||||
* Add View.GetCameraPosition(), View.GetCameraTarget() and View:GetCameraRoom() functions.
|
||||
|
||||
Version 1.2
|
||||
===========
|
||||
|
|
|
@ -633,52 +633,55 @@ static bool DoRayBox(const GameVector& origin, const GameVector& target, const G
|
|||
return true;
|
||||
}
|
||||
|
||||
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObject)
|
||||
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObjectID)
|
||||
{
|
||||
ClosestItem = NO_LOS_ITEM;
|
||||
ClosestDist = SQUARE(target->x - origin->x) + SQUARE(target->y - origin->y) + SQUARE(target->z - origin->z);
|
||||
|
||||
for (int r = 0; r < NumberLosRooms; ++r)
|
||||
{
|
||||
auto* room = &g_Level.Rooms[LosRooms[r]];
|
||||
auto& room = g_Level.Rooms[LosRooms[r]];
|
||||
|
||||
auto pose = Pose::Zero;
|
||||
|
||||
for (int m = 0; m < room->mesh.size(); m++)
|
||||
if (mesh)
|
||||
{
|
||||
auto* meshp = &room->mesh[m];
|
||||
|
||||
if (meshp->flags & StaticMeshFlags::SM_VISIBLE)
|
||||
for (int m = 0; m < room.mesh.size(); m++)
|
||||
{
|
||||
auto bounds = GetBoundsAccurate(*meshp, false);
|
||||
pose = Pose(meshp->pos.Position, EulerAngles(0, meshp->pos.Orientation.y, 0));
|
||||
auto& meshp = room.mesh[m];
|
||||
|
||||
if (DoRayBox(*origin, *target, bounds, pose, *vec, -1 - meshp->staticNumber))
|
||||
if (meshp.flags & StaticMeshFlags::SM_VISIBLE)
|
||||
{
|
||||
*mesh = meshp;
|
||||
target->RoomNumber = LosRooms[r];
|
||||
auto bounds = GetBoundsAccurate(meshp, false);
|
||||
pose = Pose(meshp.pos.Position, EulerAngles(0, meshp.pos.Orientation.y, 0));
|
||||
|
||||
if (DoRayBox(*origin, *target, bounds, pose, *vec, -1 - meshp.staticNumber))
|
||||
{
|
||||
*mesh = &meshp;
|
||||
target->RoomNumber = LosRooms[r];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (short linkNumber = room->itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem)
|
||||
for (short linkNumber = room.itemNumber; linkNumber != NO_ITEM; linkNumber = g_Level.Items[linkNumber].NextItem)
|
||||
{
|
||||
auto* item = &g_Level.Items[linkNumber];
|
||||
const auto& item = g_Level.Items[linkNumber];
|
||||
|
||||
if ((item->Status == ITEM_DEACTIVATED) || (item->Status == ITEM_INVISIBLE))
|
||||
if (item.Status == ITEM_DEACTIVATED || item.Status == ITEM_INVISIBLE)
|
||||
continue;
|
||||
|
||||
if ((priorityObject != GAME_OBJECT_ID::ID_NO_OBJECT) && (item->ObjectNumber != priorityObject))
|
||||
if (priorityObjectID != GAME_OBJECT_ID::ID_NO_OBJECT && item.ObjectNumber != priorityObjectID)
|
||||
continue;
|
||||
|
||||
if ((item->ObjectNumber != ID_LARA) && (Objects[item->ObjectNumber].collision == nullptr))
|
||||
if (item.ObjectNumber != ID_LARA && Objects[item.ObjectNumber].collision == nullptr)
|
||||
continue;
|
||||
|
||||
if ((item->ObjectNumber == ID_LARA) && (priorityObject != ID_LARA))
|
||||
if (item.ObjectNumber == ID_LARA && priorityObjectID != ID_LARA)
|
||||
continue;
|
||||
|
||||
auto bounds = GameBoundingBox(item);
|
||||
pose = Pose(item->Pose.Position, EulerAngles(0, item->Pose.Orientation.y, 0));
|
||||
auto bounds = GameBoundingBox(&item);
|
||||
pose = Pose(item.Pose.Position, EulerAngles(0, item.Pose.Orientation.y, 0));
|
||||
|
||||
if (DoRayBox(*origin, *target, bounds, pose, *vec, linkNumber))
|
||||
target->RoomNumber = LosRooms[r];
|
||||
|
@ -808,3 +811,14 @@ std::optional<Vector3> GetStaticObjectLos(const Vector3& origin, int roomNumber,
|
|||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::pair<GameVector, GameVector> GetRayFrom2DPosition(Vector2 screenPos)
|
||||
{
|
||||
auto pos = g_Renderer.GetRay(screenPos);
|
||||
|
||||
auto origin = GameVector(pos.first, Camera.pos.RoomNumber);
|
||||
auto target = GameVector(pos.second, Camera.pos.RoomNumber);
|
||||
|
||||
LOS(&origin, &target);
|
||||
return std::pair<GameVector, GameVector>(origin, target);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ constexpr auto NO_LOS_ITEM = INT_MAX;
|
|||
|
||||
bool LOS(const GameVector* origin, GameVector* target);
|
||||
bool GetTargetOnLOS(GameVector* origin, GameVector* target, bool drawTarget, bool isFiring);
|
||||
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObject = GAME_OBJECT_ID::ID_NO_OBJECT);
|
||||
int ObjectOnLOS2(GameVector* origin, GameVector* target, Vector3i* vec, MESH_INFO** mesh, GAME_OBJECT_ID priorityObjectID = GAME_OBJECT_ID::ID_NO_OBJECT);
|
||||
bool LOSAndReturnTarget(GameVector* origin, GameVector* target, int push);
|
||||
|
||||
std::optional<Vector3> GetStaticObjectLos(const Vector3& origin, int roomNumber, const Vector3& dir, float dist, bool onlySolid);
|
||||
std::pair<GameVector, GameVector> GetRayFrom2DPosition(Vector2 screenPos);
|
||||
|
|
|
@ -259,8 +259,7 @@ namespace TEN::Entities::Creatures::TR3
|
|||
TriggerDynamicLight(origin.x, origin.y, origin.z, 20, 0, 255, 255);
|
||||
|
||||
auto hitPos = Vector3i::Zero;
|
||||
MESH_INFO* mesh = nullptr;
|
||||
if (ObjectOnLOS2(&origin, &target, &hitPos, &mesh, ID_LARA) == creature.Enemy->Index)
|
||||
if (ObjectOnLOS2(&origin, &target, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index)
|
||||
{
|
||||
if (creature.Enemy->HitPoints <= PUNA_LIGHTNING_DAMAGE)
|
||||
{
|
||||
|
|
|
@ -169,9 +169,8 @@ namespace TEN::Entities::Creatures::TR5
|
|||
auto origin2 = GameVector(origin, item.RoomNumber);
|
||||
auto target2 = GameVector(target);
|
||||
auto hitPos = Vector3i::Zero;
|
||||
MESH_INFO* hitJoint = nullptr;
|
||||
|
||||
if (ObjectOnLOS2(&origin2, &target2, &hitPos, &hitJoint, ID_LARA) == creature.Enemy->Index)
|
||||
if (ObjectOnLOS2(&origin2, &target2, &hitPos, nullptr, ID_LARA) == creature.Enemy->Index)
|
||||
{
|
||||
if (LaraItem->HitPoints <= HEAVY_GUARD_RAYGUN_PLAYER_BURN_HEALTH)
|
||||
{
|
||||
|
|
|
@ -400,13 +400,12 @@ namespace TEN::Entities::Creatures::TR5
|
|||
farAway = 2;
|
||||
|
||||
auto hitPos = Vector3i::Zero;
|
||||
MESH_INFO* hitMesh = nullptr;
|
||||
|
||||
auto start = GameVector(guardian->fireArcs[i]->pos1.x, guardian->fireArcs[i]->pos1.y, guardian->fireArcs[i]->pos1.z);
|
||||
start.RoomNumber = item->RoomNumber;
|
||||
auto end = GameVector(guardian->fireArcs[i]->pos4.x, guardian->fireArcs[i]->pos4.y, guardian->fireArcs[i]->pos4.z, 0);
|
||||
|
||||
if (ObjectOnLOS2(&start, &end, &hitPos, &hitMesh, ID_LARA) == LaraItem->Index)
|
||||
if (ObjectOnLOS2(&start, &end, &hitPos, nullptr, ID_LARA) == LaraItem->Index)
|
||||
{
|
||||
if (LaraItem->Effect.Type != EffectType::Smoke)
|
||||
{
|
||||
|
|
|
@ -759,9 +759,10 @@ namespace TEN::Renderer
|
|||
void SetTextureOrDefault(Texture2D& texture, std::wstring path);
|
||||
std::string GetDefaultAdapterName();
|
||||
|
||||
Vector2i GetScreenResolution() const;
|
||||
Vector2i GetScreenResolution() const;
|
||||
std::optional<Vector2> Get2DPosition(const Vector3& pos) const;
|
||||
Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero);
|
||||
std::pair<Vector3, Vector3> GetRay(const Vector2& pos) const;
|
||||
Vector3 GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset = Vector3::Zero);
|
||||
|
||||
void AddDisplaySprite(const RendererSprite& sprite, const Vector2& pos2D, short orient, const Vector2& size, const Vector4& color,
|
||||
int priority, BLEND_MODES blendMode, const Vector2& aspectCorrection, RenderView& renderView);
|
||||
|
|
|
@ -553,6 +553,14 @@ namespace TEN::Renderer
|
|||
return TEN::Utils::ConvertNDCTo2DPosition(Vector2(point));
|
||||
}
|
||||
|
||||
std::pair<Vector3, Vector3> Renderer11::GetRay(const Vector2& pos) const
|
||||
{
|
||||
auto nearPoint = m_viewportToolkit.Unproject(Vector3(pos.x, pos.y, 0.0f), gameCamera.Camera.Projection, gameCamera.Camera.View, Matrix::Identity);
|
||||
auto farPoint = m_viewportToolkit.Unproject(Vector3(pos.x, pos.y, 1.0f), gameCamera.Camera.Projection, gameCamera.Camera.View, Matrix::Identity);
|
||||
|
||||
return std::pair<Vector3, Vector3>(nearPoint, farPoint);
|
||||
}
|
||||
|
||||
Vector3 Renderer11::GetAbsEntityBonePosition(int itemNumber, int jointIndex, const Vector3& relOffset)
|
||||
{
|
||||
auto* rendererItem = &m_items[itemNumber];
|
||||
|
|
|
@ -320,6 +320,8 @@ static constexpr char ScriptReserved_ThrowAwayTorch[] = "ThrowAwayTorch";
|
|||
static constexpr char ScriptReserved_SetWeaponType[] = "SetWeaponType";
|
||||
static constexpr char ScriptReserved_TorchIsLit[] = "TorchIsLit";
|
||||
static constexpr char ScriptReserved_PrintLog[] = "PrintLog";
|
||||
static constexpr char ScriptReserved_PickMoveable[] = "PickMoveableByDisplayPosition";
|
||||
static constexpr char ScriptReserved_PickStatic[] = "PickStaticByDisplayPosition";
|
||||
static constexpr char ScriptReserved_GetDisplayPosition[] = "GetDisplayPosition";
|
||||
static constexpr char ScriptReserved_GetCursorDisplayPosition[] = "GetCursorDisplayPosition"; // Deprecated
|
||||
static constexpr char ScriptReserved_GetMouseDisplayPosition[] = "GetMouseDisplayPosition";
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "Scripting/Internal/ReservedScriptNames.h"
|
||||
#include "Scripting/Internal/ScriptAssert.h"
|
||||
#include "Scripting/Internal/ScriptUtil.h"
|
||||
#include "Scripting/Internal/TEN/Objects/Moveable/MoveableObject.h"
|
||||
#include "Scripting/Internal/TEN/Objects/Static/StaticObject.h"
|
||||
#include "Scripting/Internal/TEN/Util/LevelLog.h"
|
||||
#include "Scripting/Internal/TEN/Vec2/Vec2.h"
|
||||
#include "Scripting/Internal/TEN/Vec3/Vec3.h"
|
||||
|
@ -39,10 +41,9 @@ namespace TEN::Scripting::Util
|
|||
auto vector0 = posA.ToGameVector();
|
||||
auto vector1 = posB.ToGameVector();
|
||||
|
||||
MESH_INFO* meshPtr = nullptr;
|
||||
auto vector = Vector3i::Zero;
|
||||
return (LOS(&vector0, &vector1) &&
|
||||
ObjectOnLOS2(&vector0, &vector1, &vector, &meshPtr) == NO_LOS_ITEM);
|
||||
ObjectOnLOS2(&vector0, &vector1, &vector, nullptr) == NO_LOS_ITEM);
|
||||
}
|
||||
|
||||
///Calculate the distance between two positions.
|
||||
|
@ -129,6 +130,43 @@ namespace TEN::Scripting::Util
|
|||
return std::make_tuple(resX, resY);
|
||||
}
|
||||
|
||||
/// Pick a moveable by the given display position.
|
||||
// @function PickMoveableByDisplayPosition
|
||||
// @tparam Vec2 Display space position in percent.
|
||||
// @treturn Objects.Moveable Picked moveable (nil if no moveable was found under the cursor).
|
||||
static sol::optional <std::unique_ptr<Moveable>> PickMoveable(const Vec2& screenPos)
|
||||
{
|
||||
auto realScreenPos = PercentToScreen(screenPos.x, screenPos.y);
|
||||
auto ray = GetRayFrom2DPosition(Vector2(int(std::get<0>(realScreenPos)), int(std::get<1>(realScreenPos))));
|
||||
|
||||
auto vector = Vector3i::Zero;
|
||||
int itemNumber = ObjectOnLOS2(&ray.first, &ray.second, &vector, nullptr, GAME_OBJECT_ID::ID_LARA);
|
||||
|
||||
if (itemNumber == NO_LOS_ITEM || itemNumber < 0)
|
||||
return sol::nullopt;
|
||||
|
||||
return std::make_unique<Moveable>(itemNumber);
|
||||
}
|
||||
|
||||
/// Pick a static mesh by the given display position.
|
||||
// @function PickStaticByDisplayPosition
|
||||
// @tparam Vec2 Display space position in percent.
|
||||
// @treturn Objects.Static Picked static mesh (nil if no static mesh was found under the cursor).
|
||||
static sol::optional <std::unique_ptr<Static>> PickStatic(const Vec2& screenPos)
|
||||
{
|
||||
auto realScreenPos = PercentToScreen(screenPos.x, screenPos.y);
|
||||
auto ray = GetRayFrom2DPosition(Vector2(int(std::get<0>(realScreenPos)), int(std::get<1>(realScreenPos))));
|
||||
|
||||
MESH_INFO* mesh = nullptr;
|
||||
auto vector = Vector3i::Zero;
|
||||
int itemNumber = ObjectOnLOS2(&ray.first, &ray.second, &vector, &mesh, GAME_OBJECT_ID::ID_LARA);
|
||||
|
||||
if (itemNumber == NO_LOS_ITEM || itemNumber >= 0)
|
||||
return sol::nullopt;
|
||||
|
||||
return std::make_unique<Static>(*mesh);
|
||||
}
|
||||
|
||||
/// Write messages within the Log file
|
||||
//@advancedDesc
|
||||
//For native Lua handling of errors, see the official Lua website:
|
||||
|
@ -162,6 +200,8 @@ namespace TEN::Scripting::Util
|
|||
tableUtil.set_function(ScriptReserved_CalculateDistance, &CalculateDistance);
|
||||
tableUtil.set_function(ScriptReserved_CalculateHorizontalDistance, &CalculateHorizontalDistance);
|
||||
tableUtil.set_function(ScriptReserved_GetDisplayPosition, &GetDisplayPosition);
|
||||
tableUtil.set_function(ScriptReserved_PickMoveable, &PickMoveable);
|
||||
tableUtil.set_function(ScriptReserved_PickStatic, &PickStatic);
|
||||
tableUtil.set_function(ScriptReserved_PercentToScreen, &PercentToScreen);
|
||||
tableUtil.set_function(ScriptReserved_ScreenToPercent, &ScreenToPercent);
|
||||
tableUtil.set_function(ScriptReserved_PrintLog, &PrintLog);
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace TEN::Scripting::View
|
|||
//@tparam float angle in degrees (clamped to [10, 170])
|
||||
tableView.set_function(ScriptReserved_SetFOV, &SetFOV);
|
||||
|
||||
//Get field of view.
|
||||
///Get field of view.
|
||||
//@function GetFOV
|
||||
//@treturn float current FOV angle in degrees
|
||||
tableView.set_function(ScriptReserved_GetFOV, &GetFOV);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue