#include "orthomotionmodel.h" #include "messages.h" #include #include #include #include #include #include #include #include #include #include #include #include #include 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(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(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(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(m); for (const auto &comp : mComponents) comp.second->Tick(msg.GetDeltaRealTime()); } }