375 lines
13 KiB
C++
Executable File
375 lines
13 KiB
C++
Executable File
#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());
|
|
}
|
|
}
|