Files
qt5-legatus-legacy/Lts/Plugins/BuildingViewer/Common/BgViewer/viewerCtrl/orthomotionmodel.cpp
T
2026-08-13 18:33:10 +02:00

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());
}
}