refactor: Extract object selection into a separate class

This commit is contained in:
Vsevolod Kremianskii 2020-10-02 14:27:33 +07:00
parent 391ffb1823
commit 3c1d94d876
14 changed files with 234 additions and 131 deletions

View file

@ -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

View file

@ -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;
} }

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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"

View file

@ -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"

View file

@ -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"

View file

@ -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
View 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
View 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

View file

@ -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);