Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+2845
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,482 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/entityid.h>
|
||||
#include <osg/BoundingBox>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <osg/Vec3>
|
||||
#include <osg/Vec4>
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Geode>
|
||||
#include <dtEntity/message.h>
|
||||
|
||||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QPolygonF>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include "viewerinterface.h"
|
||||
#include "cameraviewposition.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class IconComponent;
|
||||
class TextComponent;
|
||||
class ViewWidget;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct OBB
|
||||
{
|
||||
osg::Matrix mMatrix;
|
||||
osg::Matrix mMatrixInverse;
|
||||
osg::BoundingBox mBB;
|
||||
QPolygonF mPoly;
|
||||
dtEntity::StringId mBuilding = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct BuildingData
|
||||
{
|
||||
std::string mDescription;
|
||||
std::string mDisplayName;
|
||||
std::string mFeatureId;
|
||||
std::string mFileName;
|
||||
std::string mBuildingXMLPath;
|
||||
double mX = 0;
|
||||
double mY = 0;
|
||||
double mZ = 0;
|
||||
double mOrientation = 0;
|
||||
int mBuildingGroup = 0;
|
||||
bool properlySpawned = false;
|
||||
bool roomBBoxedLoaded = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct BuildingLevel
|
||||
{
|
||||
// entity id of visible entity in building view
|
||||
dtEntity::EntityId mEntityId;
|
||||
|
||||
// floorId of xml file (-1 for floor_-1; 2 for floor_2...)
|
||||
int mFloorId;
|
||||
|
||||
// height of lowest walkable area in level above building origin
|
||||
float mHeightAboveGround;
|
||||
|
||||
// transforms from building local space to level local space
|
||||
osg::Matrix mLocalToLevel;
|
||||
|
||||
// bounding box of level in world space (untransformed by view mode)
|
||||
osg::BoundingBox mBounds;
|
||||
|
||||
BuildingLevel(dtEntity::EntityId eid, int floorId, float h, const osg::BoundingBox &bb)
|
||||
: mEntityId(eid), mFloorId(floorId), mHeightAboveGround(h), mBounds(bb)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct PlayerPosition
|
||||
{
|
||||
osg::Vec2d mPosition;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct PlayerDisplay
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
IconComponent *mIcon = nullptr;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Device
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
std::string mPath;
|
||||
osg::Vec3d mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct DeviceDisplay
|
||||
{
|
||||
Device *mDevice = nullptr;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Name
|
||||
{
|
||||
dtEntity::EntityId mWorldPlayerId;
|
||||
std::string mtext;
|
||||
std::string mdistext;
|
||||
std::string mbuilding;
|
||||
osg::Vec3d mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct NameDisplay
|
||||
{
|
||||
Name* mName = nullptr;
|
||||
dtEntity::EntityId mWorldPlayerId = 0;
|
||||
dtEntity::EntityId mLocalPlayerId = 0;
|
||||
bool visible = false;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class Shot
|
||||
{
|
||||
public:
|
||||
Shot(const int32_t id,
|
||||
const osg::Vec3d& shooterPos,
|
||||
const osg::Vec3d& targetPos,
|
||||
int buildingIdSrc,
|
||||
int rommNumberSrc,
|
||||
int buildingIdDst,
|
||||
int rommNumberDst,
|
||||
int lineType,
|
||||
const osg::Vec4& color,
|
||||
unsigned int duration_s,
|
||||
unsigned int durationMax_s,
|
||||
double simTimeCreated) :
|
||||
mId(id)
|
||||
, mShooterPos(shooterPos)
|
||||
, mTargetPos(targetPos)
|
||||
, mBuildingIdSrc(buildingIdSrc)
|
||||
, mRoomNumberSrc(rommNumberSrc)
|
||||
, mBuildingIdDst(buildingIdDst)
|
||||
, mRoomNumberDst(rommNumberDst)
|
||||
, mLineType(lineType)
|
||||
, mColor(color)
|
||||
, mDuration_s(duration_s)
|
||||
, m_DurationMax_s(durationMax_s)
|
||||
, mSimTimeCreated(simTimeCreated) {
|
||||
|
||||
}
|
||||
|
||||
void setDisplayTime(unsigned int duration_s) {
|
||||
if(duration_s > m_DurationMax_s)
|
||||
m_DurationMax_s = duration_s;
|
||||
mDuration_s = duration_s;
|
||||
}
|
||||
double simTimeCreated() const {
|
||||
return mSimTimeCreated;
|
||||
}
|
||||
|
||||
double displayTime() const {
|
||||
return mSimTimeCreated + mDuration_s;
|
||||
}
|
||||
|
||||
double lifeTime() const {
|
||||
return mSimTimeCreated + (m_DurationMax_s*2);
|
||||
}
|
||||
|
||||
const osg::Vec3d& getShooterPos() const { return mShooterPos; }
|
||||
const osg::Vec3d& getTargetPos() const { return mTargetPos; }
|
||||
int getBuildingIdSrc() const { return mBuildingIdSrc; }
|
||||
double getSimeTimeCreated() const { return mSimTimeCreated; }
|
||||
int getRoomNumberSrc() const { return mRoomNumberSrc; }
|
||||
int getBuildingIdDst() const { return mBuildingIdDst; }
|
||||
int getRoomNumberDst() const { return mRoomNumberDst; }
|
||||
int getDuration() const { return mDuration_s; }
|
||||
int getLineType() const { return mLineType; }
|
||||
|
||||
const osg::Vec4& getColor() const { return mColor; }
|
||||
int32_t getId() const { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId;
|
||||
osg::Vec3d mShooterPos;
|
||||
osg::Vec3d mTargetPos;
|
||||
int mBuildingIdSrc;
|
||||
int mRoomNumberSrc;
|
||||
int mBuildingIdDst;
|
||||
int mRoomNumberDst;
|
||||
int mLineType;
|
||||
osg::Vec4 mColor;
|
||||
unsigned int mDuration_s, m_DurationMax_s;
|
||||
double mSimTimeCreated;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShotDisplay
|
||||
{
|
||||
Shot *mShot = nullptr;
|
||||
osg::ref_ptr<osg::Geode> mGeode;
|
||||
};
|
||||
|
||||
// fwd decl
|
||||
struct Building;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// \brief The BuildingDisplay struct
|
||||
|
||||
class OrthoMotionModelComponent;
|
||||
|
||||
struct BuildingDisplay
|
||||
{
|
||||
// context id of this display
|
||||
unsigned int mContextId = 0;
|
||||
|
||||
// local entity holding building data
|
||||
dtEntity::EntityId mAttachPointId = 0;
|
||||
|
||||
// all levels in building
|
||||
std::vector<BuildingLevel> mLevels;
|
||||
|
||||
// combined bounding box of all levels of building without viewmode transformation
|
||||
osg::BoundingBox mWorldBounds;
|
||||
|
||||
// combined bounding box of all levels of building with viewmode transformation
|
||||
osg::BoundingBox mLocalBounds;
|
||||
|
||||
// entity id of camera entity
|
||||
dtEntity::EntityId mCameraId = 0;
|
||||
|
||||
// entity id of orthomotionmodel entity
|
||||
dtEntity::EntityId mMotionModelId = 0;
|
||||
OrthoMotionModelComponent *pMotion = nullptr;
|
||||
|
||||
// entity id of light source entity
|
||||
dtEntity::EntityId mLightId = 0;
|
||||
|
||||
// display players as dots or as icons?
|
||||
PlayerDisplayMode mPlayerDisplayMode = PlayerDisplayMode::Icons;
|
||||
|
||||
// how are the buildings projected?
|
||||
ViewMode mViewMode = ViewMode::ISOMETRIC;
|
||||
|
||||
// all players currently displayed in this building
|
||||
std::vector<PlayerDisplay> mPlayers;
|
||||
|
||||
// shoot lines currently displayed
|
||||
std::vector<ShotDisplay> mShotDisplays;
|
||||
|
||||
// all players currently displayed in this building
|
||||
std::vector<DeviceDisplay> mDeviceDisplays;
|
||||
|
||||
// all names currently displayed in this building
|
||||
std::vector<NameDisplay> mNameDisplays;
|
||||
|
||||
// should camera rotation be locked to global map rotation?
|
||||
bool mLockRotation = false;
|
||||
|
||||
// are the roomNames shown?
|
||||
bool mNameMode = false;
|
||||
|
||||
// how are the shoot Lines displayed?
|
||||
bool mLineMode = false;
|
||||
|
||||
BuildingDisplay() = default;
|
||||
|
||||
BuildingDisplay(unsigned int contextid, ViewMode vm)
|
||||
: mContextId(contextid)
|
||||
, mViewMode(vm)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct Building
|
||||
{
|
||||
// building entity in world space
|
||||
dtEntity::EntityId mWorldBuildingId = 0;
|
||||
|
||||
// all currently open displays of this building
|
||||
std::vector<BuildingDisplay> mDisplays;
|
||||
|
||||
// transformation of building in world space
|
||||
osg::Matrix mWorldToLocal;
|
||||
|
||||
// transformation of building in world space
|
||||
osg::Matrix mLocalToWorld;
|
||||
|
||||
// used for assigning walking entities to buildings
|
||||
std::string mNavMeshGrpName;
|
||||
|
||||
// stores shot data
|
||||
std::vector<Shot *> mShots;
|
||||
|
||||
// stores device data
|
||||
std::vector<Device *> mDevices;
|
||||
|
||||
// Building Display Name
|
||||
std::string mBuildingDisplayName;
|
||||
|
||||
// stores name data
|
||||
std::vector<Name*> mNames;
|
||||
|
||||
// the corresponding feature id from the xml file
|
||||
std::string mFeatureId;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class BuildingManager
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
explicit BuildingManager(dtEntity::EntityManager &em);
|
||||
~BuildingManager();
|
||||
|
||||
void addBuilding(dtEntity::EntityId buildingid, const std::string &featureId);
|
||||
void deleteAllBuildings();
|
||||
|
||||
BuildingDisplay *getBuildingDisplay(unsigned int contextid);
|
||||
void applyViewModeToBuildingParts(const Building &bldg, BuildingDisplay &dspl) const;
|
||||
|
||||
bool displayBuilding(const std::string& featureId, unsigned int contextid, dtEntity::EntityId buildingid, const osg::Vec4 &bgcolor, ViewMode viewmode, bool exactPos);
|
||||
bool displayBuilding(unsigned int contextid, dtEntity::EntityId buildingid, const osg::Vec4 &bgcolor, ViewMode viewmode, bool exactPos);
|
||||
|
||||
bool setCameraPosition(unsigned int contextid, const BuildingViewer::CameraViewPosition& pos);
|
||||
bool getCameraPosition(unsigned int contextid, BuildingViewer::CameraViewPosition& pos);
|
||||
bool setDefaultCameraPosition(unsigned int contextid);
|
||||
|
||||
void closeBuildingDisplay(unsigned int contextid);
|
||||
void changeViewMode(unsigned int contextId, ViewMode viewmode, bool useOriginViewPos = true);
|
||||
void changeLineMode(unsigned int contextId, bool line);
|
||||
void changeNameMode(unsigned int contextId, bool name);
|
||||
|
||||
void applyMapRotation(const Building &bd, BuildingDisplay &dspl);
|
||||
void lockViewRotationToMapRotation(unsigned int contextId, bool lock);
|
||||
void setPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode);
|
||||
void setWallTransparency(unsigned int contextId, float value);
|
||||
|
||||
float getMapRotation() const;
|
||||
void setMapRotation(float angle);
|
||||
|
||||
void openOverview(unsigned int contextid);
|
||||
|
||||
void addPlayerToBuildings(const std::string &navmeshgrpname, dtEntity::EntityId eid,
|
||||
const osg::Vec4 &color, const std::string &symbol,
|
||||
const osg::Vec3d &pos, bool visible);
|
||||
void removePlayerFromBuilding(const std::string &navmeshgrpname, dtEntity::EntityId eid, const std::string &roomname);
|
||||
void updatePlayerPosition(const std::string &navmeshgrpname, dtEntity::EntityId eid,
|
||||
const osg::Vec3d &pos, int roomNumber);
|
||||
|
||||
osg::Vec3d remapPosition(const Building &bd, const BuildingDisplay &dspl, const osg::Vec3d &world, int roomNumber = -1);
|
||||
|
||||
void setPlayerColor(dtEntity::EntityId eid, const osg::Vec4 &color);
|
||||
void setPlayerIcon(dtEntity::EntityId eid, const std::string &path);
|
||||
void reloadPlayerIcons();
|
||||
void updatePlayerPartyColor(dtEntity::EntityId eid, const VCtrl::Color& col);
|
||||
void setShowPlayerSelection(dtEntity::EntityId eid, bool show);
|
||||
void setShowDisplayNamesSelection(dtEntity::EntityId eid, bool show);
|
||||
void setShowHidePlayer(dtEntity::EntityId eid, bool show);
|
||||
void setShowHideDisplayNames(dtEntity::EntityId eid, unsigned int contextId, bool show);
|
||||
void setRoomDestructionValue(dtEntity::EntityId eid, const std::string &roomname, float value);
|
||||
void setBuildingDestructionValue(dtEntity::EntityId eid, float value);
|
||||
void setBuildingDisplayName(const std::string& featureId, dtEntity::EntityId eid, const std::string& strDisplayName);
|
||||
void setBuildingDisplayName(dtEntity::EntityId eid, const std::string& strDisplayName);
|
||||
void setRoomDisplayName(const std::string& featureId, dtEntity::EntityId eid, const std::string& roomname, const std::string& strDisplayName);
|
||||
void setRoomDisplayName(Building *building, const std::string &roomname, const std::string& strDisplayName);
|
||||
|
||||
void removeShoot(int32_t id);
|
||||
void showShoot(int32_t id, dtEntity::EntityId shooter, dtEntity::EntityId target,
|
||||
const dtEntity::Vec3d &shooterPos, const dtEntity::Vec3d &targetPos, int buildingIdSrc, int roomNumberSrc,
|
||||
int buildingIdDst, int roomNumberDst, int lineType, float duration, double simTimeCreated);
|
||||
|
||||
dtEntity::EntityId getWorldPlayerIdFromLocalPlayer(dtEntity::EntityId local) const;
|
||||
dtEntity::EntityId getWorldNameIdFromLocalName(dtEntity::EntityId local, std::string &buildingName, std::string &room) const;
|
||||
|
||||
void addDeviceToBuilding(dtEntity::EntityId iconmainid, dtEntity::EntityId buildingid,
|
||||
const osg::Vec3d &pos, const std::string &iconpath);
|
||||
void removeDeviceFromBuilding(dtEntity::EntityId iconmainid);
|
||||
|
||||
|
||||
// Load building XML and add room OBBs to tree
|
||||
bool AddRoomOBBs(const BuildingData &);
|
||||
const std::map<std::string, VCtrl::OBB> &GetRoomOBBs() const { return mRooms; }
|
||||
|
||||
// Look up room OBB, return true if room exists
|
||||
bool getRoomBounds(const std::string &bldgname, const std::string &roomname, VCtrl::OBB &obb) const;
|
||||
|
||||
|
||||
bool LoadBuildings(const std::string &path, std::vector<BuildingData> &);
|
||||
|
||||
size_t getNumBuildings() const;
|
||||
void getBuildingIds(std::vector<dtEntity::EntityId> &toFill) const;
|
||||
dtEntity::EntityId getNextBuilding(const osg::Vec3d &pos, float &distance, std::string &featureId) const;
|
||||
Building getBuildingFromFeatureId(const std::string &bldname) const;
|
||||
|
||||
// all players currently in this room
|
||||
using RoomPlayers = std::vector<PlayerPosition>;
|
||||
// add player to room
|
||||
osg::Vec2d AddRoomUsages(const std::string& bldgname, const std::string& roomname, VCtrl::PlayerPosition& playPos);
|
||||
const std::map<std::string, RoomPlayers> &GetRoomUsages() const { return mUsedRooms; }
|
||||
// delete player in room
|
||||
void deleteRoomUsagePlayer(const std::string& bldgname, const std::string& roomname, dtEntity::EntityId playerId);
|
||||
void SetExactPos(bool exactPos) { mExactPos = exactPos; }
|
||||
bool GetExactPos() const { return mExactPos; }
|
||||
void updateShotDuration(unsigned int newDuration_s);
|
||||
using CallbackCamPosChanged = std::function<void(unsigned int, const BuildingViewer::CameraViewPosition &)>;
|
||||
void setCallbackCamPosChanged(const CallbackCamPosChanged &cb);
|
||||
|
||||
private:
|
||||
void updateShots(const Building &bd, BuildingDisplay &dspl);
|
||||
void updateDevices(const Building &bd, BuildingDisplay &dspl);
|
||||
void createRoomNames(dtEntity::EntityId buildingid, Building& building);
|
||||
void updateNames(const Building& bd, BuildingDisplay& dspl);
|
||||
void repositionCamera(const Building &bd, const BuildingDisplay &dspl, bool useOriginViewPos = true);
|
||||
void updatePlayerPositions(const Building &bd, BuildingDisplay &dspl);
|
||||
void addPlayerToBuilding(const Building &bd, BuildingDisplay &dspl, dtEntity::EntityId eid,
|
||||
const osg::Vec4 &color, const std::string &symbol, const osg::Vec3d &pos,
|
||||
bool visible);
|
||||
static osg::Vec2d shiftPosition(const VCtrl::OBB& obb, const osg::Vec2d& pos, double& shiftValue);
|
||||
void cameraViewPositionChanged(unsigned int contextId, const BuildingViewer::CameraViewPosition &viewPos);
|
||||
|
||||
std::set<unsigned int> m_setInitialCameraPositionSet; // If an context ID of a building is included in this set the initial camera position had been set
|
||||
|
||||
std::map<std::string, std::map<std::string, std::string>> m_mapBuildingRoomNames; // Maps a building feature id (not the dtEntity::EntityId!) to the building's room names
|
||||
std::map<std::string, std::string> m_mapBuildingDisplayNames; // key = feature id value = BuildingDisplayName
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
|
||||
std::vector<Building *> mBuildings;
|
||||
QMutex m_mutexShots;
|
||||
|
||||
bool mShotOverview;
|
||||
bool mExactPos;
|
||||
float mMapRotation;
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
|
||||
void Tick(const dtEntity::Message &message);
|
||||
|
||||
std::map<std::string, VCtrl::OBB> mRooms;
|
||||
std::map<std::string, RoomPlayers> mUsedRooms;
|
||||
CallbackCamPosChanged mCbCamPosChanged;
|
||||
|
||||
// NLDEVCTRL-495
|
||||
// Die Positionierung der a) TeilnehmerSymbole, b) RaumBezeichner und c) Trefferlinien der Kanalisation ist problembehaftet.
|
||||
// Bei Raum 027 und 028 der Kanalisation wurde der RaumBezeichner nicht im unteren Level, sondern im darüberliegenden Level dargestellt.
|
||||
// Level entspricht den floors/Ebenen in der Standard-Darstellung isometric, also in "gespreizter" Darstellung.
|
||||
// Als Ursache hat sich Ansatz in BuildingManager::remapPosition() herausgestellt. Beim Remapping wird versucht, die aktuelle Position aufgrund des z-Wertes einem Floor/Level zuzuordnen. Wenn die Gebäude waagerechte Floors haben, funktioniert dies sehr gut.
|
||||
// Die Kanalisation weist aber im linken Bereich (Raum 027 und 028) einen Anstieg auf. Betritt also ein Teilnehmer einen der Räume, so wird aufgrund seines z-Wertes die darüberliegenden Etage ermittelt und der Tln "zu hoch" angezeigt.
|
||||
// Lösung:
|
||||
// Beim Einlesen der Struktur-XML-Datei wird ein Lookup-Table erstellt. mRoomToFloorPerBldg stellt dann zu jedem Raum den Floor zur Verfügung.
|
||||
// Bei Positionsmeldungen wird Bldg/Room durchgereicht, sodass es beim Remapping einbezogen werden kann.
|
||||
// Bei der Darstellung der RaumBezeichner verhält es sich analog.
|
||||
// Bei den Trefferlinien beinhaltet das DDS-Topic HitLineInfo den Information Bldg/Room nur für den Getroffenen. Daher wird die Peilspitze der Trefferlinien korrekt dargestellt.
|
||||
// ToDo:
|
||||
// Der Ursprung der Trefferlinien wird nach wie vor durch Analyse des z-Wertes vorgenommen -> Probleme bei Raum 027, 028.
|
||||
// Wahrscheinlich müsst im SVC PPM (ParticipantHandlerForExercise::createHitlineInfo) nixcht nur die OriginatorPosition, sondern ggf. auch Bldg/Room in das DDS-Topic HitLineInfo eingetragen werden.
|
||||
// Wahrscheinlich wegen dem Replay eine DB-Änderung notwendig.
|
||||
bool getFloorOfRoom(const std::string &bdlgFeatureId, int roomNumber, int &floorOut) const;
|
||||
// <bldg , <roomNumber, floor>
|
||||
// <featureId, <roomNumber, floor>
|
||||
std::map<std::string, std::map<int,int> > mRoomToFloorPerBldg;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
struct CameraViewPosition
|
||||
{
|
||||
CameraViewPosition() = default;
|
||||
CameraViewPosition(double left, double right, double bottom, double top)
|
||||
: m_left(left), m_right(right), m_bottom(bottom), m_top(top)
|
||||
{}
|
||||
|
||||
double m_left = 0;
|
||||
double m_right = 0;
|
||||
double m_bottom = 0;
|
||||
double m_top = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#if defined VIEWER_CTRL_LIBRARY_STATIC
|
||||
# define VIEWER_CTRL_EXPORT
|
||||
#else
|
||||
# if defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__) || defined( __BCPLUSPLUS__) || defined( __MWERKS__)
|
||||
# ifdef VIEWER_CTRL_LIBRARY
|
||||
# define VIEWER_CTRL_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
# define VIEWER_CTRL_EXPORT __declspec(dllimport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef VIEWER_CTRL_LIBRARY
|
||||
# define VIEWER_CTRL_EXPORT __attribute__ ((visibility("default")))
|
||||
# else
|
||||
# define VIEWER_CTRL_EXPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# pragma warning (disable: 4251)
|
||||
# pragma warning(disable : 4355) // 'this' used in initializer list
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "iconcomponent.h"
|
||||
|
||||
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/LineWidth>
|
||||
#include <osg/Node>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Texture2D>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId IconComponent::TYPE(dtEntity::SID("Icon"));
|
||||
const dtEntity::StringId IconComponent::PathId(dtEntity::SID("Path"));
|
||||
const dtEntity::StringId IconComponent::VOffsetId(dtEntity::SID("VOffset"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
IconComponent::IconComponent()
|
||||
: dtEntityOSG::TransformComponent(new osg::AutoTransform())
|
||||
, mPath(
|
||||
dtEntity::DynamicStringProperty::SetValueCB(this, &IconComponent::SetPath),
|
||||
dtEntity:: DynamicStringProperty::GetValueCB(this, &IconComponent::GetPath)
|
||||
)
|
||||
, mVOffset(
|
||||
dtEntity::DynamicFloatProperty::SetValueCB(this, &IconComponent::SetVOffset),
|
||||
dtEntity:: DynamicFloatProperty::GetValueCB(this, &IconComponent::GetVOffset)
|
||||
)
|
||||
{
|
||||
Register(PathId, &mPath);
|
||||
Register(VOffsetId, &mVOffset);
|
||||
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setName("icon");
|
||||
tr->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
|
||||
tr->setAutoScaleToScreen(true);
|
||||
tr->setNodeMask(dtEntity::NodeMasks::PICKABLE | dtEntity::NodeMasks::VISIBLE);
|
||||
tr->setNormal(osg::Vec3(0, 1, 0));
|
||||
osg::StateSet *ss = tr->getOrCreateStateSet();
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->setRenderBinDetails(90, "DepthSortedBin");
|
||||
ss->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||
ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
osg::ref_ptr<osg::LineWidth> lw = new osg::LineWidth();
|
||||
lw->setWidth(2);
|
||||
ss->setAttributeAndModes(lw, osg::StateAttribute::ON);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::Rebuild()
|
||||
{
|
||||
#define DOT_RADIUS 5
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->dirtyBound();
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 10));
|
||||
tr->removeChildren(0, tr->getNumChildren());
|
||||
|
||||
if (!mVisible) return;
|
||||
|
||||
osg::ref_ptr<osg::Geode> g = new osg::Geode();
|
||||
tr->addChild(g);
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 1));
|
||||
|
||||
int x, y, w, h;
|
||||
if (mShowDot)
|
||||
{
|
||||
x = y = -DOT_RADIUS * 2;
|
||||
w = h = DOT_RADIUS * 4;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> circle = new osg::Geometry();
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = mColor;
|
||||
circle->setColorArray(colours);
|
||||
circle->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
const unsigned int n_points = 16;
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(n_points + 2);
|
||||
(*coords)[0] = osg::Vec3(0, 0, 0);
|
||||
const double dx = 2.0 * osg::PI / n_points;
|
||||
|
||||
for (unsigned int j = 1; j < n_points + 2; ++j)
|
||||
(*coords)[j].set(osg::Vec3(cos(dx * j) * DOT_RADIUS, sin(dx * j) * DOT_RADIUS, 0));
|
||||
circle->setVertexArray(coords);
|
||||
circle->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_FAN, 0, n_points + 2));
|
||||
g->addDrawable(circle);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::ref_ptr<osg::Image> img = osgDB::readImageFile(mPathVal);
|
||||
if (img.valid())
|
||||
{
|
||||
int b = 4;
|
||||
g->addDrawable(IconSystem::CreateSquare(img->s(), img->t(), mVOffsetVal, mOriginAtBottom, img));
|
||||
if (mOriginAtBottom)
|
||||
{
|
||||
x = -img->s() / 2 - b;
|
||||
y = 0 - b;
|
||||
w = img->s() + b * 2;
|
||||
h = img->t() + b * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = -img->s() / 2 - b;
|
||||
y = -img->t() / 2 - b;
|
||||
w = img->s() + b * 2;
|
||||
h = img->t() + b * 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Could not read symbol from path '" << mPathVal<< "'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mSelected)
|
||||
{
|
||||
osg::ref_ptr<osg::Geometry> sel = new osg::Geometry();
|
||||
g->addDrawable(sel);
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1, 0, 0, 1);
|
||||
sel->setColorArray(colours);
|
||||
sel->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(4);
|
||||
(*coords)[0] = osg::Vec3(x , y , 0);
|
||||
(*coords)[1] = osg::Vec3(x , y + h, 0);
|
||||
(*coords)[2] = osg::Vec3(x + w, y + h, 0);
|
||||
(*coords)[3] = osg::Vec3(x + w, y , 0);
|
||||
sel->setVertexArray(coords);
|
||||
sel->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4));
|
||||
osg::ref_ptr<osg::PolygonMode> p = new osg::PolygonMode;
|
||||
p->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
||||
sel->getOrCreateStateSet()->setAttribute(p);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string IconComponent::GetPath() const
|
||||
{
|
||||
return mPathVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetPath(const std::string &path)
|
||||
{
|
||||
mPathVal = path;
|
||||
Rebuild();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::Reload()
|
||||
{
|
||||
if(mPathVal.size())
|
||||
{
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
float IconComponent::GetVOffset() const
|
||||
{
|
||||
return mVOffsetVal;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetVOffset(float v)
|
||||
{
|
||||
if (mVOffsetVal != v)
|
||||
{
|
||||
mVOffsetVal = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d IconComponent::GetTranslation() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getPosition();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetTranslation(const dtEntity::Vec3d &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setPosition(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d IconComponent::GetScale() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getScale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetScale(const dtEntity::Vec3d &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setScale(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Quat IconComponent::GetRotation() const
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
return tr->getRotation();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetRotation(const dtEntity::Quat &v)
|
||||
{
|
||||
osg::AutoTransform *tr = static_cast<osg::AutoTransform *>(GetNode());
|
||||
tr->setRotation(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetColor(const osg::Vec4 &v)
|
||||
{
|
||||
if (mColor != v)
|
||||
{
|
||||
mColor = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetShowDot(bool v)
|
||||
{
|
||||
if (mShowDot != v)
|
||||
{
|
||||
mShowDot = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetOriginAtBottom(bool v)
|
||||
{
|
||||
if (mOriginAtBottom != v)
|
||||
{
|
||||
mOriginAtBottom = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool IconComponent::GetShowSelection() const
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetShowSelection(bool v)
|
||||
{
|
||||
if (mSelected != v)
|
||||
{
|
||||
mSelected = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetVisible(bool v)
|
||||
{
|
||||
if (mVisible != v)
|
||||
{
|
||||
mVisible = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void IconComponent::SetRoomNumber(int roomNumber)
|
||||
{
|
||||
mRoomNumber = roomNumber;
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
IconSystem::IconSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<IconComponent>(em, dtEntityOSG::TransformComponent::TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
osg::Drawable *IconSystem::CreateSquare(float width, float height, float voffset, bool originAtBottom, osg::Image *image)
|
||||
{
|
||||
// set up the Geometry.
|
||||
osg::Geometry *geom = new osg::Geometry;
|
||||
|
||||
osg::Vec3Array *coords = new osg::Vec3Array(4);
|
||||
if (originAtBottom)
|
||||
{
|
||||
(*coords)[0] = osg::Vec3(-width / 2.0f, voffset, 0);
|
||||
(*coords)[1] = osg::Vec3(width / 2.0f, voffset, 0);
|
||||
(*coords)[2] = osg::Vec3(width / 2.0f, voffset + height, 0);
|
||||
(*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*coords)[0] = osg::Vec3(-width / 2.0f, voffset - height / 2, 0);
|
||||
(*coords)[1] = osg::Vec3(width / 2.0f, voffset - height / 2, 0);
|
||||
(*coords)[2] = osg::Vec3(width / 2.0f, voffset + height / 2, 0);
|
||||
(*coords)[3] = osg::Vec3(-width / 2.0f, voffset + height / 2, 0);
|
||||
}
|
||||
|
||||
geom->setVertexArray(coords);
|
||||
|
||||
osg::Vec3Array *norms = new osg::Vec3Array(1);
|
||||
(*norms)[0] = osg::Vec3(0, 1, 0);
|
||||
|
||||
geom->setNormalArray(norms);
|
||||
geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec4Array *colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1, 1, 1, 1);
|
||||
geom->setColorArray(colours);
|
||||
geom->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
|
||||
osg::Vec2Array *tcoords = new osg::Vec2Array(4);
|
||||
(*tcoords)[0].set(0.0f, 0.0f);
|
||||
(*tcoords)[1].set(1.0f, 0.0f);
|
||||
(*tcoords)[2].set(1.0f, 1.0f);
|
||||
(*tcoords)[3].set(0.0f, 1.0f);
|
||||
geom->setTexCoordArray(0, tcoords);
|
||||
|
||||
geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
|
||||
|
||||
if (image)
|
||||
{
|
||||
osg::StateSet *stateset = geom->getOrCreateStateSet();
|
||||
osg::Texture2D *texture = new osg::Texture2D;
|
||||
texture->setResizeNonPowerOfTwoHint(false);
|
||||
texture->setImage(image);
|
||||
stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
|
||||
}
|
||||
|
||||
return geom;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/nodecomponent.h>
|
||||
#include <osg/AutoTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class IconComponent : public dtEntityOSG::TransformComponent
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
static const dtEntity::StringId PathId;
|
||||
static const dtEntity::StringId VOffsetId;
|
||||
|
||||
|
||||
IconComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
std::string GetPath() const;
|
||||
void SetPath(const std::string &path);
|
||||
void Reload();
|
||||
|
||||
float GetVOffset() const;
|
||||
void SetVOffset(float v);
|
||||
|
||||
osg::Vec4 GetColor() const { return mColor; }
|
||||
void SetColor(const osg::Vec4 &);
|
||||
|
||||
bool GetShowDot() const { return mShowDot; }
|
||||
void SetShowDot(bool);
|
||||
|
||||
bool GetOriginAtBottom() const { return mOriginAtBottom; }
|
||||
void SetOriginAtBottom(bool);
|
||||
|
||||
dtEntity::Vec3d GetTranslation() const override;
|
||||
void SetTranslation(const dtEntity::Vec3d &) override;
|
||||
|
||||
dtEntity::Vec3d GetScale() const override;
|
||||
void SetScale(const dtEntity::Vec3d &) override;
|
||||
|
||||
dtEntity::Quat GetRotation() const override;
|
||||
void SetRotation(const dtEntity::Quat &) override;
|
||||
|
||||
bool GetShowSelection() const;
|
||||
void SetShowSelection(bool v);
|
||||
|
||||
void SetVisible(bool v);
|
||||
bool GetVisible() const { return mVisible; }
|
||||
|
||||
void SetRoomNumber(int roomNumber);
|
||||
int GetRoomNumber() const { return mRoomNumber; }
|
||||
|
||||
private:
|
||||
|
||||
void Rebuild();
|
||||
|
||||
dtEntity::DynamicStringProperty mPath;
|
||||
dtEntity::DynamicFloatProperty mVOffset;
|
||||
|
||||
std::string mPathVal;
|
||||
osg::Vec4 mColor;
|
||||
float mVOffsetVal = 0;
|
||||
bool mShowDot = false;
|
||||
bool mOriginAtBottom = false;
|
||||
bool mSelected = false;
|
||||
bool mVisible = false;
|
||||
|
||||
int mRoomNumber{-1};
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class IconSystem final : public dtEntity::DefaultEntitySystem<IconComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit IconSystem(dtEntity::EntityManager &em);
|
||||
|
||||
static osg::Drawable *CreateSquare(float width, float height, float voffset, bool originAtBottom, osg::Image *image = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,440 @@
|
||||
#include "mainloop.h"
|
||||
|
||||
#include "iconcomponent.h"
|
||||
#include "modelsplittercomponent.h"
|
||||
#include "motionmodel.h"
|
||||
#include "orthomotionmodel.h"
|
||||
#include "playercomponent.h"
|
||||
#include "roomdestructioncomponent.h"
|
||||
#include "textcomponent.h"
|
||||
#include "viewerinterfaceimpl.h"
|
||||
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/init.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/entitymanager.h>
|
||||
#include <dtEntityOSG/initosgviewer.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/lightcomponent.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntityOSG/osgsysteminterface.h>
|
||||
#include <dtEntityOSG/osgwindowinterface.h>
|
||||
#include <dtEntityOSG/osgdebugdrawinterface.h>
|
||||
#include <dtEntityOSG/osginputinterface.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
#include "videocomponent.h"
|
||||
#endif
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MyReadFileCallback : public osgDB::Registry::ReadFileCallback
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
virtual osgDB::ReaderWriter::ReadResult readNode(const std::string &fileName, const osgDB::ReaderWriter::Options *options)
|
||||
{
|
||||
osgDB::ReaderWriter::ReadResult res = osgDB::Registry::instance()->readNodeImplementation(fileName, options);
|
||||
if (res.notFound() || res.notHandled() || res.error())
|
||||
{
|
||||
LOG_DEBUG("DatabasePager could not load file, stopped trying: " << fileName);
|
||||
return osgDB::ReaderWriter::ReadResult(nullptr, osgDB::ReaderWriter::ReadResult::FILE_LOADED);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MainLoop::Impl
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
osg::ref_ptr<osgViewer::CompositeViewer> mViewer;
|
||||
CtrlImpl *mInterface = nullptr;
|
||||
dtEntityOSG::OSGSystemInterface *mSysIf = nullptr;
|
||||
dtEntityOSG::OSGInputInterface *mInputIf = nullptr;
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
osg::Timer_t mStartFrameTick = 0;
|
||||
dtEntity::Timer_t mSimulationClockTime = 0;
|
||||
bool mProfilingEnabled = false;
|
||||
|
||||
Impl()
|
||||
: mEntityManager(new dtEntity::EntityManager)
|
||||
{
|
||||
dtEntity::MessageFunctor f(this, &MainLoop::Impl::onFastForward);
|
||||
mEntityManager->RegisterForMessages(dtEntity::SID("FastForwardMessage"), f);
|
||||
|
||||
dtEntity::MessageFunctor s(this, &MainLoop::Impl::onEntitySelected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntitySelectMessage::TYPE, s);
|
||||
|
||||
dtEntity::MessageFunctor s2(this, &MainLoop::Impl::onEntityDeselected);
|
||||
mEntityManager->RegisterForMessages(dtEntity::RequestEntityDeselectMessage::TYPE, s2);
|
||||
}
|
||||
|
||||
~Impl()
|
||||
{
|
||||
delete mEntityManager;
|
||||
delete mSysIf;
|
||||
delete mInputIf;
|
||||
delete mInterface;
|
||||
}
|
||||
|
||||
// react to fast forward message by
|
||||
void onFastForward(const dtEntity::Message &msg)
|
||||
{
|
||||
// TODO Test!
|
||||
double endtime = msg.GetDouble(dtEntity::SID("EndTime"));
|
||||
|
||||
while (mInterface->GetSimulationTime() < endtime)
|
||||
{
|
||||
constexpr auto step = 0.5;
|
||||
double t = mInterface->GetSimulationTime() + step;
|
||||
mSimulationClockTime += step / osg::Timer::instance()->getSecondsPerTick();
|
||||
mInterface->SetSimulationTime(t);
|
||||
mSysIf->SetTimeValues(t, step, step, mSimulationClockTime);
|
||||
mViewer->advance(t);
|
||||
mViewer->eventTraversal();
|
||||
mSysIf->EmitTickMessagesAndQueuedMessages();
|
||||
mViewer->updateTraversal();
|
||||
mSysIf->EmitPostUpdateMessage();
|
||||
}
|
||||
}
|
||||
|
||||
// translate RequestEntitySelectMessage to EntityDeselectedMessage
|
||||
// (normally this would be handled by a selection manager, but
|
||||
// selection in this viewer is so simple that it is not necessary
|
||||
// to have real selection management)
|
||||
void onEntitySelected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntitySelectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntitySelectMessage &>(m);
|
||||
dtEntity::EntitySelectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
// translate RequestEntityDeselectMessage to EntityDeselectedMessage
|
||||
void onEntityDeselected(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::RequestEntityDeselectMessage &msg =
|
||||
static_cast<const dtEntity::RequestEntityDeselectMessage &>(m);
|
||||
dtEntity::EntityDeselectedMessage mo;
|
||||
mo.SetAboutEntityId(msg.GetAboutEntityId());
|
||||
mEntityManager->EmitMessage(mo);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::MainLoop(int argc, char **argv, QWidget *parentWidget)
|
||||
: mImpl(new Impl)
|
||||
{
|
||||
osgDB::Registry::instance()->setReadFileCallback(new MyReadFileCallback());
|
||||
|
||||
assert(!mImpl->mViewer.valid());
|
||||
|
||||
//////////////////////////// Setup OSG Viewer /////////////////////////
|
||||
// osg arguments parser wants to modify argc, argv
|
||||
{
|
||||
int argc_cpy = argc;
|
||||
std::vector<char *> argv_cpy;
|
||||
argv_cpy.reserve(argc);
|
||||
for (int i = 0; i < argc; ++i)
|
||||
argv_cpy.push_back(argv[i]);
|
||||
osg::ArgumentParser args(&argc_cpy, argv_cpy.data());
|
||||
|
||||
#ifdef _MSC_VER
|
||||
_putenv_s("OSG_RUN_FRAME_SCHEME", "ON_DEMAND");
|
||||
#else
|
||||
setenv("OSG_RUN_FRAME_SCHEME", "ON_DEMAND", 1);
|
||||
#endif
|
||||
// turn on antialiasing
|
||||
osg::DisplaySettings::instance()->setNumMultiSamples(4);
|
||||
osg::DisplaySettings::instance()->setDepthBuffer(true);
|
||||
|
||||
|
||||
mImpl->mViewer = new osgViewer::CompositeViewer(args);
|
||||
// Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different
|
||||
// thread" when the viewer is run multi-threaded, this is regression from Qt4
|
||||
mImpl->mViewer->setThreadingModel(osgViewer::CompositeViewer::SingleThreaded);
|
||||
|
||||
// don't exit on escape
|
||||
mImpl->mViewer->setKeyEventSetsDone(0);
|
||||
|
||||
//mImpl->mViewer->setEndBarrierPosition(osgViewer::ViewerBase::BeforeSwapBuffers);
|
||||
|
||||
#ifdef LTS_DEBUG
|
||||
dtEntity::LogManager::GetInstance().AddListener(new dtEntity::ConsoleLogHandler());
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////// setup dtEntity -> OSG interfaces ////////////////////////
|
||||
{
|
||||
mImpl->mSysIf = new dtEntityOSG::OSGSystemInterface(mImpl->mEntityManager->GetMessagePump(), argc, (const char **)argv);
|
||||
mImpl->mInputIf = new dtEntityOSG::OSGInputInterface(mImpl->mEntityManager->GetMessagePump());
|
||||
// give application system access to viewer
|
||||
mImpl->mSysIf->SetViewer(mImpl->mViewer);
|
||||
dtEntity::SetSystemInterface(mImpl->mSysIf);
|
||||
dtEntity::SetInputInterface(mImpl->mInputIf);
|
||||
dtEntity::SetWindowInterface(new dtEntityOSG::OSGWindowInterface(*mImpl->mEntityManager));
|
||||
|
||||
dtEntity::SetupDataPaths(argc, argv, false);
|
||||
}
|
||||
|
||||
|
||||
dtEntity::EntityManager &em = *mImpl->mEntityManager;
|
||||
|
||||
//////////////////////////// Add entity systems /////////////////////////
|
||||
{
|
||||
// this is a required component system, so add it immediately
|
||||
em.AddEntitySystem(*new dtEntity::MapSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LayerSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::CameraSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::PositionAttitudeTransformSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::StaticMeshSystem(em));
|
||||
em.AddEntitySystem(*new RoomDestructionSystem(em));
|
||||
em.AddEntitySystem(*new MotionModelSystem(em));
|
||||
em.AddEntitySystem(*new ModelSplitterSystem(em));
|
||||
em.AddEntitySystem(*new OrthoMotionModelSystem(em));
|
||||
em.AddEntitySystem(*new dtEntityOSG::LightSystem(em));
|
||||
em.AddEntitySystem(*new PlayerSystem(em));
|
||||
em.AddEntitySystem(*new IconSystem(em));
|
||||
em.AddEntitySystem(*new TextSystem(em));
|
||||
#ifdef BUILD_WITH_GSTREAMER
|
||||
em.AddEntitySystem(*new VideoSystem(em));
|
||||
#endif
|
||||
|
||||
dtEntityOSG::LayerAttachPointSystem *layerattach = new dtEntityOSG::LayerAttachPointSystem(em);
|
||||
em.AddEntitySystem(*layerattach);
|
||||
layerattach->CreateSceneGraphRootEntity(new osg::Group());
|
||||
|
||||
mImpl->mInterface = new CtrlImpl(em, parentWidget);
|
||||
|
||||
// need layer system for debug draw interface, so set it up now
|
||||
dtEntity::SetDebugDrawInterface(new dtEntityOSG::OSGDebugDrawInterface(em));
|
||||
}
|
||||
|
||||
//////////////////////////// Init time tracking /////////////////////////
|
||||
{
|
||||
mImpl->mStartFrameTick = osg::Timer::instance()->tick();
|
||||
mImpl->mInterface->SetSimulationTime(0);
|
||||
time_t t;
|
||||
time(&t);
|
||||
mImpl->mSimulationClockTime = t / osg::Timer::instance()->getSecondsPerTick();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i < argc; ++i)
|
||||
{
|
||||
std::string curArgv = argv[i];
|
||||
if (!curArgv.empty() && curArgv == "--openOverview")
|
||||
mImpl->mInterface->OpenOverview();
|
||||
}
|
||||
|
||||
//////////////////////////// Start simulation /////////////////////////
|
||||
{
|
||||
dtEntity::StartSystemMessage msg;
|
||||
em.EnqueueMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
MainLoop::~MainLoop()
|
||||
{
|
||||
delete mImpl;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::EntityManager *MainLoop::getEntityManager() const
|
||||
{
|
||||
return mImpl->mEntityManager;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ViewerInterface *MainLoop::getViewerInterface() const
|
||||
{
|
||||
return mImpl->mInterface;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool MainLoop::getProfilingEnabled() const
|
||||
{
|
||||
return mImpl->mProfilingEnabled;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::setProfilingEnabled(bool v)
|
||||
{
|
||||
mImpl->mProfilingEnabled = v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::tick()
|
||||
{
|
||||
dtEntityOSG::OSGSystemInterface *iface = dtEntityOSG::GetOSGSystemInterface();
|
||||
|
||||
if (!mImpl->mInterface->allViewWindowsExposed())
|
||||
return;
|
||||
|
||||
if (getViewerInterface()->GetNonRealtimeMode())
|
||||
{
|
||||
float deltaTime = 1.0f / mImpl->mInterface->GetFrameRate();
|
||||
float deltaSimTime = deltaTime;
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
float deltaTime = 0;
|
||||
float deltaSimTime = 0;
|
||||
|
||||
dtEntity::Timer_t tick = osg::Timer::instance()->tick();
|
||||
deltaTime = static_cast<float>(osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, tick));
|
||||
deltaSimTime = deltaTime * mImpl->mInterface->GetTimeScale();
|
||||
mImpl->mStartFrameTick = tick;
|
||||
|
||||
mImpl->mSimulationClockTime += deltaSimTime / osg::Timer::instance()->getSecondsPerTick();
|
||||
mImpl->mInterface->SetSimulationTime(mImpl->mInterface->GetSimulationTime() + deltaSimTime);
|
||||
iface->SetTimeValues(mImpl->mInterface->GetSimulationTime(), deltaSimTime, deltaTime, mImpl->mSimulationClockTime);
|
||||
}
|
||||
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
|
||||
static dtEntity::StringId frameId = dtEntity::SID("Frame");
|
||||
static dtEntity::StringId frameAdvanceId = dtEntity::SID("Frame_Advance");
|
||||
static dtEntity::StringId frameEvTrId = dtEntity::SID("Frame_EventTraversal");
|
||||
static dtEntity::StringId frameUpTrId = dtEntity::SID("Frame_UpdateTraversal");
|
||||
static dtEntity::StringId frameRenderTrId = dtEntity::SID("Frame_RenderingTraversals");
|
||||
|
||||
static unsigned int framecount = 0;
|
||||
|
||||
CProfileManager::Increment_Frame_Counter();
|
||||
|
||||
CProfileManager::Start_Profile(frameId);
|
||||
|
||||
CProfileManager::Start_Profile(frameAdvanceId);
|
||||
mImpl->mViewer->advance();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameEvTrId);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
if (mImpl->mViewer->getNumViews() > 0 && mImpl->mViewer->checkNeedToDoFrame())
|
||||
{
|
||||
CProfileManager::Start_Profile(frameUpTrId);
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
CProfileManager::Stop_Profile();
|
||||
|
||||
CProfileManager::Start_Profile(frameRenderTrId);
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
|
||||
CProfileManager::Stop_Profile(); // frameId
|
||||
|
||||
if (++framecount > 99)
|
||||
{
|
||||
CProfileManager::dumpAll();
|
||||
fflush(stdout);
|
||||
framecount = 0;
|
||||
CProfileManager::Reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**
|
||||
NASTY BUG WORKAROUND:
|
||||
Somehow, changes made to the frame are not immediately shown when
|
||||
a new frame is requested. This only happens when more than one view is opened.
|
||||
The workaround is to render again two more times even if no frame redraw
|
||||
was requested.
|
||||
*/
|
||||
static int renderagaincnt = 0;
|
||||
|
||||
mImpl->mViewer->advance(DBL_MAX);
|
||||
mImpl->mViewer->eventTraversal();
|
||||
iface->EmitTickMessagesAndQueuedMessages();
|
||||
bool needFrame = mImpl->mViewer->checkNeedToDoFrame();
|
||||
if (mImpl->mViewer->getNumViews() > 0 && (renderagaincnt != 0 || needFrame))
|
||||
{
|
||||
if (mImpl->mViewer->getNumViews() == 1)
|
||||
renderagaincnt = 0;
|
||||
else if (needFrame)
|
||||
renderagaincnt = 2;
|
||||
else
|
||||
--renderagaincnt;
|
||||
|
||||
mImpl->mViewer->updateTraversal();
|
||||
iface->EmitPostUpdateMessage();
|
||||
mImpl->mViewer->renderingTraversals();
|
||||
}
|
||||
else
|
||||
iface->EmitPostUpdateMessage();
|
||||
}
|
||||
|
||||
if (!getViewerInterface()->GetNonRealtimeMode() && mImpl->mViewer->getRunMaxFrameRate() > 0.0)
|
||||
{
|
||||
if (mImpl->mProfilingEnabled)
|
||||
{
|
||||
static dtEntity::StringId sleepId = dtEntity::SID("Frame_Sleep");
|
||||
CProfileManager::Start_Profile(sleepId);
|
||||
}
|
||||
osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
|
||||
double frameTime =
|
||||
osg::Timer::instance()->delta_s(mImpl->mStartFrameTick, endFrameTick);
|
||||
|
||||
double minFrameTime = 1.0 / mImpl->mViewer->getRunMaxFrameRate();
|
||||
if (frameTime < minFrameTime)
|
||||
OpenThreads::Thread::microSleep(1000000.0 * (minFrameTime - frameTime));
|
||||
if (mImpl->mProfilingEnabled)
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void MainLoop::GetCurrentPosition(Vec3d &position, Vec3d &lookAt)
|
||||
{
|
||||
position = Vec3d();
|
||||
lookAt = Vec3d();
|
||||
dtEntity::MapSystem *ms;
|
||||
mImpl->mEntityManager->GetES(ms);
|
||||
if (!ms)
|
||||
return;
|
||||
dtEntity::EntityId eid = ms->GetEntityIdByUniqueId("cam_overview");
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
if (!mImpl->mEntityManager->GetComponent(eid, camcomp))
|
||||
{
|
||||
LOG_ERROR("GetCurrentPosition: Error accessing camera");
|
||||
return;
|
||||
}
|
||||
|
||||
osg::Vec3d p = camcomp->GetPosition();
|
||||
osg::Vec3d la = camcomp->GetEyeDirection() + camcomp->GetPosition();
|
||||
position.x = p[0]; position.y = p[1]; position.z = p[2];
|
||||
lookAt.x = la[0]; lookAt.y = la[1]; lookAt.z = la[2];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "export.h"
|
||||
|
||||
class QWidget;
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class ViewerInterface;
|
||||
struct Vec3d;
|
||||
|
||||
class VIEWER_CTRL_EXPORT MainLoop
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
MainLoop(int argc, char **argv, QWidget *parentWidget);
|
||||
~MainLoop();
|
||||
|
||||
dtEntity::EntityManager *getEntityManager() const;
|
||||
ViewerInterface *getViewerInterface() const;
|
||||
|
||||
bool getProfilingEnabled() const;
|
||||
void setProfilingEnabled(bool v);
|
||||
|
||||
void shutDown();
|
||||
bool isRunning() const;
|
||||
|
||||
void tick();
|
||||
void GetCurrentPosition(Vec3d &position, Vec3d &lookAt);
|
||||
private:
|
||||
|
||||
class Impl;
|
||||
Impl *mImpl;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
#include "messages.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void RegisterMessageTypes(dtEntity::MessageFactory& em)
|
||||
{
|
||||
em.RegisterMessageType<NavMeshGroupChangedMessage>(NavMeshGroupChangedMessage::TYPE);
|
||||
em.RegisterMessageType<TransformSendMessage>(TransformSendMessage::TYPE);
|
||||
em.RegisterMessageType<PlayerPickedMessage>(PlayerPickedMessage::TYPE);
|
||||
em.RegisterMessageType<DisplayNameClickedMessage>(DisplayNameClickedMessage::TYPE);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType NavMeshGroupChangedMessage::TYPE(dtEntity::SID("NavMeshGroupChangedMessage"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::GroupNameId(dtEntity::SID("GroupName"));
|
||||
const dtEntity::StringId NavMeshGroupChangedMessage::PreviousGroupNameId(dtEntity::SID("PreviousGroupName"));
|
||||
|
||||
NavMeshGroupChangedMessage::NavMeshGroupChangedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(GroupNameId, &mGroupName);
|
||||
this->Register(PreviousGroupNameId, &mPreviousGroupName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType TransformSendMessage::TYPE(dtEntity::SID("TransformSendMessage"));
|
||||
const dtEntity::StringId TransformSendMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId TransformSendMessage::PositionId(dtEntity::SID("Position"));
|
||||
const dtEntity::StringId TransformSendMessage::AttitudeId(dtEntity::SID("Attitude"));
|
||||
const dtEntity::StringId TransformSendMessage::RoomNumberId(dtEntity::SID("RoomNumber"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TransformSendMessage::TransformSendMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
Register(AboutEntityId, &mAboutEntity);
|
||||
Register(PositionId, &mPosition);
|
||||
Register(AttitudeId, &mAttitude);
|
||||
Register(RoomNumberId, &mRoomNumber);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType PlayerPickedMessage::TYPE(dtEntity::SID("PlayerPickedMessage"));
|
||||
const dtEntity::StringId PlayerPickedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId PlayerPickedMessage::PositionId(dtEntity::SID("Position"));
|
||||
|
||||
|
||||
PlayerPickedMessage::PlayerPickedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(PositionId, &mPosition);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType FastForwardMessage::TYPE(dtEntity::SID("FastForwardMessage"));
|
||||
const dtEntity::StringId FastForwardMessage::EndTimeId(dtEntity::SID("EndTime"));
|
||||
|
||||
FastForwardMessage::FastForwardMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(EndTimeId, &mEndTime);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType HideSelectionMessage::TYPE(dtEntity::SID("HideSelectionMessage"));
|
||||
const dtEntity::StringId HideSelectionMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId HideSelectionMessage::NameFlagId(dtEntity::SID("NameFlag"));
|
||||
|
||||
HideSelectionMessage::HideSelectionMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(NameFlagId, &mNameFlag);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType RemoveShootMessage::TYPE(dtEntity::SID("RemoveShootMessage"));
|
||||
|
||||
RemoveShootMessage::RemoveShootMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType ShootMessage::TYPE(dtEntity::SID("ShootMessage"));
|
||||
|
||||
ShootMessage::ShootMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType ShowHidePlayerMessage::TYPE(dtEntity::SID("ShowHidePlayerMessage"));
|
||||
const dtEntity::StringId ShowHidePlayerMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
|
||||
ShowHidePlayerMessage::ShowHidePlayerMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::MessageType DisplayNameClickedMessage::TYPE(dtEntity::SID("DisplayNameClickedMessage"));
|
||||
const dtEntity::StringId DisplayNameClickedMessage::AboutEntityId(dtEntity::SID("AboutEntity"));
|
||||
const dtEntity::StringId DisplayNameClickedMessage::PositionId(dtEntity::SID("Position"));
|
||||
|
||||
|
||||
DisplayNameClickedMessage::DisplayNameClickedMessage()
|
||||
: Message(TYPE)
|
||||
{
|
||||
this->Register(AboutEntityId, &mAboutEntity);
|
||||
this->Register(PositionId, &mPosition);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/messagefactory.h>
|
||||
#include <dtEntity/message.h>
|
||||
#include <dtEntity/property.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
void RegisterMessageTypes(dtEntity::MessageFactory& em);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class NavMeshGroupChangedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
// type identifier of this message class
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId GroupNameId;
|
||||
static const dtEntity::StringId PreviousGroupNameId;
|
||||
|
||||
NavMeshGroupChangedMessage();
|
||||
|
||||
// Create a copy of this message on the heap
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<NavMeshGroupChangedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId id) { mAboutEntity.Set(id); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetGroupName(const std::string& v) { mGroupName.Set(v); }
|
||||
std::string GetGroupName() const { return mGroupName.Get(); }
|
||||
|
||||
void SetPreviousGroupName(const std::string& v) { mPreviousGroupName.Set(v); }
|
||||
std::string GetPreviousGroupName() const { return mPreviousGroupName.Get(); }
|
||||
private:
|
||||
|
||||
dtEntity::IntProperty mAboutEntity;
|
||||
dtEntity::StringProperty mGroupName;
|
||||
dtEntity::StringProperty mPreviousGroupName;
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class TransformSendMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
static const dtEntity::StringId AttitudeId;
|
||||
static const dtEntity::StringId RoomNumberId;
|
||||
|
||||
TransformSendMessage();
|
||||
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<TransformSendMessage>(); }
|
||||
|
||||
void SetAboutEntity(dtEntity::EntityId id) { mAboutEntity.Set(id); }
|
||||
dtEntity::EntityId GetAboutEntity() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& id) { mPosition.Set(id); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
void SetAttitude(const osg::Quat& id) { mAttitude.Set(id); }
|
||||
osg::Quat GetAttitude() const { return mAttitude.Get(); }
|
||||
|
||||
void SetRoomNumber(dtEntity::EntityId roomNumber) { mRoomNumber.Set(roomNumber); }
|
||||
dtEntity::EntityId GetRoomNumber() const { return mRoomNumber.Get(); }
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
dtEntity::QuatProperty mAttitude;
|
||||
dtEntity::UIntProperty mRoomNumber;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class PlayerPickedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
|
||||
PlayerPickedMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<PlayerPickedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& v) { mPosition.Set(v); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FastForwardMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
// type identifier of this message class
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId EndTimeId;
|
||||
|
||||
FastForwardMessage();
|
||||
|
||||
// Create a copy of this message on the heap
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<FastForwardMessage>(); }
|
||||
|
||||
void SetEndTime(double v) { mEndTime.Set(v); }
|
||||
double GetEndTime() const { return mEndTime.Get(); }
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::DoubleProperty mEndTime;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class HideSelectionMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId NameFlagId;
|
||||
|
||||
HideSelectionMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<HideSelectionMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetNameFlagId(bool v) { mNameFlag.Set(v); }
|
||||
bool GetNameFlagId() const { return mNameFlag.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::BoolProperty mNameFlag;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class RemoveShootMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
|
||||
RemoveShootMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<RemoveShootMessage>(); }
|
||||
|
||||
void SetId(int32_t id) { mId = id; }
|
||||
int32_t GetId() { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId { 0 };
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class ShootMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
|
||||
ShootMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<ShootMessage>(); }
|
||||
|
||||
void SetShooter(dtEntity::EntityId v) { mShooter = v; }
|
||||
dtEntity::EntityId GetShooter() const { return mShooter; }
|
||||
void SetShooterPos(const dtEntity::Vec3d &shooterPos) { mShooterPos = shooterPos; }
|
||||
dtEntity::Vec3d GetShooterPos() const { return mShooterPos; }
|
||||
|
||||
void SetTarget(dtEntity::EntityId v) { mTarget = v; }
|
||||
dtEntity::EntityId GetTarget() const { return mTarget; }
|
||||
void SetTargetPos(const dtEntity::Vec3d &targetPos) { mTargetPos = targetPos; }
|
||||
dtEntity::Vec3d GetTargetPos() const { return mTargetPos; }
|
||||
|
||||
void SetBuildingIdSrc(dtEntity::EntityId v) { mBuildingIdSrc = v; }
|
||||
dtEntity::EntityId GetBuildingIdSrc() const { return mBuildingIdSrc; }
|
||||
void SetRoomNumberSrc(const dtEntity::EntityId &v) { mRoomNumberSrc = v; }
|
||||
dtEntity::EntityId GetRoomNumberSrc() const { return mRoomNumberSrc; }
|
||||
|
||||
void SetBuildingIdDst(dtEntity::EntityId v) { mBuildingIdDst = v; }
|
||||
dtEntity::EntityId GetBuildingIdDst() const { return mBuildingIdDst; }
|
||||
void SetRoomNumberDst(const dtEntity::EntityId &v) { mRoomNumberDst = v; }
|
||||
dtEntity::EntityId GetRoomNumberDst() const { return mRoomNumberDst; }
|
||||
|
||||
void SetDuration(float v) { mDuration = v; }
|
||||
float GetDuration() const { return mDuration; }
|
||||
|
||||
void SetLineType(int v) { mLineType = v; }
|
||||
float GetLineType() const { return mLineType; }
|
||||
|
||||
void SetSimTimeCreated(double v) { mSimTimeCreated = v; }
|
||||
double GetSimTimeCreated() const { return mSimTimeCreated; }
|
||||
|
||||
void SetId(int32_t id) { mId = id; }
|
||||
int32_t GetId() const { return mId; }
|
||||
|
||||
private:
|
||||
int32_t mId { 0 };
|
||||
dtEntity::Vec3d mShooterPos;
|
||||
dtEntity::Vec3d mTargetPos;
|
||||
dtEntity::EntityId mShooter = 0;
|
||||
dtEntity::EntityId mTarget = 0;
|
||||
dtEntity::EntityId mBuildingIdSrc = 0;
|
||||
dtEntity::EntityId mRoomNumberSrc = 0;
|
||||
dtEntity::EntityId mBuildingIdDst = 0;
|
||||
dtEntity::EntityId mRoomNumberDst = 0;
|
||||
int mLineType = 0;
|
||||
float mDuration = 0.f;
|
||||
double mSimTimeCreated = 0;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class ShowHidePlayerMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
|
||||
ShowHidePlayerMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<ShowHidePlayerMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetShow(bool v) { mShow = v; }
|
||||
bool GetShow() const { return mShow; }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity = 0;
|
||||
bool mShow = false;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////<
|
||||
class DisplayNameClickedMessage
|
||||
: public dtEntity::Message
|
||||
{
|
||||
public:
|
||||
|
||||
static const dtEntity::MessageType TYPE;
|
||||
static const dtEntity::StringId AboutEntityId;
|
||||
static const dtEntity::StringId PositionId;
|
||||
|
||||
DisplayNameClickedMessage();
|
||||
dtEntity::Message* Clone() const override { return CloneContainer<DisplayNameClickedMessage>(); }
|
||||
|
||||
void SetAboutEntityId(dtEntity::EntityId v) { mAboutEntity.Set(v); }
|
||||
dtEntity::EntityId GetAboutEntityId() const { return mAboutEntity.Get(); }
|
||||
|
||||
void SetPosition(const osg::Vec3f& v) { mPosition.Set(v); }
|
||||
osg::Vec3f GetPosition() const { return mPosition.Get(); }
|
||||
|
||||
private:
|
||||
dtEntity::UIntProperty mAboutEntity;
|
||||
dtEntity::Vec3Property mPosition;
|
||||
};
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
#include "modelsplittercomponent.h"
|
||||
|
||||
#include "visitors.h"
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Group>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QSet>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId ModelSplitterComponent::TYPE(dtEntity::SID("ModelSplitter"));
|
||||
const dtEntity::StringId ModelSplitterComponent::VerticalDisplaceId(dtEntity::SID("VerticalDisplace"));
|
||||
const dtEntity::StringId ModelSplitterComponent::HorizontalDisplaceId(dtEntity::SID("HorizontalDisplace"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
ModelSplitterComponent::ModelSplitterComponent()
|
||||
{
|
||||
Register(VerticalDisplaceId, &mVerticalDisplace);
|
||||
Register(HorizontalDisplaceId, &mHorizontalDisplace);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ModelSplitterComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
BaseClass::OnAddedToEntity(entity);
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ModelSplitterComponent::Split(std::vector<dtEntity::EntityId> &eids, std::vector<float> &heights, std::vector<int> &floors, dtEntity::StringId layerName)
|
||||
{
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smc;
|
||||
if (!mEntity->GetComponent(smc))
|
||||
{
|
||||
LOG_ERROR("Cannot split: Has no staticmeshcomponent");
|
||||
return;
|
||||
}
|
||||
osg::ref_ptr<osg::Node> mesh = osgDB::readNodeFile(smc->GetMesh());
|
||||
if (mesh == nullptr) return;
|
||||
|
||||
SplitVisitor v;
|
||||
mesh->accept(v);
|
||||
heights = v._heights;
|
||||
mesh = nullptr;
|
||||
|
||||
for (const auto &part : v._parts)
|
||||
{
|
||||
osg::ref_ptr<osg::Node> node = osg::clone(part.get(), osg::CopyOp(
|
||||
osg::CopyOp::DEEP_COPY_OBJECTS |
|
||||
osg::CopyOp::DEEP_COPY_NODES |
|
||||
osg::CopyOp::DEEP_COPY_USERDATA
|
||||
));
|
||||
|
||||
|
||||
dtEntity::Entity *e;
|
||||
if (!mEntity->GetEntityManager().CreateEntity(e))
|
||||
continue;
|
||||
eids.push_back(e->GetId());
|
||||
|
||||
std::string nname = node->getName();
|
||||
std::string floorstr = nname.substr(6, nname.size() - 1);
|
||||
|
||||
int floor = QString::fromStdString(floorstr).toInt();
|
||||
floors.push_back(floor);
|
||||
|
||||
std::ostringstream entityname;
|
||||
entityname << dtEntity::GetStringFromSID(layerName) << "_" << floorstr;
|
||||
|
||||
dtEntity::MapComponent *mc;
|
||||
if (!e->CreateComponent(mc))
|
||||
continue;
|
||||
mc->SetEntityName(entityname.str());
|
||||
mc->SetUniqueId(entityname.str());
|
||||
mc->SetMapName("parts");
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smcFloor;
|
||||
if (!e->CreateComponent(smcFloor))
|
||||
continue;
|
||||
smcFloor->SetStaticMesh(node);
|
||||
dtEntityOSG::PositionAttitudeTransformComponent *pc;
|
||||
if (!e->CreateComponent(pc))
|
||||
continue;
|
||||
pc->AddChildComponent(smcFloor->GetType());
|
||||
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (!e->CreateComponent(lc))
|
||||
continue;
|
||||
lc->SetAttachedComponent(pc->GetType());
|
||||
lc->SetLayer(layerName);
|
||||
lc->Finished();
|
||||
|
||||
}
|
||||
|
||||
// sort
|
||||
std::sort(floors.begin(), floors.end());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId ModelSplitterSystem::TYPE(dtEntity::SID("ModelSplitter"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
ModelSplitterSystem::ModelSplitterSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<ModelSplitterComponent>(em)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/message.h>
|
||||
#include <dtEntity/stringid.h>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntity/scriptaccessor.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
class ModelSplitterComponent final : public dtEntity::Component
|
||||
{
|
||||
|
||||
using BaseClass = dtEntity::Component;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId VerticalDisplaceId;
|
||||
static const dtEntity::StringId HorizontalDisplaceId;
|
||||
|
||||
|
||||
ModelSplitterComponent();
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
void Split(std::vector<dtEntity::EntityId> &eids, std::vector<float> &heights, std::vector<int> &floors, dtEntity::StringId layerName);
|
||||
|
||||
dtEntity::FloatProperty mVerticalDisplace;
|
||||
dtEntity::Vec2Property mHorizontalDisplace;
|
||||
|
||||
void SetBuildingId(dtEntity::StringId id) { mBuildingId = id; }
|
||||
dtEntity::StringId GetBuildingId() const { return mBuildingId; }
|
||||
|
||||
private:
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
dtEntity::StringId mBuildingId = 0;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
class ModelSplitterSystem final
|
||||
: public dtEntity::DefaultEntitySystem<ModelSplitterComponent>
|
||||
, public dtEntity::ScriptAccessor
|
||||
{
|
||||
public:
|
||||
explicit ModelSplitterSystem(dtEntity::EntityManager &em);
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
#include "motionmodel.h"
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osg/io_utils>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId MotionModelComponent::TYPE(dtEntity::SID("MotionModel"));
|
||||
|
||||
const dtEntity::StringId MotionModelComponent::ContextIdId(dtEntity::SID("ContextId"));
|
||||
const dtEntity::StringId MotionModelComponent::MoveSpeedId(dtEntity::SID("MoveSpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::RotateSpeedId(dtEntity::SID("RotateSpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::RotateKeySpeedId(dtEntity::SID("RotateKeySpeed"));
|
||||
const dtEntity::StringId MotionModelComponent::EnabledId(dtEntity::SID("Enabled"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId MotionModelSystem::TYPE(dtEntity::SID("MotionModel"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
MotionModelComponent::MotionModelComponent()
|
||||
{
|
||||
Register(ContextIdId, &mContextId);
|
||||
Register(MoveSpeedId, &mMoveSpeed);
|
||||
Register(RotateSpeedId, &mRotateSpeed);
|
||||
Register(RotateKeySpeedId, &mRotateKeySpeed);
|
||||
Register(EnabledId, &mEnabled);
|
||||
|
||||
mContextId.Set(0);
|
||||
mMoveSpeed.Set(100);
|
||||
mRotateSpeed.Set(0.001f);
|
||||
mRotateKeySpeed.Set(2);
|
||||
mEnabled.Set(true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
dtEntity::GetInputInterface()->AddInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::OnRemovedFromEntity(dtEntity::Entity &)
|
||||
{
|
||||
mEntity = nullptr;
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::Finished()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
bool success = mEntity->GetComponent(mCamera);
|
||||
if (success)
|
||||
mContextId.Set(mCamera->GetContextId());
|
||||
else
|
||||
LOG_ERROR("MotionModelComponent on entity without camera component!");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::KeyUp(const std::string &key, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!handled && mEnabled.Get() && (int)contextid == mContextId.Get())
|
||||
{
|
||||
if (key == "t")
|
||||
{
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
LOG_ALWAYS("Translation: " << campos)
|
||||
}
|
||||
else if (key == "1") mMoveSpeed.Set(5);
|
||||
else if (key == "2") mMoveSpeed.Set(15);
|
||||
else if (key == "3") mMoveSpeed.Set(40);
|
||||
else if (key == "4") mMoveSpeed.Set(100);
|
||||
else if (key == "5") mMoveSpeed.Set(250);
|
||||
else if (key == "6") mMoveSpeed.Set(600);
|
||||
else if (key == "7") mMoveSpeed.Set(1500);
|
||||
else if (key == "8") mMoveSpeed.Set(4000);
|
||||
else if (key == "9") mMoveSpeed.Set(9000);
|
||||
else if (key == "0") mMoveSpeed.Set(20000);
|
||||
else if (key == "KP_Add") mMoveSpeed.Set(mMoveSpeed.Get() * 1.1f);
|
||||
else if (key == "KP_Subtract") mMoveSpeed.Set(mMoveSpeed.Get() / 1.1f);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::KeyDown(const std::string &, bool, unsigned int)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseButtonUp(int button, bool, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
if (button == 1 || button == 2)
|
||||
dtEntity::GetInputInterface()->SetLockCursor(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseButtonDown(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled) return false;
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
if (button == 1)
|
||||
inputif->SetLockCursor(true);
|
||||
else if (button == 2)
|
||||
{
|
||||
// do intersection test to get pivot point to rotate around
|
||||
inputif->SetLockCursor(true);
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYId);
|
||||
osg::Vec3 pickray = dtEntity::GetWindowInterface()->GetPickRay(contextid, mouseX, mouseY);
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
|
||||
std::vector<dtEntity::WindowInterface::Intersection> isects;
|
||||
bool found = dtEntity::GetWindowInterface()->GetIntersections(campos, campos + pickray * 10000, isects);
|
||||
if (found)
|
||||
mPivot = isects.front().mPosition;
|
||||
else
|
||||
mPivot = campos + pickray * 100;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseWheel(int dir, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get())
|
||||
return false;
|
||||
|
||||
if (!handled && mCamera != nullptr && mContextId.Get() == (int)contextid)
|
||||
{
|
||||
osg::Vec3d campos = mCamera->GetPosition();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
mCamera->SetPosition(campos + eyedir * dir * 20);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool MotionModelComponent::MouseMove(float, float, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled)
|
||||
return false;
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get() || mContextId.Get() != (int)contextid)
|
||||
return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaXRawId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaYRawId);
|
||||
|
||||
osg::Vec3d up = mCamera->GetUp();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
osg::Vec3d toRight = eyedir ^ up;
|
||||
|
||||
if (inputif->GetMouseButton(1, mContextId.Get()))
|
||||
{
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(-mouseX * mRotateSpeed.Get(), up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * mRotateSpeed.Get(), toRight);
|
||||
eyedir = (rotateop1 * rotateop2) * eyedir;
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
else if (inputif->GetMouseButton(2, mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d pivotToCam = mCamera->GetPosition() - mPivot;
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(mouseX * -0.001f, up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * 0.001f, toRight);
|
||||
pivotToCam = (rotateop1 * rotateop2) * pivotToCam;
|
||||
mCamera->SetPosition(pivotToCam + mPivot);
|
||||
|
||||
pivotToCam *= -1;
|
||||
pivotToCam.normalize();
|
||||
mCamera->SetEyeDirection(pivotToCam);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelComponent::Tick(float dt)
|
||||
{
|
||||
if (mCamera == nullptr || !mEnabled.Get())
|
||||
return;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
float speed = mMoveSpeed.Get();
|
||||
if (inputif->GetKey("Shift_L", mContextId.Get()))
|
||||
speed *= 4;
|
||||
|
||||
bool modified = false;
|
||||
if (inputif->GetKey("w", mContextId.Get()))
|
||||
{
|
||||
mCamera->SetPosition(mCamera->GetPosition() + mCamera->GetEyeDirection() * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("s", mContextId.Get()))
|
||||
{
|
||||
mCamera->SetPosition(mCamera->GetPosition() + mCamera->GetEyeDirection() * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("a", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + toRight * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("d", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + toRight * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("q", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + (toRight ^ mCamera->GetEyeDirection()) * (dt * -speed));
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("e", mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d toRight = mCamera->GetEyeDirection() ^ mCamera->GetUp();
|
||||
mCamera->SetPosition(mCamera->GetPosition() + (toRight ^ mCamera->GetEyeDirection()) * (dt * speed));
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (inputif->GetKey("Left", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * mRotateKeySpeed.Get(), mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Right", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * mRotateKeySpeed.Get(), mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Up", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * mRotateKeySpeed.Get(), mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Down", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * mRotateKeySpeed.Get(), mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
mCamera->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
MotionModelSystem::MotionModelSystem(dtEntity::EntityManager &em)
|
||||
: BaseClass(em)
|
||||
{
|
||||
mTickFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::Tick);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::TickMessage::TYPE,
|
||||
mTickFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::Tick");
|
||||
|
||||
mMoveToPosFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::MoveToPos);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::MoveCameraToPositionMessage::TYPE,
|
||||
mMoveToPosFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::MoveToPos");
|
||||
|
||||
mMoveToEntityFunctor = dtEntity::MessageFunctor(this, &MotionModelSystem::MoveToEntity);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::MoveCameraToEntityMessage::TYPE,
|
||||
mMoveToEntityFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "MotionModelSystem::MoveToEntity");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::Tick(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
for (auto i : mComponents)
|
||||
i.second->Tick(msg.GetDeltaRealTime());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::MoveToPos(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::MoveCameraToPositionMessage &msg = static_cast<const dtEntity::MoveCameraToPositionMessage &>(m);
|
||||
for (auto i : mComponents)
|
||||
{
|
||||
MotionModelComponent *mmc = i.second;
|
||||
if ((int)mmc->GetContextId() == msg.GetContextId())
|
||||
{
|
||||
dtEntityOSG::CameraComponent *cam = mmc->GetCamera();
|
||||
if (cam)
|
||||
{
|
||||
cam->SetPosition(msg.GetPosition());
|
||||
osg::Vec3d eyedir = msg.GetLookAt() - msg.GetPosition();
|
||||
eyedir.normalize();
|
||||
cam->SetEyeDirection(eyedir);
|
||||
cam->SetUp(msg.GetUp());
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void MotionModelSystem::MoveToEntity(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::MoveCameraToEntityMessage &msg = static_cast<const dtEntity::MoveCameraToEntityMessage &>(m);
|
||||
|
||||
dtEntityOSG::TransformComponent *transcomp;
|
||||
if (!GetEntityManager().GetComponent(msg.GetAboutEntityId(), transcomp, true))
|
||||
{
|
||||
LOG_ERROR("Cannot jump to entity: has no transform component!");
|
||||
return;
|
||||
}
|
||||
osg::Vec3d targetpos = transcomp->GetTranslation();
|
||||
|
||||
for (auto i : mComponents)
|
||||
{
|
||||
MotionModelComponent *mmc = i.second;
|
||||
if ((int)mmc->GetContextId() != msg.GetContextId()) continue;
|
||||
|
||||
dtEntityOSG::CameraComponent *cam = mmc->GetCamera();
|
||||
if (!cam) continue;
|
||||
|
||||
if (msg.GetKeepCameraDirection())
|
||||
{
|
||||
osg::Vec3d eyedir = cam->GetEyeDirection();
|
||||
eyedir *= msg.GetDistance();
|
||||
cam->SetPosition(targetpos - eyedir);
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Vec3d eyedir = targetpos - cam->GetPosition();
|
||||
eyedir.normalize();
|
||||
cam->SetEyeDirection(eyedir);
|
||||
cam->SetPosition(targetpos + eyedir * -msg.GetDistance());
|
||||
cam->UpdateViewMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntity/inputinterface.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class MotionModelComponent final
|
||||
: public dtEntity::Component
|
||||
, public dtEntity::InputCallbackInterface
|
||||
{
|
||||
public:
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId ContextIdId;
|
||||
static const dtEntity::StringId MoveSpeedId;
|
||||
static const dtEntity::StringId RotateSpeedId;
|
||||
static const dtEntity::StringId RotateKeySpeedId;
|
||||
static const dtEntity::StringId EnabledId;
|
||||
|
||||
|
||||
MotionModelComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return (id == TYPE);
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
void OnRemovedFromEntity(dtEntity::Entity &) override;
|
||||
|
||||
void Finished() override;
|
||||
void Tick(float dt);
|
||||
|
||||
unsigned int GetContextId() const { return mContextId.Get(); }
|
||||
void SetContextId(unsigned int i) { mContextId.Set(i); }
|
||||
|
||||
bool KeyUp(const std::string &key, bool handled, unsigned int contextid) override;
|
||||
bool KeyDown(const std::string &name, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonUp(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonDown(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseWheel(int dir, bool handled, unsigned int contextid) override;
|
||||
bool MouseMove(float x, float y, bool handled, unsigned int contextid) override;
|
||||
void MouseEnterLeave(bool, unsigned int) override {}
|
||||
|
||||
dtEntityOSG::CameraComponent *GetCamera() const { return mCamera; }
|
||||
private:
|
||||
dtEntity::IntProperty mContextId;
|
||||
dtEntity::UIntProperty mMoveSpeed;
|
||||
dtEntity::FloatProperty mRotateSpeed;
|
||||
dtEntity::FloatProperty mRotateKeySpeed;
|
||||
dtEntity::BoolProperty mEnabled;
|
||||
dtEntityOSG::CameraComponent *mCamera = nullptr;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
osg::Vec3d mPivot;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class MotionModelSystem final
|
||||
: public dtEntity::DefaultEntitySystem<MotionModelComponent>
|
||||
{
|
||||
using BaseClass = dtEntity::DefaultEntitySystem<MotionModelComponent>;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
explicit MotionModelSystem(dtEntity::EntityManager &em);
|
||||
|
||||
private:
|
||||
|
||||
void Tick(const dtEntity::Message &m);
|
||||
void MoveToPos(const dtEntity::Message &m);
|
||||
void MoveToEntity(const dtEntity::Message &m);
|
||||
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
dtEntity::MessageFunctor mMoveToPosFunctor;
|
||||
dtEntity::MessageFunctor mMoveToEntityFunctor;
|
||||
};
|
||||
}
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
#include "orthomotionmodel.h"
|
||||
|
||||
#include "messages.h"
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/systeminterface.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/layerattachpointcomponent.h>
|
||||
#include <dtEntityOSG/skyboxcomponent.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
#include <osgViewer/View>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
constexpr int LeftMouseButton = 0;
|
||||
//const int RightMouseButton = 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId OrthoMotionModelComponent::TYPE(dtEntity::SID("OrthoMotionModel"));
|
||||
|
||||
const dtEntity::StringId OrthoMotionModelComponent::ContextIdId(dtEntity::SID("ContextId"));
|
||||
const dtEntity::StringId OrthoMotionModelComponent::EnabledId(dtEntity::SID("Enabled"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId OrthoMotionModelSystem::TYPE(dtEntity::SID("OrthoMotionModel"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
OrthoMotionModelComponent::OrthoMotionModelComponent()
|
||||
{
|
||||
Register(ContextIdId, &mContextId);
|
||||
Register(EnabledId, &mEnabled);
|
||||
|
||||
mContextId.Set(0);
|
||||
mEnabled.Set(true);
|
||||
|
||||
m_mouseMovedWhileLeftButtonPressed = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
dtEntity::GetInputInterface()->AddInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::OnRemovedFromEntity(dtEntity::Entity &)
|
||||
{
|
||||
mEntity = nullptr;
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::Finished()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
bool success = mEntity->GetComponent(mCamera);
|
||||
if (success)
|
||||
mContextId.Set(mCamera->GetContextId());
|
||||
else
|
||||
LOG_ERROR("MotionModelComponent on entity without camera component!");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseButtonUp(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
(void)(handled);
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
if (button == LeftMouseButton)
|
||||
{
|
||||
if(!m_mouseMovedWhileLeftButtonPressed)
|
||||
{
|
||||
/*
|
||||
* Mouse has not been moved, this means user clicked and immediately released the left button.
|
||||
* This means: Select object under cursor (if existent)
|
||||
*/
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXRawId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYRawId);
|
||||
dtEntityOSG::CameraSystem *camsys;
|
||||
mEntity->GetEntityManager().GetES(camsys);
|
||||
if (!camsys)
|
||||
return false;
|
||||
dtEntity::EntityId camid = camsys->GetCameraEntityByContextId(mContextId.Get());
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
mEntity->GetEntityManager().GetComponent(camid, camcomp);
|
||||
if (!camcomp)
|
||||
return false;
|
||||
|
||||
osgUtil::LineSegmentIntersector::Intersections isects;
|
||||
osgViewer::View *v = dynamic_cast<osgViewer::View *>(camcomp->GetCamera()->getView());
|
||||
bool found = v->computeIntersections(mouseX, mouseY, isects, 0xFFFFFFFF);
|
||||
|
||||
if (found)
|
||||
{
|
||||
osgUtil::LineSegmentIntersector::Intersections::const_iterator i;
|
||||
for (const osgUtil::LineSegmentIntersector::Intersection &isect : isects)
|
||||
{
|
||||
for (osg::NodePath::const_reverse_iterator j = isect.nodePath.rbegin(); j != isect.nodePath.rend(); ++j)
|
||||
{
|
||||
const osg::Node *node = *j;
|
||||
if (node->getName() == "icon")
|
||||
{
|
||||
const osg::Referenced *referenced = node->getUserData();
|
||||
if (referenced == nullptr) continue;
|
||||
const dtEntityOSG::EntityData *ed = dynamic_cast<const dtEntityOSG::EntityData *>(referenced);
|
||||
if (ed != nullptr && ed->mEntity->GetId() != camid)
|
||||
{
|
||||
PlayerPickedMessage msg;
|
||||
msg.SetAboutEntityId(ed->mEntity->GetId());
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
if(node->getName() == "text")
|
||||
{
|
||||
const osg::Referenced* referenced = node->getUserData();
|
||||
if(referenced == nullptr) continue;
|
||||
const dtEntityOSG::EntityData* ed = dynamic_cast<const dtEntityOSG::EntityData*>(referenced);
|
||||
if(ed != nullptr && ed->mEntity->GetId() != camid)
|
||||
{
|
||||
DisplayNameClickedMessage msg;
|
||||
msg.SetAboutEntityId(ed->mEntity->GetId());
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mouseMovedWhileLeftButtonPressed = false;
|
||||
|
||||
dtEntity::GetInputInterface()->SetLockCursor(false);
|
||||
dtEntity::GetWindowInterface()->SetShowCursor(contextid, true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseButtonDown(int button, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (handled) return false;
|
||||
if (!mEnabled.Get() || (int)contextid != mContextId.Get()) return false;
|
||||
|
||||
if (button == LeftMouseButton)
|
||||
{
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
inputif->SetLockCursor(true);
|
||||
dtEntity::GetWindowInterface()->SetShowCursor(contextid, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseMove(float x, float y, bool handled, unsigned int contextid)
|
||||
{
|
||||
(void)(x);
|
||||
(void)(y);
|
||||
if (handled)
|
||||
return false;
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get() || mContextId.Get() != (int)contextid)
|
||||
return false;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseDeltaYId);
|
||||
|
||||
if (inputif->GetMouseButton(LeftMouseButton, mContextId.Get()))
|
||||
{
|
||||
m_mouseMovedWhileLeftButtonPressed = true;
|
||||
|
||||
double left, right, bottom, top, znear, zfar;
|
||||
mCamera->GetCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, znear, zfar);
|
||||
|
||||
// scale movement speed by zoom factor
|
||||
float speed = -0.35f * (right - left);
|
||||
|
||||
left = left + speed * mouseX;
|
||||
right = right + speed * mouseX;
|
||||
bottom = bottom + speed * mouseY;
|
||||
top = top + speed * mouseY;
|
||||
|
||||
mCamera->SetOrthoLeft(left);
|
||||
mCamera->SetOrthoRight(right);
|
||||
mCamera->SetOrthoBottom(bottom);
|
||||
mCamera->SetOrthoTop(top);
|
||||
|
||||
mCamera->UpdateViewMatrix();
|
||||
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
|
||||
|
||||
if(m_callbackCamPosChanged)
|
||||
{
|
||||
m_callbackCamPosChanged(GetContextId(), BuildingViewer::CameraViewPosition(left, right, bottom, top));
|
||||
}
|
||||
}
|
||||
/*else if(inputif->GetMouseButton(LeftButton, mContextId.Get()))
|
||||
{
|
||||
osg::Vec3d up = mCamera->GetUp();
|
||||
osg::Vec3d eyedir = mCamera->GetEyeDirection();
|
||||
osg::Vec3d toRight = eyedir ^ up;
|
||||
osg::Vec3d pivotToCam = mCamera->GetPosition();
|
||||
osg::Quat rotateop1; rotateop1.makeRotate(mouseX * -0.001f, up);
|
||||
osg::Quat rotateop2; rotateop2.makeRotate(mouseY * 0.001f, toRight);
|
||||
pivotToCam = (rotateop1 * rotateop2) * pivotToCam;
|
||||
osg::Vec3d eyedir = pivotToCam;
|
||||
eyedir *= -1;
|
||||
eyedir.normalize();
|
||||
if(fabs(eyedir[2]) < 0.99f)
|
||||
{
|
||||
mCamera->SetPosition(pivotToCam);
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
}*/
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::performZoom(int dir, const osg::Vec2& zoompoint)
|
||||
{
|
||||
double left, right, bottom, top, znear, zfar;
|
||||
mCamera->GetCamera()->getProjectionMatrixAsOrtho(left, right, bottom, top, znear, zfar);
|
||||
|
||||
osg::Vec2 zoompointabs(right * zoompoint[0] + left * (1 - zoompoint[0]),
|
||||
top * zoompoint[1] + bottom * (1 - zoompoint[1]));
|
||||
|
||||
float zoom = 1.0f - dir * 0.2f;
|
||||
|
||||
left = zoompointabs[0] - (zoompointabs[0] - left) * zoom;
|
||||
right = zoompointabs[0] - (zoompointabs[0] - right) * zoom;
|
||||
bottom = zoompointabs[1] - (zoompointabs[1] - bottom) * zoom;
|
||||
top = zoompointabs[1] - (zoompointabs[1] - top) * zoom;
|
||||
|
||||
mCamera->SetOrthoLeft(left);
|
||||
mCamera->SetOrthoRight(right);
|
||||
mCamera->SetOrthoBottom(bottom);
|
||||
mCamera->SetOrthoTop(top);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
|
||||
if(m_callbackCamPosChanged)
|
||||
{
|
||||
m_callbackCamPosChanged(GetContextId(), BuildingViewer::CameraViewPosition(left, right, bottom, top));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool OrthoMotionModelComponent::MouseWheel(int dir, bool handled, unsigned int contextid)
|
||||
{
|
||||
if (!mEnabled.Get())
|
||||
return false;
|
||||
|
||||
if (!handled && mCamera != nullptr && mContextId.Get() == (int)contextid)
|
||||
{
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
double mouseX = inputif->GetAxis(dtEntity::InputInterface::MouseXId);
|
||||
double mouseY = inputif->GetAxis(dtEntity::InputInterface::MouseYId);
|
||||
|
||||
osg::Vec2 zoompoint(0.5f, 0.5f);
|
||||
int x, y, w, h;
|
||||
dtEntity::GetWindowInterface()->GetWindowGeometry(contextid, x, y, w, h);
|
||||
if (mouseX >= -1 && mouseX <= 1 && mouseY >= -1 && mouseY <= 1)
|
||||
{
|
||||
zoompoint[0] = (mouseX + 1) / 2.0f;
|
||||
zoompoint[1] = (mouseY + 1) / 2.0f;
|
||||
}
|
||||
|
||||
performZoom(dir, zoompoint);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelComponent::Tick(float dt)
|
||||
{
|
||||
static const dtEntity::StringId MotionModelTick = dtEntity::SID("MotionModel Tick");
|
||||
CProfileManager::Start_Profile(MotionModelTick);
|
||||
|
||||
if (mCamera == nullptr || !mEnabled.Get())
|
||||
return;
|
||||
|
||||
dtEntity::InputInterface *inputif = dtEntity::GetInputInterface();
|
||||
|
||||
bool modified = false;
|
||||
osg::Vec3d pos = mCamera->GetPosition();
|
||||
|
||||
float rotateKeySpeed = 1.0f;
|
||||
if (inputif->GetKey("Left", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * rotateKeySpeed, mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Right", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * rotateKeySpeed, mCamera->GetUp());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Up", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(-dt * rotateKeySpeed, mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
if (inputif->GetKey("Down", mContextId.Get()))
|
||||
{
|
||||
osg::Quat q; q.makeRotate(dt * rotateKeySpeed, mCamera->GetUp() ^ mCamera->GetEyeDirection());
|
||||
osg::Vec3d eyedir = q * mCamera->GetEyeDirection();
|
||||
eyedir.normalize();
|
||||
mCamera->SetEyeDirection(eyedir);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (modified)
|
||||
{
|
||||
mCamera->SetPosition(pos);
|
||||
mCamera->UpdateViewMatrix();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(mContextId.Get());
|
||||
}
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
OrthoMotionModelSystem::OrthoMotionModelSystem(dtEntity::EntityManager &em)
|
||||
: BaseClass(em)
|
||||
{
|
||||
/*mTickFunctor = dtEntity::MessageFunctor(this, &OrthoMotionModelSystem::Tick);
|
||||
GetEntityManager().RegisterForMessages(dtEntity::TickMessage::TYPE,
|
||||
mTickFunctor, dtEntity::FilterOptions::ORDER_DEFAULT, "OrthoMotionModelSystem::Tick");*/
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelSystem::OnRemoveFromEntityManager(dtEntity::EntityManager &)
|
||||
{
|
||||
for (const auto &comp : mComponents)
|
||||
dtEntity::GetInputInterface()->RemoveInputCallback(comp.second);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void OrthoMotionModelSystem::Tick(const dtEntity::Message &m)
|
||||
{
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->Tick(msg.GetDeltaRealTime());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/inputinterface.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include "cameraviewposition.h"
|
||||
#include <functional>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class OrthoMotionModelComponent final
|
||||
: public dtEntity::Component
|
||||
, public dtEntity::InputCallbackInterface
|
||||
{
|
||||
public:
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
static const dtEntity::StringId ContextIdId;
|
||||
static const dtEntity::StringId EnabledId;
|
||||
|
||||
|
||||
OrthoMotionModelComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return (id == TYPE);
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
void OnRemovedFromEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
void Finished() override;
|
||||
void Tick(float dt);
|
||||
|
||||
unsigned int GetContextId() const { return mContextId.Get(); }
|
||||
void SetContextId(unsigned int i) { mContextId.Set(i); }
|
||||
|
||||
bool MouseButtonUp(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseButtonDown(int button, bool handled, unsigned int contextid) override;
|
||||
bool MouseWheel(int dir, bool handled, unsigned int contextid) override;
|
||||
bool MouseMove(float x, float y, bool handled, unsigned int contextid) override;
|
||||
void MouseEnterLeave(bool, unsigned int) override {}
|
||||
|
||||
void performZoom(int dir, const osg::Vec2& zoompoint);
|
||||
|
||||
dtEntityOSG::CameraComponent *GetCamera() const { return mCamera; }
|
||||
|
||||
|
||||
// First parameter: contextID as returned by OrthoMotionModelComponent::GetContextId
|
||||
std::function<void(unsigned int, const BuildingViewer::CameraViewPosition &)> m_callbackCamPosChanged;
|
||||
|
||||
private:
|
||||
bool m_mouseMovedWhileLeftButtonPressed;
|
||||
|
||||
dtEntity::IntProperty mContextId;
|
||||
dtEntity::BoolProperty mEnabled;
|
||||
dtEntityOSG::CameraComponent *mCamera = nullptr;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class OrthoMotionModelSystem final
|
||||
: public dtEntity::DefaultEntitySystem<OrthoMotionModelComponent>
|
||||
{
|
||||
using BaseClass = dtEntity::DefaultEntitySystem<OrthoMotionModelComponent>;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
explicit OrthoMotionModelSystem(dtEntity::EntityManager &em);
|
||||
|
||||
void OnRemoveFromEntityManager(dtEntity::EntityManager &) override;
|
||||
|
||||
private:
|
||||
|
||||
void Tick(const dtEntity::Message &m);
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,401 @@
|
||||
#include "playercomponent.h"
|
||||
|
||||
#include "iconcomponent.h"
|
||||
#include "messages.h"
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/profile.h>
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/shadercomponent.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
#include <osgDB/ReadFile>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShowHidePlayerCommand : public PlayerComponent::Command
|
||||
{
|
||||
bool mShow;
|
||||
|
||||
ShowHidePlayerCommand(double when, bool show)
|
||||
: Command(when)
|
||||
, mShow(show)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (component->GetEntity()->GetComponent(lc))
|
||||
{
|
||||
lc->SetVisible(mShow);
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
}
|
||||
IconComponent *ic;
|
||||
if (component->GetEntity()->GetComponent(ic))
|
||||
ic->SetVisible(mShow);
|
||||
|
||||
ShowHidePlayerMessage msg;
|
||||
msg.SetAboutEntityId(component->GetEntity()->GetId());
|
||||
msg.SetShow(mShow);
|
||||
component->GetEntity()->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct TeleportToTargetCommand : public PlayerComponent::Command
|
||||
{
|
||||
osg::Vec3d mGoal;
|
||||
VCtrl::OBB mOBB;
|
||||
int mRoomNumber;
|
||||
std::string mRoomname;
|
||||
|
||||
TeleportToTargetCommand(double when, const osg::Vec3d& goal, const VCtrl::OBB& obb, int roomNumber, const std::string& roomname)
|
||||
: Command(when)
|
||||
, mGoal(goal)
|
||||
, mOBB(obb)
|
||||
, mRoomNumber(roomNumber)
|
||||
, mRoomname(roomname)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntityOSG::TransformComponent *tc = component->GetTransform();
|
||||
if (tc)
|
||||
{
|
||||
tc->SetTranslation(mGoal);
|
||||
tc->Finished();
|
||||
}
|
||||
else
|
||||
LOG_ERROR("Cannot teleport: no transform component!");
|
||||
component->PlaceAt(mGoal, mOBB, mRoomNumber, mRoomname);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct RemoveShootCommand : public PlayerComponent::Command
|
||||
{
|
||||
int mId;
|
||||
RemoveShootCommand(double when, int32_t id)
|
||||
: Command(when)
|
||||
, mId(id)
|
||||
{}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntity::EntityManager &em = component->GetEntity()->GetEntityManager();
|
||||
|
||||
RemoveShootMessage msg;
|
||||
msg.SetId(mId);
|
||||
em.EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
struct ShootCommand : public PlayerComponent::Command
|
||||
{
|
||||
int mId;
|
||||
Vec3d mShooterPos;
|
||||
Vec3d mTargetPos;
|
||||
dtEntity::EntityId mShooter;
|
||||
dtEntity::EntityId mTarget;
|
||||
int mBuildingIdSrc;
|
||||
int mRoomNumberSrc;
|
||||
int mBuildingIdDst;
|
||||
int mRoomNumberDst;
|
||||
int mLineType;
|
||||
float mDuration;
|
||||
double mSimTimeCreated;
|
||||
|
||||
ShootCommand(double when, int id, dtEntity::EntityId shooter, dtEntity::EntityId target,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType, float duration)
|
||||
: Command(when)
|
||||
, mId(id)
|
||||
, mShooterPos(shooterPos)
|
||||
, mTargetPos(targetPos)
|
||||
, mShooter(shooter)
|
||||
, mTarget(target)
|
||||
, mBuildingIdSrc(buildingIdSrc)
|
||||
, mRoomNumberSrc(roomNumberSrc)
|
||||
, mBuildingIdDst(buildingIdDst)
|
||||
, mRoomNumberDst(roomNumberDst)
|
||||
, mLineType(lineType)
|
||||
, mDuration(duration)
|
||||
, mSimTimeCreated(when)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(PlayerComponent *component) override
|
||||
{
|
||||
dtEntity::EntityManager &em = component->GetEntity()->GetEntityManager();
|
||||
|
||||
// check if source/target is visible
|
||||
|
||||
dtEntity::Vec3d shooterpos(mShooterPos.x, mShooterPos.y, mShooterPos.z);
|
||||
dtEntity::Vec3d targetpos(mTargetPos.x, mTargetPos.y, mTargetPos.z);
|
||||
|
||||
// draw an arrow
|
||||
const osg::Vec4 shooterColor = component->GetColor();
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(shooterpos, targetpos, shooterColor, 2, mDuration, false);
|
||||
osg::Vec3d edge = shooterpos - targetpos;
|
||||
edge.normalize();
|
||||
edge *= 0.5f;
|
||||
osg::Quat q;
|
||||
q.makeRotate(osg::PI / 4.0, 0, 0, 1);
|
||||
|
||||
osg::Vec3d result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
q.makeRotate(-osg::PI / 4.0, 0, 0, 1);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
osg::Vec3d left = edge ^ osg::Vec3d(0, 0, 1);
|
||||
q.makeRotate(osg::PI / 4.0, left[0], left[1], left[2]);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
q.makeRotate(-osg::PI / 4.0, left[0], left[1], left[2]);
|
||||
result = q * edge;
|
||||
dtEntity::GetDebugDrawInterface()->AddLine(targetpos, targetpos + result, shooterColor, 2, mDuration, false);
|
||||
|
||||
ShootMessage msg;
|
||||
msg.SetId(mId);
|
||||
msg.SetShooter(mShooter);
|
||||
msg.SetShooterPos(osg::Vec3d(mShooterPos.x, mShooterPos.y, mShooterPos.z));
|
||||
msg.SetTarget(mTarget);
|
||||
msg.SetTargetPos(osg::Vec3d(mTargetPos.x, mTargetPos.y, mTargetPos.z));
|
||||
msg.SetBuildingIdSrc(mBuildingIdSrc);
|
||||
msg.SetRoomNumberSrc(mRoomNumberSrc);
|
||||
msg.SetBuildingIdDst(mBuildingIdDst);
|
||||
msg.SetRoomNumberDst(mRoomNumberDst);
|
||||
msg.SetLineType(mLineType);
|
||||
msg.SetDuration(mDuration);
|
||||
msg.SetSimTimeCreated(mSimTimeCreated);
|
||||
em.EmitMessage(msg);
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId PlayerComponent::TYPE(dtEntity::SID("Player"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::OnAddedToEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::OnRemovedFromEntity(dtEntity::Entity &entity)
|
||||
{
|
||||
NavMeshGroupChangedMessage msg;
|
||||
msg.SetPreviousGroupName(dtEntity::GetStringFromSID(mCurrentCellGroup));
|
||||
msg.SetAboutEntityId(GetEntity()->GetId());
|
||||
msg.SetGroupName("");
|
||||
entity.GetEntityManager().EmitMessage(msg);
|
||||
|
||||
mEntity = nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntityOSG::TransformComponent *PlayerComponent::GetTransform()
|
||||
{
|
||||
assert(mEntity != nullptr);
|
||||
if (mTransform == nullptr)
|
||||
{
|
||||
mEntity->GetComponent(mTransform, true);
|
||||
assert(mTransform);
|
||||
}
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::ExecuteCommands(double timenow)
|
||||
{
|
||||
if (mCommands.empty())
|
||||
return;
|
||||
|
||||
double nexttime = timenow;
|
||||
osg::ref_ptr<Command> execcommand = nullptr;
|
||||
for (const auto &command : mCommands)
|
||||
{
|
||||
if (command->mStartTime < nexttime)
|
||||
{
|
||||
execcommand = command;
|
||||
nexttime = command->mStartTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (execcommand.valid())
|
||||
{
|
||||
mCommands.erase(execcommand);
|
||||
execcommand->Execute(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::PositionOnMesh(const VCtrl::OBB& bb, osg::Vec3d& pos, const std::string& roomname)
|
||||
{
|
||||
GetTransform()->SetTranslation(pos);
|
||||
mPreviousRoom = mCurrentRoom;
|
||||
mCurrentRoom = dtEntity::SID(roomname);
|
||||
|
||||
if (bb.mBuilding != mCurrentCellGroup)
|
||||
{
|
||||
NavMeshGroupChangedMessage msg;
|
||||
msg.SetPreviousGroupName(dtEntity::GetStringFromSID(mCurrentCellGroup));
|
||||
msg.SetAboutEntityId(GetEntity()->GetId());
|
||||
msg.SetGroupName(dtEntity::GetStringFromSID(bb.mBuilding));
|
||||
|
||||
mCurrentCellGroup = bb.mBuilding;
|
||||
|
||||
GetEntity()->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::PlaceAt(const osg::Vec3d &_goal, const VCtrl::OBB &obb, int roomNumber, const std::string &roomname)
|
||||
{
|
||||
LOG_DEBUG("PlayerComponent::PlaceAt: " << "mEntity='"<< mEntity << "'"
|
||||
<< ", _goal: x=" << _goal.x() << " y=" << _goal.y() << " z=" << _goal.z()
|
||||
<< ", roomNumber="<< roomNumber
|
||||
<< ", roomname='"<< roomname << "'");
|
||||
|
||||
osg::Vec3d pgoal = _goal;
|
||||
|
||||
PositionOnMesh(obb, pgoal, roomname);
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
|
||||
TransformSendMessage msg;
|
||||
msg.SetAboutEntity(mEntity->GetId());
|
||||
msg.SetPosition(pgoal);
|
||||
msg.SetRoomNumber(roomNumber);
|
||||
mEntity->GetEntityManager().EmitMessage(msg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::SetColor(const osg::Vec4f &color)
|
||||
{
|
||||
mColor = color;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::DeleteQueuedCommands()
|
||||
{
|
||||
mCommands.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
osg::Vec4f PlayerComponent::GetColor() const
|
||||
{
|
||||
return mColor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId PlayerSystem::TYPE(dtEntity::SID("Player"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
PlayerSystem::PlayerSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<PlayerComponent>(em)
|
||||
{
|
||||
mTickFunctor = dtEntity::MessageFunctor(this, &PlayerSystem::OnTick);
|
||||
em.RegisterForMessages(dtEntity::TickMessage::TYPE, mTickFunctor, dtEntity::FilterOptions::ORDER_LATE, "PlayerSystem::OnTick");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::OnTick(const dtEntity::Message &m)
|
||||
{
|
||||
static const dtEntity::StringId PlayerSystemTick = dtEntity::SID("PlayerSystem Tick");
|
||||
CProfileManager::Start_Profile(PlayerSystemTick);
|
||||
|
||||
const dtEntity::TickMessage &msg = static_cast<const dtEntity::TickMessage &>(m);
|
||||
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->ExecuteCommands(msg.GetSimulationTime());
|
||||
|
||||
CProfileManager::Stop_Profile();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::PlayerShoot(int32_t id, dtEntity::EntityId shooterid, dtEntity::EntityId targetid,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType, double when, double duration)
|
||||
{
|
||||
ComponentStore::iterator shooter = mComponents.find(shooterid);
|
||||
if (shooter == mComponents.end())
|
||||
return;
|
||||
// targetid may be a building
|
||||
//if (mComponents.find(targetid) == mComponents.end())
|
||||
// return;
|
||||
|
||||
PlayerComponent *shooterc = shooter->second;
|
||||
shooterc->AddCommand(new ShootCommand(when, id, shooterid, targetid, shooterPos, targetPos, buildingIdSrc, roomNumberSrc, buildingIdDst, roomNumberDst, lineType, duration));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::RemovePlayerShoot(int32_t id, double when)
|
||||
{
|
||||
ComponentStore::iterator shooter = mComponents.find(id);
|
||||
if (shooter == mComponents.end())
|
||||
return;
|
||||
|
||||
PlayerComponent *shooterc = shooter->second;
|
||||
shooterc->AddCommand(new RemoveShootCommand(when, id));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::ShowHidePlayer(dtEntity::EntityId eid, bool show, double when)
|
||||
{
|
||||
ComponentStore::iterator i = mComponents.find(eid);
|
||||
if (i != mComponents.end())
|
||||
{
|
||||
PlayerComponent *player = i->second;
|
||||
if (when <= 0)
|
||||
{
|
||||
IconComponent *ic;
|
||||
if (player->GetEntity()->GetComponent(ic))
|
||||
ic->SetVisible(show);
|
||||
}
|
||||
else
|
||||
player->AddCommand(new ShowHidePlayerCommand(when, show));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::TeleportToTarget(dtEntity::EntityId id, double when, const osg::Vec3d &goal, const VCtrl::OBB &obb, int roomNumber, const std::string& roomname)
|
||||
{
|
||||
LOG_DEBUG("PlayerSystem::TeleportToTarget: " << "id='"<< id << "'"
|
||||
<< ", when="<< when
|
||||
<< ", goal: x=" << goal.x() << " y=" << goal.y() << " z=" << goal.z()
|
||||
<< ", roomNumber="<< roomNumber
|
||||
<< ", roomname='"<< roomname << "'");
|
||||
|
||||
ComponentStore::iterator i = mComponents.find(id);
|
||||
if (i != mComponents.end())
|
||||
{
|
||||
PlayerComponent *player = i->second;
|
||||
player->AddCommand(new TeleportToTargetCommand(when, goal, obb, roomNumber, roomname));
|
||||
}
|
||||
else
|
||||
{
|
||||
dtEntityOSG::TransformComponent *pat;
|
||||
if (GetEntityManager().GetComponent(id, pat, true))
|
||||
pat->SetTranslation(goal);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerSystem::DeleteQueuedCommands()
|
||||
{
|
||||
for (const auto &comp : mComponents)
|
||||
comp.second->DeleteQueuedCommands();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntity/scriptaccessor.h>
|
||||
#include <osg/Referenced>
|
||||
#include <osg/PositionAttitudeTransform>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/osgdebugdrawinterface.h>
|
||||
#include "buildingmanager.h"
|
||||
#include <set>
|
||||
|
||||
namespace dtEntityOSG
|
||||
{
|
||||
class TransformComponent;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PlayerComponent final : public dtEntity::Component
|
||||
{
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
PlayerComponent() = default;
|
||||
|
||||
virtual dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
void OnRemovedFromEntity(dtEntity::Entity &entity) override;
|
||||
|
||||
dtEntity::Entity *GetEntity() const { return mEntity; }
|
||||
|
||||
void PlaceAt(const osg::Vec3d& _goal, const VCtrl::OBB& obb, int roomNumber, const std::string& roomname);
|
||||
|
||||
struct Command : public osg::Referenced
|
||||
{
|
||||
double mStartTime = 0;
|
||||
Command(double startTime) : mStartTime(startTime) {}
|
||||
virtual ~Command() = default;
|
||||
virtual void Execute(PlayerComponent *component) = 0;
|
||||
};
|
||||
|
||||
void AddCommand(Command *c) { mCommands.insert(c); }
|
||||
size_t GetNumCommands() const { return mCommands.size(); }
|
||||
void ExecuteCommands(double timenow);
|
||||
void DeleteQueuedCommands();
|
||||
|
||||
dtEntityOSG::TransformComponent *GetTransform();
|
||||
|
||||
osg::Vec4 GetColor() const;
|
||||
void SetColor(const osg::Vec4 &);
|
||||
|
||||
dtEntity::StringId GetCurrentCellGroup() const { return mCurrentCellGroup; }
|
||||
dtEntity::StringId GetCurrentRoom() const { return mCurrentRoom; }
|
||||
dtEntity::StringId GetPreviousRoom() const { return mPreviousRoom; }
|
||||
|
||||
private:
|
||||
void PositionOnMesh(const VCtrl::OBB&, osg::Vec3d& pos, const std::string& roomname);
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
|
||||
using Commands = std::set<osg::ref_ptr<Command>>;
|
||||
Commands mCommands;
|
||||
|
||||
dtEntityOSG::TransformComponent *mTransform = nullptr;
|
||||
osg::Vec4f mColor;
|
||||
dtEntity::StringId mCurrentCellGroup = dtEntity::StringId();
|
||||
dtEntity::StringId mCurrentRoom = dtEntity::StringId();
|
||||
dtEntity::StringId mPreviousRoom = dtEntity::StringId();
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class PlayerSystem final
|
||||
: public dtEntity::DefaultEntitySystem<PlayerComponent>
|
||||
, public dtEntity::ScriptAccessor
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
explicit PlayerSystem(dtEntity::EntityManager &em);
|
||||
|
||||
void OnTick(const dtEntity::Message &m);
|
||||
|
||||
void ShowHidePlayer(dtEntity::EntityId eid, bool show, double when);
|
||||
void TeleportToTarget(dtEntity::EntityId id, double when, const osg::Vec3d &goal, const VCtrl::OBB &obb, int roomNumber, const std::string &roomname);
|
||||
void PlayerShoot(int32_t id, dtEntity::EntityId shooterid, dtEntity::EntityId targetid,
|
||||
const Vec3d &shooterPos, const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst, int lineType,
|
||||
double when, double duration);
|
||||
void RemovePlayerShoot(int32_t id, double when);
|
||||
|
||||
// delete commands from all players
|
||||
void DeleteQueuedCommands();
|
||||
|
||||
private:
|
||||
dtEntity::MessageFunctor mTickFunctor;
|
||||
};
|
||||
}
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#include "roomdestructioncomponent.h"
|
||||
|
||||
#include "visitors.h"
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osg/Depth>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Material>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/Node>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId RoomDestructionComponent::TYPE(dtEntity::SID("RoomDestruction"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void RoomDestructionComponent::OnEnteredWorld()
|
||||
{
|
||||
|
||||
osg::Shader *vShader = osg::Shader::readShaderFile(osg::Shader::VERTEX, osgDB::findDataFile("shaders/roomdestruction.vert"));
|
||||
osg::Shader *fShader = osg::Shader::readShaderFile(osg::Shader::FRAGMENT, osgDB::findDataFile("shaders/roomdestruction.frag"));
|
||||
|
||||
if (vShader == nullptr || fShader == nullptr)
|
||||
{
|
||||
LOG_ERROR("Could not load building transparency shaders!");
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
osg::Program *p = new osg::Program();
|
||||
p->setName("RoomDestructionShader");
|
||||
p->addShader(vShader);
|
||||
p->addShader(fShader);
|
||||
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
if (mEntity->GetComponent(lc))
|
||||
{
|
||||
osg::Node *n = lc->GetAttachedComponentNode();
|
||||
if (n != nullptr)
|
||||
{
|
||||
ClearVertexColorsVisitor v;
|
||||
lc->GetAttachedComponentNode()->accept(v);
|
||||
osg::StateSet *ss = n->getOrCreateStateSet();
|
||||
ss->setAttributeAndModes(p);
|
||||
ss->addUniform(new osg::Uniform("room_color", osg::Vec4(1, 1, 1, 1)));
|
||||
ss->addUniform(new osg::Uniform("wall_color", osg::Vec4(1, 1, 1, 1)));
|
||||
}
|
||||
}
|
||||
|
||||
dtEntityOSG::StaticMeshComponent *smc;
|
||||
if (mEntity->GetComponent(smc))
|
||||
{
|
||||
FindRoomNamesVisitor v;
|
||||
smc->GetNode()->accept(v);
|
||||
for (const auto &roomName: v.mNames)
|
||||
mRoomDestructions[roomName] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool RoomDestructionComponent::SetRoomDestructionValue(const std::string &room, float value)
|
||||
{
|
||||
if (mRoomDestructions.find(room) == mRoomDestructions.end())
|
||||
return false;
|
||||
|
||||
FindRoomByNumberVisitor fn;
|
||||
fn.setNameToFind(room);
|
||||
dtEntityOSG::LayerComponent *lc;
|
||||
|
||||
if (!mEntity->GetComponent(lc))
|
||||
return false;
|
||||
|
||||
osg::Node *n = lc->GetAttachedComponentNode();
|
||||
if (n == nullptr)
|
||||
return false;
|
||||
|
||||
lc->GetAttachedComponentNode()->accept(fn);
|
||||
|
||||
|
||||
for (const auto &node : fn.getNodeList())
|
||||
{
|
||||
RoomDestructionSystem *bts;
|
||||
mEntity->GetEntityManager().GetES(bts);
|
||||
|
||||
FindRoomComponentsVisitor frc;
|
||||
node->accept(frc);
|
||||
|
||||
FindExactNameVisitor v(frc.mNamesFound);
|
||||
//LOG_ERROR("Found " + std::to_string(frc.mNamesFound.size()) + " component names");
|
||||
osg::Node *partNode = lc->GetAttachedComponentNode();
|
||||
if (partNode)
|
||||
partNode->accept(v);
|
||||
|
||||
for (const auto &visitedNodes : v.mNodes)
|
||||
{
|
||||
osg::StateSet *ss = visitedNodes->getOrCreateStateSet();
|
||||
ss->addUniform(new osg::Uniform("room_color", osg::Vec4(1, 1 - value, 1 - value, 1)));
|
||||
}
|
||||
}
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(0);
|
||||
|
||||
mRoomDestructions[room] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool RoomDestructionComponent::SetBuildingDestructionValue(float value)
|
||||
{
|
||||
for (const auto &rd : mRoomDestructions)
|
||||
SetRoomDestructionValue(rd.first, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId RoomDestructionSystem::TYPE(dtEntity::SID("RoomDestruction"));
|
||||
|
||||
RoomDestructionSystem::RoomDestructionSystem(dtEntity::EntityManager &em)
|
||||
: dtEntity::DefaultEntitySystem<RoomDestructionComponent>(em)
|
||||
{
|
||||
mEnterWorldFunctor = dtEntity::MessageFunctor(this, &RoomDestructionSystem::OnEnterWorld);
|
||||
em.RegisterForMessages(dtEntity::EntityAddedToSceneMessage::TYPE, mEnterWorldFunctor, "RoomDestructionSystem::OnEnterWorld");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void RoomDestructionSystem::OnEnterWorld(const dtEntity::Message &msg)
|
||||
{
|
||||
dtEntity::EntityId id = msg.Get(dtEntity::EntityAddedToSceneMessage::AboutEntityId)->UIntValue();
|
||||
RoomDestructionComponent *bt;
|
||||
if (GetEntityManager().GetComponent(id, bt))
|
||||
bt->OnEnteredWorld();
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <osgSim/DOFTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class RoomDestructionComponent final : public dtEntity::Component
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
void OnAddedToEntity(dtEntity::Entity &entity) override
|
||||
{
|
||||
mEntity = &entity;
|
||||
}
|
||||
|
||||
void OnEnteredWorld();
|
||||
|
||||
void OnRemovedFromEntity(dtEntity::Entity &) override
|
||||
{
|
||||
mEntity = nullptr;
|
||||
}
|
||||
|
||||
bool SetRoomDestructionValue(const std::string &room, float value);
|
||||
bool SetBuildingDestructionValue(float value);
|
||||
|
||||
using RoomDestructions = std::map<std::string, float>;
|
||||
|
||||
const RoomDestructions &GetRoomDestructions() const
|
||||
{
|
||||
return mRoomDestructions;
|
||||
}
|
||||
private:
|
||||
|
||||
RoomDestructions mRoomDestructions;
|
||||
dtEntity::Entity *mEntity = nullptr;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class RoomDestructionSystem final
|
||||
: public dtEntity::DefaultEntitySystem<RoomDestructionComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
explicit RoomDestructionSystem(dtEntity::EntityManager &em);
|
||||
void OnEnterWorld(const dtEntity::Message &msg);
|
||||
|
||||
private:
|
||||
|
||||
dtEntity::MessageFunctor mEnterWorldFunctor;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
#include "textcomponent.h"
|
||||
|
||||
|
||||
#include <dtEntity/nodemasks.h>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <osg/LineWidth>
|
||||
#include <osg/Node>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osgText/Text>
|
||||
#include <sstream>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId TextComponent::TYPE(dtEntity::SID("Text"));
|
||||
const dtEntity::StringId TextComponent::PathId(dtEntity::SID("Path"));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TextComponent::TextComponent()
|
||||
: dtEntityOSG::TransformComponent(new osg::AutoTransform())
|
||||
, mPath(
|
||||
dtEntity::DynamicStringProperty::SetValueCB(this, &TextComponent::SetText),
|
||||
dtEntity:: DynamicStringProperty::GetValueCB(this, &TextComponent::GetText)
|
||||
)
|
||||
{
|
||||
Register(PathId, &mPath);
|
||||
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setName("text");
|
||||
tr->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
|
||||
tr->setAutoScaleToScreen(true);
|
||||
tr->setNodeMask(dtEntity::NodeMasks::PICKABLE | dtEntity::NodeMasks::VISIBLE);
|
||||
tr->setNormal(osg::Vec3(0,1,0));
|
||||
osg::StateSet* ss = tr->getOrCreateStateSet();
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->setRenderBinDetails(90, "DepthSortedBin");
|
||||
ss->setMode(GL_BLEND,osg::StateAttribute::ON);
|
||||
ss->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||
osg::ref_ptr<osg::LineWidth> lw = new osg::LineWidth();
|
||||
lw->setWidth(2);
|
||||
ss->setAttributeAndModes(lw, osg::StateAttribute::ON);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::Rebuild()
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->dirtyBound();
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 10));
|
||||
tr->removeChildren(0, tr->getNumChildren());
|
||||
|
||||
if(!mVisible) return;
|
||||
|
||||
osg::ref_ptr<osg::Geode> g = new osg::Geode();
|
||||
tr->addChild(g);
|
||||
tr->setInitialBound(osg::BoundingSphere(osg::Vec3(), 1));
|
||||
|
||||
osgText::Text* text = new osgText::Text();
|
||||
text->setBackdropType(osgText::Text::NONE);
|
||||
text->setCharacterSize(20);
|
||||
text->setCharacterSizeMode(osgText::TextBase::SCREEN_COORDS);
|
||||
//text->setColor(color);
|
||||
if(mDisText.empty())
|
||||
{
|
||||
text->setText(mText);
|
||||
}
|
||||
else
|
||||
{
|
||||
text->setText(mDisText);
|
||||
}
|
||||
text->setAlignment(osgText::TextBase::CENTER_CENTER);
|
||||
text->setAxisAlignment(osgText::TextBase::SCREEN);
|
||||
//text->setPosition(position);
|
||||
osg::StateSet* ss = text->getOrCreateStateSet();
|
||||
osg::PolygonMode* polyModeObj = new osg::PolygonMode;
|
||||
polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::FILL);
|
||||
ss->setAttribute(polyModeObj);
|
||||
|
||||
g->addDrawable(text);
|
||||
|
||||
if(mSelected)
|
||||
{
|
||||
int x, y, w, h;
|
||||
int b = 6;
|
||||
x = -25 / 2 - b;
|
||||
y = 0 - b;
|
||||
w = 25 + b * 2;
|
||||
h = 4 + b * 2;
|
||||
|
||||
osg::ref_ptr<osg::Geometry> sel = new osg::Geometry();
|
||||
g->addDrawable(sel);
|
||||
osg::Vec4Array* colours = new osg::Vec4Array(1);
|
||||
(*colours)[0] = osg::Vec4(1,0,0,1);
|
||||
sel->setColorArray(colours);
|
||||
sel->setColorBinding(osg::Geometry::BIND_OVERALL);
|
||||
osg::Vec3Array* coords = new osg::Vec3Array(4);
|
||||
(*coords)[0] = osg::Vec3(x , y , 0);
|
||||
(*coords)[1] = osg::Vec3(x , y + h, 0);
|
||||
(*coords)[2] = osg::Vec3(x + w, y + h, 0);
|
||||
(*coords)[3] = osg::Vec3(x + w, y , 0);
|
||||
sel->setVertexArray(coords);
|
||||
sel->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, 4));
|
||||
osg::ref_ptr<osg::PolygonMode> p = new osg::PolygonMode;
|
||||
p->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE);
|
||||
sel->getOrCreateStateSet()->setAttribute(p);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string TextComponent::GetText() const
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetText(const std::string& text)
|
||||
{
|
||||
if(mText != text)
|
||||
{
|
||||
mText = text;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string TextComponent::GetDisText() const
|
||||
{
|
||||
return mDisText;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetDisText(const std::string& text)
|
||||
{
|
||||
if(mDisText != text)
|
||||
{
|
||||
mDisText = text;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d TextComponent::GetTranslation() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getPosition();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetTranslation(const dtEntity::Vec3d& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setPosition(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Vec3d TextComponent::GetScale() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getScale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetScale(const dtEntity::Vec3d& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setScale(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
dtEntity::Quat TextComponent::GetRotation() const
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
return tr->getRotation();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetRotation(const dtEntity::Quat& v)
|
||||
{
|
||||
osg::AutoTransform* tr = static_cast<osg::AutoTransform*>(GetNode());
|
||||
tr->setRotation(v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetColor(const osg::Vec4& v)
|
||||
{
|
||||
if(mColor != v)
|
||||
{
|
||||
mColor = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool TextComponent::GetShowSelection() const
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetShowSelection(bool v)
|
||||
{
|
||||
//if(mSelected != v)
|
||||
{
|
||||
mSelected = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TextComponent::SetVisible(bool v)
|
||||
{
|
||||
//if(mVisible != v)
|
||||
{
|
||||
mVisible = v;
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
TextSystem::TextSystem(dtEntity::EntityManager& em)
|
||||
: dtEntity::DefaultEntitySystem<TextComponent>(em, dtEntityOSG::TransformComponent::TYPE)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntityOSG/nodecomponent.h>
|
||||
#include <osg/AutoTransform>
|
||||
#include <dtEntity/dynamicproperty.h>
|
||||
#include <dtEntityOSG/transformcomponent.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class TextComponent final : public dtEntityOSG::TransformComponent
|
||||
{
|
||||
|
||||
public:
|
||||
static const dtEntity::StringId TYPE;
|
||||
|
||||
static const dtEntity::StringId PathId;
|
||||
|
||||
|
||||
TextComponent();
|
||||
|
||||
dtEntity::ComponentType GetType() const override { return TYPE; }
|
||||
|
||||
virtual bool IsInstanceOf(dtEntity::ComponentType id) const
|
||||
{
|
||||
return ((id == TYPE));
|
||||
}
|
||||
|
||||
std::string GetText() const;
|
||||
void SetText(const std::string& text);
|
||||
|
||||
std::string GetDisText() const;
|
||||
void SetDisText(const std::string& text);
|
||||
|
||||
osg::Vec4 GetColor() const { return mColor; }
|
||||
void SetColor(const osg::Vec4&);
|
||||
|
||||
dtEntity::Vec3d GetTranslation() const override;
|
||||
void SetTranslation(const dtEntity::Vec3d&) override;
|
||||
|
||||
dtEntity::Vec3d GetScale() const override;
|
||||
void SetScale(const dtEntity::Vec3d&) override;
|
||||
|
||||
dtEntity::Quat GetRotation() const override;
|
||||
void SetRotation(const dtEntity::Quat&) override;
|
||||
|
||||
bool GetShowSelection() const;
|
||||
void SetShowSelection(bool v);
|
||||
|
||||
void SetVisible(bool v);
|
||||
bool GetVisible() const { return mVisible; }
|
||||
|
||||
private:
|
||||
|
||||
void Rebuild();
|
||||
|
||||
dtEntity::DynamicStringProperty mPath;
|
||||
|
||||
std::string mText;
|
||||
std::string mDisText;
|
||||
osg::Vec4 mColor;
|
||||
bool mSelected = false;
|
||||
bool mVisible = false;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
|
||||
|
||||
// iterates over MovementComponents and updates the translation of the entity
|
||||
// after applying forces
|
||||
class TextSystem final
|
||||
: public dtEntity::DefaultEntitySystem<TextComponent>
|
||||
{
|
||||
|
||||
public:
|
||||
explicit TextSystem(dtEntity::EntityManager& em);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "videocomponent.h"
|
||||
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/entity.h>
|
||||
#include <dtEntity/stringid.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
const dtEntity::StringId VideoSystem::TYPE(dtEntity::SID("Video"));
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool VideoSystem::StartVideoRecording(unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality)
|
||||
{
|
||||
if (mWindowCaptureCallback.valid())
|
||||
{
|
||||
LOG_ERROR("Cannot start video recording, already started!");
|
||||
return false;
|
||||
}
|
||||
StopVideoRecording(contextid);
|
||||
|
||||
dtEntityOSG::CameraSystem *cs;
|
||||
GetEntityManager().GetES(cs);
|
||||
|
||||
dtEntity::EntityId camid = cs ? cs->GetCameraEntityByContextId(contextid) : 0;
|
||||
|
||||
dtEntityOSG::CameraComponent *camcomp;
|
||||
if (camid == 0 || !GetEntityManager().GetComponent(camid, camcomp))
|
||||
{
|
||||
LOG_ERROR("Cannot set up video stream, camera not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
mWindowCaptureCallback = new WindowCaptureCallback(GL_BACK, contextid, path, w, h, framerate, quality);
|
||||
|
||||
camcomp->GetCamera()->setFinalDrawCallback(mWindowCaptureCallback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
bool VideoSystem::StopVideoRecording(unsigned int contextid)
|
||||
{
|
||||
if (mWindowCaptureCallback.valid())
|
||||
{
|
||||
dtEntityOSG::CameraSystem *camsys;
|
||||
if (GetEntityManager().GetES(camsys))
|
||||
{
|
||||
dtEntity::EntityId camid = camsys->GetCameraEntityByContextId(contextid);
|
||||
if (camid != 0)
|
||||
{
|
||||
dtEntityOSG::CameraComponent *cam;
|
||||
if (GetEntityManager().GetComponent(camid, cam))
|
||||
cam->GetCamera()->setFinalDrawCallback(nullptr);
|
||||
}
|
||||
}
|
||||
mWindowCaptureCallback = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <dtEntity/component.h>
|
||||
#include <dtEntity/defaultentitysystem.h>
|
||||
#include <dtEntity/property.h>
|
||||
#include <dtEntity/debugdrawinterface.h>
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VideoSystem final
|
||||
: public dtEntity::EntitySystem
|
||||
{
|
||||
using BaseClass = dtEntity::EntitySystem;
|
||||
|
||||
public:
|
||||
|
||||
static const dtEntity::ComponentType TYPE;
|
||||
|
||||
using dtEntity::EntitySystem::EntitySystem;
|
||||
|
||||
dtEntity::ComponentType GetComponentType() const override { return TYPE; }
|
||||
|
||||
bool StartVideoRecording(unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality);
|
||||
bool StopVideoRecording(unsigned int contextid);
|
||||
|
||||
private:
|
||||
|
||||
osg::ref_ptr<WindowCaptureCallback> mWindowCaptureCallback;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,695 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <QJsonValue>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <exccommands.h>
|
||||
|
||||
class QWidget;
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
using Timer_t = __int64;
|
||||
#else
|
||||
using Timer_t = unsigned long long;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Class representing 2-dimensional float vector
|
||||
*/
|
||||
struct Vec2
|
||||
{
|
||||
Vec2() = default;
|
||||
Vec2(float _x, float _y) : x(_x) , y(_y) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing 3-dimensional float vector
|
||||
*/
|
||||
struct Vec3
|
||||
{
|
||||
Vec3() = default;
|
||||
Vec3(float _x, float _y, float _z) : x(_x) , y(_y) , z(_z) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing 3-dimensional double vector
|
||||
*/
|
||||
struct Vec3d
|
||||
{
|
||||
Vec3d() = default;
|
||||
Vec3d(double _x, double _y, double _z) : x(_x) , y(_y) , z(_z) { }
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a color value.
|
||||
* Colors are encoded with 0.0 - 1.0 values for each channel.
|
||||
* w component represents alpha / transparency.
|
||||
*/
|
||||
|
||||
struct Color
|
||||
{
|
||||
Color() = default;
|
||||
Color(float _x, float _y, float _z, float _w) : x(_x) , y(_y) , z(_z) , w(_w) { }
|
||||
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float z = 0;
|
||||
float w = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Class representing a quaternion.
|
||||
* Used for representing rotations.
|
||||
*/
|
||||
struct Quat
|
||||
{
|
||||
Quat() = default;
|
||||
Quat(double _x, double _y, double _z, double _w) : x(_x) , y(_y) , z(_z) , w(_w) { }
|
||||
|
||||
double x = 0;
|
||||
double y = 0;
|
||||
double z = 0;
|
||||
double w = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* How to treat the z value
|
||||
*/
|
||||
enum class ZValue
|
||||
{
|
||||
AboveMsl, //!< treat z as above msl
|
||||
RelativeBuildings, //!< the z position is relative to the buildings
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerates view modes for 2d building displays
|
||||
*/
|
||||
enum class ViewMode
|
||||
{
|
||||
ISOMETRIC,
|
||||
ORTHOGRAPHIC
|
||||
};
|
||||
|
||||
/**
|
||||
* Enumerates view modes for 2d building displays
|
||||
*/
|
||||
enum class PlayerDisplayMode
|
||||
{
|
||||
Icons,
|
||||
Dots
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback class for receiving events from viewer side.
|
||||
* Use with ViewerInterface::SetViewerCallback()
|
||||
*/
|
||||
class ViewerCallback
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ViewerCallback() = default;
|
||||
|
||||
/**
|
||||
* Gets called when building position map has finished loading and
|
||||
* system is ready for use
|
||||
*/
|
||||
virtual void SystemReady() = 0;
|
||||
|
||||
/**
|
||||
* Gets called when the position of an entity has changed
|
||||
* @param id Id of moving entity
|
||||
* @param pos Position of entity relative to terrain origin in meters
|
||||
* @param attitude rotation of entity relative to posititive y axis
|
||||
*/
|
||||
virtual void TransformChanged(const std::string &id, const Vec3d &pos, const Quat &attitude) = 0;
|
||||
|
||||
/**
|
||||
* Gets called when entity moves from one navmesh group (building or outside mesh)
|
||||
* to the next
|
||||
* @param id Id of moving entity
|
||||
* @param grpname Name of navmesh group
|
||||
*/
|
||||
virtual void NavMeshGroupChanged(const std::string &id, const std::string &grpname) = 0;
|
||||
|
||||
/**
|
||||
* Player has clicked on an entity symbol with the left mouse button.
|
||||
* @param id Id of picked entity
|
||||
*/
|
||||
virtual void PlayerPicked(const std::string &id) = 0;
|
||||
|
||||
/**
|
||||
* Player has clicked on an displayName with the left mouse button.
|
||||
* @param buildingid Id of picked entity
|
||||
* @param roomname roomname of picked entity
|
||||
*/
|
||||
virtual void DisplayNamePicked(const std::string& buildingid, const std::string& roomname) = 0;
|
||||
|
||||
/**
|
||||
* A building view was opened.
|
||||
* @param contextId id of graphics context. Can be used to close the view.
|
||||
* @param viewmode Initial view mode of view
|
||||
*/
|
||||
virtual void ViewCreated(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
|
||||
/**
|
||||
* View mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeViewMode or a click on the view mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param viewmode New view mode of view
|
||||
*/
|
||||
virtual void ViewModeChanged(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
|
||||
/**
|
||||
* Line mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeLineMode or a click on the line mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param line Is line on or off
|
||||
*/
|
||||
virtual void ViewLineModeChanged(unsigned int contextId, bool line) = 0;
|
||||
|
||||
/**
|
||||
* Name mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::ChangeNameMode or a click on the name mode buttons in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param name Is name on or off
|
||||
*/
|
||||
virtual void ViewNameModeChanged(unsigned int contextId, bool name) = 0;
|
||||
|
||||
/**
|
||||
* Lock ViewTransparencyChanged mode of view was changed. Triggered by slider
|
||||
*/
|
||||
virtual void ViewTransparencyChanged() = 0;
|
||||
|
||||
/**
|
||||
* Lock Rotation mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::LockViewRotationToMapRotation or a click on
|
||||
* the lock checkbox in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param lock Is lock on or off
|
||||
*/
|
||||
virtual void ViewLockRotationChanged(unsigned int contextId, bool lock) = 0;
|
||||
|
||||
/**
|
||||
* Player display mode of view was changed. This was either triggered by a call to
|
||||
* ViewerInterface::SetViewerDisplayMode or a click on
|
||||
* the display mode checkbox in the GUI
|
||||
* @param contextId id of graphics context.
|
||||
* @param mode Mode enumerator
|
||||
*/
|
||||
virtual void PlayerDisplayModeChanged(unsigned int contextId, PlayerDisplayMode mode) = 0;
|
||||
|
||||
/**
|
||||
* View was closed via ViewerInterface::CloseView or click on window
|
||||
* close GUI element
|
||||
* @param contextId id of graphics context.
|
||||
*/
|
||||
virtual void ViewClosed(unsigned int contextId) = 0;
|
||||
|
||||
virtual void HandleViewerEvent(BuildingViewer::BgViewerEvents event,
|
||||
const std::vector<std::string> &args) = 0;
|
||||
virtual void ViewZoomChanged(const std::string &buildingId,
|
||||
double top, double left, double bottom, double right) = 0;
|
||||
|
||||
enum class Severity
|
||||
{
|
||||
Always,
|
||||
Debug,
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
||||
/**
|
||||
* Receives error and other log messages from viewer
|
||||
* @param severity The severity of the message
|
||||
* @param filename The file that the log command was called from
|
||||
* @param methodname The name of the method containing the log command
|
||||
* @param linenumber The line number the log command was issued from
|
||||
* @param msg Text of the log message
|
||||
*/
|
||||
virtual void LogMessage(Severity &severity, const std::string &filename,
|
||||
const std::string &methodname,
|
||||
int linenumber, const std::string &msg) = 0;
|
||||
|
||||
};
|
||||
|
||||
class ViewerInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~ViewerInterface() = default;
|
||||
|
||||
/**
|
||||
* Register object for receiving viewer event callbacks
|
||||
*/
|
||||
virtual void SetViewerCallback(ViewerCallback *) = 0;
|
||||
virtual void RemoveViewerCallback() = 0;
|
||||
|
||||
/**
|
||||
* Is used to set location of project specific terrain and building data.
|
||||
* Example: "/home/martin/ProjectAssetsBremen"
|
||||
*/
|
||||
virtual void SetProjectDataPaths(const std::vector<std::string> &paths) = 0;
|
||||
|
||||
/**
|
||||
* Open 3d view of whole terrain - for debugging purposes only!
|
||||
*/
|
||||
virtual void OpenOverview() = 0;
|
||||
|
||||
virtual QWidget* getMainWindow() = 0;
|
||||
virtual quintptr requestMainWindowHandle() = 0;
|
||||
|
||||
virtual void reloadPlayerIcons() = 0;
|
||||
virtual void UpdatePlayerPartyColors(const std::map<std::string, VCtrl::Color>& mapPlayerColors) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief true if positioningsystem gets exact position of player. Will be used for all opened views (GLOBAL FLAG)
|
||||
* @param exactPos
|
||||
*/
|
||||
virtual void UseExactPositioning(bool exactPos) = 0;
|
||||
|
||||
/**
|
||||
* Open a new display showing the building identified by buildingid.
|
||||
* @param buildingid ID of the building. Use GetBuildingIds() to get all building ids
|
||||
* @param windowtitle Title to display on window top
|
||||
* @param bgcolor Background color of window
|
||||
* @param viewmode The perspective mode to show building in
|
||||
* @param screennum Number of screen to open display on
|
||||
* @param fullscreen Ignore width and position and display as fullscreen instead
|
||||
* @param x X-Position of window
|
||||
* @param y Y-Position of window
|
||||
* @param width Width of display in pixels
|
||||
* @param height Height of display in pixels
|
||||
* @param contextId receives context ID of the new view. Use it to close the view programmatically.
|
||||
* @param exactPos true if positioningsystem gets exact position of player
|
||||
* @return true if success
|
||||
*/
|
||||
virtual bool OpenView(const std::string &buildingid, const std::string &windowtitle, const Color &bgcolor, ViewMode viewmode,
|
||||
int screennum, bool fullscreen, int x, int y, int width, int height,
|
||||
unsigned int &contextId, bool exactPos = true) = 0;
|
||||
virtual void openViews(const std::vector<std::string> &bldIds, bool exactPos) = 0;
|
||||
|
||||
/**
|
||||
* Is a certain view opened?
|
||||
* @param bldId ID of the building.
|
||||
*/
|
||||
virtual bool isViewOpen(const std::string &bldId) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Close display previously opened with OpenView
|
||||
* @param contextid context id of view, as returned from OpenView()
|
||||
*/
|
||||
virtual void CloseView(unsigned int contextid) = 0;
|
||||
virtual void closeViews(const std::vector<std::string> &bldIds) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param viewmode Viewmode enum value
|
||||
*/
|
||||
virtual void ChangeViewMode(unsigned int contextId, ViewMode viewmode) = 0;
|
||||
virtual void setViewMode(ViewMode m) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param line true if view should show lines outside , false if not
|
||||
*/
|
||||
virtual void ChangeLineMode(unsigned int contextId, bool line) = 0;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param name true if view should show names, false if not
|
||||
*/
|
||||
virtual void ChangeNameMode(unsigned int contextId, bool name) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Set if view should rotate in accord with map rotation
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param lock true if view should rotate, false if it should remain static
|
||||
*/
|
||||
virtual void LockViewRotationToMapRotation(unsigned int contextId, bool lock) = 0;
|
||||
|
||||
/**
|
||||
* Set if view should display movable players as dots or as icons
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param mode Display mode enumerator
|
||||
*/
|
||||
virtual void SetPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode) = 0;
|
||||
virtual void setDisplayMode(PlayerDisplayMode m) = 0;
|
||||
|
||||
/**
|
||||
* Set wall transparency for a building window.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param transparency 0 equals opaque, 1 equals invisible
|
||||
*/
|
||||
virtual void SetWallTransparency(unsigned int contextId, float transparency) = 0;
|
||||
virtual void setTransparency(double percent) = 0;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @returnRotation angle in degrees from north CCW
|
||||
*/
|
||||
virtual float GetMapRotation() const = 0;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @param angle Rotation angle in degrees from north CCW
|
||||
*/
|
||||
virtual void SetMapRotation(float angle) = 0;
|
||||
|
||||
/**
|
||||
* add buildings to scene and recalculate navigation meshes
|
||||
* @param path Load map from this path. example: "Projections/data.xml"
|
||||
*/
|
||||
virtual bool LoadBuildingPositionMap(const std::string &path, bool loadAllAvailableBuildings) = 0;
|
||||
|
||||
/**
|
||||
* Create new player at (0,0,0). Player is initially invisible!
|
||||
* @param id a unique string that can later be used to reference the player
|
||||
* @param iconpath system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* @param color Initial color of the player
|
||||
*/
|
||||
virtual void CreatePlayer(const std::string &id, const std::string &iconpath, const Color &color) = 0;
|
||||
|
||||
/**
|
||||
* Delete player with given id
|
||||
* @param seconds Delete player n seconds from now
|
||||
*/
|
||||
virtual void DeletePlayer(const std::string &id, float seconds = 0) = 0;
|
||||
|
||||
/**
|
||||
* This color is added to the player texture color.
|
||||
*/
|
||||
virtual void SetPlayerColor(const std::string &id, const Color &color) = 0;
|
||||
|
||||
/**
|
||||
* Set icon path for existing player
|
||||
* @param path system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* If path is to current icon path then icon is reloaded from file.
|
||||
*/
|
||||
virtual void SetPlayerIcon(const std::string &id, const std::string &path) = 0;
|
||||
|
||||
/**
|
||||
* Return number of soldier instances
|
||||
*/
|
||||
virtual size_t GetNumPlayers() const = 0;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing players
|
||||
*/
|
||||
virtual void GetPlayerIds(std::vector<std::string> &toFill) = 0;
|
||||
|
||||
/**
|
||||
* Hide or unhide player with given id
|
||||
* @param show true to show, false to hide
|
||||
* @param when simulation time when show or hide should be executed - < 0 --> show immediatelly
|
||||
*/
|
||||
virtual void SetPlayerShown(const std::string &id, bool show, double when = -1) = 0;
|
||||
|
||||
/**
|
||||
* Return number of building instances
|
||||
*/
|
||||
virtual size_t GetNumBuildings() const = 0;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing buildings
|
||||
*/
|
||||
virtual void GetBuildingIds(std::vector<std::string> &toFill) const = 0;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around entity
|
||||
* @param id unique id of entity
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
virtual void SetShowSelectionBox(const std::string &id,
|
||||
bool show,
|
||||
float duration = -1) = 0;
|
||||
|
||||
/**
|
||||
* Add a line from start to end
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
virtual void Shoot(const int id,
|
||||
const std::string &shooterId,
|
||||
const std::string &targetId,
|
||||
const Vec3d &shooterPos,
|
||||
const Vec3d &targetPos,
|
||||
int buildingIdSrc,
|
||||
int roomNumberSrc,
|
||||
int buildingIdDst,
|
||||
int roomNumberDst,
|
||||
int lineType,
|
||||
double when) = 0;
|
||||
|
||||
/**
|
||||
* Add a line from start to end where end is a room in the given building
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
virtual void Shoot(const int id,
|
||||
const std::string &shooterId,
|
||||
const std::string &targetBuildingId,
|
||||
const std::string &targetRoomId,
|
||||
const Vec3d &shooterPos,
|
||||
int lineType,
|
||||
double when) = 0;
|
||||
|
||||
/**
|
||||
* Remove a line
|
||||
*/
|
||||
virtual void removeShoot(const int id) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Directly move player to target position, do not use pathfinding. Cancels current path following activity.
|
||||
* @param id Id of player
|
||||
* @param when Simulation time when teleport should happen
|
||||
* @param target position to teleport to
|
||||
* @param bldgname name of building containing position, empty string to ignore
|
||||
* @param roomname name of room containing position, empty string to ignore
|
||||
*/
|
||||
virtual void Teleport(const std::string &id,
|
||||
double when,
|
||||
const Vec3d &target,
|
||||
const std::string &bldgname,
|
||||
int roomNumber,
|
||||
const std::string &roomname,
|
||||
ZValue zval) = 0;
|
||||
/**
|
||||
* Get names of all rooms in building
|
||||
* @param id Id of building player
|
||||
* @param names will be filled with room names
|
||||
*/
|
||||
virtual void GetRoomNames(const std::string &id, std::vector<std::string> &names) = 0;
|
||||
|
||||
/**
|
||||
* Sets destruction value for room of a building.
|
||||
* @param id Id of building player
|
||||
* @param roomnumber number of room to set (ex: "2001")
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
virtual bool SetRoomDestructionValue(const std::string &id,
|
||||
const std::string &roomname,
|
||||
float value) = 0;
|
||||
|
||||
/**
|
||||
* Sets destruction value for all rooms of a building.
|
||||
* @param id Id of building player
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
virtual bool SetBuildingDestructionValue(const std::string &id, float value) = 0;
|
||||
|
||||
/**
|
||||
* Get names of all cameras, loudspeakers and other devices in building
|
||||
* @param buildingid Id of building player
|
||||
* @param names will be filled with device names
|
||||
*/
|
||||
virtual void GetDeviceNames(const std::string &buildingid, std::vector<std::string> &names) = 0;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param devicename name of device node to show icon at
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
virtual bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const std::string &devicename, const std::string &iconpath) = 0;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param position Position of camera relative to building
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
virtual bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const Vec3d &position, const std::string &iconpath) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Hide device icon created with ShowDevice
|
||||
* @param id Id used in call to ShowDevice
|
||||
* @return true if device entity was found and successfully removed
|
||||
*/
|
||||
virtual bool HideDeviceIcon(const std::string &id) = 0;
|
||||
|
||||
/**
|
||||
* Set the displayName of the given room in a given building
|
||||
* @param buildingid id of building
|
||||
* @param roomname
|
||||
* @param strDisplayName
|
||||
* @return true if room was found in building
|
||||
*/
|
||||
virtual bool SetDisplayName(const std::string& buildingid, const std::string& roomname,
|
||||
const std::string& strDisplayName) = 0;
|
||||
|
||||
/**
|
||||
* Show the displayName in a given building
|
||||
* @param buildingid id of building
|
||||
* @param show set true to show displayNames, false to make invisible
|
||||
*/
|
||||
virtual void ShowDisplayNames(const std::string& buildingid, bool show) = 0;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around displayName entity
|
||||
* @param buildingid unique id of building
|
||||
* @param id id of room
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
virtual void SetShowDisplayNamesSelectionBox(const std::string& buildingid,
|
||||
const std::string& id,
|
||||
bool show,
|
||||
float duration = -1) = 0;
|
||||
|
||||
/**
|
||||
* Get time scale. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
virtual float GetTimeScale() const = 0;
|
||||
|
||||
/**
|
||||
* Scale time. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
virtual void SetTimeScale(float scale) = 0;
|
||||
|
||||
/**
|
||||
* Set current simulation time in seconds
|
||||
*/
|
||||
virtual void SetSimulationTime(double t) = 0;
|
||||
|
||||
/**
|
||||
* Get current simulation time in seconds
|
||||
*/
|
||||
virtual double GetSimulationTime() const = 0;
|
||||
|
||||
/**
|
||||
* Pause simulation time and all events
|
||||
*/
|
||||
virtual void SetPaused(bool) = 0;
|
||||
virtual bool GetPaused() const = 0;
|
||||
|
||||
/**
|
||||
* Switch on or off non realtime mode.
|
||||
* Non realtime mode is used for recording videos at faster than real time speed.
|
||||
* Frames are rendered and compressed as fast as possible, simulation time
|
||||
* does not correspond to real time.
|
||||
*/
|
||||
virtual void SetNonRealtimeMode(bool on) = 0;
|
||||
|
||||
/**
|
||||
* Is non-realtime mode on or off?
|
||||
*/
|
||||
virtual bool GetNonRealtimeMode() const = 0;
|
||||
|
||||
/**
|
||||
* Advance simulation until given simulation time is reached
|
||||
*/
|
||||
virtual void FastForwardSimulationTo(double t) = 0;
|
||||
|
||||
/**
|
||||
* Remove all queued commands for soldiers
|
||||
*/
|
||||
virtual void DeleteQueuedCommands() = 0;
|
||||
|
||||
/**
|
||||
* Start recording an mpeg video of the view.
|
||||
* @param contextid context id of the view to record.
|
||||
* @param path Record to this file. Extension should be .mpg
|
||||
* @param w width of recorded video file (input is rescaled)
|
||||
* @param h height of recorded video file (input is rescaled)
|
||||
* @param framerate frames per second to record. Reasonable value: 15 - 30
|
||||
* @param quality Compression quality in percent.
|
||||
*/
|
||||
virtual bool StartVideoRecording(unsigned int contextid, const std::string &path,
|
||||
int w, int h, int framerate, int quality) = 0;
|
||||
virtual bool StartVideoRecording(const std::string &buildingId, const std::string &path,
|
||||
int w, int h, int framerate, int quality) = 0;
|
||||
|
||||
/**
|
||||
* Stop recording
|
||||
* @param contextid context id of the view to record.
|
||||
*/
|
||||
virtual bool StopVideoRecording(unsigned int contextid) = 0;
|
||||
virtual bool StopVideoRecording(const std::string &buildingId) = 0;
|
||||
|
||||
|
||||
virtual QJsonValue getViewState() const = 0;
|
||||
virtual void setViewState(const QJsonValue &val) = 0;
|
||||
virtual void highlightView(const std::string &buildingId) = 0;
|
||||
virtual void setBuildingDisplayName(const std::string &buildingId, const std::string &displayName) = 0;
|
||||
|
||||
virtual void setHitLineDuration(uint32_t durationSec) = 0;
|
||||
struct MountingPointDescription
|
||||
{
|
||||
std::string buildingId;
|
||||
std::string mountingPointId;
|
||||
Vec3d position;
|
||||
BuildingViewer::AssetTypes assetType;
|
||||
};
|
||||
virtual void setMountingPointAsset(const MountingPointDescription &asset) = 0;
|
||||
|
||||
struct BuildingState
|
||||
{
|
||||
std::string buildingId;
|
||||
std::string description;
|
||||
int entityId = 0;
|
||||
bool isShown = false;
|
||||
};
|
||||
virtual std::vector<BuildingState> getBuildingState() const = 0;
|
||||
};
|
||||
}
|
||||
+2344
File diff suppressed because it is too large.
Load diff
+524
@@ -0,0 +1,524 @@
|
||||
#pragma once
|
||||
|
||||
#include "viewerinterface.h"
|
||||
#include "viewwidgetcontainer.h"
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QPointer>
|
||||
#include <QWidget>
|
||||
|
||||
#include <dtEntity/mapcomponent.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/commandmessages.h>
|
||||
#include <dtEntity/systemmessages.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
#include <dtEntityOSG/cameracomponent.h>
|
||||
#include <dtEntityOSG/layercomponent.h>
|
||||
#include <dtEntityOSG/positionattitudetransformcomponent.h>
|
||||
#include <dtEntityOSG/osgsysteminterface.h>
|
||||
#include <dtEntityOSG/staticmeshcomponent.h>
|
||||
#include <osg/io_utils>
|
||||
#include <osgDB/FileNameUtils>
|
||||
#include <osgDB/FileUtils>
|
||||
#include <osg/ComputeBoundsVisitor>
|
||||
#include <osgViewer/CompositeViewer>
|
||||
#include "buildingmanager.h"
|
||||
#include "exccommands.h"
|
||||
#include "viewwidgetstate.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace dtEntity
|
||||
{
|
||||
class EntityManager;
|
||||
class MapSystem;
|
||||
class Message;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class PlayerSystem;
|
||||
class BuildingManager;
|
||||
class ViewWidget;
|
||||
class LogHandler;
|
||||
|
||||
class CtrlMainWindow;
|
||||
|
||||
class CtrlImpl : public QObject, public ViewerInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
CtrlImpl(dtEntity::EntityManager &em, QWidget *parentWidget);
|
||||
~CtrlImpl();
|
||||
|
||||
void SetViewerCallback(ViewerCallback *) override;
|
||||
void RemoveViewerCallback() override;
|
||||
|
||||
/**
|
||||
* Is used to set location of project specific terrain and building data.
|
||||
* Example: "/home/martin/ProjectAssetsBremen"
|
||||
*/
|
||||
void SetProjectDataPaths(const std::vector<std::string> &paths) override;
|
||||
|
||||
QWidget* getMainWindow() override;
|
||||
quintptr requestMainWindowHandle() override;
|
||||
|
||||
|
||||
void openViews(const std::vector<std::string> &bldIds, bool exactPos) override;
|
||||
bool isViewOpen(const std::string &strBldId) const override;
|
||||
|
||||
void closeViews(const std::vector<std::string> &vecFeatureIDs) override;
|
||||
void closeAllViews();
|
||||
|
||||
void UseExactPositioning(bool exactPos) override;
|
||||
|
||||
/**
|
||||
* Open a new display showing the building identified by buildingid.
|
||||
* @param buildingid ID of the building. Use GetBuildingIds() to get all building ids
|
||||
* @param windowtitle Title to display on window top
|
||||
* @param bgcolor Window background color
|
||||
* @param viewmode The perspective mode to show building in
|
||||
* @param screennum Number of screen to open display on
|
||||
* @param fullscreen Ignore width and position and display as fullscreen instead
|
||||
* @param x X-Position of window
|
||||
* @param y Y-Position of window
|
||||
* @param width Width of display in pixels
|
||||
* @param height Height of display in pixels
|
||||
* @param contextId receives context ID of the new view. Use it to close the view programmatically.
|
||||
* @param exactPos true if positioningsystem gets exact position of player
|
||||
* @return true if success
|
||||
*/
|
||||
bool OpenView(const std::string &buildingid, const std::string &windowtitle, const Color &col,
|
||||
ViewMode viewmode, int screennum,
|
||||
bool fullscreen, int x, int y, int w, int h, unsigned int &contextid, bool exactPos = true) override;
|
||||
|
||||
|
||||
/**
|
||||
* Close display previously opened with OpenView
|
||||
* @param contextid context id of view, as returned from OpenView()
|
||||
*/
|
||||
void CloseView(unsigned int contextid) override;
|
||||
|
||||
/**
|
||||
* Change view mode of an existing view.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param viewmode Viewmode enum value
|
||||
*/
|
||||
void ChangeViewMode(unsigned int contextId, ViewMode viewmode) override;
|
||||
|
||||
/**
|
||||
* Set if view should rotate in accord with map rotation
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param lock true if view should rotate, false if it should remain static
|
||||
*/
|
||||
void LockViewRotationToMapRotation(unsigned int contextId, bool lock) override;
|
||||
|
||||
/**
|
||||
* Set if view should display movable players as dots or as icons
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param mode Display mode enumerator
|
||||
*/
|
||||
void SetPlayerDisplayMode(unsigned int contextId, PlayerDisplayMode mode) override;
|
||||
|
||||
/**
|
||||
* Set wall transparency for a building window.
|
||||
* @param contextId context id of view, as returned from OpenView()
|
||||
* @param transparency 0 equals opaque, 1 equals invisible
|
||||
*/
|
||||
void SetWallTransparency(unsigned int contextId, float transparency) override;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @returnRotation angle in degrees from north CCW
|
||||
*/
|
||||
float GetMapRotation() const override;
|
||||
|
||||
/**
|
||||
* All views with "LockViewRotationToMapRotation" enabled will rotate their camera
|
||||
* to have a camera angle looking towards north, rotated by input angle.
|
||||
* @param angle Rotation angle in degrees from north CCW
|
||||
*/
|
||||
void SetMapRotation(float angle) override;
|
||||
|
||||
/**
|
||||
* Open 3d view of whole terrain - for debugging purposes only!
|
||||
*/
|
||||
void OpenOverview() override;
|
||||
|
||||
|
||||
/**
|
||||
* add buildings to scene and recalculate navigation meshes
|
||||
* @param path Load map from this path. example: "Projections/data.xml"
|
||||
* @param loadAllAvailableBuildings If true, the path variable (=XML file with building configuration) will be ignored)
|
||||
*/
|
||||
bool LoadBuildingPositionMap(const std::string &path, bool loadAllAvailableBuildings) override;
|
||||
|
||||
|
||||
void LoadAllBuildings();
|
||||
|
||||
/**
|
||||
* Create new player at (0,0,0). Player is initially invisible!
|
||||
* @param id a unique string that can later be used to reference the player
|
||||
* @param iconpath system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* @param color Initial color of the player
|
||||
*/
|
||||
void CreatePlayer(const std::string &id, const std::string &iconpath, const Color &color) override;
|
||||
|
||||
/**
|
||||
* Delete player with given id
|
||||
* @param seconds Delete player n seconds from now
|
||||
*/
|
||||
void DeletePlayer(const std::string &id, float seconds = 0) override;
|
||||
|
||||
/**
|
||||
* This color is added to the player texture color.
|
||||
*/
|
||||
void SetPlayerColor(const std::string &id, const Color &color) override;
|
||||
|
||||
/**
|
||||
* Set icon path for existing player
|
||||
* @param path system file path to player icon. Can be relative to ProjectAssets folder root.
|
||||
* If path is to current icon path then icon is reloaded from file.
|
||||
*/
|
||||
void SetPlayerIcon(const std::string &id, const std::string &path) override;
|
||||
|
||||
|
||||
void reloadPlayerIcons() override;
|
||||
|
||||
void UpdatePlayerPartyColors(const std::map<std::string, VCtrl::Color>& mapPlayerColors) override;
|
||||
|
||||
/**
|
||||
* Return number of soldier instances
|
||||
*/
|
||||
size_t GetNumPlayers() const override;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing players
|
||||
*/
|
||||
void GetPlayerIds(std::vector<std::string> &toFill) override;
|
||||
|
||||
/**
|
||||
* Hide or unhide player with given id
|
||||
* @param show true to show, false to hide
|
||||
* @param when simulation time when show or hide should be executed
|
||||
*/
|
||||
void SetPlayerShown(const std::string &id, bool show, double when = -1) override;
|
||||
|
||||
/**
|
||||
* Return number of building instances
|
||||
*/
|
||||
size_t GetNumBuildings() const override;
|
||||
|
||||
/**
|
||||
* Fill vector with ids of all existing buildings
|
||||
*/
|
||||
void GetBuildingIds(std::vector<std::string> &toFill) const override;
|
||||
|
||||
/**
|
||||
* Add or remove visible bounding box around entity
|
||||
* @param id unique id of entity
|
||||
* @param show set true to show box, false to make invisible
|
||||
* @param duration If non-negative, remove box after duration seconds
|
||||
*/
|
||||
void SetShowSelectionBox(const std::string &id,
|
||||
bool show,
|
||||
float duration = -1) override;
|
||||
|
||||
/**
|
||||
* Add a line from start to end
|
||||
* Line is displayed by an array of sprites, placed
|
||||
* in equal intervals.
|
||||
* Sprites move toward target with given speed in m/s
|
||||
* Line is deleted after duration seconds.
|
||||
* If duration is 0 then line is never deleted
|
||||
*/
|
||||
void Shoot(const int32_t id,
|
||||
const std::string &shooter,
|
||||
const std::string &target,
|
||||
const Vec3d &shooterPos,
|
||||
const Vec3d &targetPos,
|
||||
int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst,
|
||||
int lineType,
|
||||
double when) override;
|
||||
void Shoot(const int32_t id,
|
||||
const std::string &shooter,
|
||||
const std::string &targetBuildingId,
|
||||
const std::string &targetRoomId,
|
||||
const Vec3d &shooterPos, int lineType,
|
||||
double when) override;
|
||||
|
||||
void removeShoot(const int32_t id) override;
|
||||
|
||||
/**
|
||||
* Directly move player to target position, do not use pathfinding. Cancels current path following activity.
|
||||
* @param id Id of player
|
||||
* @param when Simulation time when teleport should happen
|
||||
* @param target position to teleport to
|
||||
* @param bldgname name of building containing position, empty string to ignore
|
||||
* @param roomname name of room containing position, empty string to ignore
|
||||
*/
|
||||
void Teleport(const std::string &id,
|
||||
double when,
|
||||
const Vec3d &target,
|
||||
const std::string &bldgname,
|
||||
int roomNumber,
|
||||
const std::string &roomname,
|
||||
ZValue zval) override;
|
||||
|
||||
/**
|
||||
* Get names of all rooms in building
|
||||
* @param id Id of building player
|
||||
* @param names will be filled with room names
|
||||
*/
|
||||
void GetRoomNames(const std::string &id, std::vector<std::string> &names) override;
|
||||
|
||||
/**
|
||||
* Sets destruction value for room of a building.
|
||||
* @param id Id of building player
|
||||
* @param roomnumber number of room to set (ex: "2001")
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
bool SetRoomDestructionValue(const std::string &id,
|
||||
const std::string &roomname,
|
||||
float value) override;
|
||||
|
||||
/**
|
||||
* Sets destruction value for all rooms of a building.
|
||||
* @param id Id of building player
|
||||
* @param value destruction value. 0: not destroyed, 1: fully destroyed
|
||||
* @return true if room was found
|
||||
*/
|
||||
bool SetBuildingDestructionValue(const std::string &id, float value) override;
|
||||
|
||||
/**
|
||||
* Get names of all cameras, loudspeakers and other devices in building
|
||||
* @param buildingid Id of building player
|
||||
* @param names will be filled with device names
|
||||
*/
|
||||
void GetDeviceNames(const std::string &buildingId, std::vector<std::string> &names) override;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param devicename name of device node to show icon at
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const std::string &devicename, const std::string &iconpath) override;
|
||||
|
||||
/**
|
||||
* Show an icon at center position of device node
|
||||
* @param id unique id for entity that can be used to hide it at a later point
|
||||
* @param buildingid id of building containing the device
|
||||
* @param position Position of camera relative to building
|
||||
* @param iconpath absolute path to icon to show at device position
|
||||
* @return true if device was found in building
|
||||
*/
|
||||
bool ShowDeviceIcon(const std::string &id, const std::string &buildingid,
|
||||
const Vec3d &position, const std::string &iconpath) override;
|
||||
|
||||
void ChangeLineMode(unsigned int contextId, bool line) override;
|
||||
void ChangeNameMode(unsigned int contextId, bool name) override;
|
||||
|
||||
bool SetDisplayName(const std::string& buildingid, const std::string& roomname, const std::string& strDisplayName) override;
|
||||
void ShowDisplayNames(const std::string& buildingid, bool show) override;
|
||||
void SetShowDisplayNamesSelectionBox(const std::string& buildingid, const std::string& id, bool show, float duration = -1) override;
|
||||
void setHitLineDuration(uint32_t durationSec) override;
|
||||
void setMountingPointAsset(const MountingPointDescription &asset) override;
|
||||
std::vector<BuildingState> getBuildingState() const override;
|
||||
|
||||
/**
|
||||
* Hide device icon created with ShowDevice
|
||||
* @param id Id used in call to ShowDevice
|
||||
* @return true if device entity was found and successfully removed
|
||||
*/
|
||||
bool HideDeviceIcon(const std::string &id) override;
|
||||
|
||||
/**
|
||||
* Get time scale. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
float GetTimeScale() const override;
|
||||
|
||||
/**
|
||||
* Scale time. Scale 1 is normal, scale 2 is double normal speed
|
||||
*/
|
||||
void SetTimeScale(float scale) override;
|
||||
|
||||
/**
|
||||
* Set current simulation time in seconds
|
||||
*/
|
||||
void SetSimulationTime(double t) override;
|
||||
|
||||
/**
|
||||
* Get current simulation time in seconds
|
||||
*/
|
||||
double GetSimulationTime() const override;
|
||||
|
||||
/**
|
||||
* Pause simulation time and all events
|
||||
*/
|
||||
void SetPaused(bool) override;
|
||||
|
||||
/**
|
||||
* Is simulation currently paused?
|
||||
*/
|
||||
bool GetPaused() const override;
|
||||
|
||||
/**
|
||||
* Advance simulation until given simulation time is reached
|
||||
*/
|
||||
void FastForwardSimulationTo(double t) override;
|
||||
|
||||
/**
|
||||
* Remove all queued commands for soldiers
|
||||
*/
|
||||
void DeleteQueuedCommands() override;
|
||||
|
||||
/**
|
||||
* Switch on or off non realtime mode.
|
||||
* Non realtime mode is used for recording videos at faster than real time speed.
|
||||
* Frames are rendered and compressed as fast as possible, simulation time
|
||||
* does not correspond to real time.
|
||||
*/
|
||||
void SetNonRealtimeMode(bool on) override;
|
||||
|
||||
/**
|
||||
* Is non-realtime mode on or off?
|
||||
*/
|
||||
bool GetNonRealtimeMode() const override;
|
||||
|
||||
/**
|
||||
* Start recording an mpeg video of the view.
|
||||
* @param contextid context id of the view to record.
|
||||
* @param path Record to this file. Extension should be .mpg
|
||||
* @param w width of recorded video file (input is rescaled)
|
||||
* @param h height of recorded video file (input is rescaled)
|
||||
* @param framerate frames per second to record. Reasonable value: 15 - 30
|
||||
* @param quality Compression quality in percent.
|
||||
*/
|
||||
bool StartVideoRecording(unsigned int contextid, const std::string &path,
|
||||
int w, int h, int framerate, int quality) override;
|
||||
bool StartVideoRecording(const std::string &buildingId, const std::string &path,
|
||||
int w, int h, int framerate, int quality) override;
|
||||
|
||||
/**
|
||||
* Stop recording
|
||||
* @param contextid context id of the view to record.
|
||||
*/
|
||||
bool StopVideoRecording(unsigned int contextid) override;
|
||||
bool StopVideoRecording(const std::string &buildingId) override;
|
||||
|
||||
void setTransparency(double percent) override;
|
||||
void setViewMode(ViewMode m) override;
|
||||
void setDisplayMode(PlayerDisplayMode m) override;
|
||||
|
||||
int GetFrameRate() const { return mFrameRate; }
|
||||
void OnShowMsgBox(const std::string &strText);
|
||||
|
||||
bool allViewWindowsExposed() const
|
||||
{
|
||||
for (auto *vw : m_openedViewWidgets.getViewWidgets())
|
||||
{
|
||||
if (!vw->isOpenGlWindowExposed())
|
||||
return false;
|
||||
}
|
||||
return !m_openedViewWidgets.getViewWidgets().empty();
|
||||
}
|
||||
|
||||
private:
|
||||
bool open(const std::string& strFeatureID, bool exactPos);
|
||||
bool open(const std::vector<std::string> &vecFeatureIDs, bool exactPos);
|
||||
bool openAll(bool exactPos);
|
||||
|
||||
void onEXCOpen(const QString& strIDs, bool exactPos);
|
||||
void onEXCClose(const QString& strIDs);
|
||||
void convertAssetsToPngFiles();
|
||||
|
||||
void OnTransformSend(const dtEntity::Message &m);
|
||||
void OnMapLoaded(const dtEntity::Message &m);
|
||||
void OnMapUnloaded(const dtEntity::Message &m);
|
||||
void OnNavMeshGroupChanged(const dtEntity::Message &m);
|
||||
void OnPlayerPicked(const dtEntity::Message &m);
|
||||
void OnHideSelection(const dtEntity::Message &m);
|
||||
//void OnRemoveShoot(const dtEntity::Message &m);
|
||||
void OnShoot(const dtEntity::Message &m);
|
||||
void OnShowHidePlayer(const dtEntity::Message &m);
|
||||
void OnDisplayNameClicked(const dtEntity::Message& m);
|
||||
|
||||
bool SpawnBuilding(const BuildingData &b, bool useStaticMeshesFolder = true);
|
||||
void LoadBuilding(BuildingData& bd, bool useStaticMeshesFolder);
|
||||
void deleteAllBuildings();
|
||||
|
||||
bool getBuildingString(const std::string &strFeatureID, std::string *strBuildingNameID);
|
||||
|
||||
bool OpenView(unsigned int contextId);
|
||||
bool CreateView(dtEntity::EntityId bid, const std::string &windowtitle, const Color &col, ViewMode viewmode,
|
||||
int screennum, bool fullscreen, int x, int y, int w, int h,
|
||||
unsigned int &contextid, bool exactPos);
|
||||
|
||||
QPointer<CtrlMainWindow> m_pMainWindow;
|
||||
|
||||
dtEntity::EntityManager *mEntityManager;
|
||||
ViewerCallback *mViewerCallback;
|
||||
LogHandler* mLogHandler = nullptr;
|
||||
dtEntity::MapSystem *mMapSystem;
|
||||
PlayerSystem *mPlayerSystem;
|
||||
BuildingManager *mBuildingManager;
|
||||
|
||||
float mTimeScale;
|
||||
double mSimTime;
|
||||
bool mPaused;
|
||||
bool mNonRealtimeMode;
|
||||
int mFrameRate; // only for non realtime mode
|
||||
std::map<unsigned int, ViewWidget *> mViewWidgets; // contextIDs to ViewWidgets
|
||||
|
||||
|
||||
ViewWidget *GetViewWidget(unsigned int contextid);
|
||||
void storeWidget(ViewWidget *pWidget, const std::string &strBuildingNameID, unsigned int contextid, VCtrl::ViewMode vmode, VCtrl::PlayerDisplayMode displayMode);
|
||||
|
||||
|
||||
const std::size_t m_maxParallelViewWidgets = 8;
|
||||
// Global setting for all ViewWidgets
|
||||
unsigned int m_hitlineDuration_s = 10;
|
||||
double m_desiredTransparencyValue = 0.75;
|
||||
bool m_showHitLines = true;
|
||||
ViewWidget *CreateMainWindowView(dtEntity::EntityId bid, const std::string &featureId, unsigned int &contextid, bool exactPos);
|
||||
|
||||
|
||||
std::unordered_map<std::string, BuildingData> m_loadedBuildings; // Feature_IDs
|
||||
|
||||
ViewWidgetContainer m_openedViewWidgets;
|
||||
bool m_isInFullscreenMode = false;
|
||||
|
||||
// Global Settings valid for all newly opened widgets
|
||||
ViewMode m_desiredViewMode = ViewMode::ORTHOGRAPHIC;
|
||||
VCtrl::PlayerDisplayMode m_desiredPlayerDisplayMode = VCtrl::PlayerDisplayMode::Icons;
|
||||
|
||||
void CloseView(ViewWidget *pWidget);
|
||||
|
||||
void onExcRestoreViewState(const std::string &strFeatureID);
|
||||
void restoreViewWidgetStates(const std::vector<BuildingViewer::ViewWidgetState> &vecStates);
|
||||
void restoreViewWidgetStateDeferred(ViewWidget *pViewWidget);
|
||||
std::unordered_map<std::string, BuildingViewer::ViewWidgetState> m_deferredViewStates;
|
||||
|
||||
QJsonValue getViewState() const override;
|
||||
void setViewState(const QJsonValue &val) override;
|
||||
void highlightView(const std::string &buildingId) override;
|
||||
void setBuildingDisplayName(const std::string &buildingId, const std::string &displayName) override;
|
||||
//NGL::INGLLogger &m_logger;
|
||||
|
||||
private slots:
|
||||
void onViewWidget_MaximizeRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_MinimizeRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_CloseRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_FocusRequest(ViewWidget *pWidget);
|
||||
void onViewWidget_Zoom(ViewWidget *pWidget, bool zoomIn);
|
||||
};
|
||||
}
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
#include "viewermainwindow.h"
|
||||
#include "viewwidget.h"
|
||||
#include "viewerinterfaceimpl.h"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
TransparencyDialog::TransparencyDialog(QWidget *parent)
|
||||
: QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
|
||||
{
|
||||
setWindowTitle(tr("BgViewer - Set Global Transparency"));
|
||||
|
||||
auto plabel = new QLabel(tr("Set transparency value:"));
|
||||
m_pSlider = new QSlider(Qt::Horizontal);
|
||||
m_pSlider->setMinimum(0);
|
||||
m_pSlider->setMaximum(100);
|
||||
m_pSlider->setValue(50);
|
||||
m_pSlider->setMinimumWidth(200);
|
||||
|
||||
auto pButton = new QPushButton(tr("Apply"));
|
||||
connect(pButton, &QPushButton::clicked, this, &VCtrl::TransparencyDialog::accept);
|
||||
|
||||
|
||||
auto pLayout = new QHBoxLayout(this);
|
||||
pLayout->addWidget(plabel);
|
||||
pLayout->addWidget(m_pSlider);
|
||||
pLayout->addWidget(pButton);
|
||||
pLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CtrlMainWindow::CtrlMainWindow(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
connect(&m_highlighterTimer, &QTimer::timeout,
|
||||
this, &CtrlMainWindow::onHighlighterTimerTimeout);
|
||||
setWindowTitle(tr("BgViewer"));
|
||||
// Remove minimize/maximize and close button
|
||||
setWindowFlags(Qt::Window | Qt::CustomizeWindowHint);
|
||||
|
||||
new QGridLayout(this);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::updateHighlightThreads(ViewWidget *pWidget)
|
||||
{
|
||||
m_highlighterCounter[pWidget] = 6;
|
||||
if (!m_highlighterTimer.isActive())
|
||||
m_highlighterTimer.start(500);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::onHighlighterTimerTimeout()
|
||||
{
|
||||
auto it = m_highlighterCounter.begin();
|
||||
while (it != m_highlighterCounter.end())
|
||||
{
|
||||
ViewWidget *ww = it.key();
|
||||
ww->highlightBorder(it.value() % 2 == 0);
|
||||
it.value() = it.value() - 1;
|
||||
if (it.value() <= 0)
|
||||
it = m_highlighterCounter.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
if (m_highlighterCounter.isEmpty())
|
||||
m_highlighterTimer.stop();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::openView(ViewWidget *pViewWidget)
|
||||
{
|
||||
openViews({pViewWidget});
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::openViews(const std::vector<ViewWidget *> &vecMainWindowSubWidgets)
|
||||
{
|
||||
constexpr int maxViewsPerCol = 4;
|
||||
|
||||
// Append where we stopped last time
|
||||
QGridLayout *gridLayout = static_cast<QGridLayout *>(layout());
|
||||
int row = gridLayout->count() / maxViewsPerCol, col = gridLayout->count() % maxViewsPerCol;
|
||||
|
||||
// Add all requested ViewWidgets which are actually new
|
||||
for (auto &pWidget : vecMainWindowSubWidgets)
|
||||
{
|
||||
auto itm = gridLayout->itemAtPosition(row, col);
|
||||
if (itm && itm->widget() == pWidget)
|
||||
continue;
|
||||
gridLayout->addWidget(pWidget, row, col);
|
||||
pWidget->show();
|
||||
|
||||
if (++col >= maxViewsPerCol)
|
||||
{
|
||||
col = 0;
|
||||
++row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CtrlMainWindow::closeView(ViewWidget *pViewWidget)
|
||||
{
|
||||
if (!pViewWidget)
|
||||
return;
|
||||
QGridLayout *gridLayout = dynamic_cast<QGridLayout *>(layout());
|
||||
std::vector<ViewWidget*> currentViews;
|
||||
currentViews.reserve(gridLayout->count());
|
||||
for (int idx = 0; idx < gridLayout->count(); idx++)
|
||||
{
|
||||
QLayoutItem *item = gridLayout->itemAt(idx);
|
||||
ViewWidget *vw = static_cast<ViewWidget*>(item->widget());
|
||||
if (vw != pViewWidget)
|
||||
currentViews.push_back(vw);
|
||||
}
|
||||
m_highlighterCounter.remove(pViewWidget);
|
||||
pViewWidget->close();
|
||||
|
||||
delete gridLayout;
|
||||
setLayout(new QGridLayout);
|
||||
openViews(currentViews);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void CtrlMainWindow::clearGridLayout()
|
||||
{
|
||||
QGridLayout *gridLayout = dynamic_cast<QGridLayout *>(layout());
|
||||
for (int idx = 0; idx < gridLayout->count(); idx++)
|
||||
{
|
||||
QLayoutItem *item = gridLayout->itemAt(idx);
|
||||
item->widget()->hide();
|
||||
}
|
||||
m_highlighterCounter.clear();
|
||||
|
||||
delete gridLayout;
|
||||
setLayout(new QGridLayout);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef VCTRL_CTRLMAINWINDOW_H
|
||||
#define VCTRL_CTRLMAINWINDOW_H
|
||||
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSlider>
|
||||
#include <QTimer>
|
||||
#include <QHash>
|
||||
|
||||
#include "viewerinterface.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class TransparencyDialog final : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TransparencyDialog(QWidget *parent = nullptr);
|
||||
double getTransparencyValue() const
|
||||
{
|
||||
return m_pSlider->value() / 100.0;
|
||||
}
|
||||
private:
|
||||
QSlider *m_pSlider;
|
||||
};
|
||||
|
||||
|
||||
class ViewWidget;
|
||||
class CtrlImpl;
|
||||
|
||||
|
||||
class CtrlMainWindow final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CtrlMainWindow(QWidget *parent);
|
||||
|
||||
void openView(ViewWidget *pViewWidget);
|
||||
void openViews(const std::vector<ViewWidget *> &vecMainWindowSubWidgets);
|
||||
void closeView(ViewWidget *pViewWidget);
|
||||
void updateHighlightThreads(ViewWidget *pWidget);
|
||||
void clearGridLayout();
|
||||
|
||||
private:
|
||||
void onHighlighterTimerTimeout();
|
||||
private:
|
||||
QTimer m_highlighterTimer;
|
||||
QHash<ViewWidget *, int> m_highlighterCounter;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // VCTRL_CTRLMAINWINDOW_H
|
||||
@@ -0,0 +1,390 @@
|
||||
#include "viewwidget.h"
|
||||
#include "viewwidgetstate.h"
|
||||
#include <QApplication>
|
||||
#include <QVBoxLayout>
|
||||
#include <QEvent>
|
||||
#include <QGLWidget>
|
||||
#include <QWindow>
|
||||
#include <dtEntity/log.h>
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
ViewWidgetState::ViewWidgetState(VCtrl::ViewWidget* pView)
|
||||
: m_featureID(pView->featureID())
|
||||
, m_usedTransparencyValue(pView->transparency())
|
||||
, m_windowWidth(pView->accessView()->width())
|
||||
, m_windowHeight(pView->accessView()->height())
|
||||
, m_lockActive(pView->lockedRotation())
|
||||
, m_dotsActive(pView->dotModeActive())
|
||||
, m_isMaximized(pView->isMaximized())
|
||||
, m_namesActive(pView->nameModeActive())
|
||||
, m_usesOrtho(pView->viewMode() == VCtrl::ViewMode::ORTHOGRAPHIC)
|
||||
, m_usesExactPos(pView->exactPos())
|
||||
{}
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
const QColor ViewWidget::ColorBorder = QColor(48, 136, 209);
|
||||
const QColor ViewWidget::ColorSelected = QColor(90, 200, 255);
|
||||
const QColor ViewWidget::ColorHighlighted = Qt::green;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ViewWidget::ViewWidget(unsigned int contextid, dtEntity::EntityId bid, const std::string &strFeatureID, bool usesExactPos, QWidget *parent)
|
||||
: QFrame(parent),
|
||||
m_locked(false),
|
||||
m_useDotMode(false),
|
||||
m_entityID(bid),
|
||||
m_featureID(strFeatureID),
|
||||
mContextId(contextid),
|
||||
m_usesExactPos(usesExactPos),
|
||||
mViewerInterface(nullptr),
|
||||
mClosedByAPI(false),
|
||||
m_pView(nullptr)
|
||||
{
|
||||
setupUi(this);
|
||||
|
||||
m_toolButton_maximize->setIcon(QIcon(QStringLiteral("icon:bgv_view_maximize.svg")));
|
||||
m_toolButton_close->setIcon(QIcon(QStringLiteral("icon:bgv_view_close.svg")));
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
m_toolButton_dots->setIcon(QIcon(QStringLiteral("icon:bgv_view_symbols.svg")));
|
||||
m_toolButton_lockRotation->setIcon(QIcon(QStringLiteral("icon:bgv_view_unlock.svg")));
|
||||
m_toolButton_rooms->setIcon(QIcon(QStringLiteral("icon:bgv_room_edit.svg")));
|
||||
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
|
||||
m_toolButton_ZoomOut->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_out.svg")));
|
||||
m_toolButton_ZoomIn->setIcon(QIcon(QStringLiteral("icon:bgv_zoom_in.svg")));
|
||||
|
||||
QIcon iconT(QStringLiteral("icon:bgv_transparency.svg"));
|
||||
QPixmap image(iconT.pixmap(30,30));
|
||||
m_label_transparency->setPixmap(image);
|
||||
|
||||
connect(m_toolButton_viewmode, &QToolButton::clicked, this, &ViewWidget::viewModeChanged);
|
||||
connect(_transparency, &QSlider::valueChanged, this, &ViewWidget::transparencyChanged);
|
||||
connect(m_toolButton_lockRotation, &QToolButton::clicked, this, &ViewWidget::lockRotationToggled);
|
||||
connect(m_toolButton_dots, &QToolButton::clicked, this, &ViewWidget::dotModeToggled);
|
||||
connect(m_toolButton_rooms, &QToolButton::clicked, this, &ViewWidget::nameModeToggled);
|
||||
connect(m_toolButton_more, &QToolButton::clicked, this, &ViewWidget::slotShowMore);
|
||||
connect(m_toolButton_maximize, &QToolButton::clicked, this, &ViewWidget::OnButtonMaximize);
|
||||
connect(m_toolButton_close, &QToolButton::clicked, this, &ViewWidget::OnButtonClose);
|
||||
|
||||
connect(m_toolButton_ZoomOut, &QToolButton::clicked, this, [this](){
|
||||
emit signal_Zoom(this, false);
|
||||
});
|
||||
connect(m_toolButton_ZoomIn, &QToolButton::clicked, this, [this](){
|
||||
emit signal_Zoom(this, true);
|
||||
});
|
||||
|
||||
m_toolButton_maximize->setEnabled(true);
|
||||
|
||||
setSelected(false);
|
||||
setMouseTracking(true); // Otherwise ViewWidget::mouseMoveEvent would not receive any events
|
||||
|
||||
slotShowMore(false);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::highlightBorder(bool highlight)
|
||||
{
|
||||
if (highlight)
|
||||
drawBorder(ColorHighlighted);
|
||||
else
|
||||
drawBorder(isSelected() ? ColorSelected : ColorBorder);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::dotModeToggled()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
m_useDotMode ^= true;
|
||||
mViewerInterface->SetPlayerDisplayMode(mContextId, m_useDotMode ? PlayerDisplayMode::Dots : PlayerDisplayMode::Icons);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::drawBorder(const QColor &col)
|
||||
{
|
||||
setStyleSheet(QStringLiteral("#ViewWidget { border: 2px solid %1; }").arg(col.name()));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::closeByAPI()
|
||||
{
|
||||
mClosedByAPI = true;
|
||||
this->close();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setText(const QString &strText)
|
||||
{
|
||||
m_label_description->setText(strText);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::closeEvent(QCloseEvent *e)
|
||||
{
|
||||
if (mViewerInterface && !mClosedByAPI)
|
||||
mViewerInterface->CloseView(mContextId);
|
||||
QFrame::closeEvent(e);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setDisplayedViewMode(ViewMode vm)
|
||||
{
|
||||
if (vm == ViewMode::ORTHOGRAPHIC)
|
||||
{
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
}
|
||||
else if (vm == ViewMode::ISOMETRIC)
|
||||
{
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_ortho.svg")));
|
||||
}
|
||||
|
||||
m_viewmode = vm;
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::viewModeChanged()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
if (m_viewmode == ViewMode::ORTHOGRAPHIC)
|
||||
{
|
||||
m_viewmode = ViewMode::ISOMETRIC;
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_iso.svg")));
|
||||
mViewerInterface->ChangeViewMode(mContextId, m_viewmode);
|
||||
}
|
||||
else if (m_viewmode == ViewMode::ISOMETRIC)
|
||||
{
|
||||
m_viewmode = ViewMode::ORTHOGRAPHIC;
|
||||
m_toolButton_viewmode->setIcon(QIcon(QStringLiteral("icon:bgv_view_ortho.svg")));
|
||||
mViewerInterface->ChangeViewMode(mContextId, m_viewmode);
|
||||
}
|
||||
m_toolButton_viewmode->setChecked(m_viewmode != ViewMode::ISOMETRIC);
|
||||
}
|
||||
|
||||
bool ViewWidget::isOpenGlWindowExposed() const
|
||||
{
|
||||
QGLWidget *gl = qobject_cast<QGLWidget*>(m_pView);
|
||||
if (!gl || !gl->windowHandle())
|
||||
return false;
|
||||
return gl->windowHandle()->isExposed();
|
||||
}
|
||||
|
||||
void ViewWidget::setMaximized(bool maximized)
|
||||
{
|
||||
m_toolButton_maximize->setIcon(maximized ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_minimize.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_maximize.svg")));
|
||||
m_isMaximized = maximized;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::setSelected(bool selected)
|
||||
{
|
||||
m_isSelected = selected;
|
||||
drawBorder(m_isSelected ? ColorSelected : ColorBorder);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double ViewWidget::transparency() const {
|
||||
return static_cast<double>(_transparency->value()) / 100.0;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setTransparency(float value)
|
||||
{
|
||||
_transparency->setValue(qRound(value * 100));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::transparencyChanged(int v)
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
mViewerInterface->SetWallTransparency(mContextId, float(v) / 100.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ViewWidget::lockedRotation() const
|
||||
{
|
||||
return m_locked;
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::dotModeActive() const
|
||||
{
|
||||
return m_useDotMode;
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::nameModeActive() const
|
||||
{
|
||||
return m_toolButton_rooms->isChecked();
|
||||
}
|
||||
|
||||
|
||||
ViewMode ViewWidget::viewMode() const {
|
||||
return m_viewmode;
|
||||
}
|
||||
|
||||
bool ViewWidget::exactPos() const
|
||||
{
|
||||
return m_usesExactPos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setLockRotationCheckbox(bool v)
|
||||
{
|
||||
m_locked = v;
|
||||
m_toolButton_lockRotation->setIcon(m_locked ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_lock.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_unlock.svg")));
|
||||
m_toolButton_lockRotation->setChecked(m_locked);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setDotModeCheckbox(bool v)
|
||||
{
|
||||
m_useDotMode = v;
|
||||
m_toolButton_dots->setIcon(m_useDotMode ?
|
||||
QIcon(QStringLiteral("icon:bgv_view_dots.svg")) :
|
||||
QIcon(QStringLiteral("icon:bgv_view_symbols.svg")));
|
||||
m_toolButton_dots->setChecked(m_useDotMode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setNameModeCheckbox(bool v)
|
||||
{
|
||||
m_toolButton_rooms->setChecked(v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::lockRotationToggled()
|
||||
{
|
||||
if (!mViewerInterface) return;
|
||||
|
||||
m_locked ^= true;
|
||||
mViewerInterface->LockViewRotationToMapRotation(mContextId, m_locked);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::slotShowMore(bool v)
|
||||
{
|
||||
widget->setVisible(v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::nameModeToggled(bool v)
|
||||
{
|
||||
if(!mViewerInterface) return;
|
||||
mViewerInterface->ChangeNameMode(mContextId, v);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::OnButtonMaximize(bool)
|
||||
{
|
||||
if (m_isMaximized)
|
||||
{
|
||||
emit signal_MinimizeRequest(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
emit signal_MaximizeRequest(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::OnButtonClose(bool)
|
||||
{
|
||||
emit signal_CloseRequest(this);
|
||||
}
|
||||
|
||||
|
||||
QWidget* ViewWidget::accessView()
|
||||
{
|
||||
return m_pView;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
emit signal_FocusRequest(this);
|
||||
QFrame::mouseMoveEvent(event);
|
||||
}
|
||||
|
||||
|
||||
bool ViewWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseMove)
|
||||
emit signal_FocusRequest(this);
|
||||
if (obj == m_pView && event->type() == QEvent::Show)
|
||||
emit signal_ViewIsShown(this);
|
||||
|
||||
return QFrame::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void ViewWidget::showEvent(QShowEvent *event)
|
||||
{
|
||||
QWidget::showEvent(event);
|
||||
updateTlwTransientParent();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::setView(QWidget *view)
|
||||
{
|
||||
if (m_pView)
|
||||
{
|
||||
m_pView->removeEventFilter(this);
|
||||
layout()->removeWidget(m_pView);
|
||||
}
|
||||
m_pView = view;
|
||||
m_pView->installEventFilter(this);
|
||||
QVBoxLayout *vLay = qobject_cast<QVBoxLayout*>(layout());
|
||||
if (!vLay)
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
vLay->addWidget(m_pView);
|
||||
updateTlwTransientParent();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void ViewWidget::updateTlwTransientParent()
|
||||
{
|
||||
// this is a workaround for Qt < 5.12 which does not set the correct blocking state for
|
||||
// the toplevel widget where this ViewWidget lives in when there is a model dialog (which
|
||||
// means all other TLWs are blocked) and a native window (like e.g. QGLWidget) is added as
|
||||
// a child therefore we have to trigger and update of the blocking state of the complete
|
||||
// hierarchy to make sure we don't get out of sync. It's fixed in at least 5.12, but could
|
||||
// not find out the commit / bug report for it. If you want to debug,
|
||||
// QGuiApplicationPrivate::updateBlockedStatus() is a good starting point for this.
|
||||
if (QApplication::activeModalWidget())
|
||||
{
|
||||
QWidget *tlw = window();
|
||||
if (tlw && tlw->windowHandle())
|
||||
tlw->windowHandle()->setTransientParent(tlw->windowHandle()->transientParent());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include <QFrame>
|
||||
#include <QColor>
|
||||
#include <QWidget>
|
||||
#include <QDockWidget>
|
||||
#include "ui_viewwidget.h"
|
||||
#include "viewerinterface.h"
|
||||
|
||||
#include <string>
|
||||
#include "dtEntity/entityid.h"
|
||||
|
||||
|
||||
namespace osgViewer {
|
||||
class View;
|
||||
}
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidget
|
||||
: public QFrame, // QWidget, (Needs to be QFrame to set border properties such as color)
|
||||
public Ui::ViewWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ViewWidget(unsigned int contextid,
|
||||
dtEntity::EntityId bid = 0,
|
||||
const std::string &strFeatureID = std::string(),
|
||||
bool usesExactPos = false,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
static const QColor ColorBorder;
|
||||
static const QColor ColorSelected;
|
||||
static const QColor ColorHighlighted;
|
||||
|
||||
void setView(QWidget *view);
|
||||
QWidget* accessView();
|
||||
void setText(const QString &strText);
|
||||
void closeEvent(QCloseEvent *e) override;
|
||||
|
||||
void setViewerInterface(ViewerInterface *v) { mViewerInterface = v; }
|
||||
|
||||
|
||||
bool isOpenGlWindowExposed() const;
|
||||
|
||||
inline bool isMaximized() const
|
||||
{
|
||||
return m_isMaximized;
|
||||
}
|
||||
|
||||
void setMaximized(bool maximized);
|
||||
void setSelected(bool selected);
|
||||
inline bool isSelected() const
|
||||
{
|
||||
return m_isSelected;
|
||||
}
|
||||
|
||||
inline unsigned int contextID() const
|
||||
{
|
||||
return mContextId;
|
||||
}
|
||||
|
||||
inline dtEntity::EntityId entityID() const
|
||||
{
|
||||
return m_entityID;
|
||||
}
|
||||
|
||||
inline const std::string featureID() const
|
||||
{
|
||||
return m_featureID;
|
||||
}
|
||||
|
||||
inline const std::string description() const
|
||||
{
|
||||
return m_label_description->text().toStdString();
|
||||
}
|
||||
|
||||
|
||||
double transparency() const;
|
||||
bool lockedRotation() const;
|
||||
bool dotModeActive() const;
|
||||
bool nameModeActive() const;
|
||||
ViewMode viewMode() const;
|
||||
bool exactPos() const;
|
||||
|
||||
signals:
|
||||
void signal_Zoom(ViewWidget *pWidget, bool zoomIn);
|
||||
void signal_MaximizeRequest(ViewWidget *pWidget);
|
||||
void signal_MinimizeRequest(ViewWidget *pWidget);
|
||||
void signal_CloseRequest(ViewWidget *pWidget);
|
||||
void signal_FocusRequest(ViewWidget *pWidget);
|
||||
void signal_ViewIsShown(ViewWidget *pWidget);
|
||||
|
||||
|
||||
public slots:
|
||||
void setLockRotationCheckbox(bool);
|
||||
void setDotModeCheckbox(bool);
|
||||
void setNameModeCheckbox(bool);
|
||||
void setDisplayedViewMode(ViewMode);
|
||||
void setTransparency(float value);
|
||||
void closeByAPI();
|
||||
|
||||
void highlightBorder(bool highlight);
|
||||
|
||||
|
||||
protected slots:
|
||||
void viewModeChanged();
|
||||
void transparencyChanged(int);
|
||||
void lockRotationToggled();
|
||||
void dotModeToggled();
|
||||
void nameModeToggled(bool);
|
||||
void slotShowMore(bool);
|
||||
|
||||
void OnButtonMaximize(bool);
|
||||
void OnButtonClose(bool);
|
||||
|
||||
private:
|
||||
void updateTlwTransientParent();
|
||||
void mouseMoveEvent(QMouseEvent *event) override;
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
void showEvent(QShowEvent *event) override;
|
||||
|
||||
bool m_isMaximized = false;
|
||||
bool m_isSelected = false;
|
||||
void drawBorder(const QColor &col);
|
||||
|
||||
bool m_locked, m_useDotMode;
|
||||
ViewMode m_viewmode = ViewMode::ISOMETRIC;
|
||||
|
||||
dtEntity::EntityId m_entityID;
|
||||
std::string m_featureID; // E.g., "House_11" (as specified within the xml files)
|
||||
unsigned int mContextId;
|
||||
|
||||
bool m_usesExactPos;
|
||||
|
||||
ViewerInterface *mViewerInterface;
|
||||
bool mClosedByAPI;
|
||||
QWidget* m_pView;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ViewWidget</class>
|
||||
<widget class="QWidget" name="ViewWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>333</width>
|
||||
<height>96</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_label_description">
|
||||
<property name="text">
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_dots">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Dots</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_viewmode">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Ortho</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="m_toolButton_more">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">...</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_maximize">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">O</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_close">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">X</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_lockRotation">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Lock</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_rooms">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Name</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_ZoomOut">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZOut</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="m_toolButton_ZoomIn">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>35</width>
|
||||
<height>35</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ZoomIn</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="m_label_transparency">
|
||||
<property name="text">
|
||||
<string notr="true">Transparency: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="_transparency">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
#include "viewwidgetcontainer.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
ViewWidget *ViewWidgetContainer::getViewWidget(unsigned int contextID) const
|
||||
{
|
||||
for (const auto &pView : m_vecViewWidgets)
|
||||
{
|
||||
if (pView->contextID() == contextID)
|
||||
return pView;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void ViewWidgetContainer::add(ViewWidget *pWidget)
|
||||
{
|
||||
m_vecViewWidgets.push_back(pWidget);
|
||||
m_mapFeatureID_To_ViewWidget[pWidget->featureID()] = pWidget;
|
||||
connect(pWidget, &QObject::destroyed, this, &ViewWidgetContainer::onWidgetDestroyed);
|
||||
}
|
||||
|
||||
|
||||
void ViewWidgetContainer::remove(const std::string &featureID)
|
||||
{
|
||||
auto it = m_mapFeatureID_To_ViewWidget.find(featureID);
|
||||
if (it != m_mapFeatureID_To_ViewWidget.end())
|
||||
{
|
||||
ViewWidget *pWidget = it->second;
|
||||
|
||||
auto vecIt = std::find(m_vecViewWidgets.begin(), m_vecViewWidgets.end(), pWidget);
|
||||
if (vecIt != m_vecViewWidgets.end())
|
||||
m_vecViewWidgets.erase(vecIt);
|
||||
|
||||
m_mapFeatureID_To_ViewWidget.erase(it);
|
||||
|
||||
assert(m_vecViewWidgets.size() == m_mapFeatureID_To_ViewWidget.size());
|
||||
}
|
||||
}
|
||||
|
||||
void ViewWidgetContainer::onWidgetDestroyed(QObject *obj)
|
||||
{
|
||||
ViewWidget *pWidget = static_cast<ViewWidget*>(obj);
|
||||
auto vecIt = std::find(m_vecViewWidgets.begin(), m_vecViewWidgets.end(), pWidget);
|
||||
if (vecIt != m_vecViewWidgets.end())
|
||||
m_vecViewWidgets.erase(vecIt);
|
||||
for (auto it = m_mapFeatureID_To_ViewWidget.begin(); it != m_mapFeatureID_To_ViewWidget.end(); ++it)
|
||||
{
|
||||
if (it->second == pWidget)
|
||||
{
|
||||
m_mapFeatureID_To_ViewWidget.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "viewwidget.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidgetContainer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
void add(ViewWidget *pWidget);
|
||||
void remove(const std::string &featureID);
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_vecViewWidgets.clear();
|
||||
m_mapFeatureID_To_ViewWidget.clear();
|
||||
}
|
||||
|
||||
|
||||
bool exist(const std::string &featureID) const
|
||||
{
|
||||
return (m_mapFeatureID_To_ViewWidget.find(featureID) != m_mapFeatureID_To_ViewWidget.end());
|
||||
}
|
||||
|
||||
ViewWidget *getViewWidget(const std::string &featureID) const
|
||||
{
|
||||
return exist(featureID) ? m_mapFeatureID_To_ViewWidget.at(featureID) : nullptr;
|
||||
}
|
||||
|
||||
ViewWidget *getViewWidget(unsigned int contextID) const;
|
||||
|
||||
const std::vector<ViewWidget*> &getViewWidgets() const
|
||||
{
|
||||
return m_vecViewWidgets;
|
||||
}
|
||||
|
||||
std::size_t size() const
|
||||
{
|
||||
return m_vecViewWidgets.size();
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void onWidgetDestroyed(QObject *obj);
|
||||
private:
|
||||
// Both containers will always have same size
|
||||
std::vector<ViewWidget *> m_vecViewWidgets; // Keeps track of the ViewWidget ordering (used for the gridlayout)
|
||||
std::map<std::string, ViewWidget *> m_mapFeatureID_To_ViewWidget; // Keeps track about the currently used FeatureIDs (respectively opened ViewWidgets)
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "cameraviewposition.h"
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
class ViewWidget;
|
||||
}
|
||||
|
||||
namespace BuildingViewer
|
||||
{
|
||||
class ViewWidgetState
|
||||
{
|
||||
public:
|
||||
explicit ViewWidgetState(VCtrl::ViewWidget *pView);
|
||||
explicit ViewWidgetState(const QJsonObject &jsonObj)
|
||||
{
|
||||
m_featureID = jsonObj[QStringLiteral("featureID")].toString().toStdString();
|
||||
m_usedTransparencyValue = jsonObj[QStringLiteral("usedTransparencyValue")].toDouble();
|
||||
|
||||
m_posCamera.m_top = jsonObj[QStringLiteral("posCameraTop")].toDouble();
|
||||
m_posCamera.m_left = jsonObj[QStringLiteral("posCameraLeft")].toDouble();
|
||||
m_posCamera.m_bottom = jsonObj[QStringLiteral("posCameraBottom")].toDouble();
|
||||
m_posCamera.m_right = jsonObj[QStringLiteral("posCameraRight")].toDouble();
|
||||
|
||||
m_windowWidth = jsonObj[QStringLiteral("windowWidth")].toInt();
|
||||
m_windowHeight = jsonObj[QStringLiteral("windowHeight")].toInt();
|
||||
|
||||
m_usesExactPos = jsonObj[QStringLiteral("usesExactPos")].toBool();
|
||||
m_lockActive = jsonObj[QStringLiteral("lockActive")].toBool();
|
||||
m_dotsActive = jsonObj[QStringLiteral("dotsActive")].toBool();
|
||||
m_isMaximized = jsonObj[QStringLiteral("isMaximized")].toBool();
|
||||
m_namesActive = jsonObj[QStringLiteral("namesActive")].toBool();
|
||||
m_usesOrtho = jsonObj[QStringLiteral("usesOrtho")].toBool();
|
||||
}
|
||||
|
||||
QJsonObject toJson() const
|
||||
{
|
||||
return {
|
||||
{QStringLiteral("featureID"), QString::fromStdString(m_featureID)},
|
||||
{QStringLiteral("usedTransparencyValue"), m_usedTransparencyValue},
|
||||
{QStringLiteral("posCameraTop"), m_posCamera.m_top},
|
||||
{QStringLiteral("posCameraLeft"), m_posCamera.m_left},
|
||||
{QStringLiteral("posCameraBottom"), m_posCamera.m_bottom},
|
||||
{QStringLiteral("posCameraRight"), m_posCamera.m_right},
|
||||
{QStringLiteral("windowWidth"), m_windowWidth},
|
||||
{QStringLiteral("windowHeight"), m_windowHeight},
|
||||
{QStringLiteral("usesExactPos"), m_usesExactPos},
|
||||
{QStringLiteral("lockActive"), m_lockActive},
|
||||
{QStringLiteral("dotsActive"), m_dotsActive},
|
||||
{QStringLiteral("namesActive"), m_namesActive},
|
||||
{QStringLiteral("isMaximized"), m_isMaximized},
|
||||
{QStringLiteral("usesOrtho"), m_usesOrtho},
|
||||
};
|
||||
}
|
||||
|
||||
std::string m_featureID; // We use featureID (manual string description of a building) since contextID may differ/change depending on implementation
|
||||
double m_usedTransparencyValue = 0.0;
|
||||
BuildingViewer::CameraViewPosition m_posCamera;
|
||||
int m_windowWidth = -1, m_windowHeight = -1;
|
||||
|
||||
bool m_lockActive = false;
|
||||
bool m_dotsActive = false;
|
||||
bool m_isMaximized = false;
|
||||
bool m_namesActive = false;
|
||||
bool m_usesOrtho = false;
|
||||
bool m_usesExactPos = false;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "visitors.h"
|
||||
|
||||
#include <dtEntity/property.h>
|
||||
#include <osg/Material>
|
||||
#include <osg/BlendFunc>
|
||||
#include <osg/BlendColor>
|
||||
#include <QStringRef>
|
||||
#include <QVector>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindByNameVisitor::apply(osg::Node &node)
|
||||
{
|
||||
const QString grpName(QString::fromStdString(node.getName()));
|
||||
if (grpName.contains(mName, Qt::CaseInsensitive))
|
||||
mNodes.push_back(&node);
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindExactNameVisitor::apply(osg::Node &node)
|
||||
{
|
||||
auto it = mNamesToSearch.find(node.getName());
|
||||
if (it != mNamesToSearch.end())
|
||||
{
|
||||
mNamesToSearch.erase(it);
|
||||
mNodes.push_back(&node);
|
||||
}
|
||||
if (mNamesToSearch.size())
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomNamesVisitor::apply(osg::Node &n)
|
||||
{
|
||||
const std::string &nm = n.getName();
|
||||
|
||||
if (nm.size() > 8 && nm.substr(0, 8) == "SW_room_")
|
||||
{
|
||||
if (n.getNumDescriptions() > 0)
|
||||
{
|
||||
std::string desc = n.getDescription(0);
|
||||
size_t pos = desc.find('@');
|
||||
if (pos != std::string::npos)
|
||||
mNames.push_back(desc.substr(pos + 1, desc.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string roomName = "2" + nm.substr(8, nm.size());
|
||||
mNames.push_back(roomName);
|
||||
std::vector<std::string> descList;
|
||||
descList.push_back(nm + "@" + roomName);
|
||||
n.setDescriptions(descList);
|
||||
}
|
||||
}
|
||||
traverse(n);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void ClearVertexColorsVisitor::apply(osg::Geode &geode)
|
||||
{
|
||||
for (unsigned int i = 0; i < geode.getNumDrawables(); ++i)
|
||||
{
|
||||
osg::Geometry *geo = geode.getDrawable(i)->asGeometry();
|
||||
if (geo && geo->getColorArray() != nullptr)
|
||||
{
|
||||
geo->setColorArray(nullptr);
|
||||
geo->setColorBinding(osg::Geometry::BIND_OFF);
|
||||
}
|
||||
}
|
||||
traverse(geode);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SplitVisitor::apply(osg::Group &node)
|
||||
{
|
||||
static const std::string floorPrefix("floor_");
|
||||
const std::string &nodename = node.getName();
|
||||
if (nodename.size() >= floorPrefix.size() &&
|
||||
std::equal(floorPrefix.begin(), floorPrefix.end(), nodename.begin()))
|
||||
{
|
||||
_parts.emplace_back(&node);
|
||||
float h = 0;
|
||||
for (unsigned int i = 0; i < node.getNumDescriptions(); ++i)
|
||||
{
|
||||
QString descr = QString::fromStdString(node.getDescription(i));
|
||||
const QVector<QStringRef> descprt = descr.splitRef(QLatin1Char(';'));
|
||||
for (const QStringRef &prt : descprt)
|
||||
{
|
||||
const QVector<QStringRef> items = prt.split(QLatin1Char('='));
|
||||
if (items.size() == 2 && items[0] == QLatin1String("base_height"))
|
||||
h = items[1].toFloat();
|
||||
}
|
||||
}
|
||||
_heights.push_back(h);
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomComponentsVisitor::apply(osg::Group &node)
|
||||
{
|
||||
static const std::string roomPrefix("undest_room_");
|
||||
const std::string &nodename = node.getName();
|
||||
if (nodename.size() >= roomPrefix.size() &&
|
||||
std::equal(roomPrefix.begin(), roomPrefix.end(), nodename.begin()))
|
||||
{
|
||||
//parts.push_back(&node);
|
||||
//float h = 0;
|
||||
for (unsigned int i = 0; i < node.getNumDescriptions(); ++i)
|
||||
{
|
||||
const std::string &descr = node.getDescription(i);
|
||||
std::istringstream f(descr);
|
||||
std::string s;
|
||||
while (getline(f, s, ';'))
|
||||
{
|
||||
if (s.size() != 0)
|
||||
mNamesFound.insert(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(node);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void FindRoomByNumberVisitor::apply(osg::Node &searchNode)
|
||||
{
|
||||
if (searchNode.getNumDescriptions() > 0)
|
||||
{
|
||||
const std::string &desc = searchNode.getDescription(0);
|
||||
size_t pos = desc.find('@');
|
||||
if (pos != std::string::npos && desc.substr(pos + 1, desc.size()) == searchForName)
|
||||
foundNodeList.push_back(&searchNode);
|
||||
}
|
||||
|
||||
traverse(searchNode);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SetWallsTransparentVisitor::SetAlpha(osg::Node *node, float alpha)
|
||||
{
|
||||
node->setNodeMask(0xFFFFFFFF);
|
||||
osg::StateSet *ss = node->getOrCreateStateSet();
|
||||
if (alpha > 0.99f)
|
||||
{
|
||||
ss->removeMode(GL_BLEND);
|
||||
ss->setRenderingHint(osg::StateSet::DEFAULT_BIN);
|
||||
/*osg::Material* mat = new osg::Material();
|
||||
mat->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||
ss->setAttributeAndModes(mat, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
mat->setAlpha(osg::Material::FRONT_AND_BACK, 1);*/
|
||||
|
||||
ss->removeUniform("wall_color");
|
||||
}
|
||||
else if (alpha < 0.01f)
|
||||
node->setNodeMask(0x0);
|
||||
else
|
||||
{
|
||||
ss->setMode(GL_BLEND, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
osg::BlendFunc *bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
|
||||
ss->setAttributeAndModes(bf, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||
ss->addUniform(new osg::Uniform("wall_color", osg::Vec4(1, 1, 1, alpha)));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
void SetWallsTransparentVisitor::apply(osg::Node &node)
|
||||
{
|
||||
std::string nm = node.getName();
|
||||
if (nm.size() > 4 && nm.substr(0, 4) == "wall")
|
||||
SetAlpha(&node, mTransparency);
|
||||
traverse(node);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
#pragma once
|
||||
|
||||
#include <osg/Group>
|
||||
#include <osg/NodeVisitor>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Geometry>
|
||||
#include <QtCore/QString>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindByNameVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
std::vector<osg::Node *> mNodes;
|
||||
QString mName;
|
||||
explicit FindByNameVisitor(const QString &name)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mName(name)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class FindExactNameVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
std::vector<osg::Node *> mNodes;
|
||||
std::set<std::string> mNamesToSearch;
|
||||
|
||||
explicit FindExactNameVisitor(const std::set<std::string> &namesToSearch)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mNamesToSearch(namesToSearch)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
class SplitVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
std::vector<osg::ref_ptr<osg::Node> > _parts;
|
||||
std::vector<float> _heights;
|
||||
SplitVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Group &node) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomComponentsVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
|
||||
public:
|
||||
std::set<std::string> mNamesFound;
|
||||
|
||||
FindRoomComponentsVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Group &node) override;
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomNamesVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
std::vector<std::string> mNames;
|
||||
|
||||
// Default constructor - initialize searchForName to "" and
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
FindRoomNamesVisitor() : osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Node &n) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class FindRoomByNumberVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
// Default constructor - initialize searchForName to "" and
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
FindRoomByNumberVisitor()
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
|
||||
searchForName()
|
||||
{}
|
||||
|
||||
// Constructor that accepts string argument
|
||||
// Initializes searchForName to user string
|
||||
// set the traversal mode to TRAVERSE_ALL_CHILDREN
|
||||
explicit FindRoomByNumberVisitor(const std::string &searchName) :
|
||||
osg::NodeVisitor(TRAVERSE_ALL_CHILDREN),
|
||||
searchForName(searchName)
|
||||
{
|
||||
}
|
||||
|
||||
void apply(osg::Node &searchNode) override;
|
||||
|
||||
// Set the searchForName to user-defined string
|
||||
void setNameToFind(const std::string &searchName)
|
||||
{
|
||||
searchForName = searchName;
|
||||
foundNodeList.clear();
|
||||
}
|
||||
|
||||
// Return a pointer to the first node in the list
|
||||
// with a matching name
|
||||
osg::Node *getFirst()
|
||||
{
|
||||
return *(foundNodeList.begin());
|
||||
}
|
||||
|
||||
|
||||
// typedef a vector of node pointers for convenience
|
||||
using NodeList = std::vector<osg::Node *>;
|
||||
|
||||
// return a reference to the list of nodes we found
|
||||
NodeList &getNodeList() { return foundNodeList; }
|
||||
|
||||
private:
|
||||
|
||||
// the name we are looking for
|
||||
std::string searchForName;
|
||||
|
||||
// List of nodes with names that match the searchForName string
|
||||
NodeList foundNodeList;
|
||||
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ClearVertexColorsVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
public:
|
||||
|
||||
ClearVertexColorsVisitor()
|
||||
: osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
|
||||
{}
|
||||
|
||||
void apply(osg::Geode &geode) override;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class SetWallsTransparentVisitor final : public osg::NodeVisitor
|
||||
{
|
||||
float mTransparency;
|
||||
public:
|
||||
|
||||
explicit SetWallsTransparentVisitor(float transparency)
|
||||
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||
, mTransparency(transparency)
|
||||
{
|
||||
setNodeMaskOverride(0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void SetAlpha(osg::Node *node, float alpha);
|
||||
|
||||
void apply(osg::Node &node) override;
|
||||
};
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commericial and non commericial applications,
|
||||
* as long as this copyright notice is maintained.
|
||||
*
|
||||
* This application 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.
|
||||
*/
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Cedric Pinson
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <osg/RenderInfo>
|
||||
#include <osg/GL>
|
||||
#include <osg/GLExtensions>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "windowcapturecallback.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/app/gstappsrc.h>
|
||||
#include <dtEntity/property.h>
|
||||
#include <dtEntity/core.h>
|
||||
#include <dtEntity/windowinterface.h>
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::operator()(osg::RenderInfo &renderInfo) const
|
||||
{
|
||||
glReadBuffer(_readBuffer);
|
||||
|
||||
osg::GraphicsContext *gc = renderInfo.getState()->getGraphicsContext();
|
||||
osg::ref_ptr<ContextData> cd = getContextData(gc);
|
||||
cd->read();
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(_contextId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::WindowCaptureCallback(GLenum readBuffer, unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality):
|
||||
_readBuffer(readBuffer),
|
||||
_contextId(contextid),
|
||||
_filename(path),
|
||||
_w(w),
|
||||
_h(h),
|
||||
_framerate(framerate),
|
||||
_quality(quality)
|
||||
{
|
||||
dtEntity::GetWindowInterface()->RequestRedraw(_contextId);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData *WindowCaptureCallback::createContextData(osg::GraphicsContext *gc) const
|
||||
{
|
||||
return new ContextData(gc, _readBuffer, _filename, _w, _h, _framerate, _quality);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData *WindowCaptureCallback::getContextData(osg::GraphicsContext *gc) const
|
||||
{
|
||||
osg::ref_ptr<ContextData> &data = _contextDataMap[gc];
|
||||
if (!data) data = createContextData(gc);
|
||||
|
||||
return data.get();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
static gboolean bus_message(GstBus *, GstMessage *message, WindowCaptureCallback *)
|
||||
{
|
||||
switch (GST_MESSAGE_TYPE(message))
|
||||
{
|
||||
case GST_MESSAGE_WARNING:
|
||||
{
|
||||
GError *err = nullptr;
|
||||
gchar *dbg_info = nullptr;
|
||||
|
||||
gst_message_parse_warning(message, &err, &dbg_info);
|
||||
g_printerr("WARN from element %s: %s\n",
|
||||
GST_OBJECT_NAME(message->src), err->message);
|
||||
g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_ERROR:
|
||||
{
|
||||
GError *err = nullptr;
|
||||
gchar *dbg_info = nullptr;
|
||||
|
||||
gst_message_parse_error(message, &err, &dbg_info);
|
||||
g_printerr("ERROR from element %s: %s\n",
|
||||
GST_OBJECT_NAME(message->src), err->message);
|
||||
g_printerr("Debugging info: %s\n", (dbg_info) ? dbg_info : "none");
|
||||
g_error_free(err);
|
||||
g_free(dbg_info);
|
||||
break;
|
||||
}
|
||||
#ifdef LTS_DEBUG
|
||||
case GST_MESSAGE_PROGRESS:
|
||||
{
|
||||
GstProgressType type;
|
||||
gchar *code, *text;
|
||||
bool in_progress = false;
|
||||
|
||||
gst_message_parse_progress (message, &type, &code, &text);
|
||||
|
||||
switch (type) {
|
||||
case GST_PROGRESS_TYPE_START:
|
||||
case GST_PROGRESS_TYPE_CONTINUE:
|
||||
in_progress = true;
|
||||
break;
|
||||
case GST_PROGRESS_TYPE_COMPLETE:
|
||||
case GST_PROGRESS_TYPE_CANCELED:
|
||||
case GST_PROGRESS_TYPE_ERROR:
|
||||
in_progress = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
g_printerr("Progress: (%s) %s, is in progress: %d\n", code, text, in_progress);
|
||||
g_free (code);
|
||||
g_free (text);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_QOS:
|
||||
{
|
||||
gboolean live;
|
||||
guint64 running_time, stream_time, time_stamp, duration;
|
||||
gst_message_parse_qos(message, &live, &running_time, &stream_time, &time_stamp, &duration);
|
||||
g_printerr("QOS message: %d, %ld, %ld, %ld, %ld\n", live, running_time, stream_time, time_stamp, duration);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_EOS:
|
||||
g_printerr("End-Of-Stream received!n");
|
||||
break;
|
||||
case GST_MESSAGE_STATE_CHANGED:
|
||||
{
|
||||
GstState oldState, newState, pendingState;
|
||||
gst_message_parse_state_changed(message, &oldState, &newState, &pendingState);
|
||||
g_printerr("State change from %d to %d (pending: %d)\n", oldState, newState, pendingState);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_printerr("got message %s\n",
|
||||
gst_message_type_get_name(GST_MESSAGE_TYPE(message)));
|
||||
break;
|
||||
#else
|
||||
default:
|
||||
g_print("got message %s\n",
|
||||
gst_message_type_get_name(GST_MESSAGE_TYPE(message)));
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return GST_BUS_PASS;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData::ContextData(osg::GraphicsContext *gc, GLenum readBuffer,
|
||||
const std::string &path, int w, int h, int framerate, int quality):
|
||||
_gc(gc),
|
||||
_readBuffer(readBuffer),
|
||||
_fileName(path),
|
||||
_width(0),
|
||||
_height(0)
|
||||
{
|
||||
(void)quality;
|
||||
|
||||
_startTick = _previousFrameTick = osg::Timer::instance()->tick();
|
||||
_pboBuffer.push_back(0);
|
||||
|
||||
getSize(gc, _width, _height);
|
||||
|
||||
osg::notify(osg::INFO) << this << " Window size " << _width << ", " << _height << std::endl;
|
||||
|
||||
GstBus *bus;
|
||||
|
||||
/* Initialize GStreamer */
|
||||
gst_init(nullptr, nullptr);
|
||||
|
||||
std::ostringstream gstpipeline;
|
||||
gstpipeline << "appsrc name=\"inputsrc\" ";
|
||||
gstpipeline << "! videorate ";
|
||||
gstpipeline << "! videoscale ";
|
||||
gstpipeline << "! videoconvert ";
|
||||
gstpipeline << "! video/x-raw, width=" << w << ", height=" << h << ", framerate=" << framerate << "/1 ";
|
||||
gstpipeline << "! videoflip method=5 ";
|
||||
|
||||
//#define SHOW_DIRECTLY
|
||||
|
||||
#ifdef SHOW_DIRECTLY
|
||||
gstpipeline << "! xvimagesink ";
|
||||
#else
|
||||
gstpipeline << " ! vp9enc end-usage=cbr";
|
||||
gstpipeline << " ! webmmux ";
|
||||
gstpipeline << " ! filesink location=" << path;
|
||||
#endif
|
||||
// g_warning("pipeline: '%s'\n", gstpipeline.str().c_str());
|
||||
|
||||
/* Build the pipeline */
|
||||
_pipeline = gst_parse_launch(gstpipeline.str().c_str(), nullptr);
|
||||
|
||||
_app_source = gst_bin_get_by_name((GstBin *) _pipeline, "inputsrc");
|
||||
|
||||
bus = gst_pipeline_get_bus(GST_PIPELINE(_pipeline));
|
||||
g_assert(bus);
|
||||
|
||||
gst_bus_add_watch(bus, (GstBusFunc) bus_message, this);
|
||||
gst_object_unref(bus);
|
||||
|
||||
GstCaps *video_caps = gst_caps_new_simple("video/x-raw",
|
||||
"format", G_TYPE_STRING, "RGBA",
|
||||
"width", G_TYPE_INT, _width,
|
||||
"height", G_TYPE_INT, _height,
|
||||
"framerate", GST_TYPE_FRACTION, framerate, 1,
|
||||
nullptr);
|
||||
gst_app_src_set_caps(GST_APP_SRC(_app_source), video_caps);
|
||||
g_object_set(GST_APP_SRC(_app_source), "format", GST_FORMAT_TIME, nullptr);
|
||||
gst_caps_unref(video_caps);
|
||||
|
||||
// make gstreamer more verbose:
|
||||
g_signal_connect( _pipeline, "deep-notify", G_CALLBACK(gst_object_default_deep_notify ), nullptr );
|
||||
|
||||
/* Start playing */
|
||||
gst_element_set_state(_pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::ContextData::getSize(osg::GraphicsContext *gc, int &width, int &height)
|
||||
{
|
||||
if (gc->getTraits())
|
||||
{
|
||||
width = gc->getTraits()->width;
|
||||
height = gc->getTraits()->height;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void WindowCaptureCallback::ContextData::read()
|
||||
{
|
||||
osg::GLExtensions *ext = osg::GLExtensions::Get(_gc->getState()->getContextID(), true);
|
||||
int width = 0, height = 0;
|
||||
getSize(_gc, width, height);
|
||||
if (width != _width || _height != height)
|
||||
{
|
||||
osg::notify(osg::INFO) << this << " Window resized " << width << ", " << height << std::endl;
|
||||
_width = width;
|
||||
_height = height;
|
||||
}
|
||||
|
||||
unsigned int size = _width * _height * 4;
|
||||
|
||||
GLuint &pbo = _pboBuffer[0];
|
||||
|
||||
if (pbo == 0)
|
||||
{
|
||||
ext->glGenBuffers(1, &pbo);
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
|
||||
ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, size, nullptr, GL_STREAM_READ);
|
||||
|
||||
osg::notify(osg::INFO) << this << " Generating pbo " << pbo << std::endl;
|
||||
}
|
||||
else
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
|
||||
|
||||
osg::Timer_t tick_now = osg::Timer::instance()->tick();
|
||||
|
||||
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLubyte *src = (GLubyte *)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
|
||||
GL_READ_ONLY_ARB);
|
||||
if (src)
|
||||
{
|
||||
guint64 timestamp = (tick_now - _startTick) * 1000;
|
||||
guint64 duration = (tick_now - _previousFrameTick) * 1000;
|
||||
GstBuffer *buffer = gst_buffer_new_allocate(nullptr, size, nullptr);
|
||||
GstMapInfo info;
|
||||
gst_buffer_map(buffer, &info, GST_MAP_WRITE);
|
||||
memcpy(info.data, src, size);
|
||||
gst_buffer_unmap(buffer, &info);
|
||||
GST_BUFFER_PTS(buffer) = timestamp;
|
||||
GST_BUFFER_DTS(buffer) = timestamp;
|
||||
GST_BUFFER_DURATION(buffer) = duration;
|
||||
_previousFrameTick = tick_now;
|
||||
|
||||
GstFlowReturn ret;
|
||||
g_signal_emit_by_name(_app_source, "push-buffer", buffer, &ret);
|
||||
gst_buffer_unref(buffer);
|
||||
|
||||
if (ret != GST_FLOW_OK)
|
||||
{
|
||||
// some error, stop sending data
|
||||
GST_DEBUG("some error");
|
||||
}
|
||||
|
||||
ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
|
||||
}
|
||||
|
||||
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
WindowCaptureCallback::ContextData::~ContextData()
|
||||
{
|
||||
gboolean ret = gst_element_send_event(_pipeline, gst_event_new_eos());
|
||||
if (ret)
|
||||
{
|
||||
GstMessageType types = GST_MESSAGE_EOS;
|
||||
GstMessage *msg = gst_bus_timed_pop_filtered(GST_ELEMENT_BUS(_pipeline), GST_CLOCK_TIME_NONE, types);
|
||||
gst_message_unref(msg);
|
||||
}
|
||||
gst_element_set_state(_pipeline, GST_STATE_NULL);
|
||||
gst_object_unref(_pipeline);
|
||||
}
|
||||
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
|
||||
*
|
||||
* This application is open source and may be redistributed and/or modified
|
||||
* freely and without restriction, both in commericial and non commericial applications,
|
||||
* as long as this copyright notice is maintained.
|
||||
*
|
||||
* This application 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.
|
||||
*/
|
||||
/* -*-c++-*-
|
||||
*
|
||||
* Copyright (C) 2009 Cedric Pinson
|
||||
*
|
||||
*
|
||||
* 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Authors:
|
||||
* Cedric Pinson <cedric.pinson@plopbyte.net>
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <osg/Camera>
|
||||
|
||||
// fwd decl for gstreamer objects
|
||||
struct _GstElement;
|
||||
|
||||
namespace VCtrl
|
||||
{
|
||||
|
||||
class WindowCaptureCallback : public osg::Camera::DrawCallback
|
||||
{
|
||||
public:
|
||||
struct ContextData : public osg::Referenced
|
||||
{
|
||||
ContextData(osg::GraphicsContext *gc, GLenum readBuffer, const std::string &path, int w, int h, int framerate, int quality);
|
||||
~ContextData();
|
||||
|
||||
static void getSize(osg::GraphicsContext *gc, int &width, int &height);
|
||||
|
||||
void read();
|
||||
|
||||
osg::GraphicsContext *_gc;
|
||||
GLenum _readBuffer;
|
||||
std::string _fileName;
|
||||
|
||||
int _width;
|
||||
int _height;
|
||||
|
||||
std::vector< GLuint > _pboBuffer;
|
||||
|
||||
osg::Timer_t _previousFrameTick;
|
||||
osg::Timer_t _startTick;
|
||||
_GstElement *_pipeline;
|
||||
_GstElement *_app_source;
|
||||
};
|
||||
|
||||
WindowCaptureCallback(GLenum readBuffer, unsigned int contextid, const std::string &path, int w, int h, int framerate, int quality);
|
||||
~WindowCaptureCallback() = default;
|
||||
|
||||
ContextData *createContextData(osg::GraphicsContext *gc) const;
|
||||
ContextData *getContextData(osg::GraphicsContext *gc) const;
|
||||
void operator()(osg::RenderInfo &renderInfo) const override;
|
||||
|
||||
using ContextDataMap = std::map<osg::GraphicsContext *, osg::ref_ptr<ContextData> >;
|
||||
|
||||
GLenum _readBuffer;
|
||||
unsigned int _contextId;
|
||||
std::string _filename;
|
||||
int _w;
|
||||
int _h;
|
||||
int _framerate;
|
||||
int _quality;
|
||||
mutable ContextDataMap _contextDataMap;
|
||||
};
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user