refactor: Extract object selection into a separate class
This commit is contained in:
parent
391ffb1823
commit
3c1d94d876
14 changed files with 234 additions and 131 deletions
|
@ -66,14 +66,14 @@ set(HEADERS
|
||||||
src/game/console.h
|
src/game/console.h
|
||||||
src/game/dialog.h
|
src/game/dialog.h
|
||||||
src/game/game.h
|
src/game/game.h
|
||||||
src/game/gui/classsel.h
|
src/game/gui/classselect.h
|
||||||
src/game/gui/container.h
|
src/game/gui/container.h
|
||||||
src/game/gui/debug.h
|
src/game/gui/debug.h
|
||||||
src/game/gui/dialog.h
|
src/game/gui/dialog.h
|
||||||
src/game/gui/equip.h
|
src/game/gui/equip.h
|
||||||
src/game/gui/hud.h
|
src/game/gui/hud.h
|
||||||
src/game/gui/mainmenu.h
|
src/game/gui/mainmenu.h
|
||||||
src/game/gui/portraitsel.h
|
src/game/gui/portraitselect.h
|
||||||
src/game/gui/target.h
|
src/game/gui/target.h
|
||||||
src/game/module.h
|
src/game/module.h
|
||||||
src/game/multiplayer/area.h
|
src/game/multiplayer/area.h
|
||||||
|
@ -93,6 +93,7 @@ set(HEADERS
|
||||||
src/game/object/spatial.h
|
src/game/object/spatial.h
|
||||||
src/game/object/trigger.h
|
src/game/object/trigger.h
|
||||||
src/game/object/waypoint.h
|
src/game/object/waypoint.h
|
||||||
|
src/game/objectselect.h
|
||||||
src/game/pathfinder.h
|
src/game/pathfinder.h
|
||||||
src/game/paths.h
|
src/game/paths.h
|
||||||
src/game/player.h
|
src/game/player.h
|
||||||
|
@ -199,7 +200,7 @@ set(SOURCES
|
||||||
src/game/console.cpp
|
src/game/console.cpp
|
||||||
src/game/dialog.cpp
|
src/game/dialog.cpp
|
||||||
src/game/game.cpp
|
src/game/game.cpp
|
||||||
src/game/gui/classsel.cpp
|
src/game/gui/classselect.cpp
|
||||||
src/game/gui/colors.cpp
|
src/game/gui/colors.cpp
|
||||||
src/game/gui/container.cpp
|
src/game/gui/container.cpp
|
||||||
src/game/gui/debug.cpp
|
src/game/gui/debug.cpp
|
||||||
|
@ -207,7 +208,7 @@ set(SOURCES
|
||||||
src/game/gui/equip.cpp
|
src/game/gui/equip.cpp
|
||||||
src/game/gui/hud.cpp
|
src/game/gui/hud.cpp
|
||||||
src/game/gui/mainmenu.cpp
|
src/game/gui/mainmenu.cpp
|
||||||
src/game/gui/portraitsel.cpp
|
src/game/gui/portraitselect.cpp
|
||||||
src/game/gui/target.cpp
|
src/game/gui/target.cpp
|
||||||
src/game/module.cpp
|
src/game/module.cpp
|
||||||
src/game/multiplayer/area.cpp
|
src/game/multiplayer/area.cpp
|
||||||
|
@ -226,6 +227,7 @@ set(SOURCES
|
||||||
src/game/object/spatial.cpp
|
src/game/object/spatial.cpp
|
||||||
src/game/object/trigger.cpp
|
src/game/object/trigger.cpp
|
||||||
src/game/object/waypoint.cpp
|
src/game/object/waypoint.cpp
|
||||||
|
src/game/objectselect.cpp
|
||||||
src/game/pathfinder.cpp
|
src/game/pathfinder.cpp
|
||||||
src/game/paths.cpp
|
src/game/paths.cpp
|
||||||
src/game/player.cpp
|
src/game/player.cpp
|
||||||
|
|
|
@ -56,13 +56,11 @@ namespace reone {
|
||||||
|
|
||||||
namespace game {
|
namespace game {
|
||||||
|
|
||||||
|
|
||||||
static const float kDefaultFieldOfView = 75.0f;
|
static const float kDefaultFieldOfView = 75.0f;
|
||||||
static const float kDrawDebugDistance = 64.0f;
|
static const float kDrawDebugDistance = 64.0f;
|
||||||
static const float kPartyMemberFollowDistance = 4.0f;
|
static const float kPartyMemberFollowDistance = 4.0f;
|
||||||
static const float kMaxDistanceToTestCollision = 64.0f;
|
static const float kMaxDistanceToTestCollision = 64.0f;
|
||||||
static const float kElevationTestZ = 1024.0f;
|
static const float kElevationTestZ = 1024.0f;
|
||||||
static const float kSelectionDistance = 64.0f;
|
|
||||||
|
|
||||||
static const char kPartyLeaderTag[] = "party-leader";
|
static const char kPartyLeaderTag[] = "party-leader";
|
||||||
static const char kPartyMember1Tag[] = "party-member-1";
|
static const char kPartyMember1Tag[] = "party-member-1";
|
||||||
|
@ -80,7 +78,8 @@ Area::Area(
|
||||||
_objectFactory(objectFactory),
|
_objectFactory(objectFactory),
|
||||||
_sceneGraph(sceneGraph),
|
_sceneGraph(sceneGraph),
|
||||||
_opts(opts),
|
_opts(opts),
|
||||||
_collisionDetector(this) {
|
_collisionDetector(this),
|
||||||
|
_objectSelector(this) {
|
||||||
|
|
||||||
_cameraAspect = opts.width / static_cast<float>(opts.height);
|
_cameraAspect = opts.width / static_cast<float>(opts.height);
|
||||||
}
|
}
|
||||||
|
@ -149,7 +148,7 @@ void Area::loadPTH() {
|
||||||
_sceneGraph->addRoot(aabb);
|
_sceneGraph->addRoot(aabb);
|
||||||
}
|
}
|
||||||
|
|
||||||
_pathfinding.load(paths, pointZ);
|
_pathfinder.load(paths, pointZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Area::loadARE(const GffStruct &are) {
|
void Area::loadARE(const GffStruct &are) {
|
||||||
|
@ -387,11 +386,11 @@ bool Area::handle(const SDL_Event &event) {
|
||||||
bool Area::handleKeyDown(const SDL_KeyboardEvent &event) {
|
bool Area::handleKeyDown(const SDL_KeyboardEvent &event) {
|
||||||
switch (event.keysym.scancode) {
|
switch (event.keysym.scancode) {
|
||||||
case SDL_SCANCODE_Q:
|
case SDL_SCANCODE_Q:
|
||||||
selectNextObject(true);
|
_objectSelector.selectNext(true);
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case SDL_SCANCODE_E:
|
case SDL_SCANCODE_E:
|
||||||
selectNextObject();
|
_objectSelector.selectNext();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -399,62 +398,6 @@ bool Area::handleKeyDown(const SDL_KeyboardEvent &event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Area::selectNextObject(bool reverse) {
|
|
||||||
static vector<uint32_t> selectables;
|
|
||||||
|
|
||||||
selectables.clear();
|
|
||||||
getSelectableObjects(selectables);
|
|
||||||
|
|
||||||
if (selectables.empty()) {
|
|
||||||
_selectedObjectId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (_selectedObjectId == -1) {
|
|
||||||
_selectedObjectId = selectables.front();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (reverse) {
|
|
||||||
auto selected = std::find(selectables.rbegin(), selectables.rend(), _selectedObjectId);
|
|
||||||
if (selected != selectables.rend()) {
|
|
||||||
selected++;
|
|
||||||
}
|
|
||||||
_selectedObjectId = selected != selectables.rend() ? *selected : selectables.back();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
auto selected = std::find(selectables.begin(), selectables.end(), _selectedObjectId);
|
|
||||||
if (selected != selectables.end()) {
|
|
||||||
selected++;
|
|
||||||
}
|
|
||||||
_selectedObjectId = selected != selectables.end() ? *selected : selectables.front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Area::getSelectableObjects(vector<uint32_t> &ids) const {
|
|
||||||
static vector<pair<uint32_t, float>> selectables;
|
|
||||||
|
|
||||||
glm::vec3 origin(_player->position());
|
|
||||||
selectables.clear();
|
|
||||||
|
|
||||||
for (auto &object : _objects) {
|
|
||||||
if (!object->isSelectable() || object.get() == _player.get()) continue;
|
|
||||||
|
|
||||||
shared_ptr<ModelSceneNode> model(object->model());
|
|
||||||
if (!model || !model->isVisible()) continue;
|
|
||||||
|
|
||||||
float dist = object->distanceTo(origin);
|
|
||||||
if (dist > kSelectionDistance) continue;
|
|
||||||
|
|
||||||
selectables.push_back(make_pair(object->id(), dist));
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(selectables.begin(), selectables.end(), [](const pair<uint32_t, float> &left, const pair<uint32_t, float> &right) {
|
|
||||||
return left.second < right.second;
|
|
||||||
});
|
|
||||||
for (auto &selectable : selectables) {
|
|
||||||
ids.push_back(selectable.first);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Area::getElevationAt(const glm::vec2 &position, Room *&room, float &z) const {
|
bool Area::getElevationAt(const glm::vec2 &position, Room *&room, float &z) const {
|
||||||
RaycastProperties props;
|
RaycastProperties props;
|
||||||
props.origin = glm::vec3(position, kElevationTestZ);
|
props.origin = glm::vec3(position, kElevationTestZ);
|
||||||
|
@ -490,7 +433,7 @@ void Area::update(const UpdateContext &updateCtx) {
|
||||||
object->update(updateCtx);
|
object->update(updateCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSelection();
|
_objectSelector.update();
|
||||||
|
|
||||||
_sceneGraph->prepare(updateCtx.cameraPosition);
|
_sceneGraph->prepare(updateCtx.cameraPosition);
|
||||||
}
|
}
|
||||||
|
@ -649,19 +592,6 @@ void Area::updateRoomVisibility() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Area::selectNearestObject() {
|
|
||||||
_selectedObjectId = -1;
|
|
||||||
selectNextObject();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Area::hilight(uint32_t objectId) {
|
|
||||||
_hilightedObjectId = objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Area::select(uint32_t objectId) {
|
|
||||||
_selectedObjectId = objectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpatialObject *Area::getObjectAt(int x, int y) const {
|
SpatialObject *Area::getObjectAt(int x, int y) const {
|
||||||
Camera *camera = getCamera();
|
Camera *camera = getCamera();
|
||||||
shared_ptr<CameraSceneNode> sceneNode(camera->sceneNode());
|
shared_ptr<CameraSceneNode> sceneNode(camera->sceneNode());
|
||||||
|
@ -685,50 +615,30 @@ SpatialObject *Area::getObjectAt(int x, int y) const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Area::updateSelection() {
|
|
||||||
if (_hilightedObjectId != -1) {
|
|
||||||
shared_ptr<SpatialObject> object(find(_hilightedObjectId));
|
|
||||||
if (!object || !object->isSelectable()) {
|
|
||||||
_hilightedObjectId = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_selectedObjectId != -1) {
|
|
||||||
shared_ptr<SpatialObject> object(find(_selectedObjectId));
|
|
||||||
if (!object || !object->isSelectable()) {
|
|
||||||
_selectedObjectId = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Area::fill(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
void Area::fill(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
||||||
addPartyMemberPortrait(_partyLeader, guiCtx);
|
addPartyMemberPortrait(_partyLeader, guiCtx);
|
||||||
addPartyMemberPortrait(_partyMember1, guiCtx);
|
addPartyMemberPortrait(_partyMember1, guiCtx);
|
||||||
addPartyMemberPortrait(_partyMember2, guiCtx);
|
addPartyMemberPortrait(_partyMember2, guiCtx);
|
||||||
|
|
||||||
if (_hilightedObjectId != -1) {
|
int hilightedObjectId = _objectSelector.hilightedObjectId();
|
||||||
glm::vec3 coords(getSelectableScreenCoords(_hilightedObjectId, updateCtx));
|
if (hilightedObjectId != -1) {
|
||||||
|
glm::vec3 coords(getSelectableScreenCoords(hilightedObjectId, updateCtx));
|
||||||
if (coords.z < 1.0f) {
|
if (coords.z < 1.0f) {
|
||||||
guiCtx.target.hasHilighted = true;
|
guiCtx.target.hasHilighted = true;
|
||||||
guiCtx.target.hilightedScreenCoords = coords;
|
guiCtx.target.hilightedScreenCoords = coords;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_selectedObjectId != -1) {
|
int selectedObjectId = _objectSelector.selectedObjectId();
|
||||||
glm::vec3 coords(getSelectableScreenCoords(_selectedObjectId, updateCtx));
|
if (selectedObjectId != -1) {
|
||||||
|
glm::vec3 coords(getSelectableScreenCoords(selectedObjectId, updateCtx));
|
||||||
if (coords.z < 1.0f) {
|
if (coords.z < 1.0f) {
|
||||||
guiCtx.target.hasSelected = true;
|
guiCtx.target.hasSelected = true;
|
||||||
guiCtx.target.selectedScreenCoords = coords;
|
guiCtx.target.selectedScreenCoords = coords;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addDebugInfo(updateCtx, guiCtx);
|
addDebugInfo(updateCtx, guiCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Area::addPartyMemberPortrait(const shared_ptr<SpatialObject> &object, GuiContext &ctx) {
|
|
||||||
if (object) {
|
|
||||||
ctx.hud.partyPortraits.push_back(static_cast<Creature &>(*object).portrait());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 Area::getSelectableScreenCoords(uint32_t objectId, const UpdateContext &ctx) const {
|
glm::vec3 Area::getSelectableScreenCoords(uint32_t objectId, const UpdateContext &ctx) const {
|
||||||
static glm::vec4 viewport(0.0f, 0.0f, 1.0f, 1.0f);
|
static glm::vec4 viewport(0.0f, 0.0f, 1.0f, 1.0f);
|
||||||
|
|
||||||
|
@ -738,6 +648,12 @@ glm::vec3 Area::getSelectableScreenCoords(uint32_t objectId, const UpdateContext
|
||||||
return glm::project(position, ctx.view, ctx.projection, viewport);
|
return glm::project(position, ctx.view, ctx.projection, viewport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Area::addPartyMemberPortrait(const shared_ptr<SpatialObject> &object, GuiContext &ctx) {
|
||||||
|
if (object) {
|
||||||
|
ctx.hud.partyPortraits.push_back(static_cast<Creature &>(*object).portrait());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Area::addDebugInfo(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
void Area::addDebugInfo(const UpdateContext &updateCtx, GuiContext &guiCtx) {
|
||||||
if (getDebugMode() == DebugMode::GameObjects) {
|
if (getDebugMode() == DebugMode::GameObjects) {
|
||||||
guiCtx.debug.objects.clear();
|
guiCtx.debug.objects.clear();
|
||||||
|
@ -816,10 +732,6 @@ Camera *Area::getCamera() const {
|
||||||
return _cameraType == CameraType::ThirdPerson ? _thirdPersonCamera.get() : static_cast<Camera *>(_firstPersonCamera.get());
|
return _cameraType == CameraType::ThirdPerson ? _thirdPersonCamera.get() : static_cast<Camera *>(_firstPersonCamera.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t Area::selectedObjectId() const {
|
|
||||||
return _selectedObjectId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CameraStyle &Area::cameraStyle() const {
|
const CameraStyle &Area::cameraStyle() const {
|
||||||
return _cameraStyle;
|
return _cameraStyle;
|
||||||
}
|
}
|
||||||
|
@ -848,6 +760,10 @@ ThirdPersonCamera *Area::thirdPersonCamera() {
|
||||||
return _thirdPersonCamera.get();
|
return _thirdPersonCamera.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ObjectSelector &Area::objectSelector() {
|
||||||
|
return _objectSelector;
|
||||||
|
}
|
||||||
|
|
||||||
shared_ptr<SpatialObject> Area::player() const {
|
shared_ptr<SpatialObject> Area::player() const {
|
||||||
return _player;
|
return _player;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "object/placeable.h"
|
#include "object/placeable.h"
|
||||||
#include "object/trigger.h"
|
#include "object/trigger.h"
|
||||||
#include "object/waypoint.h"
|
#include "object/waypoint.h"
|
||||||
|
#include "objectselect.h"
|
||||||
#include "pathfinder.h"
|
#include "pathfinder.h"
|
||||||
#include "room.h"
|
#include "room.h"
|
||||||
|
|
||||||
|
@ -67,9 +68,6 @@ public:
|
||||||
bool moveCreatureTowards(Creature &creature, const glm::vec2 &dest, bool run, float dt);
|
bool moveCreatureTowards(Creature &creature, const glm::vec2 &dest, bool run, float dt);
|
||||||
void updateTriggers(const Creature &creature);
|
void updateTriggers(const Creature &creature);
|
||||||
void updateRoomVisibility();
|
void updateRoomVisibility();
|
||||||
void selectNearestObject();
|
|
||||||
void hilight(uint32_t objectId);
|
|
||||||
void select(uint32_t objectId);
|
|
||||||
SpatialObject *getObjectAt(int x, int y) const;
|
SpatialObject *getObjectAt(int x, int y) const;
|
||||||
|
|
||||||
void update3rdPersonCameraTarget();
|
void update3rdPersonCameraTarget();
|
||||||
|
@ -90,7 +88,6 @@ public:
|
||||||
void loadState(const GameState &state);
|
void loadState(const GameState &state);
|
||||||
|
|
||||||
// General getters
|
// General getters
|
||||||
uint32_t selectedObjectId() const;
|
|
||||||
const CameraStyle &cameraStyle() const;
|
const CameraStyle &cameraStyle() const;
|
||||||
CameraType cameraType() const;
|
CameraType cameraType() const;
|
||||||
const std::string &music() const;
|
const std::string &music() const;
|
||||||
|
@ -98,6 +95,7 @@ public:
|
||||||
const ObjectList &objects() const;
|
const ObjectList &objects() const;
|
||||||
const CollisionDetector &collisionDetector() const;
|
const CollisionDetector &collisionDetector() const;
|
||||||
ThirdPersonCamera *thirdPersonCamera();
|
ThirdPersonCamera *thirdPersonCamera();
|
||||||
|
ObjectSelector &objectSelector();
|
||||||
|
|
||||||
// Party getters
|
// Party getters
|
||||||
std::shared_ptr<SpatialObject> player() const;
|
std::shared_ptr<SpatialObject> player() const;
|
||||||
|
@ -159,7 +157,8 @@ private:
|
||||||
resources::GameVersion _version { resources::GameVersion::KotOR };
|
resources::GameVersion _version { resources::GameVersion::KotOR };
|
||||||
render::GraphicsOptions _opts;
|
render::GraphicsOptions _opts;
|
||||||
CollisionDetector _collisionDetector;
|
CollisionDetector _collisionDetector;
|
||||||
Pathfinder _pathfinding;
|
Pathfinder _pathfinder;
|
||||||
|
ObjectSelector _objectSelector;
|
||||||
std::string _name;
|
std::string _name;
|
||||||
RoomMap _rooms;
|
RoomMap _rooms;
|
||||||
std::unique_ptr<resources::Visibility> _visibility;
|
std::unique_ptr<resources::Visibility> _visibility;
|
||||||
|
@ -169,8 +168,6 @@ private:
|
||||||
std::list<DelayedCommand> _delayed;
|
std::list<DelayedCommand> _delayed;
|
||||||
std::map<int, UserDefinedEvent> _events;
|
std::map<int, UserDefinedEvent> _events;
|
||||||
int _eventCounter { 0 };
|
int _eventCounter { 0 };
|
||||||
int _hilightedObjectId { -1 };
|
|
||||||
int _selectedObjectId { -1 };
|
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
std::function<void(const std::string &, const std::string &)> _onModuleTransition;
|
std::function<void(const std::string &, const std::string &)> _onModuleTransition;
|
||||||
|
@ -184,12 +181,9 @@ private:
|
||||||
void selectNextPathPoint(Creature::Path &path);
|
void selectNextPathPoint(Creature::Path &path);
|
||||||
void updateCreaturePath(Creature &creature, const glm::vec3 &dest);
|
void updateCreaturePath(Creature &creature, const glm::vec3 &dest);
|
||||||
bool getElevationAt(const glm::vec2 &position, Room *&room, float &z) const;
|
bool getElevationAt(const glm::vec2 &position, Room *&room, float &z) const;
|
||||||
void updateSelection();
|
|
||||||
void addPartyMemberPortrait(const std::shared_ptr<SpatialObject> &object, GuiContext &ctx);
|
void addPartyMemberPortrait(const std::shared_ptr<SpatialObject> &object, GuiContext &ctx);
|
||||||
glm::vec3 getSelectableScreenCoords(uint32_t objectId, const UpdateContext &ctx) const;
|
|
||||||
void addDebugInfo(const UpdateContext &updateCtx, GuiContext &guiCtx);
|
void addDebugInfo(const UpdateContext &updateCtx, GuiContext &guiCtx);
|
||||||
void selectNextObject(bool reverse = false);
|
glm::vec3 getSelectableScreenCoords(uint32_t objectId, const UpdateContext &ctx) const;
|
||||||
void getSelectableObjects(std::vector<uint32_t> &ids) const;
|
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ void Area::selectNextPathPoint(Creature::Path &path) {
|
||||||
|
|
||||||
void Area::updateCreaturePath(Creature &creature, const glm::vec3 &dest) {
|
void Area::updateCreaturePath(Creature &creature, const glm::vec3 &dest) {
|
||||||
const glm::vec3 &origin = creature.position();
|
const glm::vec3 &origin = creature.position();
|
||||||
vector<glm::vec3> points(_pathfinding.findPath(origin, dest));
|
vector<glm::vec3> points(_pathfinder.findPath(origin, dest));
|
||||||
uint32_t now = SDL_GetTicks();
|
uint32_t now = SDL_GetTicks();
|
||||||
|
|
||||||
creature.setPath(dest, move(points), now);
|
creature.setPath(dest, move(points), now);
|
||||||
|
|
|
@ -107,7 +107,6 @@ bool CollisionDetector::rayTestRooms(const RaycastProperties &props, RaycastResu
|
||||||
|
|
||||||
for (auto &pair : _area->rooms()) {
|
for (auto &pair : _area->rooms()) {
|
||||||
Room &room = *pair.second;
|
Room &room = *pair.second;
|
||||||
if (!room.visible()) continue;
|
|
||||||
|
|
||||||
const Walkmesh *walkmesh = room.walkmesh();
|
const Walkmesh *walkmesh = room.walkmesh();
|
||||||
if (!walkmesh) continue;
|
if (!walkmesh) continue;
|
||||||
|
|
|
@ -24,14 +24,14 @@
|
||||||
#include "../render/window.h"
|
#include "../render/window.h"
|
||||||
#include "../resources/types.h"
|
#include "../resources/types.h"
|
||||||
|
|
||||||
#include "gui/classsel.h"
|
#include "gui/classselect.h"
|
||||||
#include "gui/container.h"
|
#include "gui/container.h"
|
||||||
#include "gui/debug.h"
|
#include "gui/debug.h"
|
||||||
#include "gui/dialog.h"
|
#include "gui/dialog.h"
|
||||||
#include "gui/equip.h"
|
#include "gui/equip.h"
|
||||||
#include "gui/hud.h"
|
#include "gui/hud.h"
|
||||||
#include "gui/mainmenu.h"
|
#include "gui/mainmenu.h"
|
||||||
#include "gui/portraitsel.h"
|
#include "gui/portraitselect.h"
|
||||||
#include "gui/target.h"
|
#include "gui/target.h"
|
||||||
|
|
||||||
#include "area.h"
|
#include "area.h"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "classsel.h"
|
#include "classselect.h"
|
||||||
|
|
||||||
#include "../../resources/resources.h"
|
#include "../../resources/resources.h"
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "portraitsel.h"
|
#include "portraitselect.h"
|
||||||
|
|
||||||
#include "../../core/random.h"
|
#include "../../core/random.h"
|
||||||
#include "../../resources/resources.h"
|
#include "../../resources/resources.h"
|
|
@ -163,7 +163,7 @@ bool Module::handle(const SDL_Event &event) {
|
||||||
|
|
||||||
bool Module::handleMouseMotion(const SDL_MouseMotionEvent &event) {
|
bool Module::handleMouseMotion(const SDL_MouseMotionEvent &event) {
|
||||||
const SpatialObject *object = _area->getObjectAt(event.x, event.y);
|
const SpatialObject *object = _area->getObjectAt(event.x, event.y);
|
||||||
_area->hilight(object ? object->id() : -1);
|
_area->objectSelector().hilight(object ? object->id() : -1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -175,9 +175,9 @@ bool Module::handleMouseButtonUp(const SDL_MouseButtonEvent &event) {
|
||||||
}
|
}
|
||||||
debug(boost::format("Object '%s' clicked on") % object->tag());
|
debug(boost::format("Object '%s' clicked on") % object->tag());
|
||||||
|
|
||||||
uint32_t selectedObjectId = _area->selectedObjectId();
|
uint32_t selectedObjectId = _area->objectSelector().selectedObjectId();
|
||||||
if (object->id() != selectedObjectId) {
|
if (object->id() != selectedObjectId) {
|
||||||
_area->select(object->id());
|
_area->objectSelector().select(object->id());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
138
src/game/objectselect.cpp
Normal file
138
src/game/objectselect.cpp
Normal file
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2020 Vsevolod Kremianskii
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "objectselect.h"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include "glm/vec3.hpp"
|
||||||
|
|
||||||
|
#include "area.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
using namespace reone::render;
|
||||||
|
|
||||||
|
namespace reone {
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
|
||||||
|
static const float kSelectionDistance = 64.0f;
|
||||||
|
|
||||||
|
ObjectSelector::ObjectSelector(Area *area) : _area(area) {
|
||||||
|
if (!area) {
|
||||||
|
throw invalid_argument("Area must not be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::update() {
|
||||||
|
if (_hilightedObjectId != -1) {
|
||||||
|
shared_ptr<SpatialObject> object(_area->find(_hilightedObjectId));
|
||||||
|
if (!object || !object->isSelectable()) {
|
||||||
|
_hilightedObjectId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_selectedObjectId != -1) {
|
||||||
|
shared_ptr<SpatialObject> object(_area->find(_selectedObjectId));
|
||||||
|
if (!object || !object->isSelectable()) {
|
||||||
|
_selectedObjectId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::selectNext(bool reverse) {
|
||||||
|
static vector<uint32_t> selectables;
|
||||||
|
|
||||||
|
selectables.clear();
|
||||||
|
getSelectableObjects(selectables);
|
||||||
|
|
||||||
|
if (selectables.empty()) {
|
||||||
|
_selectedObjectId = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_selectedObjectId == -1) {
|
||||||
|
_selectedObjectId = selectables.front();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (reverse) {
|
||||||
|
auto selected = std::find(selectables.rbegin(), selectables.rend(), _selectedObjectId);
|
||||||
|
if (selected != selectables.rend()) {
|
||||||
|
selected++;
|
||||||
|
}
|
||||||
|
_selectedObjectId = selected != selectables.rend() ? *selected : selectables.back();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
auto selected = std::find(selectables.begin(), selectables.end(), _selectedObjectId);
|
||||||
|
if (selected != selectables.end()) {
|
||||||
|
selected++;
|
||||||
|
}
|
||||||
|
_selectedObjectId = selected != selectables.end() ? *selected : selectables.front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::getSelectableObjects(vector<uint32_t> &ids) const {
|
||||||
|
static vector<pair<uint32_t, float>> selectables;
|
||||||
|
|
||||||
|
shared_ptr<SpatialObject> player(_area->player());
|
||||||
|
|
||||||
|
glm::vec3 origin(player->position());
|
||||||
|
selectables.clear();
|
||||||
|
|
||||||
|
for (auto &object : _area->objects()) {
|
||||||
|
if (!object->isSelectable() || object.get() == player.get()) continue;
|
||||||
|
|
||||||
|
shared_ptr<ModelSceneNode> model(object->model());
|
||||||
|
if (!model || !model->isVisible()) continue;
|
||||||
|
|
||||||
|
float dist = object->distanceTo(origin);
|
||||||
|
if (dist > kSelectionDistance) continue;
|
||||||
|
|
||||||
|
selectables.push_back(make_pair(object->id(), dist));
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(selectables.begin(), selectables.end(), [](const pair<uint32_t, float> &left, const pair<uint32_t, float> &right) {
|
||||||
|
return left.second < right.second;
|
||||||
|
});
|
||||||
|
for (auto &selectable : selectables) {
|
||||||
|
ids.push_back(selectable.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::selectNearest() {
|
||||||
|
_selectedObjectId = -1;
|
||||||
|
selectNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::hilight(uint32_t objectId) {
|
||||||
|
_hilightedObjectId = objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObjectSelector::select(uint32_t objectId) {
|
||||||
|
_selectedObjectId = objectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectSelector::hilightedObjectId() const {
|
||||||
|
return _hilightedObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObjectSelector::selectedObjectId() const {
|
||||||
|
return _selectedObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace game
|
||||||
|
|
||||||
|
} // namespace reone
|
54
src/game/objectselect.h
Normal file
54
src/game/objectselect.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2020 Vsevolod Kremianskii
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace reone {
|
||||||
|
|
||||||
|
namespace game {
|
||||||
|
|
||||||
|
class Area;
|
||||||
|
|
||||||
|
class ObjectSelector {
|
||||||
|
public:
|
||||||
|
ObjectSelector(Area *area);
|
||||||
|
|
||||||
|
void update();
|
||||||
|
void selectNext(bool reverse = false);
|
||||||
|
void getSelectableObjects(std::vector<uint32_t> &ids) const;
|
||||||
|
void selectNearest();
|
||||||
|
void hilight(uint32_t objectId);
|
||||||
|
void select(uint32_t objectId);
|
||||||
|
|
||||||
|
int hilightedObjectId() const;
|
||||||
|
int selectedObjectId() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Area *_area { nullptr };
|
||||||
|
int _hilightedObjectId { -1 };
|
||||||
|
int _selectedObjectId { -1 };
|
||||||
|
|
||||||
|
ObjectSelector(const ObjectSelector &) = delete;
|
||||||
|
ObjectSelector &operator=(const ObjectSelector &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace game
|
||||||
|
|
||||||
|
} // namespace reone
|
|
@ -131,7 +131,7 @@ void Player::update(float dt) {
|
||||||
_creature->setMovementType(MovementType::Run);
|
_creature->setMovementType(MovementType::Run);
|
||||||
_module->area()->update3rdPersonCameraTarget();
|
_module->area()->update3rdPersonCameraTarget();
|
||||||
_area->updateRoomVisibility();
|
_area->updateRoomVisibility();
|
||||||
_area->selectNearestObject();
|
_area->objectSelector().selectNearest();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_creature->setMovementType(MovementType::None);
|
_creature->setMovementType(MovementType::None);
|
||||||
|
|
Loading…
Reference in a new issue