Compare commits

...

38 Commits

Author SHA1 Message Date
36667bb144 修复标题栏双击最大化和正常切换的问题 2025-07-20 19:39:12 +08:00
fc4dd95e72 图表上上显示文件名称 2025-07-20 16:34:48 +08:00
d2627b1527 修复播放之后,改变缩放的问题 2025-07-20 15:30:57 +08:00
37b0259579 修复组件能多次加载得问题 2025-07-20 15:19:43 +08:00
cdb7894e64 modify chat plot 2025-07-07 00:12:06 +08:00
8f0a32869e modify worksapce mansger onframe 2025-07-06 23:33:27 +08:00
63eeca0086 modify play menu and add label and update sim 2025-07-06 22:34:23 +08:00
57f8c1b6af modify chatplot menu ui 2025-07-06 00:10:59 +08:00
69caff5ce7 modify new ui 2025-07-05 12:07:30 +08:00
cf189a7600 modify code merge 2025-07-04 08:14:15 +08:00
eba320eaeb mofify cone to remove warning 2025-07-03 07:53:32 +08:00
9cf724588a modify set home viewpoint 2025-07-03 07:44:12 +08:00
0f6d6e3a72 modify property not work 2025-07-03 07:25:56 +08:00
17449baf1e modify propty manager 2025-07-02 22:43:23 +08:00
13345128f5 add entity visible 2025-06-28 00:23:58 +08:00
a88557220b modify cone wave 2025-06-27 23:53:41 +08:00
09767ecdbd add rebuild cone wave 2025-06-27 08:29:36 +08:00
1d7ba7c418 update conewave 2025-06-26 08:12:25 +08:00
8d957bbbb2 modify cone wave 2025-06-26 00:13:22 +08:00
22ae2a57d2 modify cone wave 2025-06-25 08:10:01 +08:00
52c20bd297 modify effects conwav alple 2025-06-24 23:40:11 +08:00
e271e78200 modify conwave 2025-06-24 07:47:18 +08:00
d2a724bde6 modify conewave 2025-06-23 01:49:35 +08:00
2e8a12ba34 modify label 2025-06-22 18:18:46 +08:00
36ba2b1009 add label 2025-06-22 16:27:44 +08:00
da535ac8c3 add label 2025-06-20 07:57:30 +08:00
474e853f2e modify skin menu 2025-06-20 00:10:57 +08:00
cee15ff862 modify skin and add png 2025-06-20 00:06:56 +08:00
b6a60713e9 remove unuse code 2025-06-19 22:30:05 +08:00
43a30fefe3 fix close crash 2025-06-19 22:05:52 +08:00
8bbf971540 remove view ui 2025-06-19 07:49:31 +08:00
286a48a658 modify mouse right menu 2025-06-18 23:33:06 +08:00
a3fc986d4e 修改跟踪和位置初始位置 2025-06-18 02:05:47 +08:00
4acbf05ae0 modify workspace 2025-04-21 08:20:00 +08:00
8a15b09464 modify frame title bar 2025-04-20 11:57:25 +08:00
65cbe121bf 修改ui显示和osg的库 2025-04-13 23:12:17 +08:00
9b47b518d5 修改osgearth ui 2025-03-26 00:04:39 +08:00
ea260fcaaa add new osg 2025-03-13 08:42:41 +08:00
134 changed files with 6596 additions and 5529 deletions

View File

@ -4,7 +4,7 @@ set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
SET(CMAKE_CXX_STANDARD 17) SET(CMAKE_CXX_STANDARD 11)
SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_INCLUDE_CURRENT_DIR ON) SET(CMAKE_INCLUDE_CURRENT_DIR ON)
@ -85,8 +85,9 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${Thirdparty}/spdlog/include ${Thirdparty}/spdlog/include
${Thirdparty}/breakpad/include ${Thirdparty}/breakpad/include
${Thirdparty}/3rdParty_x64/include ${Thirdparty}/3rdparty_vc15/include
${Thirdparty}/OpenSceneGraph-3.6.5/include ${Thirdparty}/OSG-3.5.1/include
${Thirdparty}/OSGEARTH-2.8/include
${Thirdparty}/TritonSDK/PublicHeaders ${Thirdparty}/TritonSDK/PublicHeaders
${Thirdparty}/matlab/include ${Thirdparty}/matlab/include
# ${Thirdparty}/Python39/include # ${Thirdparty}/Python39/include
@ -94,8 +95,9 @@ INCLUDE_DIRECTORIES(
LINK_DIRECTORIES( LINK_DIRECTORIES(
${Thirdparty}/spdlog/lib ${Thirdparty}/spdlog/lib
${Thirdparty}/3rdParty_x64/lib ${Thirdparty}/3rdparty_vc15/lib
${Thirdparty}/OpenSceneGraph-3.6.5/lib ${Thirdparty}/OSG-3.5.1/lib
${Thirdparty}/OSGEARTH-2.8/lib
${Thirdparty}/matlab/lib/win64/microsoft ${Thirdparty}/matlab/lib/win64/microsoft
${Thirdparty}/TritonSDK/lib/vc143/x64 ${Thirdparty}/TritonSDK/lib/vc143/x64
# ${Thirdparty}/Python39/libs # ${Thirdparty}/Python39/libs
@ -167,6 +169,7 @@ target_link_libraries(
osgWidget osgWidget
osgText osgText
osgEarth osgEarth
osgEarthUtil
Triton-MT-DLL Triton-MT-DLL
libeng libeng
libmx libmx

View File

@ -25,6 +25,7 @@
<file>res/default/menu_setting.png</file> <file>res/default/menu_setting.png</file>
<file>res/default/menu_uisetting.png</file> <file>res/default/menu_uisetting.png</file>
<file>res/default/menu_window_manager.png</file> <file>res/default/menu_window_manager.png</file>
<file>res/default/menu_window_setting.png</file>
</qresource> </qresource>
<qresource prefix="/qss"> <qresource prefix="/qss">
</qresource> </qresource>

View File

@ -16,7 +16,6 @@ Application::Application(int& argc, char** argv, int /*= ApplicationFlags*/)
} }
Application::~Application() { Application::~Application() {
Uninit();
} }
QString Application::GetWorkSpacePath() { QString Application::GetWorkSpacePath() {
@ -24,14 +23,24 @@ QString Application::GetWorkSpacePath() {
return path; return path;
} }
QString Application::GetBinPath() {
return applicationDirPath();
}
void Application::Init() { void Application::Init() {
Singleton<MeshManager>::Create(this); Singleton<MeshManager>::Create(this);
Singleton<OsgViewer>::Create(this);
Singleton<RecourceHelper>::Create(this); Singleton<RecourceHelper>::Create(this);
Singleton<EntitiesManager>::Create(this); Singleton<EntitiesManager>::Create(this);
Singleton<WorkSpaceManager>::Create(this); Singleton<WorkSpaceManager>::Create(this);
Singleton<NetDriver>::Create(this); Singleton<NetDriver>::Create(this);
//Singleton<PythonModule>::Create(this); //Singleton<PythonModule>::Create(this);
connect(&timer_, &QTimer::timeout, this, &Application::OnTimeout);
timer_.start(1000 / 60); // 60 FPS
}
void Application::OnTimeout() {
WorkSpaceManager::Get().OnFrame();
} }
void Application::Uninit() { void Application::Uninit() {
@ -40,6 +49,5 @@ void Application::Uninit() {
Singleton<WorkSpaceManager>::Destory(); Singleton<WorkSpaceManager>::Destory();
Singleton<EntitiesManager>::Destory(); Singleton<EntitiesManager>::Destory();
Singleton<RecourceHelper>::Destory(); Singleton<RecourceHelper>::Destory();
Singleton<OsgViewer>::Destory();
Singleton<MeshManager>::Destory(); Singleton<MeshManager>::Destory();
} }

View File

@ -2,6 +2,8 @@
#include <QApplication> #include <QApplication>
#include <QTimer>
class Application : public QApplication { class Application : public QApplication {
Q_OBJECT Q_OBJECT
@ -10,8 +12,14 @@ public:
~Application() override; ~Application() override;
static QString GetWorkSpacePath(); static QString GetWorkSpacePath();
static QString GetBinPath();
void Uninit();
protected: protected:
void Init(); void Init();
void Uninit();
private:
void OnTimeout();
protected:
QTimer timer_;
}; };

View File

@ -1,5 +1,6 @@
#include "CrashHandler.h" #include "CrashHandler.h"
#if 0
#include <QCoreApplication> #include <QCoreApplication>
#include <QMessageBox> #include <QMessageBox>
#include <QDir> #include <QDir>
@ -79,7 +80,6 @@ std::unique_ptr<google_breakpad::ExceptionHandler> exceptionHandler;
#endif #endif
bool InstallCrashHandler() { bool InstallCrashHandler() {
#if NDEBUG #if NDEBUG
FindFileForDelete("D:/pcm");
QString appDirPath = QCoreApplication::applicationDirPath() + "/crash"; QString appDirPath = QCoreApplication::applicationDirPath() + "/crash";
QDir dir; QDir dir;
if (!dir.exists(appDirPath)) { if (!dir.exists(appDirPath)) {
@ -94,7 +94,7 @@ bool InstallCrashHandler() {
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
exceptionHandler.reset(new google_breakpad::ExceptionHandler( exceptionHandler.reset(new google_breakpad::ExceptionHandler(
appDirPath.toStdWString(), NULL, OnMinidumpCallback, NULL, appDirPath.toStdWString(), nullptr, OnMinidumpCallback, nullptr,
google_breakpad::ExceptionHandler::HANDLER_ALL)); google_breakpad::ExceptionHandler::HANDLER_ALL));
#else #else
exceptionHandler.reset(new google_breakpad::ExceptionHandler( exceptionHandler.reset(new google_breakpad::ExceptionHandler(
@ -106,7 +106,10 @@ bool InstallCrashHandler() {
return true; return true;
} }
void TestCrash() { #else
volatile int* a = (int*)(nullptr);
*a = 1; bool InstallCrashHandler() {
return false;
} }
#endif

View File

@ -2,4 +2,3 @@
bool InstallCrashHandler(); bool InstallCrashHandler();
void TestCrash();

View File

@ -226,6 +226,12 @@ QWidget#SystemManagerMenu > QToolButton#menu_logs {
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean { QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
qproperty-icon: url(:/res/default/menu_logs_clean.png); qproperty-icon: url(:/res/default/menu_logs_clean.png);
} }
QWidget#SystemManagerMenu > QToolButton#menu_window_manager {
qproperty-icon: url(:/res/default/menu_window_manager.png);
}
QWidget#SystemManagerMenu > QToolButton#menu_uisetting {
qproperty-icon: url(:/res/default/menu_window_setting.png);
}
QWidget#viewDisplay { QWidget#viewDisplay {
border: 5 solid #1C1D1F; border: 5 solid #1C1D1F;
@ -293,7 +299,3 @@ QDockWidget DockTitleWidget QPushButton::menu-indicator,
QDockWidget DockTitleWidget QToolButton::menu-indicator { QDockWidget DockTitleWidget QToolButton::menu-indicator {
image: none; image: none;
} }
QListWidget {
border: none;
}

View File

@ -91,17 +91,7 @@ QPushButton#sys_max {
border: none; border: none;
background: transparent; background: transparent;
image: url(:/res/sys_max.png); image: url(:/res/sys_max.png);
padding: 0;
}
QPushButton#sys_restore {
max-width:48px;
min-width:48px;
max-height:28px;
min-height:28px;
border: none;
background: transparent;
image: url(:/res/sys_restore.png);
padding: 0; padding: 0;
} }
@ -125,7 +115,6 @@ QPushButton#sys_close::hover, QPushButton#sys_close::pressed {
QPushButton#sys_min::hover, QPushButton#sys_min::pressed, QPushButton#sys_min::hover, QPushButton#sys_min::pressed,
QPushButton#sys_max::hover, QPushButton#sys_max::pressed, QPushButton#sys_max::hover, QPushButton#sys_max::pressed,
QPushButton#sys_restore::hover, QPushButton#sys_restore::pressed,
QToolButton#sys_skin::hover, QToolButton#sys_skin::pressed { QToolButton#sys_skin::hover, QToolButton#sys_skin::pressed {
background: #38C0C0C0; background: #38C0C0C0;
border: 1 solid #C0C0C0; border: 1 solid #C0C0C0;
@ -255,6 +244,12 @@ QWidget#SystemManagerMenu > QToolButton#menu_logs {
QWidget#SystemManagerMenu > QToolButton#menu_logs_clean { QWidget#SystemManagerMenu > QToolButton#menu_logs_clean {
qproperty-icon: url(:/res/default/menu_logs_clean.png); qproperty-icon: url(:/res/default/menu_logs_clean.png);
} }
QWidget#SystemManagerMenu > QToolButton#menu_window_manager {
qproperty-icon: url(:/res/default/menu_window_manager.png);
}
QWidget#SystemManagerMenu > QToolButton#menu_uisetting {
qproperty-icon: url(:/res/default/menu_window_setting.png);
}
QWidget#viewDisplay { QWidget#viewDisplay {
border: 5 solid #1C1D1F; border: 5 solid #1C1D1F;
@ -323,6 +318,26 @@ QDockWidget DockTitleWidget QToolButton::menu-indicator {
image: none; image: none;
} }
QListWidget { QMenu {
border: none; background: #212F3C;
color: #e0e0e0;
padding: 4px;
}
QMenu::item {
padding: 6px 30px 6px 20px;
margin: 2px;
border-radius: 3px;
}
QMenu::item:selected {
background:rgb(41, 59, 75);
color: white;
}
QMenu::item:checked {
background:rgb(41, 59, 75);
}
QMenu::separator {
height: 1px;
background: #555;
margin: 5px 10px;
} }

View File

@ -1,5 +1,5 @@
#include "effects/ConeWave.h" #include "effects/ConeWave.h"
/*
#include <osg/BlendFunc> #include <osg/BlendFunc>
#include <osg/Material> #include <osg/Material>
#include <osg/Texture2D> #include <osg/Texture2D>
@ -11,6 +11,7 @@
#include <osg/Program> #include <osg/Program>
#include <osg/Uniform> #include <osg/Uniform>
#include <osg/Depth> #include <osg/Depth>
#include <osg/Cullface>
#include <osgEarth/Registry> #include <osgEarth/Registry>
class WaveSurfaceCallback : public osg::NodeCallback { class WaveSurfaceCallback : public osg::NodeCallback {
@ -20,14 +21,12 @@ public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) { virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
timeElapsed += (nv->getFrameStamp()->getSimulationTime() - SimulationTime); timeElapsed += (nv->getFrameStamp()->getSimulationTime() - SimulationTime);
// 获取并更新geometry的顶点
osg::Geode* geode = dynamic_cast<osg::Geode*>(node); osg::Geode* geode = dynamic_cast<osg::Geode*>(node);
if (geode) { if (geode) {
osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode->getDrawable(0)); osg::Geometry* geometry = dynamic_cast<osg::Geometry*>(geode->getDrawable(0));
if (geometry) { if (geometry) {
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
if (vertices) { if (vertices) {
// 更新顶点位置来模拟波动
float amplitude = 2.0f; float amplitude = 2.0f;
float frequency = 1.0f; float frequency = 1.0f;
for (unsigned int i = 0; i < vertices->size(); ++i) { for (unsigned int i = 0; i < vertices->size(); ++i) {
@ -35,12 +34,11 @@ public:
vertex.z() = amplitude * sin(frequency * (vertex.x() + timeElapsed)); vertex.z() = amplitude * sin(frequency * (vertex.x() + timeElapsed));
} }
geometry->setVertexArray(vertices); geometry->setVertexArray(vertices);
geometry->dirtyBound(); // 更新几何体边界 geometry->dirtyBound();
} }
} }
} }
// 继续遍历场景图
traverse(node, nv); traverse(node, nv);
SimulationTime = nv->getFrameStamp()->getSimulationTime(); SimulationTime = nv->getFrameStamp()->getSimulationTime();
} }
@ -50,9 +48,49 @@ private:
double SimulationTime; double SimulationTime;
}; };
class RadarWaveTimeCallback : public osg::NodeCallback {
public:
RadarWaveTimeCallback(osg::ref_ptr<osg::Uniform> waveTimeUniform)
: waveTimeUniform_(waveTimeUniform), startTime_(0.0) {}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
if (nv->getFrameStamp()) {
double currentTime = nv->getFrameStamp()->getSimulationTime();
if (startTime_ == 0.0) {
startTime_ = currentTime;
}
float elapsedTime = static_cast<float>(currentTime - startTime_);
if (waveTimeUniform_.valid()) {
waveTimeUniform_->set(elapsedTime);
}
}
traverse(node, nv);
}
private:
osg::ref_ptr<osg::Uniform> waveTimeUniform_;
double startTime_;
};
ConeWave::ConeWave() { ConeWave::ConeWave() {
osgEarth::Registry::shaderGenerator().run(this); osgEarth::Registry::shaderGenerator().run(this);
currentTime_ = 0.0;
height_ = 1000.0f;
radius_ = 50.0f;
waveRadius_ = 100.0f;
waveSpeed_ = 20.0f;
waveCount_ = 3;
baseColor_ = osg::Vec4(0.0f, 0.8f, 1.0f, 1.0f);
waveColor_ = osg::Vec4(1.0f, 0.5f, 1.0f, 0.8f);
ringBrightAlpha_ = 0.8f;
ringDarkAlpha_ = 0.3f;
coneAlpha_ = 0.7f;
} }
@ -61,15 +99,15 @@ ConeWave::~ConeWave(void)
} }
void ConeWave::Render(double dt) { void ConeWave::Render(double dt) {
} }
void ConeWave::InitGeode() { void ConeWave::InitGeode() {
CreateTexturedCone(this); Rebuild();
//getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON); getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
//getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
//setCullingActive(false); getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
setCullingActive(true);
} }
void ConeWave::Destory() { void ConeWave::Destory() {
@ -78,105 +116,188 @@ void ConeWave::Destory() {
void ConeWave::SetHeight(float height) { void ConeWave::SetHeight(float height) {
height_ = height; height_ = height;
if (cone_) {
cone_->setHeight(height_);
}
// coneDrawable_->build();
}
void ConeWave::SetRadius(float radius) { Rebuild();
radius_ = radius;
if (cone_) {
cone_->setRadius(radius);
}
// coneDrawable_->build();
} }
void ConeWave::SetBaseColor(const osg::Vec4& color) { void ConeWave::SetBaseColor(const osg::Vec4& color) {
baseColor_ = color; baseColor_ = color;
if (baseColorUniform_) {
baseColorUniform_->set(color); if (baseColorUniform_.valid()) {
baseColorUniform_->set(baseColor_);
} }
} }
void ConeWave::SetLevelCount(int count) { void ConeWave::SetWaveCount(int count) {
levelCount_ = count; waveCount_ = count;
if (levelCountUniform_) {
levelCountUniform_->set(float(levelCount_)); if (waveCountUniform_.valid()) {
waveCountUniform_->set(static_cast<float>(waveCount_));
} else {
Rebuild();
} }
} }
void ConeWave::SetLevelHeight(float height) { void ConeWave::SetWaveSpeed(float speed) {
levelHeight_ = height; waveSpeed_ = speed;
if (levelHeightUniform_) {
levelHeightUniform_->set(levelHeight_); if (waveSpeedUniform_.valid()) {
waveSpeedUniform_->set(waveSpeed_);
} }
} }
void ConeWave::CreateTexturedCone(osg::Geode* geode) { void ConeWave::SetWaveRadius(float radius) {
// cone_ = new osg::Cone(osg::Vec3(0, 0, 0.), radius_, height_); waveRadius_ = radius;
// osg::TessellationHints* tesselate = new osg::TessellationHints; radius_ = radius;
// tesselate->setCreateBottom(false); Rebuild();
// tesselate->setCreateBackFace(false); }
// coneDrawable_ = new osg::ShapeDrawable(cone_, tesselate);
// geode->addDrawable(coneDrawable_);
// coneDrawable_->setColor(baseColor_);
// osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN");
// ss->setRenderBinDetails(120, "RenderBin");
// osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc();
// ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
// ss->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
void ConeWave::SetWaveColor(const osg::Vec4& color) {
waveColor_ = color;
osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry(); if (waveColorUniform_.valid()) {
waveColorUniform_->set(waveColor_);
// 创建顶点数组
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
int rows = 20, cols=20;
for (unsigned int i = 0; i < rows; ++i) {
for (unsigned int j = 0; j < cols; ++j) {
// 坐标
float x = (float)i / (rows - 1) * 100;
float y = (float)j / (cols - 1) * 100;
vertices->push_back(osg::Vec3f(x, y, 0.0f));
} }
} }
geometry->setVertexArray(vertices); void ConeWave::SetRingBrightAlpha(float alpha) {
ringBrightAlpha_ = alpha;
// 生成索引来连接顶点 if (ringBrightAlphaUniform_.valid()) {
osg::ref_ptr<osg::DrawElementsUShort> indices = new osg::DrawElementsUShort(osg::PrimitiveSet::QUADS); ringBrightAlphaUniform_->set(alpha);
for (unsigned int i = 0; i < rows - 1; ++i) {
for (unsigned int j = 0; j < cols - 1; ++j) {
unsigned short bottomLeft = i * cols + j;
unsigned short bottomRight = bottomLeft + 1;
unsigned short topLeft = (i + 1) * cols + j;
unsigned short topRight = topLeft + 1;
indices->push_back(bottomLeft);
indices->push_back(bottomRight);
indices->push_back(topRight);
indices->push_back(topLeft);
} }
} }
geometry->addPrimitiveSet(indices);
// 创建表面颜色 void ConeWave::SetRingDarkAlpha(float alpha) {
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; ringDarkAlpha_ = alpha;
colors->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); // 蓝色 if (ringDarkAlphaUniform_.valid()) {
ringDarkAlphaUniform_->set(alpha);
}
}
geometry->setColorArray(colors); void ConeWave::SetConeAlpha(float alpha) {
geometry->setColorBinding(osg::Geometry::BIND_OVERALL); coneAlpha_ = alpha;
if (coneGeometry_.valid()) {
osg::StateSet* ss = coneGeometry_->getOrCreateStateSet();
osg::ref_ptr<osg::Material> material = new osg::Material();
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0.0f, 0.8f, 1.0f, alpha));
material->setTransparency(osg::Material::FRONT_AND_BACK, 1.0f - alpha);
ss->setAttributeAndModes(material, osg::StateAttribute::ON);
}
}
// 添加geometry到geode void ConeWave::Clear() {
geode->addDrawable(geometry); if (coneCallback_.valid()) {
geode->setUpdateCallback(new WaveSurfaceCallback()); setUpdateCallback(nullptr);
coneCallback_ = nullptr;
}
if (coneGeometry_.valid()) {
removeDrawable(coneGeometry_);
coneGeometry_ = nullptr;
coneDrawable_ = nullptr;
}
waveTimeUniform_ = nullptr;
baseColorUniform_ = nullptr;
waveColorUniform_ = nullptr;
levelHeightUniform_ = nullptr;
waveSpeedUniform_ = nullptr;
ringBrightAlphaUniform_ = nullptr;
ringDarkAlphaUniform_ = nullptr;
}
void ConeWave::Rebuild() {
Clear();
CreateRadarScanWave();
}
void ConeWave::CreateConeGeometry() {
osg::ref_ptr<osg::Geometry> coneGeometry = new osg::Geometry();
const int segments = 64;
const float angleStep = 2.0f * osg::PI / segments;
osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array();
osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array();
osg::ref_ptr<osg::Vec2Array> texCoords = new osg::Vec2Array();
vertices->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
normals->push_back(osg::Vec3(0.0f, 0.0f, -1.0f));
texCoords->push_back(osg::Vec2(0.5f, 0.5f));
for (int i = 0; i <= segments; ++i) {
float angle = i * angleStep;
float x = radius_ * cos(angle);
float y = radius_ * sin(angle);
float z = height_;
vertices->push_back(osg::Vec3(x, y, z));
osg::Vec3 normal(x, y, radius_);
normal.normalize();
normals->push_back(normal);
texCoords->push_back(osg::Vec2((x/radius_ + 1.0f) * 0.5f, (y/radius_ + 1.0f) * 0.5f));
}
coneGeometry->setVertexArray(vertices);
coneGeometry->setNormalArray(normals);
coneGeometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
coneGeometry->setTexCoordArray(0, texCoords);
osg::ref_ptr<osg::DrawElementsUInt> indices = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
for (int i = 0; i < segments; ++i) {
indices->push_back(0);
indices->push_back(i + 1);
indices->push_back(i + 2);
}
coneGeometry->addPrimitiveSet(indices);
if (coneGeometry_.valid() && coneGeometry_->getNumParents() > 0) {
removeDrawable(coneGeometry_);
coneGeometry_ = coneGeometry;
coneDrawable_ = coneGeometry_.get();
waveTimeUniform_ = nullptr;
levelHeightUniform_ = nullptr;
addDrawable(coneDrawable_);
} else {
coneGeometry_ = coneGeometry;
coneDrawable_ = coneGeometry_.get();
}
}
void ConeWave::CreateRadarScanWave() {
CreateConeGeometry();
addDrawable(coneDrawable_);
osg::StateSet* ss = coneDrawable_->getOrCreateStateSet();
ss->setRenderBinDetails(120, "RenderBin");
ss->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
ss->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
osg::ref_ptr<osg::BlendFunc> bf = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
ss->setAttributeAndModes(bf, osg::StateAttribute::ON);
ss->setMode(GL_BLEND, osg::StateAttribute::ON);
ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
ss->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
CreateRadarShader();
osg::ref_ptr<osg::NodeCallback> waveTimeCallback = new RadarWaveTimeCallback(waveTimeUniform_);
coneCallback_ = waveTimeCallback;
setUpdateCallback(coneCallback_);
}
void ConeWave::CreateRadarShader() {
if (waveTimeUniform_.valid()) {
return; return;
}
static const char* vertSource = { static const char* vertexShaderSource =
"#version 330\n"
"varying vec3 pos;\n" "varying vec3 pos;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
@ -184,340 +305,64 @@ void ConeWave::CreateTexturedCone(osg::Geode* geode) {
" pos.y = gl_Vertex.y;\n" " pos.y = gl_Vertex.y;\n"
" pos.z = gl_Vertex.z;\n" " pos.z = gl_Vertex.z;\n"
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
"}\n" "}\n";
};
static const char* fragSource = { static const char* fragmentShaderSource =
"#version 330\n"
"uniform float num; \n"
"uniform float height;\n" "uniform float height;\n"
"uniform vec4 baseColor;\n" "uniform vec4 baseColor;\n"
"uniform vec4 waveColor;\n"
"uniform float waveTime;\n"
"uniform float ringBrightAlpha;\n"
"uniform float ringDarkAlpha;\n"
"uniform float waveSpeed;\n"
"uniform float waveCount;\n"
"varying vec3 pos;\n" "varying vec3 pos;\n"
"float Alpha = 1.0; \n"
"float f = pos.z;\n"
"uniform float osg_FrameTime;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
"if (sin(f/height*3.14*2*num+ osg_FrameTime*10) > 0)\n" " float h = abs(pos.z) / max(height, 1.0);\n"
" float radialDist = sqrt(pos.x * pos.x + pos.y * pos.y);\n"
" float waveFreq = 0.2 * max(1.0, waveCount * 0.1);\n"
" float timeScale = waveTime * waveSpeed * 0.1;\n"
" float wavePhase = radialDist * waveFreq - timeScale;\n"
" float ripple = sin(wavePhase);\n"
" float ripple2 = sin(wavePhase * 1.1 + timeScale * 0.5);\n"
" ripple = (ripple + ripple2 * 0.3) / 1.3;\n"
" if (ripple > 0.3)\n"
" {\n" " {\n"
" Alpha = 0.8;\n" " gl_FragColor = vec4(waveColor.rgb, ringBrightAlpha);\n"
" }\n" " }\n"
" else\n" " else\n"
" {\n" " {\n"
" Alpha = 0.3;\n" " gl_FragColor = vec4(baseColor.rgb, ringDarkAlpha);\n"
" }\n" " }\n"
" gl_FragColor = vec4(baseColor.rgb, Alpha);\n" "}\n";
"}\n "
};
osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX); osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX, vertexShaderSource);
vertexShader->setShaderSource(vertSource); osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource);
osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT);
fragmentShader->setShaderSource(fragSource);
osg::StateSet* stateset = coneDrawable_->getOrCreateStateSet(); osg::ref_ptr<osg::Program> program = new osg::Program;
// osg::ref_ptr<osg::Material> mat = new osg::Material; program->addShader(vertexShader);
// //设置正面散射颜色 program->addShader(fragmentShader);
// mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
// //设置正面镜面颜色
// mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
//
// geode->getOrCreateStateSet()->setAttribute(mat);
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
// stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染 osg::StateSet* stateSet = coneDrawable_->getOrCreateStateSet();
// //stateset->setRenderBinDetails(120, "OSGEARTH_SCREEN_SPACE_LAYOUT_BIN"); stateSet->setAttributeAndModes(program, osg::StateAttribute::ON);
stateset->setRenderBinDetails(10, "RenderBin");
// osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();
// stateset->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
// osg::ref_ptr<osg::Program> program = new osg::Program();
// program->addShader(vertexShader);
// program->addShader(fragmentShader);
//
// baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
// stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
// stateset->addUniform(baseColorUniform_);
// // stateset->setAttributeAndModes(program, osg::StateAttribute::ON);
// // stateset->setAttributeAndModes(new osg::Depth(osg::Depth::LESS, 0.0, 1.0, false));
//
// levelCountUniform_ = new osg::Uniform("num", float(levelCount_));
// levelHeightUniform_ = new osg::Uniform("height", levelHeight_);
// stateset->addUniform(levelCountUniform_); waveTimeUniform_ = new osg::Uniform("waveTime", 0.0f);
// stateset->addUniform(levelHeightUniform_.get()); baseColorUniform_ = new osg::Uniform("baseColor", baseColor_);
waveColorUniform_ = new osg::Uniform("waveColor", waveColor_);
levelHeightUniform_ = new osg::Uniform("height", height_ > 0 ? height_ : 100.0f);
waveSpeedUniform_ = new osg::Uniform("waveSpeed", waveSpeed_ > 0 ? waveSpeed_ : 1.0f);
waveCountUniform_ = new osg::Uniform("waveCount", waveCount_ > 0 ? waveCount_ : 1);
ringBrightAlphaUniform_ = new osg::Uniform("ringBrightAlpha", ringBrightAlpha_);
ringDarkAlphaUniform_ = new osg::Uniform("ringDarkAlpha", ringDarkAlpha_);
stateSet->addUniform(waveTimeUniform_);
stateSet->addUniform(baseColorUniform_);
stateSet->addUniform(waveColorUniform_);
stateSet->addUniform(levelHeightUniform_);
stateSet->addUniform(waveSpeedUniform_);
stateSet->addUniform(waveCountUniform_);
stateSet->addUniform(ringBrightAlphaUniform_);
stateSet->addUniform(ringDarkAlphaUniform_);
} }
*/
#include <osg/Geode>
#include <osg/Geometry>
#include <osg/Material>
#include <osgFX/Outline>
#include <osgFX/Scribe>
#include <osg/MatrixTransform>
#include <osgEarth/Ellipsoid>
#include "scene/SceneContent.h"
class WaveBeamConeCallBack : public osg::NodeCallback {
public:
WaveBeamConeCallBack();
~WaveBeamConeCallBack();
virtual void operator() (osg::Node *node, osg::NodeVisitor *nv);
public:
double m_latitude;
double m_longitude;
double m_height;
bool m_ifDynamic;
double m_angle;
double m_length;
osg::Vec4 m_color;
osg::Vec4 m_lineColor;
double m_lineWidth;
osg::ref_ptr<osg::Geode> m_geode;
osg::ref_ptr<osg::Geometry> m_geom;
osg::ref_ptr<osg::Vec4Array> m_colorArray;
osg::ref_ptr<osg::Vec3Array> m_pointVector;
osg::ref_ptr<osgFX::Scribe> m_nodeFX;
};
WaveBeamConeCallBack::WaveBeamConeCallBack() {
m_latitude = 0.0;
m_longitude = 0.0;
m_height = -6371000;
m_ifDynamic = false;
m_angle = 20.0;
m_length = 100000;
m_color = osg::Vec4(1, 0, 0, 0.5);
m_lineColor = osg::Vec4(1.0, 0.0, 0.0, 1.0);
m_lineWidth = 1.0;
}
WaveBeamConeCallBack::~WaveBeamConeCallBack() {
}
void WaveBeamConeCallBack::operator()(osg::Node *node, osg::NodeVisitor *nv) {
if (m_ifDynamic == false)
return;
//std::cout << "WaveBeamConeCallBack info=" << m_latitude << "," << m_longitude << "," << m_height << std::endl;
osg::MatrixTransform* mtCone = dynamic_cast<osg::MatrixTransform*>(node);
if (mtCone != NULL) {
osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));
//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
osg::Matrix mTarget;
double x, y, z;
osg::EllipsoidModel em;
em.convertLatLongHeightToXYZ(osg::DegreesToRadians(m_latitude),
osg::DegreesToRadians(m_longitude),
m_height, x, y, z);
mTarget.setTrans(x, y, z);
osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());
mtCone->setMatrix(mConeRate);//mTarget*m
//更改cone的形状----------------------------------------
double length = (mTarget*m).getTrans().length();
double angle = osg::DegreesToRadians(m_angle);
double radius = std::tan(angle*0.5) * length;
int splitCount = 20;
double angleStep = osg::PI * 2.0 / splitCount;
//侧面
for (int i = 1; i <= splitCount + 1; i++) {
double tempAngle = (i - 1)*angleStep;
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
m_pointVector->at(i) = pos;
}
m_pointVector->at(splitCount + 2) = osg::Vec3(0, length, 0);
//底面
for (int i = splitCount + 3; i <= splitCount + 3 + splitCount; i++) {
double tempAngle = (i - splitCount - 3) *angleStep;
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
m_pointVector->at(i) = pos;
}
m_geom->dirtyBound();
m_geom->dirtyDisplayList();
}
}
ConeWave::ConeWave() {
}
ConeWave::~ConeWave() {
}
void ConeWave::clearSelf() {
}
void ConeWave::Render(double dt)
{
}
void ConeWave::createWaveBeamCone(osg::MatrixTransform* node, double angle, double length,
osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
double angleD = osg::DegreesToRadians(angle);
double radius = std::tan(angleD*0.5) * length;
int splitCount = 20;
double angleStep = osg::PI * 2.0 / splitCount;
osg::ref_ptr<osg::Geode> geode = new osg::Geode();
osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array;
osg::ref_ptr<osg::Vec3Array> normal = new osg::Vec3Array;
osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
osg::ref_ptr<osg::DrawElementsUInt> drawElemUInt2 = new osg::DrawElementsUInt(GL_TRIANGLE_FAN);
geom->setVertexArray(vertex);
geom->setNormalArray(normal);
geode->addDrawable(geom);
vertex->push_back(osg::Vec3(0, 0, 0));
drawElemUInt->push_back(0);
normal->push_back(osg::Vec3(0, -1, 0));
//侧面
for (int i = 0; i <= splitCount; i++) {
double tempAngle = i*angleStep;
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
vertex->push_back(osg::Vec3(pos));
pos.normalize();
normal->push_back(pos);
drawElemUInt->push_back(i + 1);
}
//底面
int indexBegin = vertex->size();
vertex->push_back(osg::Vec3(0, length, 0));
drawElemUInt2->push_back(indexBegin);
normal->push_back(osg::Vec3(0, 1, 0));
for (int i = 0; i <= splitCount; i++) {
double tempAngle = i*angleStep;
osg::Vec3 pos(radius * cos(tempAngle), length, radius * sin(tempAngle) + 3);
vertex->push_back(osg::Vec3(pos));
normal->push_back(osg::Vec3(0, 1, 0));
drawElemUInt2->push_back(indexBegin + i + 1);
}
geom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
geom->addPrimitiveSet(drawElemUInt);
geom->addPrimitiveSet(drawElemUInt2);
//创建材质对象
osg::ref_ptr<osg::Material> mat = new osg::Material;
//设置正面散射颜色
mat->setDiffuse(osg::Material::FRONT, osg::Vec4(1.0, 1.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
//设置正面镜面颜色
mat->setSpecular(osg::Material::FRONT, osg::Vec4(1.0, 0.0, 0.0, 0.3));//1.0, 0.0, 0.0, 0.3
geode->getOrCreateStateSet()->setAttribute(mat.get());
geode->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON);
//设置透明效果
geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
//设置渲染顺序 仿真模型被波束遮盖 ,1000000-指的是若有1000000个Node 则此节点最后一个被渲染
geode->getOrCreateStateSet()->setRenderBinDetails(12, "RenderBin");
osg::ref_ptr<osg::MatrixTransform> mtCone = new osg::MatrixTransform;
// mtCone->addChild(nodeFX);
//给callback中赋值
WaveBeamConeCallBack* coneCallBack = new WaveBeamConeCallBack;
coneCallBack->m_angle = angle;
coneCallBack->m_length = length;
coneCallBack->m_color = color;
coneCallBack->m_lineColor = lineColor;
coneCallBack->m_lineWidth = lineWidth;
coneCallBack->m_geode = geode;
coneCallBack->m_geom = geom;
coneCallBack->m_pointVector = vertex;
//添加到模型中
// osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(node->getChild(0));
// osg::MatrixTransform* mtS = dynamic_cast<osg::MatrixTransform*>(mtR->getChild(0));
// mtR->addChild(mtCone);
_waveBeamCone = mtCone;
}
void ConeWave::changeWaveBeamConeTarget(double latitude, double longitude, double height, bool ifDynamic) {
WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
if (coneCallBack != NULL) {
coneCallBack->m_ifDynamic = ifDynamic;
coneCallBack->m_latitude = latitude;
coneCallBack->m_longitude = longitude;
coneCallBack->m_height = height;
if (ifDynamic == false) {
osg::MatrixTransform* mtCone = _waveBeamCone;
osg::MatrixTransform* mtR = dynamic_cast<osg::MatrixTransform*>(mtCone->getParent(0));
osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(mtR->getParent(0));
//osg::Matrix m = osg::computeWorldToLocal(mtCone->getParentalNodePaths().at(0));
osg::Matrix m = osg::Matrix::inverse(mt->getMatrix()*mtR->getMatrix());
osg::Matrix mTarget;
double x, y, z;
osg::EllipsoidModel em;
em.convertLatLongHeightToXYZ(osg::DegreesToRadians(latitude),
osg::DegreesToRadians(longitude),
height, x, y, z);
mTarget.setTrans(x, y, z);
osg::Matrix mConeRate = osg::Matrix::rotate(osg::Vec3d(0, 1, 0), (mTarget*m).getTrans());
mtCone->setMatrix(mConeRate);
}
}
}
void ConeWave::changeWaveBeamConeAppearance( osg::Vec4 color, osg::Vec4 lineColor, double lineWidth) {
WaveBeamConeCallBack* coneCallBack = dynamic_cast<WaveBeamConeCallBack*>(_waveBeamCone->getUpdateCallback());
if (coneCallBack != NULL) {
coneCallBack->m_color = color;
coneCallBack->m_lineColor = lineColor;
coneCallBack->m_lineWidth = lineWidth;
//创建材质对象
osg::ref_ptr<osg::Material> mat = new osg::Material;
//设置正面散射颜色
mat->setDiffuse(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
//设置正面镜面颜色
mat->setSpecular(osg::Material::FRONT, color);//1.0, 0.0, 0.0, 0.3
coneCallBack->m_geode->getOrCreateStateSet()->setAttribute(mat.get());
if (lineWidth < 0.1) {
_waveBeamCone->addChild(coneCallBack->m_geode);
_waveBeamCone->removeChild(coneCallBack->m_nodeFX);
} else {
_waveBeamCone->removeChild(coneCallBack->m_geode);
_waveBeamCone->addChild(coneCallBack->m_nodeFX);
coneCallBack->m_nodeFX->setWireframeColor(lineColor);
coneCallBack->m_nodeFX->setWireframeLineWidth(lineWidth);
}
}
}

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
/*
#include <osg/Matrix> #include <osg/Matrix>
#include <osg/Array> #include <osg/Array>
#include <osg/Geometry> #include <osg/Geometry>
@ -20,78 +20,73 @@ public:
void InitGeode(); void InitGeode();
void Destory(); void Destory();
void CreateRadarScanWave();
void CreateConeGeometry();
void CreateRadarShader();
void SetWaveRadius(float radius);
float GetWaveRadius() const { return waveRadius_; }
void SetWaveSpeed(float speed);
float GetWaveSpeed() const { return waveSpeed_; }
void SetWaveCount(int count);
int GetWaveCount() const { return waveCount_; }
void SetWaveColor(const osg::Vec4& color);
const osg::Vec4& GetWaveColor() const { return waveColor_; }
void SetHeight(float height); void SetHeight(float height);
float GetHeght() const { float GetHeght() const {
return height_; return height_;
} }
void SetRadius(float radius);
float GetRadius() const {
return radius_;
}
void SetBaseColor(const osg::Vec4& color); void SetBaseColor(const osg::Vec4& color);
const osg::Vec4 GetBaseColor() const { const osg::Vec4 GetBaseColor() const {
return baseColor_; return baseColor_;
} }
void SetLevelCount(int count); void SetRingBrightAlpha(float alpha);
int GetLevelCount() const { float GetRingBrightAlpha() const { return ringBrightAlpha_; }
return levelCount_;
}
void SetLevelHeight(float height); void SetRingDarkAlpha(float alpha);
float GetLevelHeihgt() const { float GetRingDarkAlpha() const { return ringDarkAlpha_; }
return levelHeight_;
} void SetConeAlpha(float alpha);
float GetConeAlpha() const { return coneAlpha_; }
protected: protected:
virtual void CreateTexturedCone(osg::Geode* geode); void Clear();
void Rebuild();
private: private:
osg::ref_ptr<osg::Cone> cone_; osg::ref_ptr<osg::Geometry> coneGeometry_;
osg::ref_ptr<osg::ShapeDrawable> coneDrawable_; osg::ref_ptr<osg::Drawable> coneDrawable_;
osg::ref_ptr<osg::Uniform> baseColorUniform_; osg::ref_ptr<osg::NodeCallback> coneCallback_;
osg::Vec4 baseColor_{ 0.0f, 0.2f, 0.5f, 0.2f };
osg::ref_ptr<osg::Uniform> levelCountUniform_;
int levelCount_{ 4 };
osg::ref_ptr<osg::Uniform> levelHeightUniform_;
float levelHeight_{ 500.0f };
float height_{ 60.0f }; float height_{ 6.0f };
float radius_{ 10.0f }; float radius_{ 10.0f };
osg::ref_ptr<osg::Uniform> waveTimeUniform_;
osg::ref_ptr<osg::Uniform> waveRadiusUniform_;
osg::ref_ptr<osg::Uniform> waveSpeedUniform_;
osg::ref_ptr<osg::Uniform> waveCountUniform_;
osg::ref_ptr<osg::Uniform> baseColorUniform_;
osg::ref_ptr<osg::Uniform> waveColorUniform_;
osg::ref_ptr<osg::Uniform> levelHeightUniform_;
osg::ref_ptr<osg::Uniform> ringBrightAlphaUniform_;
osg::ref_ptr<osg::Uniform> ringDarkAlphaUniform_;
osg::ref_ptr<osg::Uniform> coneAlphaUniform_;
float waveRadius_{ 100.0f };
float waveSpeed_{ 20.0f };
int waveCount_{ 30 };
osg::Vec4 baseColor_{ 1.0f, 0.2f, 0.5f, 1.f };
osg::Vec4 waveColor_{ 0.0f, 0.5f, 1.0f, 0.8f };
double currentTime_{ 0.0 };
float ringBrightAlpha_{ 0.8f };
float ringDarkAlpha_{ 0.3f };
float coneAlpha_{ 0.7f };
}; };
*/
#pragma once
#include <osg/Node>
#include <osg/Geode>
#include <osg/MatrixTransform>
#include "viewer/UpdateRenderStd.h"
//三维实体的圆锥波束
class ConeWave : public osg::Geode
, public UpdateRenderStd {
public:
ConeWave();
~ConeWave();
void clearSelf() ;
void Render(double dt) override;
void createWaveBeamCone(osg::MatrixTransform* node,double angle, double length, osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);
void changeWaveBeamConeTarget(/*osg::MatrixTransform* mt,*/ double latitude, double longitude, double height, bool ifDynamic);
void changeWaveBeamConeAppearance(osg::Vec4 color, osg::Vec4 lineColor, double lineWidth);
osg::ref_ptr<osg::MatrixTransform> getWaveBeamCone() {
return _waveBeamCone;
}
private:
osg::ref_ptr<osg::MatrixTransform> _waveBeamCone;
};

View File

@ -102,7 +102,7 @@ void DashedLine::CreateTexturedCone(osg::Geode* geode) {
"#version 330\n" "#version 330\n"
"in vec4 osg_Vertex;\n" "in vec4 osg_Vertex;\n"
"in vec2 osg_MultiTexCoord0;\n" "in vec2 osg_MultiTexCoord0;\n"
"uniform mat4 osg_ModelViewProjectionMatrix;\n"//当前OSG摄像机的观察矩阵 "uniform mat4 osg_ModelViewProjectionMatrix;\n"//<EFBFBD><EFBFBD>ǰOSG<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĺ۲<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
"uniform float time;\n" "uniform float time;\n"
"out vec2 texCoord;\n" "out vec2 texCoord;\n"
"void main()\n" "void main()\n"
@ -151,7 +151,8 @@ void DashedLine::UpdateRotaion() {
float height = direction.length(); float height = direction.length();
cylinder_->setHeight(height); cylinder_->setHeight(height);
cylinderDrawable_->build(); // cylinderDrawable_->b();
// cylinderDrawable_-
osg::Vec3 center = (start_ + end_) * 0.5f; osg::Vec3 center = (start_ + end_) * 0.5f;
direction.normalize(); direction.normalize();

View File

@ -13,7 +13,7 @@ public:
~AngleReflexComponent(); ~AngleReflexComponent();
static std::string GetTypeName(); static std::string GetTypeName();
std::string GetSelfTypeName() override { std::string GetSelfTypeName() const override {
return AngleReflexComponent::GetTypeName(); return AngleReflexComponent::GetTypeName();
} }

View File

@ -13,7 +13,7 @@ public:
~ChaffBombsComponent(); ~ChaffBombsComponent();
static std::string GetTypeName(); static std::string GetTypeName();
std::string GetSelfTypeName() override { std::string GetSelfTypeName() const override {
return ChaffBombsComponent::GetTypeName(); return ChaffBombsComponent::GetTypeName();
} }

View File

@ -86,6 +86,10 @@ std::vector<SceneComponent*> Component::GetChildren() const {
return std::vector<SceneComponent*>(); return std::vector<SceneComponent*>();
} }
bool Component::HasComponent(const std::string& name) const {
return false;
}
bool Component::OnDestroy() { bool Component::OnDestroy() {
return true; return true;
} }
@ -94,7 +98,7 @@ std::string Component::GetTypeName() {
return "Component"; return "Component";
} }
std::string Component::GetSelfTypeName() { std::string Component::GetSelfTypeName() const {
return Component::GetTypeName(); return Component::GetTypeName();
} }

View File

@ -26,9 +26,10 @@ public:
virtual bool OnDestroy(); virtual bool OnDestroy();
static std::string GetTypeName(); static std::string GetTypeName();
virtual std::string GetSelfTypeName(); virtual std::string GetSelfTypeName() const;
virtual void AttachEntity(class Entity* owner); virtual void AttachEntity(class Entity* owner);
virtual bool AttachTo(class SceneComponent* parent); virtual bool AttachTo(class SceneComponent* parent);
virtual bool HasComponent(const std::string& name) const;
class Entity* GetEntity() const { class Entity* GetEntity() const {
return owner_; return owner_;
} }
@ -36,6 +37,7 @@ public:
return uuid_; return uuid_;
} }
protected: protected:
void SetUUId(const QString& uuid) { void SetUUId(const QString& uuid) {
uuid_ = uuid; uuid_ = uuid;

View File

@ -9,6 +9,7 @@
#include "entities/ChaffBombsComponent.h" #include "entities/ChaffBombsComponent.h"
#include "entities/ConeWaveComponent.h" #include "entities/ConeWaveComponent.h"
#include "entities/DashedLineComponent.h" #include "entities/DashedLineComponent.h"
#include "entities/LabelComponent.h"
//Component::Component(QObject* parent) //Component::Component(QObject* parent)
// : QObject(parent) { // : QObject(parent) {
@ -36,6 +37,8 @@ SceneComponent* ComponentFactory::Create(const QString& name, SceneComponent* pa
return new ConeWaveComponent(parenet); return new ConeWaveComponent(parenet);
} else if ("DashedLineComponent" == name) { } else if ("DashedLineComponent" == name) {
return new DashedLineComponent(parenet); return new DashedLineComponent(parenet);
} else if ("LabelComponent" == name) {
return new LabelComponent(parenet);
} }
return nullptr; return nullptr;
} }

View File

@ -13,16 +13,12 @@
ConeWaveComponent::ConeWaveComponent(SceneComponent* parent) ConeWaveComponent::ConeWaveComponent(SceneComponent* parent)
: SceneComponent(parent) { : SceneComponent(parent) {
// coneWave_ = new ConeWave(); coneWave_ = new ConeWave();
// coneWave_->InitGeode(); coneWave_->InitGeode();
colorMap_[1] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
colorMap_[2] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
colorMap_[3] = osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
} }
ConeWaveComponent::~ConeWaveComponent() { ConeWaveComponent::~ConeWaveComponent() {
// coneWave_->Destory(); coneWave_->Destory();
} }
std::string ConeWaveComponent::GetTypeName() { std::string ConeWaveComponent::GetTypeName() {
@ -30,47 +26,32 @@ std::string ConeWaveComponent::GetTypeName() {
} }
bool ConeWaveComponent::SetAttribute(const char* name, const char* value) { bool ConeWaveComponent::SetAttribute(const char* name, const char* value) {
if (0 == strcmp("color1" ,name)) { if (0 == strcmp("radius", name)) {
AddColor(1, StringUtils::StringToVec4(value));
} else if (0 == strcmp("color2" ,name)) {
AddColor(2, StringUtils::StringToVec4(value));
}else if (0 == strcmp("color3" ,name)) {
AddColor(3, StringUtils::StringToVec4(value));
} else if (0 == strcmp("radius", name)) {
SetRadius(atof(value)); SetRadius(atof(value));
} else if (0 == strcmp("height", name)) { } else if (0 == strcmp("height", name)) {
SetHeight(atof(value)); SetHeight(atof(value));
} else if (0 == strcmp("event", name)) { } else if (0 == strcmp("event", name)) {
SetTimeAction(value); SetTimeAction(value);
} else if (0 == strcmp("levelCount", name)) { } else if (0 == strcmp("waveRadius", name)) {
SetLevelCount(atof(value)); SetWaveRadius(atof(value));
} else if (0 == strcmp("levelHeihgt", name)) { } else if (0 == strcmp("waveSpeed", name)) {
SetLevelHeight(atof(value)); SetWaveSpeed(atof(value));
} else if (0 == strcmp("waveCount", name)) {
SetWaveCount(atoi(value));
} else if (0 == strcmp("waveColor", name)) {
SetWaveColor(StringUtils::StringToVec4(value));
} }
return SceneComponent::SetAttribute(name, value); return SceneComponent::SetAttribute(name, value);
} }
bool ConeWaveComponent::SaveAttribute(tinyxml2::XMLElement* element) { bool ConeWaveComponent::SaveAttribute(tinyxml2::XMLElement* element) {
if (colorMap_.find(1) != colorMap_.end()) {
element->SetAttribute("color1", StringUtils::Vec4ToString(colorMap_[1]).c_str());
} else {
element->SetAttribute("color1", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
}
if (colorMap_.find(2) != colorMap_.end()) {
element->SetAttribute("color2", StringUtils::Vec4ToString(colorMap_[2]).c_str());
} else {
element->SetAttribute("color2", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
}
if (colorMap_.find(3) != colorMap_.end()) {
element->SetAttribute("color3", StringUtils::Vec4ToString(colorMap_[3]).c_str());
} else {
element->SetAttribute("color3", StringUtils::Vec4ToString(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)).c_str());
}
element->SetAttribute("radius", std::to_string(GetRadius()).c_str()); element->SetAttribute("radius", std::to_string(GetRadius()).c_str());
element->SetAttribute("height", std::to_string(GetHeight()).c_str()); element->SetAttribute("height", std::to_string(GetHeight()).c_str());
element->SetAttribute("levelCount", std::to_string(GetLevelCount()).c_str()); element->SetAttribute("waveRadius", std::to_string(GetWaveRadius()).c_str());
element->SetAttribute("levelHeihgt", std::to_string(GetLevelHeight()).c_str()); element->SetAttribute("waveSpeed", std::to_string(GetWaveSpeed()).c_str());
element->SetAttribute("waveCount", std::to_string(GetWaveCount()).c_str());
element->SetAttribute("waveColor", StringUtils::Vec4ToString(GetWaveColor()).c_str());
element->SetAttribute("event", timeAction_ == nullptr ? "" : timeAction_->GetPath().toStdString().c_str()); element->SetAttribute("event", timeAction_ == nullptr ? "" : timeAction_->GetPath().toStdString().c_str());
return SceneComponent::SaveAttribute(element); return SceneComponent::SaveAttribute(element);
} }
@ -81,78 +62,36 @@ void ConeWaveComponent::Begin() {
void ConeWaveComponent::Update(double dt) { void ConeWaveComponent::Update(double dt) {
UpdateEvent(); UpdateEvent();
if (coneWave_.valid()) {
coneWave_->Render(dt);
}
} }
void ConeWaveComponent::SetHeight(float height) { void ConeWaveComponent::SetHeight(float height) {
// coneWave_->SetHeight(height); coneWave_->SetHeight(height);
// if (nullptr != mt_) { // if (nullptr != mt_) {
// mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f))); // mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f)));
// } // }
} }
float ConeWaveComponent::GetHeight() const { float ConeWaveComponent::GetHeight() const {
return 0;// coneWave_->GetHeght(); return coneWave_->GetHeght();
} }
void ConeWaveComponent::SetRadius(float radius) { void ConeWaveComponent::SetRadius(float radius) {
// coneWave_->SetRadius(radius); coneWave_->SetWaveRadius(radius);
} }
float ConeWaveComponent::GetRadius() const { float ConeWaveComponent::GetRadius() const {
return 0;// return coneWave_->GetRadius(); return coneWave_->GetWaveRadius();
}
void ConeWaveComponent::SetLevelCount(int count) {
// coneWave_->SetLevelCount(count);
}
float ConeWaveComponent::GetLevelCount() const {
return 0; // return coneWave_->GetLevelCount();
}
void ConeWaveComponent::SetLevelHeight(float height) {
// coneWave_->SetLevelHeight(height);
}
float ConeWaveComponent::GetLevelHeight() const {
// return coneWave_->GetLevelHeihgt();
return 0.0f;
} }
void ConeWaveComponent::SetBaseColor(const osg::Vec4& color) { void ConeWaveComponent::SetBaseColor(const osg::Vec4& color) {
// coneWave_->SetBaseColor(color); coneWave_->SetBaseColor(color);
} }
const osg::Vec4 ConeWaveComponent::GetBaseColor() const { const osg::Vec4 ConeWaveComponent::GetBaseColor() const {
// return coneWave_->GetBaseColor(); return coneWave_->GetBaseColor();
return osg::Vec4();
}
void ConeWaveComponent::SetColor1(const osg::Vec4& color) {
colorMap_[1] = color;
}
const osg::Vec4 ConeWaveComponent::GetColor1() const {
const auto color = colorMap_.find(1);
return color->second;
}
void ConeWaveComponent::SetColor2(const osg::Vec4& color) {
colorMap_[2] = color;
}
const osg::Vec4 ConeWaveComponent::GetColor2() const {
const auto color = colorMap_.find(2);
return color->second;
}
void ConeWaveComponent::SetColor3(const osg::Vec4& color) {
colorMap_[3] = color;
}
const osg::Vec4 ConeWaveComponent::GetColor3() const {
const auto color = colorMap_.find(3);
return color->second;
} }
void ConeWaveComponent::SetTimeAction(const QString& path) { void ConeWaveComponent::SetTimeAction(const QString& path) {
@ -171,8 +110,8 @@ void ConeWaveComponent::AddToRender() {
void ConeWaveComponent::Initialize() { void ConeWaveComponent::Initialize() {
mt_ = new osg::MatrixTransform; mt_ = new osg::MatrixTransform;
mt_->addChild(coneWave_); mt_->addChild(coneWave_);
// mt_->setMatrix(osg::Matrix::translate(osg::Vec3(0.0f, 0.0f, -coneWave_->GetHeght() * 0.75f)));
} }
void ConeWaveComponent::UpdateEvent() { void ConeWaveComponent::UpdateEvent() {
@ -194,34 +133,98 @@ void ConeWaveComponent::UpdateEvent() {
return; return;
} }
currentStatus_ = lampStatus->GetCurrent(); currentStatus_ = lampStatus->GetCurrent();
if (colorMap_.find(currentStatus_) == colorMap_.end()) {
coneWave_->setNodeMask(0x0); Timestep* timeStep = workspace->GetTimestep();
if (nullptr == timeStep) {
LOG_WARN("timeStep is nullptr");
return; return;
} }
osg::Vec4& color = colorMap_[currentStatus_]; double dt = timeStep->GetCurrent();
// coneWave_->SetBaseColor(color); int value = timeAction_->GetValue(dt);
coneWave_->setNodeMask(0xff); if (-1 == value) {
return;
//Timestep* timeStep = workspace->GetTimestep();
//if (nullptr == timeStep) {
// LOG_WARN("timeStep is nullptr");
// return;
//}
//double dt = timeStep->GetCurrent();
//int value = timeAction_->GetValue(dt);
//if (-1 == value) {
// return;
//}
//
//coneWave_->setNodeMask(value == 0 ? 0x0 : 0xff);
} }
void ConeWaveComponent::AddColor(int32_t status, const osg::Vec4& color) {
colorMap_[status] = color; coneWave_->setNodeMask(value == 0 ? 0x0 : 0xff);
} }
void ConeWaveComponent::SetWaveRadius(float radius) {
if (coneWave_.valid()) {
coneWave_->SetWaveRadius(radius);
}
}
float ConeWaveComponent::GetWaveRadius() const {
if (coneWave_.valid()) {
return coneWave_->GetWaveRadius();
}
return 0.0f;
}
void ConeWaveComponent::SetWaveSpeed(float speed) {
if (coneWave_.valid()) {
coneWave_->SetWaveSpeed(speed);
}
}
float ConeWaveComponent::GetWaveSpeed() const {
if (coneWave_.valid()) {
return coneWave_->GetWaveSpeed();
}
return 0.0f;
}
void ConeWaveComponent::SetWaveCount(int count) {
if (coneWave_.valid()) {
coneWave_->SetWaveCount(count);
}
}
int ConeWaveComponent::GetWaveCount() const {
if (coneWave_.valid()) {
return coneWave_->GetWaveCount();
}
return 0;
}
void ConeWaveComponent::SetWaveColor(const osg::Vec4& color) {
if (coneWave_.valid()) {
coneWave_->SetWaveColor(color);
}
}
const osg::Vec4& ConeWaveComponent::GetWaveColor() const {
static osg::Vec4 defaultColor(0.0f, 0.5f, 1.0f, 0.8f);
if (coneWave_.valid()) {
return coneWave_->GetWaveColor();
}
return defaultColor;
}
void ConeWaveComponent::SetRingBrightAlpha(float alpha) {
if (coneWave_.valid()) {
coneWave_->SetRingBrightAlpha(alpha);
}
}
float ConeWaveComponent::GetRingBrightAlpha() const {
if (coneWave_.valid()) {
return coneWave_->GetRingBrightAlpha();
}
return 0.0f;
}
void ConeWaveComponent::SetRingDarkAlpha(float alpha) {
if (coneWave_.valid()) {
coneWave_->SetRingDarkAlpha(alpha);
}
}
float ConeWaveComponent::GetRingDarkAlpha() const {
if (coneWave_.valid()) {
return coneWave_->GetRingDarkAlpha();
}
return 0.0f;
}

View File

@ -15,7 +15,7 @@ public:
~ConeWaveComponent(); ~ConeWaveComponent();
static std::string GetTypeName(); static std::string GetTypeName();
std::string GetSelfTypeName() override { std::string GetSelfTypeName() const override {
return ConeWaveComponent::GetTypeName(); return ConeWaveComponent::GetTypeName();
} }
@ -31,23 +31,24 @@ public:
void SetRadius(float radius); void SetRadius(float radius);
float GetRadius() const; float GetRadius() const;
void SetLevelCount(int count);
float GetLevelCount() const;
void SetLevelHeight(float height);
float GetLevelHeight() const;
void SetBaseColor(const osg::Vec4& color); void SetBaseColor(const osg::Vec4& color);
const osg::Vec4 GetBaseColor() const; const osg::Vec4 GetBaseColor() const;
void SetWaveColor(const osg::Vec4& color);
const osg::Vec4& GetWaveColor() const;
void SetColor1(const osg::Vec4& color); void SetWaveRadius(float radius);
const osg::Vec4 GetColor1() const; float GetWaveRadius() const;
void SetColor2(const osg::Vec4& color); void SetWaveSpeed(float speed);
const osg::Vec4 GetColor2() const; float GetWaveSpeed() const;
void SetColor3(const osg::Vec4& color); void SetWaveCount(int count);
const osg::Vec4 GetColor3() const; int GetWaveCount() const;
void SetRingBrightAlpha(float alpha);
float GetRingBrightAlpha() const;
void SetRingDarkAlpha(float alpha);
float GetRingDarkAlpha() const;
void SetTimeAction(const QString& path); void SetTimeAction(const QString& path);
@ -55,11 +56,9 @@ protected:
void AddToRender() override; void AddToRender() override;
void Initialize(); void Initialize();
void UpdateEvent(); void UpdateEvent();
void AddColor(int32_t status, const osg::Vec4& color);
protected: protected:
osg::ref_ptr<class ConeWave> coneWave_; osg::ref_ptr<class ConeWave> coneWave_;
std::unordered_map<int32_t, osg::Vec4> colorMap_;
class TimeAction* timeAction_{ nullptr }; class TimeAction* timeAction_{ nullptr };
int currentStatus_{ 0 }; int currentStatus_{ 0 };
}; };

View File

@ -13,7 +13,7 @@ public:
~DashedLineComponent(); ~DashedLineComponent();
static std::string GetTypeName(); static std::string GetTypeName();
std::string GetSelfTypeName() override { std::string GetSelfTypeName() const override {
return DashedLineComponent::GetTypeName(); return DashedLineComponent::GetTypeName();
} }

View File

@ -182,3 +182,32 @@ void Entity::SetParent(Entity* parent) {
SetWorkspace(workSpace); SetWorkspace(workSpace);
parent_->childer_.push_back(this); parent_->childer_.push_back(this);
} }
bool Entity::HasComponent(const std::string& name) const {
if (nullptr == rootComponet_) {
return false;
}
return rootComponet_->HasComponent(name);
}
void Entity::SetVisible(bool v) {
LOG_INFO("set visible: {}", v);
if (nullptr == rootComponet_) {
LOG_WARN("rootComponet_ is nullptr");
return;
}
rootComponet_->SetVisible(v);
for (auto item : childer_) {
item->SetVisible(v);
}
}
bool Entity::IsVisible() const {
if (nullptr == rootComponet_) {
LOG_WARN("rootComponet_ is nullptr");
return false;
}
return rootComponet_->IsVisible();
}

View File

@ -56,6 +56,8 @@ public:
return rootComponet_->GetComponent(); return rootComponet_->GetComponent();
} }
bool HasComponent(const std::string& name) const;
void SetRootComponent(SceneComponent* root) { void SetRootComponent(SceneComponent* root) {
rootComponet_ = root; rootComponet_ = root;
} }
@ -68,6 +70,9 @@ public:
return childer_; return childer_;
} }
void SetVisible(bool v);
bool IsVisible() const;
Q_SIGNALS: Q_SIGNALS:
void NameChanged(const QString& name); void NameChanged(const QString& name);

View File

@ -0,0 +1,198 @@
#include "entities/LabelComponent.h"
#include <osg/Billboard>
#include <osg/StateSet>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osgText/Font>
#include "entities/Entity.h"
#include "common/SpdLogger.h"
#include "scutcheon/osgScutcheon.h"
LabelComponent::LabelComponent(SceneComponent* parent)
: SceneComponent(parent)
, text_("Label")
, fontSize_(26.0f)
, color_(1.0f, 0.0f, 0.0f, 1.0f)
, visible_(true)
, needUpdate_(true) {
}
LabelComponent::~LabelComponent() {
}
std::string LabelComponent::GetTypeName() {
return "LabelComponent";
}
void LabelComponent::AttachEntity(Entity* entity) {
SceneComponent::AttachEntity(entity);
if (entity && !entity->GetName().isEmpty()) {
LOG_INFO("LabelComponent: Attaching to entity '{}'", entity->GetName().toUtf8().data());
SetText(entity->GetName().toLocal8Bit().data());
Entity* entity = GetEntity();
if (nullptr != entity) {
connect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText);
}
CreateTextNode();
}
}
bool LabelComponent::SetAttribute(const char* name, const char* value) {
if (0 == strcmp(name, "text")) {
SetText(value);
return true;
} else if (0 == strcmp(name, "fontSize")) {
SetFontSize(static_cast<float>(atof(value)));
return true;
} else if (0 == strcmp(name, "visible")) {
SetVisible(0 == strcmp(value, "true"));
return true;
} else if (0 == strcmp(name, "color")) {
float r, g, b, a = 1.0f;
int parsed = sscanf(value, "%f,%f,%f,%f", &r, &g, &b, &a);
if (parsed >= 3) {
SetColor(osg::Vec4(r, g, b, a));
return true;
}
}
return SceneComponent::SetAttribute(name, value);
}
bool LabelComponent::SaveAttribute(tinyxml2::XMLElement* element) {
element->SetAttribute("text", text_.c_str());
element->SetAttribute("fontSize", fontSize_);
element->SetAttribute("visible", visible_ ? "true" : "false");
// 保存颜色
char colorStr[64];
sprintf(colorStr, "%.2f,%.2f,%.2f,%.2f", color_.r(), color_.g(), color_.b(), color_.a());
element->SetAttribute("color", colorStr);
return SceneComponent::SaveAttribute(element);
}
std::string LabelComponent::GetSelfTypeName() const {
return LabelComponent::GetTypeName();
}
void LabelComponent::Begin() {
SceneComponent::Begin();
}
void LabelComponent::Update(double dt) {
SceneComponent::Update(dt);
if (needUpdate_) {
UpdateTextNode();
needUpdate_ = false;
}
}
void LabelComponent::End() {
SceneComponent::End();
Entity* entity = GetEntity();
if (nullptr != entity) {
disconnect(entity, &Entity::NameChanged, this, &LabelComponent::UpdateText);
}
}
void LabelComponent::AddToRender() {
SceneComponent::AddToRender();
}
void LabelComponent::SetText(const std::string& text) {
if (text_ != text) {
text_ = text;
needUpdate_ = true;
if (textNode_.valid()) {
textNode_->setText(text_);
}
}
}
void LabelComponent::SetFontSize(float size) {
if (fontSize_ != size) {
fontSize_ = size;
needUpdate_ = true;
}
}
void LabelComponent::SetColor(const osg::Vec4& color) {
if (color_ != color) {
color_ = color;
needUpdate_ = true;
}
}
void LabelComponent::SetVisible(bool visible) {
if (visible_ != visible) {
visible_ = visible;
if (billboard_.valid()) {
billboard_->setNodeMask(visible_ ? 0xffffffff : 0x0);
}
}
}
void LabelComponent::CreateTextNode() {
if (mt_.valid()) {
return;
}
// 使用布告板来显示文本,确保文本始终面向相机
if (!billboard_.valid()) {
billboard_ = new osg::Billboard();
billboard_->setMode(osg::Billboard::POINT_ROT_EYE);
textNode_ = new osgText::Text();
// 设置文本对齐方式为底部居中,这样文本会显示在指定位置的上方
textNode_->setAlignment(osgText::Text::CENTER_BOTTOM);
textNode_->setAxisAlignment(osgText::Text::SCREEN);
textNode_->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
textNode_->setText(text_);
textNode_->setPosition(osg::Vec3(0.0f, 0.0f, 0.0f)); // 文本相对于布告板的位置
// 直接将文本对象添加到布告板,并设置位置偏移
billboard_->addDrawable(textNode_.get(), osg::Vec3(0.0f, 0.0f, 5.0f));
// 设置渲染状态
osg::StateSet* stateSet = billboard_->getOrCreateStateSet();
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
stateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
osg::ref_ptr<osg::MatrixTransform> mt = new osg::MatrixTransform();
mt->addChild(billboard_);
if (!mt_.valid()) {
mt_ = mt;
}
needUpdate_ = true;
}
}
void LabelComponent::UpdateTextNode() {
if (textNode_.valid()) {
textNode_->setText(text_);
textNode_->setCharacterSize(fontSize_);
textNode_->setColor(color_);
SPDLOG_INFO("LabelComponent: Updated billboard text '{}' with size {}", text_, fontSize_);
}
}
void LabelComponent::UpdateText(const QString& text) {
SetText(text.toLocal8Bit().data());
needUpdate_ = true;
}

View File

@ -0,0 +1,58 @@
#pragma once
#include "entities/SceneComponent.h"
#include <qstring.h>
#include <osg/Billboard>
#include <osgText/Text>
#include <string>
class LabelComponent : public SceneComponent {
Q_OBJECT
public:
explicit LabelComponent(SceneComponent* parent = nullptr);
~LabelComponent();
static std::string GetTypeName();
void AttachEntity(class Entity* owner) override;
bool SetAttribute(const char* name, const char* value) override;
bool SaveAttribute(tinyxml2::XMLElement* element) override;
std::string GetSelfTypeName() const override;
void Begin() override;
void Update(double dt) override;
void End() override;
void AddToRender() override;
// 标签相关方法
void SetText(const std::string& text);
const std::string& GetText() const { return text_; }
void SetFontSize(float size);
float GetFontSize() const { return fontSize_; }
void SetColor(const osg::Vec4& color);
const osg::Vec4& GetColor() const { return color_; }
void SetVisible(bool visible);
bool IsVisible() const { return visible_; }
protected:
void CreateTextNode();
void UpdateTextNode();
void UpdateText(const QString& text);
protected:
std::string text_;
float fontSize_;
osg::Vec4 color_;
bool visible_;
bool needUpdate_;
//osg::ref_ptr<class osgScutcheon> scutcheon_;
osg::ref_ptr<osg::Billboard> billboard_;
osg::ref_ptr<osgText::Text> textNode_;
};

View File

@ -29,7 +29,7 @@ bool MeshComponent::SaveAttribute(tinyxml2::XMLElement* element) {
return SceneComponent::SaveAttribute(element); return SceneComponent::SaveAttribute(element);
} }
std::string MeshComponent::GetSelfTypeName() { std::string MeshComponent::GetSelfTypeName() const {
return MeshComponent::GetTypeName(); return MeshComponent::GetTypeName();
} }

View File

@ -16,7 +16,7 @@ public:
bool SetAttribute(const char* name, const char* value) override; bool SetAttribute(const char* name, const char* value) override;
bool SaveAttribute(tinyxml2::XMLElement* element) override; bool SaveAttribute(tinyxml2::XMLElement* element) override;
std::string GetSelfTypeName() override; std::string GetSelfTypeName() const override;
bool LoadNode(const char* mesh); bool LoadNode(const char* mesh);
const std::string& GetMesh() const { const std::string& GetMesh() const {

View File

@ -104,7 +104,7 @@ void PathComponent::Update(double dt) {
osg::Vec3 angle; osg::Vec3 angle;
OsgUtils::QuatToHPR(cp.getRotation(), &angle); OsgUtils::QuatToHPR(cp.getRotation(), &angle);
transform->SetRotation(angle); transform->SetRotation(angle);
transform->SetScale(cp.getScale()); // transform->SetScale(cp.getScale());
} }
void PathComponent::SetPath(const QString& path) { void PathComponent::SetPath(const QString& path) {

View File

@ -12,7 +12,7 @@ public:
~PathComponent(); ~PathComponent();
static std::string GetTypeName(); static std::string GetTypeName();
std::string GetSelfTypeName() override { std::string GetSelfTypeName() const override {
return PathComponent::GetTypeName(); return PathComponent::GetTypeName();
} }

View File

@ -261,3 +261,32 @@ void SceneComponent::AddToRender() {
AttachParent(parent); AttachParent(parent);
} }
} }
bool SceneComponent::HasComponent(const std::string& name) const {
if (GetSelfTypeName() == name) {
return true;
}
for (auto& componet : children_) {
if (componet->GetSelfTypeName() == name) {
return true;
}
}
return false;
}
void SceneComponent::SetVisible(bool v) {
visible_ = v;
if (nullptr == mt_) {
return;
}
mt_->setNodeMask(v ? ~0 : 0);
// for (auto child : children_) {
// child->SetVisible(v);
// }
}
bool SceneComponent::IsVisible() const {
return visible_;
}

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <vector>
#include "entities/Component.h" #include "entities/Component.h"
//#include "entities/Entity.h" //#include "entities/Entity.h"
#include "utils/Transform.h" #include "utils/Transform.h"
@ -9,6 +10,7 @@
#include "osg/Vec3" #include "osg/Vec3"
#include "osg/MatrixTransform" #include "osg/MatrixTransform"
#include "Entity.h"
class SceneComponent : public Component { class SceneComponent : public Component {
Q_OBJECT Q_OBJECT
@ -29,6 +31,7 @@ public:
bool AttachTo(SceneComponent* parent) override; bool AttachTo(SceneComponent* parent) override;
virtual void AddToRender(); virtual void AddToRender();
virtual bool HasComponent(const std::string& name) const override;
SceneComponent* GetRootComponent() const; SceneComponent* GetRootComponent() const;
@ -59,6 +62,9 @@ public:
void AttachParent(SceneComponent* parent); void AttachParent(SceneComponent* parent);
void UpdateLocationAndRotation(); void UpdateLocationAndRotation();
void SetVisible(bool v);
bool IsVisible() const;
protected: protected:
void RemoveRender(); void RemoveRender();
void RemoveParent(); void RemoveParent();
@ -74,4 +80,5 @@ protected:
protected: protected:
Transform transform_; Transform transform_;
bool visible_{ true };
}; };

View File

@ -1,513 +0,0 @@
#include "entities/ScutcheonComponent.h"
#include <osgViewer/Renderer>
Scutcheon::Scutcheon() {
}
Scutcheon::Scutcheon(const QString& titleText, osg::ref_ptr<osg::MatrixTransform> targetObj) :
osgWidget::Box("Scutcheon", osgWidget::Box::VERTICAL),
mTargetObj(targetObj),
mIndex(0),
mIsVisible(true),
mIsItemVisible(true),
mIsMouseDrag(false),
mIsMousePush(false) {
getBackground()->setColor(1.0, 1.0, 1.0, 0.5);
setEventMask(osgWidget::EVENT_ALL);
attachMoveCallback();
mTitleText = titleText;
addLabelTitle(titleText);
}
Scutcheon::~Scutcheon() {
}
void Scutcheon::addLabelTitle(const QString& titleText) {
osg::ref_ptr<osgWidget::Label> labelTitle = new osgWidget::Label("labelTitle");
labelTitle->setFont(FONT_TEXT);
labelTitle->setFontSize(14);
labelTitle->setFontColor(1.0f, 1.0f, 0.0f, 1.0f);
labelTitle->setColor(1.0f, 1.0f, 1.0f, 0.3f);
labelTitle->addSize(128.0f, 32.0f);
//labelTitle->setEventMask(osgWidget::EVENT_MOUSE_DRAG);
//labelTitle->addCallback(new osgWidget::Callback(&osgScutcheon::callbackMousePush, this, osgWidget::EVENT_MOUSE_DRAG));
//labelTitle->setShadow(0.08f);
labelTitle->setCanFill(true);
labelTitle->setImage(TITLE_IMAGE);
labelTitle->setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
labelTitle->setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
labelTitle->setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
labelTitle->setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(titleText);
labelTitle->setLabel(labelString);
addWidget(labelTitle);
}
void Scutcheon::addLabelItem(const QString& labelText) {
++mIndex;
ScutcheonMenu* labelItem = new ScutcheonMenu(labelText, this);
labelItem->setIndex(mIndex);
mLabelItemManager.push_back(labelItem);
addWidget(labelItem);
}
void Scutcheon::addLabelItem(ScutcheonMenu& labelItem) {
++mIndex;
labelItem.setIndex(mIndex);
mLabelItemManager.push_back(&labelItem);
if (mIsItemVisible) {
addWidget(&labelItem);
}
}
void Scutcheon::moveLabelItem() {
int x = this->getX();
int y = this->getY();
for (int i = 0; i < mLabelItemManager.size(); ++i) {
ScutcheonMenu* labelItem = mLabelItemManager.at(i);
labelItem->moveTo(x, y);
}
}
bool Scutcheon::callbackMouseDrag(osgWidget::Event& ev) {
return true;
}
bool Scutcheon::mouseDrag(double, double, const osgWidget::WindowManager*) {
qDebug() << "osgScutcheon mouseDrag called";
mIsMouseDrag = true;
return true;
}
bool Scutcheon::mousePush(double, double, const osgWidget::WindowManager*) {
mIsMousePush = true;
qDebug() << "osgScutcheon mousePush called" << mIsMousePush << ":" << mTitleText;
return true;
}
bool Scutcheon::mouseRelease(double, double, const osgWidget::WindowManager*) {
qDebug() << "osgScutcheon mouseRelease called" << mIsMouseDrag << ":" << mTitleText;
if (!mIsMouseDrag) {
if (mIsMousePush && mIsItemVisible) {
std::vector<osg::ref_ptr<ScutcheonMenu> >::const_iterator it;
for (it = mLabelItemManager.begin(); it != mLabelItemManager.end(); ++it) {
(*it)->getChildMenu()->hide();
this->removeWidget((*it));
qDebug() << "item removed!" << (*it)->getIndex();
}
} else {
if (this->getNumChildren() <= mLabelItemManager.size()) {
std::vector<osg::ref_ptr<ScutcheonMenu> >::const_iterator it;
for (it = mLabelItemManager.begin(); it != mLabelItemManager.end(); ++it) {
this->addWidget((*it));
qDebug() << "item added!" << (*it)->getIndex();
}
}
}
mIsItemVisible = !mIsItemVisible;
}
mIsMousePush = false;
mIsMouseDrag = false;
return true;
}
std::vector<osg::ref_ptr<ScutcheonMenu> > Scutcheon::getLabelItemManager() const {
return mLabelItemManager;
}
void Scutcheon::onMouseEvent(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer* viewer) {
int etype = ea.getEventType();
if (etype == ea.FRAME) {
if (mTargetObj) {
osg::Vec3 position = mTargetObj->getMatrix().getTrans() + osg::Vec3d(0, 0, 0);
osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(viewer->getCamera()->getRenderer());
osg::Vec3 renderPos;
renderer->getSceneView(0)->projectObjectIntoWindow(position, renderPos);
float x = this->getX();
float y = this->getY();
float w = this->getWidth();
float h = this->getHeight();
float offset = 0.0;
osg::Vec3 stPt(x + 0.5 * w, y + 0.5 * h, 0);
if (stPt.y()- renderPos.y()>0.5*h)
{
stPt[1] = stPt.y()-0.5*h+offset;
}
else if (stPt.y()- renderPos.y()<-0.5*h)
{
stPt[1] = stPt.y()+0.5*h+offset;
}
if (stPt.x()- renderPos.x()>0.5*w)
{
stPt[0] = stPt.x()-0.5*w-offset;
}
else if (stPt.x()- renderPos.x()<-0.5*w)
{
stPt[0] = stPt.x()+0.5*w-offset;
}
setPos(renderPos + osg::Vec3d(50, 50, 50));
createLine(stPt, renderPos);
}
}
if ((etype == ea.PUSH) && ea.getButtonMask() == ea.LEFT_MOUSE_BUTTON) {
if (mIsMousePush) {
//qDebug() << "mousePush called" ;
m_LBDownPt.set(ea.getX(), ea.getY(), 0);
m_LastPt = m_LBDownPt;
}
}
if ((etype == ea.DRAG)) {
//qDebug() << "mouseDrag called" ;
if (mIsMouseDrag) {
osg::Vec3 pt(ea.getX() - m_LastPt[0], ea.getY() - m_LastPt[1], 0);
setOffset(m_offset + pt);
m_LastPt.set(ea.getX(), ea.getY(), 0);
ea.setHandled(true);
}
}
if ((etype == ea.RELEASE)) {
//qDebug() << "mouseDrag release" ;
}
}
void Scutcheon::setPos(osg::Vec3 pos) {
m_pos = pos;
pos = m_pos + m_offset;
this->setOrigin(pos.x(), pos.y());
this->update();
moveLabelItem();
}
void Scutcheon::setOffset(osg::Vec3 offset) {
m_offset = offset;
offset = m_pos + m_offset;
this->setOrigin(offset.x(), offset.y());
this->update();
moveLabelItem();
}
osg::ref_ptr<osg::MatrixTransform> Scutcheon::getTargetObject() {
return mTargetObj;
}
int Scutcheon::getItemCount() {
return mLabelItemManager.size();
}
void Scutcheon::setVisibility(bool b) {
mIsVisible = b;
if (mIsVisible) {
this->show();
m_line->setNodeMask(1);
} else {
this->hide();
m_line->setNodeMask(0);
for (int i = 0; i < mLabelItemManager.size(); i++) {
mLabelItemManager.at(i)->getChildMenu()->hide();
}
}
}
void Scutcheon::createLine(const osg::Vec3& startPt, const osg::Vec3& endPt) {
if (NULL == m_line) {
m_line = new osg::Geometry;
osg::Vec3Array* vertices = new osg::Vec3Array;
vertices->push_back(startPt);
vertices->push_back(endPt);
m_line->setVertexArray(vertices);
osg::Vec3Array* normals = new osg::Vec3Array;
normals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
m_line->setNormalArray(normals);
m_line->setNormalBinding(osg::Geometry::BIND_OVERALL);
osg::Vec4Array* colors = new osg::Vec4Array;
colors->push_back(osg::Vec4(1.0, 1.0, 0.0, 1.0));
m_line->setColorArray(colors);
m_line->setColorBinding(osg::Geometry::BIND_OVERALL);
m_line->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, 2));
m_line->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
//m_line->getOrCreateStateSet()->setAttributeAndModes(new osg::LineWidth(1.0f),osg::StateAttribute::ON);
m_line->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
osg::Geode* geode = new osg::Geode();
geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
geode->addDrawable(m_line);
//this->addChild(geode);
this->getWindowManager()->addChild(geode);
} else {
osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(m_line->getVertexArray());
(*vertices)[0].set(startPt.x(), startPt.y(), 0.0);
(*vertices)[1].set(endPt.x(), endPt.y(), 0.0);
vertices->dirty();
m_line->setVertexArray(vertices);
m_line->dirtyDisplayList();
}
}
///////////////////////////////////////////////////////////////
/// \brief osgScutcheonManager::osgScutcheonManager
/// 标牌管理器
/// ///////////////////////////////////////////////////////////
ScutcheonManager* ScutcheonManager::m_pInstance = NULL;
ScutcheonManager::ScutcheonManager(osgViewer::Viewer* pViewer, osg::Group* pScreneRoot) {
m_bVisible = true;
mWindowManager = new osgWidget::WindowManager(pViewer, 50.0f, 50.0f, 1, /*0xF0000000*/
osgWidget::WindowManager::WM_PICK_DEBUG);
osg::Camera* camera = mWindowManager->createParentOrthoCamera();
pScreneRoot->addChild(camera);
/*pViewer->addEventHandler(new osgWidget::MouseHandler(mWindowManager));
pViewer->addEventHandler(new osgWidget::KeyboardHandler(mWindowManager));
pViewer->addEventHandler(new osgWidget::ResizeHandler(mWindowManager, camera));
pViewer->addEventHandler(new osgWidget::CameraSwitchHandler(mWindowManager, camera));*/
}
ScutcheonManager::~ScutcheonManager() {
m_bGUIStoped = true;
clear();
}
ScutcheonManager* ScutcheonManager::instance() {
if (NULL == m_pInstance) {
//osgViewer::Viewer* getOSGViewer(){ return m_pViewer; }
//osg::Group* getRoot(){ return m_pRoot.get(); }
/* m_pInstance = new osgScutcheonManager(GraphicsView::instance()->getOSGViewer(),
GraphicsView::instance()->getRoot());
GraphicsView::instance()->getOSGViewer()->addEventHandler(m_pInstance);*/
}
return m_pInstance;
}
void ScutcheonManager::destroy() {
if (NULL != m_pInstance) {
delete m_pInstance;
m_pInstance = NULL;
}
}
bool ScutcheonManager::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa) {
if (m_bStopGUI) {
m_bGUIStoped = true;
} else {
osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
int nCount = m_LabelList.size();
for (int i = 0; i < nCount; i++) {
m_LabelList[i]->onMouseEvent(ea, viewer);
}
}
return false;
}
int ScutcheonManager::addLabel(Scutcheon* label) {
m_bVisible = true;
if (label == NULL) {
return 0;
}
lock(true);
// while (!m_bStopGUI) QThread::sleep(100);
int nCount = m_LabelList.size();
for (int i = 0; i < nCount; i++) {
if (m_LabelList[i] == label) {
lock(false);
return 0;
}
}
mWindowManager->addChild(label);
mWindowManager->resizeAllWindows();
m_LabelList.push_back(label);
lock(false);
return m_LabelList.size();
}
int ScutcheonManager::delLabel(Scutcheon*& label) {
lock(true);
while (!m_bStopGUI) QThread::sleep(100);
for (std::vector<Scutcheon*>::iterator vit = m_LabelList.begin(); vit != m_LabelList.end(); vit++) {
if ((*vit) == label) {
m_LabelList.erase(vit);
//label->setVisibility(false);
delete label;
label = NULL;
lock(false);
return m_LabelList.size();
}
}
lock(false);
return 0;
}
int ScutcheonManager::delLabel(osg::MatrixTransform* tethernode) {
return 0;
}
void ScutcheonManager::clear() {
lock(true);
//while (!m_bGUIStoped) Sleep(200);
while (m_LabelList.size() > 0) {
Scutcheon* back = m_LabelList.back();
delLabel(back);
}
lock(false);
}
void ScutcheonManager::lock(bool b) {
if (b) {
m_bStopGUI = true;
m_bGUIStoped = false;
} else {
m_bStopGUI = false;
m_bGUIStoped = true;
}
}
osg::ref_ptr<osgWidget::WindowManager> ScutcheonManager::getWindowManager() const {
return mWindowManager;
}
ScutcheonMenu::ScutcheonMenu(const QString& label, osg::ref_ptr<Scutcheon> parentMenu) :
osgWidget::Label("menu1"),
mChildMenu(NULL),
mParentMenu(parentMenu),
mHasChildMenu(false),
mIndex(0),
mMenuItemCount(0) {
initLabel(label);
}
void ScutcheonMenu::addChildMenu(const QString& menuText) {
ImageLabel* childMenuContent = new ImageLabel(menuText);
if (mChildMenu == NULL) {
mChildMenu = new osgWidget::Box("childMenu", osgWidget::Box::VERTICAL, true);
mChildMenu->addWidget(childMenuContent);
mMenuItemManager.push_back(childMenuContent);
mChildMenu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 0.6f);
mChildMenu->resize();
mChildMenu->hide();
mHasChildMenu = true;
//mParentMenu->addChild(mChildMenu);
mParentMenu->getWindowManager()->addChild(mChildMenu.get());
} else {
mChildMenu->addWidget(childMenuContent);
mMenuItemManager.push_back(childMenuContent);
}
++mMenuItemCount;
}
void ScutcheonMenu::updateChildMenuText(int index, QString labelText) {
if (index >= 0 && index < getMenuItemCount()) {
//mMenuItemManager.at(index)->setLabelText(labelText);
}
}
void ScutcheonMenu::initLabel(const QString& labelText) {
setFont(FONT_TEXT);
setFontSize(15);
setFontColor(0.0f, 0.0f, 1.0f, 1.0f);
addSize(128.0f, 32.0f);
setColor(1.0f, 1.0f, 0.0f, 0.6f);
//setShadow(0.08f);
setCanFill(true);
setEventMask(osgWidget::EVENT_ALL);
setImage(ITEM_IAMGE);
setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(labelText);
setLabel(labelString);
}
void ScutcheonMenu::hideOtherChildMenu() {
for (int i = 0; i < mParentMenu->getLabelItemManager().size(); i++) {
osg::ref_ptr<ScutcheonMenu> childItem = mParentMenu->getLabelItemManager().at(i);
if (childItem->getChildMenu() != mChildMenu) {
childItem->getChildMenu()->hide();
}
qDebug() << "hideOtherChildMenu";
}
}
void ScutcheonMenu::hideAllChildMenu(osgWidget::WindowManager* wm) {
osgWidget::Window* tmp = 0;
unsigned int count = wm->getNumChildren();
for (unsigned int i = 0; i < count; ++i) {
tmp = dynamic_cast<osgWidget::Window*>(wm->getChild(i));
if (tmp) {
QString name = QString::fromStdString(tmp->getName());
if (tmp != mChildMenu.get() && name == "childMenu") {
if (tmp->isVisible()) {
tmp->hide();
}
}
}
}
}
bool ScutcheonMenu::mousePush(double, double, const osgWidget::WindowManager* wm) {
hideOtherChildMenu();
//hideAllChildMenu(mParentMenu->getWindowManager());
if (!mChildMenu->isVisible()) {
mChildMenu->show();
qDebug() << "hideOtherChildMenu show";
} else {
mChildMenu->hide();
qDebug() << "hideOtherChildMenu hide";
}
return true;
}
ImageLabel::ImageLabel(const QString& labelText) : osgWidget::Label("menu1") {
setFont(FONT_TEXT);
setFontSize(13);
setFontColor(0.0f, 0.2f, 1.0f, 1.0f);
addSize(128.0f, 32.0f);
setColor(1.0f, 1.0f, 1.0f, 0.6f);
//setPadding(1.0f);
//setShadow(0.08f);
setCanFill(true);
setEventMask(osgWidget::EVENT_ALL);
setImage(ITEM_IAMGE);
setLabelText(labelText);
}
void ImageLabel::setLabelText(QString labelText) {
setAlignHorizontal(osgWidget::Widget::HA_LEFT);
setTexCoord(0.0f, 0.0f, osgWidget::Widget::LOWER_LEFT);
setTexCoord(1.0f, 0.0f, osgWidget::Widget::LOWER_RIGHT);
setTexCoord(1.0f, 1.0f, osgWidget::Widget::UPPER_RIGHT);
setTexCoord(0.0f, 1.0f, osgWidget::Widget::UPPER_LEFT);
osgText::String labelString = TextCodecUtils::QStringToOsgTextString(labelText);
setLabel(labelString);
}

View File

@ -1,255 +0,0 @@
/**
* @brief
* @author hph
* @date 2018/07/07
*/
#ifndef OSGSCUTCHEON_H
#define OSGSCUTCHEON_H
#include <QObject>
#include <iostream>
#include <sstream>
#include <QDebug>
#include <QTextCodec>
#include <QVector>
#include <QThread>
#include <osgWidget/Box>
#include <osgWidget/Label>
#include <osgWidget/WindowManager>
#include "utils/TextCodecUtil.h"
#define FONT_TEXT "fonts/simhei.ttf"
#define TITLE_IMAGE "../publish/data/texture/mark/label_title.png"
#define ITEM_IAMGE "../publish/data/texture/mark/label_normal_01.png"
class ScutcheonMenu;
class ImageLabel;
class Scutcheon : public osgWidget::Box {
public:
Scutcheon();
Scutcheon(const QString& titleText, osg::ref_ptr<osg::MatrixTransform> targetObj);
~Scutcheon();
public:
void addLabelTitle(const QString& titleText);
void addLabelItem(const QString& labelText);
void addLabelItem(ScutcheonMenu& labelItem);
void hideOtherLabelItem();
void moveLabelItem();
void createLine(const osg::Vec3& startPt = osg::Vec3(0, 0, 0), const osg::Vec3& endPt = osg::Vec3(0, 0, 0));
void onMouseEvent(const osgGA::GUIEventAdapter& ea, osgViewer::Viewer* viewer);
osg::Geometry* getLine() const {
return m_line;
}
int getItemCount();
void setVisibility(bool b);
bool getVisibility() {
return mIsVisible;
}
void setPos(osg::Vec3 pos);
void setOffset(osg::Vec3 offset);
osg::ref_ptr<osg::MatrixTransform> getTargetObject();
std::vector<osg::ref_ptr<ScutcheonMenu> > getLabelItemManager() const;
private:
bool callbackMouseDrag(osgWidget::Event& ev);
protected:
bool mouseDrag(double, double, const osgWidget::WindowManager*);
bool mousePush(double, double, const osgWidget::WindowManager*);
bool mouseRelease(double, double, const osgWidget::WindowManager*);
public:
QString mTitleText;
std::vector<osg::ref_ptr<ScutcheonMenu> > mLabelItemManager;
int mIndex;
osg::ref_ptr<osg::MatrixTransform> mTargetObj;
osg::ref_ptr<osg::Geometry> m_line;
bool mIsVisible;
bool mIsItemVisible;
bool mIsMousePush;
bool mIsMouseDrag;
osg::Vec3 m_pos;
osg::Vec3 m_offset;
osg::Vec3 m_LastPt;
osg::Vec3 m_LBDownPt;
};
class ScutcheonManager : public osgGA::GUIEventHandler {
protected:
ScutcheonManager(osgViewer::Viewer* pViewer, osg::Group* pScreneRoot);
~ScutcheonManager();
public:
static ScutcheonManager* instance();
static void destroy();
bool handle(const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&);
int addLabel(Scutcheon* label);
int delLabel(Scutcheon*& label);
int delLabel(osg::MatrixTransform* tethernode);
void clear();
void lock(bool b);
void setVisibility(bool b);
void setVisibilityByID(unsigned int ID, bool b);
bool getVisibilityByID(unsigned int ID);
bool getVisibility() const {
return m_bVisible;
}
void setLabelTxtColor(const osg::Vec4f& color);
void setLabelBgColor(const osg::Vec4f& color);
const osg::Vec4f& getLabelTxtColor() const {
return m_clrTxt;
}
const osg::Vec4f& getLabelBgColor() const {
return m_clrBg;
}
osg::ref_ptr<osgWidget::WindowManager> getWindowManager() const;
public:
static ScutcheonManager* m_pInstance;
osg::ref_ptr<osgWidget::WindowManager> mWindowManager;
//osgWidget::WindowManager* mWindowManager;
std::vector<Scutcheon*> m_LabelList;
bool m_bStopGUI;
bool m_bGUIStoped;
bool m_bVisible;
osg::Vec4f m_clrTxt;
osg::Vec4f m_clrBg;
};
class ScutcheonMenu : public osgWidget::Label {
public:
ScutcheonMenu(const QString& label, osg::ref_ptr<Scutcheon> parentMenu);
void addChildMenu(const QString& menuText);
void updateChildMenuText(int index, QString labelText);
void initLabel(const QString& labelText);
void setIndex(int index) {
mIndex = index;
}
void moveTo(int parentX, int parentY) {
if (mChildMenu) {
mChildMenu->setOrigin(parentX + 128.0, parentY + 32.0 * mIndex);
mChildMenu->update();
}
}
bool isHasChildMenu() {
return mHasChildMenu;
}
osg::ref_ptr<osgWidget::Window> getChildMenu() {
return mChildMenu;
}
int getIndex() {
return mIndex;
}
int getMenuItemCount() {
return mMenuItemManager.size();
}
void hideOtherChildMenu();
void hideAllChildMenu(osgWidget::WindowManager* wm);
void managed(osgWidget::WindowManager* wm) {
osgWidget::Label::managed(wm);
if (mChildMenu) {
mChildMenu->hide();
}
}
void positioned() {
osgWidget::Label::positioned();
if (mChildMenu) {
//qDebug() << "mChildMenu not NULL!!" << mIndex;
mChildMenu->setOrigin(mParentMenu->getX() + 128.0, mParentMenu->getY() + 32.0 * mIndex);
}
}
bool mousePush(double, double, const osgWidget::WindowManager* wm);
bool mouseEnter(double, double, const osgWidget::WindowManager*) {
setColor(1.0f, 1.0f, 1.0f, 0.3f);
return true;
}
bool mouseLeave(double, double, const osgWidget::WindowManager*) {
setColor(1.0f, 1.0f, 1.0f, 0.6f);
return true;
}
public:
QVector<osg::ref_ptr<ImageLabel> > mMenuItemManager;
private:
osg::ref_ptr<osgWidget::Box> mChildMenu;
osg::ref_ptr<Scutcheon> mParentMenu;
int mIndex;
int mMenuItemCount;
bool mHasChildMenu;
};
class ImageLabel : public osgWidget::Label {
public:
ImageLabel(const QString& labelText);
void setLabelText(QString labelText);
bool mousePush(double, double, const osgWidget::WindowManager*) {
return true;
}
bool mouseDrag(double, double, const osgWidget::WindowManager*) {
//osg::notify(osg::NOTICE) << _name << " > mouseDrag called" << std::endl;
return false;
}
bool mouseEnter(double, double, const osgWidget::WindowManager*) {
//setColor(1.0f, 1.0f, 1.0f, 1.0f);
setFontColor(0.0f, 0.0f, 1.0f, 1.0f);
return true;
}
bool mouseLeave(double, double, const osgWidget::WindowManager*) {
//setColor(1.0f, 1.0f, 1.0f, 0.8f);
setFontColor(0.0f, 0.2f, 1.0f, 1.0f);
return true;
}
bool mouseOver(double, double, const osgWidget::WindowManager*) {
return true;
}
};
#endif // OSGSCUTCHEON_H

View File

@ -1,3 +1,4 @@
#include "app/Application.h" #include "app/Application.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
@ -5,23 +6,396 @@
#include "common/CrashHandler.h" #include "common/CrashHandler.h"
#include "ui/MainFrame.h" #include "ui/MainFrame.h"
#include "ui/MainWindow.h"
#include "viewer/OsgWidget.h"
#include <QTimer>
#include <QApplication>
#include <QGridLayout>
#include <osgViewer/CompositeViewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/MultiTouchTrackballManipulator>
#include <osgDB/ReadFile>
#include <osgEarth/MapNode>
#include <osgEarthUtil/ExampleResources>
#include <osgGA/StateSetManipulator>
// #include <osgEarth/GLUtils>
#include "osgqt/GraphicsWindowQt.h"
#include "scene/ui/CompositeWidgetManager.h"
#include "scene/ui/QueryElevationWidget.h"
#ifndef LC
#define LC "DYT"
#endif
const unsigned int MASK_2D = 0xF0000000;
std::string path = "D:\\Project\\DYT\\Source\\bin\\Release\\data\\";
bool scrollWindow(osgWidget::Event& ev) {
// The first thing we need to do is make sure we have a Frame object...
osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
if(!frame) return false;
// And now we need to make sure our Frame has a valid internal EmbeddedWindow widget.
osgWidget::Window::EmbeddedWindow* ew =
dynamic_cast<osgWidget::Window::EmbeddedWindow*>(frame->getEmbeddedWindow())
;
if(!ew) return false;
// Lets get the visible area so that we can use it to make sure our scrolling action
// is necessary in the first place.
const osgWidget::Quad& va = ew->getWindow()->getVisibleArea();
// The user wants to scroll up; make sure that the visible area's Y origin isn't already
// at 0.0f, 0.0f.
if(ev.getWindowManager()->isMouseScrollingUp() && va[1] != 0.0f)
ew->getWindow()->addVisibleArea(0, -20)
;
else if(va[1] <= (ew->getWindow()->getHeight() - ew->getHeight()))
ew->getWindow()->addVisibleArea(0, 20)
;
// We need to manually call update to make sure the visible area scissoring is done
// properly.
frame->update();
return true;
}
bool changeTheme(osgWidget::Event& ev) {
std::string theme;
if(ev.key == osgGA::GUIEventAdapter::KEY_Right)
theme = "osgWidget/theme-1.png"
;
else if(ev.key == osgGA::GUIEventAdapter::KEY_Left)
theme = "osgWidget/theme-2.png"
;
else return false;
osgWidget::Frame* frame = dynamic_cast<osgWidget::Frame*>(ev.getWindow());
if(!frame) return false;
// This is just one way to access all our Widgets; we could just as well have used:
//
// for(osgWidget::Frame::Iterator i = frame.begin(); i != frame.end() i++) {}
//
// ...and it have worked, too.
for(unsigned int row = 0; row < 3; row++) {
for(unsigned int col = 0; col < 3; col++) {
frame->getByRowCol(row, col)->setImage(theme);
}
}
return true;
}
osg::Node* createUiExample(osgViewer::View* viewer, osgWidget::WindowManager* wm) {
if(!wm) return nullptr;
// viewer.setUpViewInWindow(
// 50,
// 50,
// static_cast<int>(wm->getWidth()),
// static_cast<int>(wm->getHeight())
// );
osg::Group* group = new osg::Group();
osg::Camera* camera = wm->createParentOrthoCamera();
group->addChild(camera);
viewer->addEventHandler(new osgWidget::MouseHandler(wm));
viewer->addEventHandler(new osgWidget::KeyboardHandler(wm));
viewer->addEventHandler(new osgWidget::ResizeHandler(wm, camera));
viewer->addEventHandler(new osgWidget::CameraSwitchHandler(wm, camera));
viewer->addEventHandler(new osgViewer::StatsHandler());
viewer->addEventHandler(new osgViewer::WindowSizeHandler());
viewer->addEventHandler(new osgGA::StateSetManipulator(
viewer->getCamera()->getOrCreateStateSet()
));
wm->resizeAllWindows();
return group;
}
void creatWidget(osgViewer::View* viewer, osg::Group* root) {
osgWidget::WindowManager* wm = new osgWidget::WindowManager(
viewer,
1280.0f,
1024.0f,
MASK_2D,
osgWidget::WindowManager::WM_PICK_DEBUG
//osgWidget::WindowManager::WM_NO_INVERT_Y
);
osgWidget::Frame* frame = osgWidget::Frame::createSimpleFrameFromTheme(
"frame",
osgDB::readRefImageFile("osgWidget/theme.png"),
40.0f,
40.0f,
osgWidget::Frame::FRAME_ALL
);
osgWidget::Box* box = new osgWidget::Box("images", osgWidget::Box::VERTICAL);
osgWidget::Widget* img1 = new osgWidget::Widget("im1", 512.0f, 512.0f);
osgWidget::Widget* img2 = new osgWidget::Widget("im2", 512.0f, 512.0f);
osgWidget::Widget* img3 = new osgWidget::Widget("im3", 512.0f, 512.0f);
osgWidget::Widget* img4 = new osgWidget::Widget("im4", 512.0f, 512.0f);
img1->setImage(path + "osgWidget/scrolled1.jpg", true);
img2->setImage(path + "osgWidget/scrolled2.jpg", true);
img3->setImage(path + "osgWidget/scrolled3.jpg", true);
img4->setImage(path + "osgWidget/scrolled4.jpg", true);
img1->setMinimumSize(10.0f, 10.0f);
img2->setMinimumSize(10.0f, 10.0f);
img3->setMinimumSize(10.0f, 10.0f);
img4->setMinimumSize(10.0f, 10.0f);
box->addWidget(img1);
box->addWidget(img2);
box->addWidget(img3);
box->addWidget(img4);
box->setEventMask(osgWidget::EVENT_NONE);
//frame->getEmbeddedWindow()->setWindow(box);
frame->setWindow(box);
frame->getEmbeddedWindow()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
frame->resize(300.0f, 300.0f);
frame->addCallback(new osgWidget::Callback(&scrollWindow, osgWidget::EVENT_MOUSE_SCROLL));
frame->addCallback(new osgWidget::Callback(&changeTheme, osgWidget::EVENT_KEY_DOWN));
wm->addChild(frame);
osg::Node* ui = createUiExample(viewer, wm);
root->addChild(ui);
}
void configureView( osgViewer::View* view )
{
// default uniform values:
// GLUtils::setGlobalDefaults(view->getCamera()->getOrCreateStateSet());
// add some stock OSG handlers:
view->addEventHandler(new osgViewer::StatsHandler());
view->addEventHandler(new osgViewer::WindowSizeHandler());
view->addEventHandler(new osgViewer::ThreadingHandler());
view->addEventHandler(new osgViewer::LODScaleHandler());
view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet()));
view->addEventHandler(new osgViewer::RecordCameraPathHandler());
view->addEventHandler(new osgViewer::ScreenCaptureHandler());
}
osg::Node* LoadEarth(const std::string& earth, osgViewer::CompositeViewer* viewer) {
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile(earth);
osg::ref_ptr<osgEarth::MapNode> mapNode = osgEarth::MapNode::get(node.get());
if ( !mapNode.valid() )
{
OE_WARN << LC << "Loaded scene graph does not contain a MapNode - aborting" << std::endl;
return 0L;
}
// collect the views
osgViewer::Viewer::Views views;
if (viewer)
{
viewer->getViews(views);
}
// warn about not having an earth manip
for (osgViewer::Viewer::Views::iterator view = views.begin(); view != views.end(); ++view)
{
osgEarth::Util::EarthManipulator* manip = dynamic_cast<osgEarth::Util::EarthManipulator*>((*view)->getCameraManipulator());
if ( manip == 0L )
{
OE_WARN << LC << "Helper used before installing an EarthManipulator" << std::endl;
}
}
// a root node to hold everything:
osg::Group* root = new osg::Group();
root->addChild( node );
// parses common cmdline arguments and apply to the first view:
// if ( !views.empty() )
// {
// parse( mapNode.get(), args, views.front(), root, userContainer );
//
// float lodscale;
// if (args.read("--lodscale", lodscale))
// {
// LODScaleGroup* g = new LODScaleGroup();
// g->setLODScaleFactor(osg::maximum(lodscale, 0.0001f));
// osgEarth::insertGroup(g, mapNode->getParent(0));
// OE_NOTICE << "LOD Scale set to: " << lodscale << std::endl;
// }
// }
// configures each view with some stock goodies
for (osgViewer::Viewer::Views::iterator view = views.begin(); view != views.end(); ++view)
{
configureView( *view );
}
#ifdef OSG_GL3_AVAILABLE
if (viewer)
{
viewer->setRealizeOperation(new GL3RealizeOperation());
}
#endif
return root;
}
class ViewerWidget : public QWidget, public osgViewer::CompositeViewer
{
public:
ViewerWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel=osgViewer::CompositeViewer::SingleThreaded) : QWidget(parent, f)
{
setThreadingModel(threadingModel);
// disable the default setting of viewer.done() by pressing Escape.
setKeyEventSetsDone(0);
std::string earthPath = "D:/Project/DYT/Tool/TritonSample/TritonSample/triton.earth";
// osg::Node* node = osgDB::readNodeFile();
osg::Node* node =LoadEarth(earthPath, this);
if ( !node ) {
return;
}
// Group to hold all our annotation elements.
// osg::Group* annoGroup = new osg::Group();
// osgEarth::MapNode::get(node)->addChild( annoGroup );
QWidget* widget1 = addViewWidget( createGraphicsWindow(0,0,100,100), node);
// QWidget* widget2 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("glider.osgt") );
// QWidget* widget3 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("axes.osgt") );
// QWidget* widget4 = addViewWidget( createGraphicsWindow(0,0,100,100), osgDB::readRefNodeFile("fountain.osgt") );
// QWidget* popupWidget = addViewWidget( createGraphicsWindow(900,100,320,240,"Popup window",true), osgDB::readRefNodeFile("dumptruck.osgt") );
// popupWidget->show();
QGridLayout* grid = new QGridLayout;
grid->addWidget( widget1, 0, 0 );
// grid->addWidget( widget2, 0, 1 );
// grid->addWidget( widget3, 1, 0 );
// grid->addWidget( widget4, 1, 1 );
setLayout( grid );
connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );
_timer.start( 10 );
}
QWidget* addViewWidget( osgQt::GraphicsWindowQt* gw, osg::ref_ptr<osg::Node> scene )
{
osgViewer::View* view = new osgViewer::View;
addView( view );
view->setCameraManipulator( new osgEarth::Util::EarthManipulator() );
configureView(view);
osg::Camera* camera = view->getCamera();
camera->setGraphicsContext( gw );
const osg::GraphicsContext::Traits* traits = gw->getTraits();
camera->setClearColor( osg::Vec4(0.2, 0.2, 0.6, 1.0) );
camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0f, 10000.0f );
creatWidget(view, scene->asGroup());
osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode(scene);
if ( !mapNode )
return gw->getGLWidget();
auto skyDome_ = osgEarth::Util::SkyNode::create(mapNode);
if (!mapNode) {
LOG_WARN("eart map node is nullptr");
return gw->getGLWidget();
}
skyDome_->attach(view);
skyDome_->getSunLight()->setAmbient(osg::Vec4(0.5,0.5,0.5,1.0));
scene->asGroup()->addChild(skyDome_);
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
view->setSceneData( scene );
view->addEventHandler( new osgViewer::StatsHandler );
// view->setCameraManipulator( new osgGA::MultiTouchTrackballManipulator );
gw->setTouchEventsEnabled( true );
return gw->getGLWidget();
}
osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false )
{
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->windowName = name;
traits->windowDecoration = windowDecoration;
traits->x = x;
traits->y = y;
traits->width = w;
traits->height = h;
traits->doubleBuffer = true;
traits->alpha = ds->getMinimumNumAlphaBits();
traits->stencil = ds->getMinimumNumStencilBits();
traits->sampleBuffers = ds->getMultiSamples();
traits->samples = ds->getNumMultiSamples();
return new osgQt::GraphicsWindowQt(traits.get());
}
virtual void paintEvent( QPaintEvent* /*event*/ )
{ frame(); }
protected:
QTimer _timer;
};
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
SpdLogger logger("logs/log.txt", 5); SpdLogger logger("logs/log.txt", 5);
//
Application::setAttribute(Qt::AA_EnableHighDpiScaling); Application::setAttribute(Qt::AA_EnableHighDpiScaling);
////
Application app(argc, argv); Application app(argc, argv);
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
InstallCrashHandler(); // InstallCrashHandler();
//
RecourceHelper::ChangeSkin("default"); RecourceHelper::ChangeSkin("default");
int ret = 0;
MainFrame mainWindow; MainFrame mainWindow;
mainWindow.showMaximized(); mainWindow.showMaximized();
//
ret = app.exec(); int ret = app.exec();
app.Uninit();
return ret; return ret;
//osg::ArgumentParser arguments(&argc, argv);
//QMainWindow* mainWindow = new QMainWindow;
//OsgWidget* viewWidget = new OsgWidget(nullptr, Qt::Widget);
//mainWindow->setCentralWidget(viewWidget);
//// ViewerWidget* viewWidget = new ViewerWidget(nullptr, Qt::Widget, threadingModel);
////viewWidget->setGeometry( 100, 100, 800, 600 );
//viewWidget->Initialize();
//mainWindow->show();
//return app.exec();
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#ifndef OSGVIEWER_GRAPHICSWINDOWQT
#define OSGVIEWER_GRAPHICSWINDOWQT
#define USE_NO_STATIC_REGISTRATION 1
#include <osgViewer/GraphicsWindow>
#include <QMutex>
#include <QEvent>
#include <QQueue>
#include <QSet>
#include <QGLWidget>
class QInputEvent;
class QGestureEvent;
namespace osgViewer {
class ViewerBase;
}
namespace osgQt
{
// forward declarations
class GraphicsWindowQt;
#if USE_NO_STATIC_REGISTRATION
/// The function sets the WindowingSystem to Qt.
void initQtWindowingSystem();
#endif
/** The function sets the viewer that will be used after entering
* the Qt main loop (QCoreApplication::exec()).
*
* The function also initializes internal structures required for proper
* scene rendering.
*
* The method must be called from main thread. */
void setViewer( osgViewer::ViewerBase *viewer );
class GLWidget : public QGLWidget
{
typedef QGLWidget inherited;
public:
GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
GLWidget( QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false );
virtual ~GLWidget();
inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; }
inline GraphicsWindowQt* getGraphicsWindow() { return _gw; }
inline const GraphicsWindowQt* getGraphicsWindow() const { return _gw; }
inline bool getForwardKeyEvents() const { return _forwardKeyEvents; }
virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; }
inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; }
void setTouchEventsEnabled( bool e );
void setKeyboardModifiers( QInputEvent* event );
virtual void keyPressEvent( QKeyEvent* event );
virtual void keyReleaseEvent( QKeyEvent* event );
virtual void mousePressEvent( QMouseEvent* event );
virtual void mouseReleaseEvent( QMouseEvent* event );
virtual void mouseDoubleClickEvent( QMouseEvent* event );
virtual void mouseMoveEvent( QMouseEvent* event );
virtual void wheelEvent( QWheelEvent* event );
virtual bool gestureEvent( QGestureEvent* event );
protected:
int getNumDeferredEvents()
{
QMutexLocker lock(&_deferredEventQueueMutex);
return _deferredEventQueue.count();
}
void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None)
{
QMutexLocker lock(&_deferredEventQueueMutex);
if (removeEventType != QEvent::None)
{
if (_deferredEventQueue.removeOne(removeEventType))
_eventCompressor.remove(eventType);
}
if (_eventCompressor.find(eventType) == _eventCompressor.end())
{
_deferredEventQueue.enqueue(eventType);
_eventCompressor.insert(eventType);
}
}
void processDeferredEvents();
friend class GraphicsWindowQt;
GraphicsWindowQt* _gw;
QMutex _deferredEventQueueMutex;
QQueue<QEvent::Type> _deferredEventQueue;
QSet<QEvent::Type> _eventCompressor;
bool _touchEventsEnabled;
bool _forwardKeyEvents;
qreal _devicePixelRatio;
virtual void resizeEvent( QResizeEvent* event );
virtual void moveEvent( QMoveEvent* event );
virtual void glDraw();
virtual bool event( QEvent* event );
};
class GraphicsWindowQt : public osgViewer::GraphicsWindow
{
public:
GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0 );
GraphicsWindowQt( GLWidget* widget );
virtual ~GraphicsWindowQt();
inline GLWidget* getGLWidget() { return _widget; }
inline const GLWidget* getGLWidget() const { return _widget; }
/// deprecated
inline GLWidget* getGraphWidget() { return _widget; }
/// deprecated
inline const GLWidget* getGraphWidget() const { return _widget; }
struct WindowData : public osg::Referenced
{
WindowData( GLWidget* widget = NULL, QWidget* parent = NULL ): _widget(widget), _parent(parent) {}
GLWidget* _widget;
QWidget* _parent;
};
bool init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f );
static QGLFormat traits2qglFormat( const osg::GraphicsContext::Traits* traits );
static void qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits );
static osg::GraphicsContext::Traits* createTraits( const QGLWidget* widget );
virtual bool setWindowRectangleImplementation( int x, int y, int width, int height );
virtual void getWindowRectangle( int& x, int& y, int& width, int& height );
virtual bool setWindowDecorationImplementation( bool windowDecoration );
virtual bool getWindowDecoration() const;
virtual void grabFocus();
virtual void grabFocusIfPointerInWindow();
virtual void raiseWindow();
virtual void setWindowName( const std::string& name );
virtual std::string getWindowName();
virtual void useCursor( bool cursorOn );
virtual void setCursor( MouseCursor cursor );
inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); }
virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); }
virtual bool valid() const;
virtual bool realizeImplementation();
virtual bool isRealizedImplementation() const;
virtual void closeImplementation();
virtual bool makeCurrentImplementation();
virtual bool releaseContextImplementation();
virtual void swapBuffersImplementation();
virtual void runOperations();
virtual void requestWarpPointer( float x, float y );
protected:
friend class GLWidget;
GLWidget* _widget;
bool _ownsWidget;
QCursor _currentCursor;
bool _realized;
};
}
#endif

View File

@ -0,0 +1,149 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#include "osgqt/QFontImplementation.h"
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgText/Font>
#include <QFont>
#include <QFontMetrics>
#include <QImage>
#include <QPainter>
#ifndef OSGTEXT_GLYPH_INTERNALFORMAT
#define OSGTEXT_GLYPH_INTERNALFORMAT GL_LUMINANCE_ALPHA
#endif
#ifndef OSGTEXT_GLYPH_FORMAT
#define OSGTEXT_GLYPH_FORMAT GL_LUMINANCE_ALPHA
#endif
namespace osgQt {
QFontImplementation::QFontImplementation(const QFont& font) :
_filename(font.toString().toStdString() + ".qfont"),
_font(font)
{
}
QFontImplementation::~QFontImplementation()
{
}
std::string
QFontImplementation::getFileName() const
{
return _filename;
}
osgText::Glyph*
QFontImplementation::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode)
{
unsigned int fontSize = fontRes.second;
_font.setPixelSize(fontSize);
float coord_scale = 1.0f/float(fontSize);
QFontMetrics fontMetrics(_font);
QFontMetricsF fontMetricsF(_font);
QRect rect = fontMetrics.boundingRect(QChar(charcode));
QRectF rectF = fontMetricsF.boundingRect(QChar(charcode));
int margin = 1;
int imageWidth = rect.width() + 2*margin;
int imageHeight = rect.height() + 2*margin;
// Now paint the glyph into the image
QImage image(imageWidth, imageHeight, QImage::Format_ARGB32);
image.fill(0);
QPainter painter(&image);
painter.setRenderHint(QPainter::TextAntialiasing);
painter.setFont(_font);
painter.setBackgroundMode(Qt::TransparentMode);
painter.setBrush(Qt::white);
painter.setPen(Qt::white);
painter.drawText(margin - rect.left(), imageHeight - 1 - (margin + rect.bottom()), QString(QChar(charcode)));
painter.end();
// Transfer the rendered image to osg
osg::ref_ptr<osgText::Glyph> glyph = new osgText::Glyph(_facade, charcode);
unsigned int dataSize = imageWidth*imageHeight;
unsigned char* data = new unsigned char[dataSize];
// copy the qimage into the texture memory
for (int x = 0; x < imageWidth; ++x)
{
for (int y = 0; y < imageHeight; ++y)
{
data[x + y*imageWidth] = qAlpha(image.pixel(x, imageHeight - 1 - y));
}
}
// the glyph texture in osg
glyph->setImage(imageWidth, imageHeight, 1,
OSGTEXT_GLYPH_INTERNALFORMAT,
OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE,
data,
osg::Image::USE_NEW_DELETE,
1);
glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT);
glyph->setWidth((float)imageWidth * coord_scale);
glyph->setHeight((float)imageHeight * coord_scale);
// Layout parameters
float leftBearing = fontMetricsF.leftBearing(QChar(charcode));
float rightBearing = fontMetricsF.rightBearing(QChar(charcode));
// for horizonal layout
osg::Vec2 bottomLeft(leftBearing - margin, - rectF.bottom() - margin);
glyph->setHorizontalBearing(bottomLeft * coord_scale);
glyph->setHorizontalAdvance(fontMetricsF.width(QChar(charcode)) * coord_scale);
// for vertical layout
osg::Vec2 topMiddle(- margin + 0.5*(leftBearing - rect.width() - rightBearing),
rectF.top() - margin);
glyph->setVerticalBearing(topMiddle * coord_scale);
glyph->setVerticalAdvance((rectF.height() + fontMetricsF.overlinePos() - fontMetricsF.xHeight()) * coord_scale);
// ... ready
//addGlyph(fontRes, charcode, glyph.get());
return glyph.release();
}
//osg::Vec2
//QFontImplementation::getKerning(const osgText::FontResolution& /*fontRes*/, unsigned int /*leftcharcode*/, unsigned int /*rightcharcode*/, osgText::KerningType /*kerningType*/)
//{
// return osg::Vec2(0, 0);
//}
osg::Vec2 QFontImplementation::getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType) {
return osg::Vec2(0, 0);
}
bool
QFontImplementation::hasVertical() const
{
return true;
}
}

View File

@ -0,0 +1,52 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#ifndef QFontImplementation_H
#define QFontImplementation_H
#include <osgText/Font>
#include <QtGui/QFont>
#include <string>
namespace osgQt {
class QFontImplementation : public osgText::Font::FontImplementation
{
public:
QFontImplementation(const QFont& font);
virtual ~QFontImplementation();
virtual std::string getFileName() const;
virtual bool supportsMultipleFontResolutions() const { return true; }
virtual osgText::Glyph* getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode);
//virtual osgText::Glyph3D* getGlyph3D(const osgText::FontResolution& /*fontRes*/, unsigned int /*charcode*/) { return 0; }
virtual osgText::Glyph3D* getGlyph3D(unsigned int charcode) { return 0; }
//virtual osg::Vec2 getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType);
virtual osg::Vec2 getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType);
virtual bool hasVertical() const;
protected:
std::string _filename;
QFont _font;
};
}
#endif

View File

@ -0,0 +1,613 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#include "osgqt/QGraphicsViewAdapter.h"
#include "osgqt/QWidgetImage.h"
#include <QtOpenGL/QGLWidget>
#include <osg/Version>
#include <osgGA/GUIEventAdapter>
#include <osg/NodeVisitor>
#include <osg/io_utils>
#include <QGraphicsItem>
#include <QGraphicsProxyWidget>
#define MYQKEYEVENT 2000
#define MYQPOINTEREVENT 2001
namespace osgQt
{
QCoreApplication* getOrCreateQApplication()
{
if (QApplication::instance()==0)
{
static char** argv = 0;
static int argc = 0;
static QApplication app(argc,argv);
}
return QApplication::instance();
}
class MyQKeyEvent : public QEvent
{
public:
MyQKeyEvent( int key, bool down ):
QEvent( QEvent::Type(MYQKEYEVENT) ),
_key(key), _down(down) {}
int _key;
bool _down;
};
struct MyQPointerEvent : public QEvent
{
MyQPointerEvent(int x, int y, unsigned int buttonMask):
QEvent( QEvent::Type(MYQPOINTEREVENT) ),
_x(x), _y(y),_buttonMask(buttonMask) {}
int _x, _y;
unsigned int _buttonMask;
};
const QImage::Format s_imageFormat = QImage::Format_ARGB32_Premultiplied;
QGraphicsViewAdapter::QGraphicsViewAdapter(osg::Image* image, QWidget* widget):
_image(image),
_backgroundWidget(0),
_previousButtonMask(0),
_previousMouseX(-1),
_previousMouseY(-1),
_previousQtMouseX(-1),
_previousQtMouseY(-1),
_previousSentEvent(false),
_requiresRendering(false),
_qtKeyModifiers(Qt::NoModifier),
_backgroundColor(255, 255, 255),
_widget(widget)
{
// make sure we have a valid QApplication before we start creating widgets.
getOrCreateQApplication();
setUpKeyMap();
_graphicsScene = new QGraphicsScene;
_graphicsScene->addWidget(widget);
_graphicsView = new QGraphicsView;
_graphicsView->setScene(_graphicsScene);
_graphicsView->viewport()->setParent(0);
#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION)
_graphicsScene->setStickyFocus(true);
#endif
_width = static_cast<int>(_graphicsScene->width());
_height = static_cast<int>(_graphicsScene->height());
_qimages[0] = QImage(QSize(_width, _height), s_imageFormat);
_qimages[1] = QImage(QSize(_width, _height), s_imageFormat);
_qimages[2] = QImage(QSize(_width, _height), s_imageFormat);
_currentRead = 0;
_currentWrite = 1;
_previousWrite = 2;
_previousFrameNumber = osg::UNINITIALIZED_FRAME_NUMBER;
_newImageAvailable = false;
connect(_graphicsScene, SIGNAL(changed(const QList<QRectF> &)),
this, SLOT(repaintRequestedSlot(const QList<QRectF> &)));
connect(_graphicsScene, SIGNAL(sceneRectChanged(const QRectF &)),
this, SLOT(repaintRequestedSlot(const QRectF &)));
assignImage(0);
}
void QGraphicsViewAdapter::repaintRequestedSlot(const QList<QRectF>&)
{
// OSG_NOTICE<<"QGraphicsViewAdapter::repaintRequestedSlot"<<std::endl;
_requiresRendering = true;
}
void QGraphicsViewAdapter::repaintRequestedSlot(const QRectF&)
{
// OSG_NOTICE<<"QGraphicsViewAdapter::repaintRequestedSlot"<<std::endl;
_requiresRendering = true;
}
void QGraphicsViewAdapter::customEvent ( QEvent * event )
{
if (event->type()==MYQKEYEVENT)
{
MyQKeyEvent* keyEvent = (MyQKeyEvent*)event;
handleKeyEvent(keyEvent->_key, keyEvent->_down);
}
else if (event->type()==MYQPOINTEREVENT)
{
MyQPointerEvent* pointerEvent = (MyQPointerEvent*)event;
handlePointerEvent(pointerEvent->_x, pointerEvent->_y, pointerEvent->_buttonMask);
}
}
void QGraphicsViewAdapter::setUpKeyMap()
{
_keyMap[osgGA::GUIEventAdapter::KEY_BackSpace] = Qt::Key_Backspace;
_keyMap[osgGA::GUIEventAdapter::KEY_Tab] = Qt::Key_Tab;
_keyMap[osgGA::GUIEventAdapter::KEY_Linefeed] = Qt::Key_Return; // No LineFeed in Qt!
_keyMap[osgGA::GUIEventAdapter::KEY_Clear] = Qt::Key_Clear;
_keyMap[osgGA::GUIEventAdapter::KEY_Return] = Qt::Key_Return;
_keyMap[osgGA::GUIEventAdapter::KEY_Pause] = Qt::Key_Pause;
_keyMap[osgGA::GUIEventAdapter::KEY_Scroll_Lock] = Qt::Key_ScrollLock;
_keyMap[osgGA::GUIEventAdapter::KEY_Sys_Req] = Qt::Key_SysReq;
_keyMap[osgGA::GUIEventAdapter::KEY_Escape] = Qt::Key_Escape;
_keyMap[osgGA::GUIEventAdapter::KEY_Delete] = Qt::Key_Delete;
_keyMap[osgGA::GUIEventAdapter::KEY_Home] = Qt::Key_Home;
_keyMap[osgGA::GUIEventAdapter::KEY_Left] = Qt::Key_Left;
_keyMap[osgGA::GUIEventAdapter::KEY_Up] = Qt::Key_Up;
_keyMap[osgGA::GUIEventAdapter::KEY_Right] = Qt::Key_Right;
_keyMap[osgGA::GUIEventAdapter::KEY_Down] = Qt::Key_Down;
_keyMap[osgGA::GUIEventAdapter::KEY_Prior] = Qt::Key_Left; // no Prior in Qt
_keyMap[osgGA::GUIEventAdapter::KEY_Page_Up] = Qt::Key_PageUp;
_keyMap[osgGA::GUIEventAdapter::KEY_Next] = Qt::Key_Right; // No Next in Qt
_keyMap[osgGA::GUIEventAdapter::KEY_Page_Down] = Qt::Key_PageDown;
_keyMap[osgGA::GUIEventAdapter::KEY_End] = Qt::Key_End;
_keyMap[osgGA::GUIEventAdapter::KEY_Begin] = Qt::Key_Home; // No Begin in Qt
_keyMap[osgGA::GUIEventAdapter::KEY_Select] = Qt::Key_Select;
_keyMap[osgGA::GUIEventAdapter::KEY_Print] = Qt::Key_Print;
_keyMap[osgGA::GUIEventAdapter::KEY_Execute] = Qt::Key_Execute;
_keyMap[osgGA::GUIEventAdapter::KEY_Insert] = Qt::Key_Insert;
//_keyMap[osgGA::GUIEventAdapter::KEY_Undo] = Qt::Key_; // no Undo
//_keyMap[osgGA::GUIEventAdapter::KEY_Redo] = Qt::Key_; // no Redo
_keyMap[osgGA::GUIEventAdapter::KEY_Menu] = Qt::Key_Menu;
_keyMap[osgGA::GUIEventAdapter::KEY_Find] = Qt::Key_Search; // no Qt Find
_keyMap[osgGA::GUIEventAdapter::KEY_Cancel] = Qt::Key_Cancel;
_keyMap[osgGA::GUIEventAdapter::KEY_Help] = Qt::Key_Help;
_keyMap[osgGA::GUIEventAdapter::KEY_Break] = Qt::Key_Escape; // no break
_keyMap[osgGA::GUIEventAdapter::KEY_Mode_switch] = Qt::Key_Mode_switch;
_keyMap[osgGA::GUIEventAdapter::KEY_Script_switch] = Qt::Key_Mode_switch; // no Script switch
_keyMap[osgGA::GUIEventAdapter::KEY_Num_Lock] = Qt::Key_NumLock;
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_L] = Qt::Key_Shift;
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_R] = Qt::Key_Shift;
_keyMap[osgGA::GUIEventAdapter::KEY_Control_L] = Qt::Key_Control;
_keyMap[osgGA::GUIEventAdapter::KEY_Control_R] = Qt::Key_Control;
_keyMap[osgGA::GUIEventAdapter::KEY_Caps_Lock] = Qt::Key_CapsLock;
_keyMap[osgGA::GUIEventAdapter::KEY_Shift_Lock] = Qt::Key_CapsLock;
_keyMap[osgGA::GUIEventAdapter::KEY_Meta_L] = Qt::Key_Meta; // Qt doesn't have a Meta L
_keyMap[osgGA::GUIEventAdapter::KEY_Meta_R] = Qt::Key_Meta; // Qt doesn't have a Meta R
_keyMap[osgGA::GUIEventAdapter::KEY_Alt_L] = Qt::Key_Alt; // Qt doesn't have a Alt L
_keyMap[osgGA::GUIEventAdapter::KEY_Alt_R] = Qt::Key_Alt; // Qt doesn't have a Alt R
_keyMap[osgGA::GUIEventAdapter::KEY_Super_L] = Qt::Key_Super_L;
_keyMap[osgGA::GUIEventAdapter::KEY_Super_R] = Qt::Key_Super_R;
_keyMap[osgGA::GUIEventAdapter::KEY_Hyper_L] = Qt::Key_Hyper_L;
_keyMap[osgGA::GUIEventAdapter::KEY_Hyper_R] = Qt::Key_Hyper_R;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Space] = Qt::Key_Space;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Tab] = Qt::Key_Tab;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Enter] = Qt::Key_Enter;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F1] = Qt::Key_F1;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F2] = Qt::Key_F2;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F3] = Qt::Key_F3;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_F4] = Qt::Key_F4;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Home] = Qt::Key_Home;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Left] = Qt::Key_Left;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Up] = Qt::Key_Up;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Right] = Qt::Key_Right;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Down] = Qt::Key_Down;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Prior] = Qt::Key_Left;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Up] = Qt::Key_PageUp;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Next] = Qt::Key_Right;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Down] = Qt::Key_PageDown;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_End] = Qt::Key_End;
// _keyMap[osgGA::GUIEventAdapter::KEY_KP_Begin] = Qt::Key_Begin;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Insert] = Qt::Key_Insert;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Delete] = Qt::Key_Delete;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Equal] = Qt::Key_Equal;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Multiply] = Qt::Key_Asterisk;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Add] = Qt::Key_Plus;
//_keyMap[osgGA::GUIEventAdapter::KEY_KP_Separator] = Qt::Key_;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Subtract] = Qt::Key_Minus;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Decimal] = Qt::Key_Period;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_Divide] = Qt::Key_division;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_0] = Qt::Key_0;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_1] = Qt::Key_1;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_2] = Qt::Key_2;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_3] = Qt::Key_3;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_4] = Qt::Key_4;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_5] = Qt::Key_5;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_6] = Qt::Key_6;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_7] = Qt::Key_7;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_8] = Qt::Key_8;
_keyMap[osgGA::GUIEventAdapter::KEY_KP_9] = Qt::Key_9;
_keyMap[osgGA::GUIEventAdapter::KEY_F1] = Qt::Key_F1;
_keyMap[osgGA::GUIEventAdapter::KEY_F2] = Qt::Key_F2;
_keyMap[osgGA::GUIEventAdapter::KEY_F3] = Qt::Key_F3;
_keyMap[osgGA::GUIEventAdapter::KEY_F4] = Qt::Key_F4;
_keyMap[osgGA::GUIEventAdapter::KEY_F5] = Qt::Key_F5;
_keyMap[osgGA::GUIEventAdapter::KEY_F6] = Qt::Key_F6;
_keyMap[osgGA::GUIEventAdapter::KEY_F7] = Qt::Key_F7;
_keyMap[osgGA::GUIEventAdapter::KEY_F8] = Qt::Key_F8;
_keyMap[osgGA::GUIEventAdapter::KEY_F9] = Qt::Key_F9;
_keyMap[osgGA::GUIEventAdapter::KEY_F10] = Qt::Key_F10;
_keyMap[osgGA::GUIEventAdapter::KEY_F11] = Qt::Key_F11;
_keyMap[osgGA::GUIEventAdapter::KEY_F12] = Qt::Key_F12;
_keyMap[osgGA::GUIEventAdapter::KEY_F13] = Qt::Key_F13;
_keyMap[osgGA::GUIEventAdapter::KEY_F14] = Qt::Key_F14;
_keyMap[osgGA::GUIEventAdapter::KEY_F15] = Qt::Key_F15;
_keyMap[osgGA::GUIEventAdapter::KEY_F16] = Qt::Key_F16;
_keyMap[osgGA::GUIEventAdapter::KEY_F17] = Qt::Key_F17;
_keyMap[osgGA::GUIEventAdapter::KEY_F18] = Qt::Key_F18;
_keyMap[osgGA::GUIEventAdapter::KEY_F19] = Qt::Key_F19;
_keyMap[osgGA::GUIEventAdapter::KEY_F20] = Qt::Key_F20;
_keyMap[osgGA::GUIEventAdapter::KEY_F21] = Qt::Key_F21;
_keyMap[osgGA::GUIEventAdapter::KEY_F22] = Qt::Key_F22;
_keyMap[osgGA::GUIEventAdapter::KEY_F23] = Qt::Key_F23;
_keyMap[osgGA::GUIEventAdapter::KEY_F24] = Qt::Key_F24;
_keyMap[osgGA::GUIEventAdapter::KEY_F25] = Qt::Key_F25;
_keyMap[osgGA::GUIEventAdapter::KEY_F26] = Qt::Key_F26;
_keyMap[osgGA::GUIEventAdapter::KEY_F27] = Qt::Key_F27;
_keyMap[osgGA::GUIEventAdapter::KEY_F28] = Qt::Key_F28;
_keyMap[osgGA::GUIEventAdapter::KEY_F29] = Qt::Key_F29;
_keyMap[osgGA::GUIEventAdapter::KEY_F30] = Qt::Key_F30;
_keyMap[osgGA::GUIEventAdapter::KEY_F31] = Qt::Key_F31;
_keyMap[osgGA::GUIEventAdapter::KEY_F32] = Qt::Key_F32;
_keyMap[osgGA::GUIEventAdapter::KEY_F33] = Qt::Key_F33;
_keyMap[osgGA::GUIEventAdapter::KEY_F34] = Qt::Key_F34;
_keyMap[osgGA::GUIEventAdapter::KEY_F35] = Qt::Key_F35;
}
QWidget* QGraphicsViewAdapter::getWidgetAt(const QPoint& pos)
{
QWidget* childAt = _graphicsView->childAt(pos);
if(childAt)
{
return childAt;
}
QGraphicsItem* item = _graphicsView->itemAt(pos);
if(item /*&& item->contains(item->mapFromScene(pos))*/)
{
QGraphicsProxyWidget* p = qgraphicsitem_cast<QGraphicsProxyWidget*>(item);
if(p)
{
childAt = p->widget();
QWidget* c;
while( (c = childAt->childAt(childAt->mapFromGlobal(pos)))!=0 )
{
childAt = c;
}
// Widgets like QTextEdit will automatically add child scroll area widgets
// that will be selected by childAt(), we have to change to parents at that moment
// Hardcoded by the internal widget's name 'qt_scrollarea_viewport' at present
if (childAt->objectName() == "qt_scrollarea_viewport")
{
childAt = childAt->parentWidget();
}
return childAt;
}
}
return NULL;
}
bool QGraphicsViewAdapter::sendPointerEvent(int x, int y, int buttonMask)
{
_previousQtMouseX = x;
_previousQtMouseY = _graphicsView->size().height() - y;
QPoint pos(_previousQtMouseX, _previousQtMouseY);
QWidget* targetWidget = getWidgetAt(pos);
OSG_INFO << "Get " << (targetWidget ? targetWidget->metaObject()->className() : std::string("NULL"))
<< " at global pos " << x << ", " << y << std::endl;
if (_backgroundWidget && _backgroundWidget == targetWidget)
{
// Mouse is at background widget, so ignore such events
return false;
}
if (targetWidget != NULL || (_previousSentEvent && buttonMask != 0))
{
QCoreApplication::postEvent(this, new MyQPointerEvent(x,y,buttonMask));
OSG_INFO<<"sendPointerEvent("<<x<<", "<<y<<") sent"<<std::endl;
_previousSentEvent = true;
return true;
}
OSG_INFO<<"sendPointerEvent("<<x<<", "<<y<<") not sent"<<std::endl;
_previousSentEvent = false;
return false;
}
bool QGraphicsViewAdapter::handlePointerEvent(int x, int y, int buttonMask)
{
OSG_INFO<<"dispatchPointerEvent("<<x<<", "<<y<<", "<<buttonMask<<")"<<std::endl;
y = _graphicsView->size().height()-y;
bool leftButtonPressed = (buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0;
bool middleButtonPressed = (buttonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0;
bool rightButtonPressed = (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0;
bool prev_leftButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0;
bool prev_middleButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0;
bool prev_rightButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0;
OSG_INFO<<"leftButtonPressed "<<leftButtonPressed<<std::endl;
OSG_INFO<<"middleButtonPressed "<<middleButtonPressed<<std::endl;
OSG_INFO<<"rightButtonPressed "<<rightButtonPressed<<std::endl;
Qt::MouseButtons qtMouseButtons =
(leftButtonPressed ? Qt::LeftButton : Qt::NoButton) |
(middleButtonPressed ? Qt::MidButton : Qt::NoButton) |
(rightButtonPressed ? Qt::RightButton : Qt::NoButton);
const QPoint globalPos(x, y);
QWidget* targetWidget = getWidgetAt(globalPos);
if (buttonMask != _previousButtonMask)
{
Qt::MouseButton qtButton = Qt::NoButton;
QEvent::Type eventType = QEvent::None;
if (leftButtonPressed != prev_leftButtonPressed)
{
qtButton = Qt::LeftButton;
eventType = leftButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
}
else if (middleButtonPressed != prev_middleButtonPressed)
{
qtButton = Qt::MidButton;
eventType = middleButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
}
else if (rightButtonPressed != prev_rightButtonPressed)
{
qtButton = Qt::RightButton;
eventType = rightButtonPressed ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease ;
if(!rightButtonPressed)
{
if(targetWidget)
{
QPoint localPos = targetWidget->mapFromGlobal(globalPos);
QContextMenuEvent* cme = new QContextMenuEvent(QContextMenuEvent::Mouse, localPos, globalPos);
QCoreApplication::postEvent(targetWidget, cme);
}
}
}
if (eventType==QEvent::MouseButtonPress)
{
_image->sendFocusHint(true);
if (targetWidget) targetWidget->setFocus(Qt::MouseFocusReason);
}
QMouseEvent event(eventType, globalPos, qtButton, qtMouseButtons, 0);
QCoreApplication::sendEvent(_graphicsView->viewport(), &event);
_previousButtonMask = buttonMask;
}
else if (x != _previousMouseX || y != _previousMouseY)
{
QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, qtMouseButtons, 0);
QCoreApplication::sendEvent(_graphicsView->viewport(), &event);
_previousMouseX = x;
_previousMouseY = y;
}
return true;
}
bool QGraphicsViewAdapter::sendKeyEvent(int key, bool keyDown)
{
QPoint pos(_previousQtMouseX, _previousQtMouseY);
QWidget* targetWidget = getWidgetAt(pos);
if (_backgroundWidget && _backgroundWidget == targetWidget)
{
// Mouse is at background widget, so ignore such events
return false;
}
if (targetWidget != NULL)
{
QCoreApplication::postEvent(this, new MyQKeyEvent(key,keyDown));
return true;
}
return false;
}
bool QGraphicsViewAdapter::handleKeyEvent(int key, bool keyDown)
{
QEvent::Type eventType = keyDown ? QEvent::KeyPress : QEvent::KeyRelease;
OSG_INFO<<"sendKeyEvent("<<key<<", "<<keyDown<<")"<<std::endl;
if (key==Qt::Key_Shift)
{
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ShiftModifier) | (keyDown ? Qt::ShiftModifier : Qt::NoModifier);
}
if (key==Qt::Key_Control)
{
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ControlModifier) | (keyDown ? Qt::ControlModifier : Qt::NoModifier);
}
if (key==Qt::Key_Alt || key==Qt::Key_AltGr)
{
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::ControlModifier) | (keyDown ? Qt::ControlModifier : Qt::NoModifier);
}
if (key==Qt::Key_Meta)
{
_qtKeyModifiers = (_qtKeyModifiers & ~Qt::MetaModifier) | (keyDown ? Qt::MetaModifier : Qt::NoModifier);
}
Qt::Key qtkey;
QChar input;
KeyMap::iterator itr = _keyMap.find(key);
if (itr != _keyMap.end())
{
qtkey = itr->second;
}
else
{
qtkey = (Qt::Key)key;
input = QChar(key);
}
QKeyEvent event(eventType, qtkey, _qtKeyModifiers, input);
QCoreApplication::sendEvent(_graphicsScene.data(), &event);
return true;
}
void QGraphicsViewAdapter::setFrameLastRendered(const osg::FrameStamp* frameStamp)
{
OSG_INFO<<"setFrameLastRendered("<<frameStamp->getFrameNumber()<<")"<<std::endl;
if (_newImageAvailable && _previousFrameNumber!=frameStamp->getFrameNumber())
{
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
// make sure that _previousFrameNumber hasn't been updated by another thread since we entered this branch.
if (_previousFrameNumber==frameStamp->getFrameNumber()) return;
_previousFrameNumber = frameStamp->getFrameNumber();
std::swap(_currentRead, _previousWrite);
_newImageAvailable = false;
}
assignImage(_currentRead);
}
}
void QGraphicsViewAdapter::clearWriteBuffer()
{
QImage& image = _qimages[_currentWrite];
image.fill(_backgroundColor.rgba ());
image = QGLWidget::convertToGLFormat(image);
// swap the write buffers in a thread safe way
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
std::swap(_currentWrite, _previousWrite);
_newImageAvailable = true;
}
void QGraphicsViewAdapter::render()
{
OSG_INFO<<"Current write = "<<_currentWrite<<std::endl;
QImage& image = _qimages[_currentWrite];
_requiresRendering = false;
// If we got a resize, act on it, first by resizing the view, then the current image
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qresizeMutex);
if (_graphicsView->size().width() != _width || _graphicsView->size().height() != _height)
{
_graphicsView->setGeometry(0, 0, _width, _height);
_graphicsView->viewport()->setGeometry(0, 0, _width, _height);
_widget->setGeometry(0, 0, _width, _height);
}
if (image.width() != _width || image.height() != _height)
{
_qimages[_currentWrite] = QImage(_width, _height, s_imageFormat);
image = _qimages[_currentWrite];
}
OSG_INFO << "render image " << _currentWrite << " with size (" << _width << "," << _height << ")" <<std::endl;
}
#if 1
// paint the image with the graphics view
QPainter painter(&image);
// Clear the image otherwise there are artifacts for some widgets that overpaint.
painter.setCompositionMode(QPainter::CompositionMode_Source);
painter.fillRect(0, 0, image.width(), image.height(), _backgroundColor);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
QRectF destinationRect(0, 0, image.width(), image.height());
QRect sourceRect(0, 0, image.width(), image.height());
_graphicsView->render(&painter, destinationRect, sourceRect, Qt::IgnoreAspectRatio);
painter.end();
#elif 0
QPixmap pixmap(QPixmap::grabWidget(_graphicsView.data(), QRect(0, 0, image.width(), image.height())));
image = pixmap.toImage();
#else
// paint the image with the graphics view
QPixmap pixmap(image.width(), image.height());
// Clear the image otherwise there are artifacts for some widgets that overpaint.
pixmap.fill(Qt::transparent);
QPainter painter(&pixmap);
QRectF destinationRect(0, 0, image.width(), image.height());
QRect sourceRect(0, 0, image.width(), image.height());
_graphicsView->render(&painter, destinationRect, _graphicsView->viewport()->rect());
painter.end();
image = pixmap.toImage();
#endif
// convert into OpenGL format - flipping around the Y axis and swizzling the pixels
image = QGLWidget::convertToGLFormat(image);
// swap the write buffers in a thread safe way
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qimagesMutex);
std::swap(_currentWrite, _previousWrite);
_newImageAvailable = true;
}
void QGraphicsViewAdapter::assignImage(unsigned int i)
{
QImage& image = _qimages[i];
unsigned char* data = image.bits();
OSG_INFO<<"assignImage("<<i<<") image = "<<&image<<" size = ("<<image.width()<<","<<image.height()<<") data = "<<(void*)data<<std::endl;
_image->setImage(image.width(), image.height(), 1,
4, GL_RGBA, GL_UNSIGNED_BYTE,
data, osg::Image::NO_DELETE, 1);
}
void QGraphicsViewAdapter::resize(int width, int height)
{
OSG_INFO << "resize to (" << width << "," << height << ")" <<std::endl;
// Save the new width and height which will take effect on the next render() (in the Qt thread).
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_qresizeMutex);
_width = width;
_height = height;
}
// Force an update so render() will be called.
_graphicsScene->update(_graphicsScene->sceneRect());
}
}

View File

@ -0,0 +1,122 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#ifndef QGRAPHICSVIEWADAPTER
#define QGRAPHICSVIEWADAPTER
#include <QGLWidget>
#include <osg/Image>
#include <osg/observer_ptr>
#include <QPointer>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QApplication>
#include <QPainter>
#include <QtEvents>
namespace osgQt
{
extern QCoreApplication* getOrCreateQApplication();
class QGraphicsViewAdapter : public QObject
{
Q_OBJECT
public:
QGraphicsViewAdapter(osg::Image* image, QWidget* widget);
void setUpKeyMap();
bool sendPointerEvent(int x, int y, int buttonMask);
bool sendKeyEvent(int key, bool keyDown);
void setFrameLastRendered(const osg::FrameStamp* frameStamp);
void clearWriteBuffer();
bool requiresRendering() const { return _requiresRendering; }
void render();
void assignImage(unsigned int i);
void resize(int width, int height);
void setBackgroundColor(QColor color) { _backgroundColor = color; }
QColor getBackgroundColor() const { return _backgroundColor; }
/** The 'background widget' will ignore mouse/keyboard events and let following handlers handle them
It is mainly used for integrating scene graph and full-screen UIs
*/
void setBackgroundWidget(QWidget* w) { _backgroundWidget = w; }
QWidget* getBackgroundWidget() { return _backgroundWidget; }
QGraphicsView* getQGraphicsView() { return _graphicsView; }
QGraphicsScene* getQGraphicsScene() { return _graphicsScene; }
protected:
bool handlePointerEvent(int x, int y, int buttonMask);
bool handleKeyEvent(int key, bool keyDown);
QWidget* getWidgetAt(const QPoint& pos);
osg::observer_ptr<osg::Image> _image;
QWidget* _backgroundWidget;
int _previousButtonMask;
int _previousMouseX;
int _previousMouseY;
int _previousQtMouseX;
int _previousQtMouseY;
bool _previousSentEvent;
bool _requiresRendering;
int _width;
int _height;
typedef std::map<int, Qt::Key> KeyMap;
KeyMap _keyMap;
Qt::KeyboardModifiers _qtKeyModifiers;
QColor _backgroundColor;
QPointer<QGraphicsView> _graphicsView;
QPointer<QGraphicsScene> _graphicsScene;
QPointer<QWidget> _widget;
OpenThreads::Mutex _qimagesMutex;
OpenThreads::Mutex _qresizeMutex;
unsigned int _previousFrameNumber;
bool _newImageAvailable;
unsigned int _currentRead;
unsigned int _currentWrite;
unsigned int _previousWrite;
QImage _qimages[3];
virtual void customEvent ( QEvent * event ) ;
private slots:
void repaintRequestedSlot(const QList<QRectF> &regions);
void repaintRequestedSlot(const QRectF &region);
};
}
#endif

108
src/osgqt/QWebViewImage.h Normal file
View File

@ -0,0 +1,108 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#ifndef QWEBVIEWIMAGE
#define QWEBVIEWIMAGE
// make sure this header isn't built as par of osgQt, leaving it to applications to build
#if !defined(OSGQT_LIBRARY) && !defined(OSG_LIBRARY_STATIC)
#if QT_VERSION >= 0x050000
# include <QtWebKitWidgets>
#else
# include <QtWebKit>
#endif
#include <osgWidget/Browser>
#include "osgqt/QGraphicsViewAdapter.h"
namespace osgQt
{
class QWebViewImage : public osgWidget::BrowserImage
{
public:
QWebViewImage()
{
// make sure we have a valid QApplication before we start creating widgets.
getOrCreateQApplication();
_webView = new QWebView;
_webPage = new QWebPage;
_webPage->settings()->setAttribute(QWebSettings::JavascriptEnabled, true);
_webPage->settings()->setAttribute(QWebSettings::PluginsEnabled, true);
_webView->setPage(_webPage);
_adapter = new QGraphicsViewAdapter(this, _webView.data());
}
virtual void navigateTo(const std::string& url)
{
_webView->load(QUrl(url.c_str()));
}
QWebView* getQWebView() { return _webView; }
QWebPage* getQWebPage() { return _webPage; }
QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; }
void clearWriteBuffer()
{
_adapter->clearWriteBuffer();
}
void render()
{
if (_adapter->requiresRendering()) _adapter->render();
}
virtual bool requiresUpdateCall() const { return true; }
virtual void update( osg::NodeVisitor* nv ) { render(); }
virtual bool sendFocusHint(bool focus)
{
QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason);
QCoreApplication::sendEvent(_webPage, &event);
return true;
}
virtual bool sendPointerEvent(int x, int y, int buttonMask)
{
return _adapter->sendPointerEvent(x,y,buttonMask);
}
virtual bool sendKeyEvent(int key, bool keyDown)
{
return QWebViewImage::_adapter->sendKeyEvent(key, keyDown);
}
virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp)
{
_adapter->setFrameLastRendered(frameStamp);
}
protected:
QPointer<QGraphicsViewAdapter> _adapter;
QPointer<QWebView> _webView;
QPointer<QWebPage> _webPage;
};
}
#endif
#endif

View File

@ -0,0 +1,66 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#include "osgqt/QWidgetImage.h"
#include <QLayout>
namespace osgQt
{
QWidgetImage::QWidgetImage( QWidget* widget )
{
// make sure we have a valid QApplication before we start creating widgets.
getOrCreateQApplication();
_widget = widget;
_adapter = new QGraphicsViewAdapter(this, _widget.data());
}
bool QWidgetImage::sendFocusHint(bool focus)
{
QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason);
QCoreApplication::sendEvent(_widget, &event);
return true;
}
void QWidgetImage::clearWriteBuffer()
{
_adapter->clearWriteBuffer();
}
void QWidgetImage::render()
{
if (_adapter->requiresRendering()) _adapter->render();
}
void QWidgetImage::scaleImage(int s,int t,int /*r*/, GLenum /*newDataType*/)
{
_adapter->resize(s, t);
}
void QWidgetImage::setFrameLastRendered(const osg::FrameStamp* frameStamp)
{
_adapter->setFrameLastRendered(frameStamp);
}
bool QWidgetImage::sendPointerEvent(int x, int y, int buttonMask)
{
return _adapter->sendPointerEvent(x,y,buttonMask);
}
bool QWidgetImage::sendKeyEvent(int key, bool keyDown)
{
return _adapter->sendKeyEvent(key, keyDown);
}
}

60
src/osgqt/QWidgetImage.h Normal file
View File

@ -0,0 +1,60 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#ifndef QWIDGETIMAGE
#define QWIDGETIMAGE
#include <osg/Image>
#include "osgQt/QGraphicsViewAdapter.h"
namespace osgQt
{
class QWidgetImage : public osg::Image
{
public:
QWidgetImage( QWidget* widget=0 );
QWidget* getQWidget() { return _widget; }
QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; }
virtual bool requiresUpdateCall() const { return true; }
virtual void update( osg::NodeVisitor* /*nv*/ ) { render(); }
void clearWriteBuffer();
void render();
/// Overridden scaleImage used to catch cases where the image is
/// fullscreen and the window is resized.
virtual void scaleImage(int s,int t,int r, GLenum newDataType);
virtual bool sendFocusHint(bool focus);
virtual bool sendPointerEvent(int x, int y, int buttonMask);
virtual bool sendKeyEvent(int key, bool keyDown);
virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp);
protected:
QPointer<QGraphicsViewAdapter> _adapter;
QPointer<QWidget> _widget;
};
}
#endif

66
src/osgqt/ReaderQFont.cpp Normal file
View File

@ -0,0 +1,66 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library 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
* OpenSceneGraph Public License for more details.
*/
#include "osgqt/QFontImplementation.h"
#include <osgDB/FileNameUtils>
#include <osgDB/Registry>
#include <osgText/Font>
#include <QtCore/QThread>
#include <QApplication>
#include <QtGui/QFont>
#include <QtGui/QFontDatabase>
namespace osgQFont {
class ReaderQFont : public osgDB::ReaderWriter
{
public:
ReaderQFont()
{
supportsExtension("qfont", "Qt font meta loader");
}
virtual const char* className() const { return "QFont Font Reader"; }
virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* /*options*/) const
{
if (!acceptsExtension(osgDB::getLowerCaseFileExtension(file)))
return ReadResult::FILE_NOT_HANDLED;
if (!QApplication::instance())
{
OSG_WARN << "Trying to load qfont \"" << file << "\" from within a non qt application!" << std::endl;
return ReadResult::FILE_NOT_FOUND;
}
if (!QFontDatabase::supportsThreadedFontRendering() && QApplication::instance()->thread() != QThread::currentThread())
{
OSG_WARN << "Trying to load qfont \"" << file << "\" from a non gui thread "
"within qt application without threaded font rendering!" << std::endl;
return ReadResult::FILE_NOT_FOUND;
}
QFont font;
if (!font.fromString(QString::fromStdString(osgDB::getNameLessExtension(file))))
return ReadResult::FILE_NOT_FOUND;
return new osgText::Font(new osgQt::QFontImplementation(font));
}
};
// now register with Registry to instantiate the above
// reader/writer.
REGISTER_OSGPLUGIN(qfont, ReaderQFont)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

View File

@ -6,178 +6,85 @@
#include <osg/Program> #include <osg/Program>
#include <osg/LightSource> #include <osg/LightSource>
#include <osgDB/ReadFile> #include <osgDB/ReadFile>
#include <osgEarth/GLUtils> #include <osgEarthUtil/EarthManipulator>
#include <osgEarth/EarthManipulator> #include <osgGA/StateSetManipulator>
#include <osgShadow/ShadowedScene> #include <osgShadow/ShadowedScene>
#include <osgShadow/ViewDependentShadowMap> #include <osgShadow/ViewDependentShadowMap>
#include <osgViewer/ViewerEventHandlers> #include <osgViewer/ViewerEventHandlers>
#include "config.h" #include "config.h"
#include "app/Application.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "scene/ScopedTimer.h" #include "scene/ScopedTimer.h"
#include "viewer/OsgView.h" #include "viewer/OsgView.h"
#include "viewer/OsgCameraManipulator.h" #include "viewer/OsgCameraManipulator.h"
#include "scene/ScaleBarHandler.h" #include "scene/ScaleBarHandler.h"
#include "utils/FileUtils.h"
#include "effects/ConeWave.h"
const osgEarth::SpatialReference* g_srs_{ nullptr }; const osgEarth::SpatialReference* g_srs_{ nullptr };
OEScene::OEScene() { OEScene::OEScene() {
osgDB::FilePathList& pathList = osgDB::Registry::instance()->getDataFilePathList(); osgDB::FilePathList& pathList = osgDB::Registry::instance()->getDataFilePathList();
const std::string& basePath = RecourceHelper::Get().GetBasePath().toStdString(); const std::string& basePath = RecourceHelper::Get().GetBasePath().toStdString();
pathList.push_back(basePath + "/resources/earth/"); pathList.push_back(basePath + "/resources/earth/");
pathList.push_back(basePath + "/resources/textures/"); pathList.push_back(basePath + "/resources/textures/");
root_ = new osg::Group;
Init();
} }
void OEScene::AttachView(osgViewer::View* view) {
void OEScene::InitEventHandle(class OsgView* view) {
if (nullptr == view) {
LOG_WARN("view is nullptr");
return;
}
//view->GetView()->addEventHandler(new osgEarth::Util::EarthManipulator());
view->GetView()->addEventHandler(new osgViewer::HelpHandler);
view->GetView()->addEventHandler(new osgViewer::StatsHandler);
}
void OEScene::AttachView(OsgView* view) {
if (nullptr == view) {
LOG_WARN("view is nullptr");
return;
}
osg::Node* rootNode = view->GetView()->getSceneData();
if (nullptr != rootNode) {
int parantCount = rootNode->getNumParents();
for (int i = 0; i < parantCount; ++i) {
rootNode->getParent(i)->removeChild(rootNode);
}
root_->addChild(rootNode);
}
view->GetView()->setSceneData(root_);
earthRootNode_ = osgDB::readNodeFile("triton.earth");
dyt_check(nullptr != earthRootNode_); dyt_check(nullptr != earthRootNode_);
logarithmicDepthBuffer_ = std::make_unique<osgEarth::Util::LogarithmicDepthBuffer>(); skyDome_ = osgEarth::Util::SkyNode::create(earthMapNode_);
earthMapNode_ = osgEarth::MapNode::get(earthRootNode_);
dyt_check(nullptr != earthMapNode_);
LOG_INFO("earth map node get success: {}", earthMapNode_.valid());
g_srs_ = earthMapNode_->getMapSRS();
entityRoot_ = new osg::Group;
root_->addChild(entityRoot_);
skyDome_ = osgEarth::SkyNode::create();
if (!earthMapNode_) { if (!earthMapNode_) {
LOG_WARN("eart map node is nullptr"); LOG_WARN("eart map node is nullptr");
return; return;
} }
root_->addChild(skyDome_);
skyDome_->addChild(earthMapNode_);
skyDome_->attach(view->GetView());
skyDome_->setAtmosphereVisible(true); dyt_check(nullptr != earthManipulator_);
skyDome_->setSunVisible(true); view->setCameraManipulator(earthManipulator_);
skyDome_->setMoonVisible(true); skyDome_->attach(view);
skyDome_->setStarsVisible(true); skyDome_->getSunLight()->setAmbient(osg::Vec4(0.5,0.5,0.5,1.0));
addChild(skyDome_);
skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3)); skyDome_->setDateTime(osgEarth::DateTime(2024, 12, 24, 3));
skyDome_->setSimulationTimeTracksDateTime(true);
logarithmicDepthBuffer_->install(view->GetView()->getCamera()); view->setSceneData(this);
curentView_ = view;
ConeWave* coneWave = new ConeWave;
osgEarth::GeoTransform *geo = new osgEarth::GeoTransform;
entityRoot_->addChild(geo);
osgEarth::GeoPoint pos(g_srs_, 120.000000,25.000000,600.000000);
geo->setPosition(pos);
coneWave->createWaveBeamCone(geo, 45, 6000, osg::Vec4(1.0, 0.0, 0.0, 0.3),
osg::Vec4(1.0, 1.0, 0.0, 0.3), 30);
osg::MatrixTransform* mt =coneWave->getWaveBeamCone();
geo->addChild(mt);
} }
void OEScene::DetachView(OsgView* view) { void OEScene::DetachView(osgViewer::View* view) {
if (nullptr != earthRootNode_) { view->setSceneData(nullptr);
std::vector<osg::Group*> parents = earthRootNode_->getParents();
for (const auto& parent : parents) {
parent->removeChild(earthRootNode_);
}
}
logarithmicDepthBuffer_->uninstall(view->GetView()->getCamera());
view->GetView()->setSceneData(nullptr);
} }
#define USE_CUSTOM_SHADER bool OEScene::AddToScene(osg::Node* node) const {
osg::ref_ptr<osg::TextureCubeMap> OEScene::LoadCubeMapTextures(const std::string& dir) {
enum {
POS_X, NEG_X, POS_Y, NEG_Y, POS_Z, NEG_Z
};
std::string filenames[6];
std::string basePath = RecourceHelper::Get().GetBasePath().toStdString();
filenames[POS_X] = basePath + "/resources/textures/" + dir + "/east.png";
filenames[NEG_X] = basePath + "/resources/textures/" + dir + "/west.png";
filenames[POS_Z] = basePath + "/resources/textures/" + dir + "/north.png";
filenames[NEG_Z] = basePath + "/resources/textures/" + dir + "/south.png";
filenames[POS_Y] = basePath + "/resources/textures/" + dir + "/down.png";
filenames[NEG_Y] = basePath + "/resources/textures/" + dir + "/up.png";
osg::ref_ptr<osg::TextureCubeMap> cubeMap = new osg::TextureCubeMap;
cubeMap->setInternalFormat(GL_RGBA);
cubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
cubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
cubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
cubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_X, osgDB::readImageFile(filenames[NEG_X]));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_X, osgDB::readImageFile(filenames[POS_X]));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Y, osgDB::readImageFile(filenames[NEG_Y]));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Y, osgDB::readImageFile(filenames[POS_Y]));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Z, osgDB::readImageFile(filenames[NEG_Z]));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Z, osgDB::readImageFile(filenames[POS_Z]));
return cubeMap;
}
osg::Group* OEScene::GetData() {
return root_;
}
void OEScene::AddToScene(osg::Node* node) {
dyt_check(nullptr != entityRoot_); dyt_check(nullptr != entityRoot_);
entityRoot_->addChild(node); return entityRoot_->addChild(node);
/* osgOcean::OceanScene* oceanScene = GetOceanScene(); }
if (nullptr == oceanScene) {
LOG_WARN("oceanScene is nullptr"); void OEScene::SetHomeViewpoint(const osgEarth::Viewpoint& viewpoint, double duration_s) {
dyt_check(nullptr != earthManipulator_);
earthManipulator_->setViewpoint(viewpoint, duration_s);
if (homeViewpointSet_) {
LOG_INFO("Home viewpoint already set, skipping...");
return; return;
} }
earthManipulator_->setHomeViewpoint(viewpoint, duration_s);
node->setNodeMask(oceanScene->getNormalSceneMask() | homeViewpointSet_ = true;
oceanScene->getReflectedSceneMask() | LOG_INFO("Home viewpoint set successfully");
oceanScene->getRefractedSceneMask() | }
CAST_SHADOW | RECEIVE_SHADOW);
oceanScene->addChild(node);*/ bool OEScene::TrackEntity(osg::Node* entity, bool track) const {
/* osg::Group* root = GetScene(); dyt_check(nullptr != earthManipulator_);
root->addChild(node);*/ if (track) {
earthManipulator_->setTetherNode(entity, 5.0);
} else {
earthManipulator_->clearViewpoint();
}
return true;
} }
OESceneUI* OEScene::GetOrCreateSceneUI() { OESceneUI* OEScene::GetOrCreateSceneUI() {
@ -189,3 +96,41 @@ OESceneUI* OEScene::GetOrCreateSceneUI() {
sceneUI_ = new OESceneUI(this); sceneUI_ = new OESceneUI(this);
return sceneUI_.get(); return sceneUI_.get();
} }
osg::Viewport* OEScene::GetViewport() const {
dyt_check(nullptr != curentView_);
return curentView_->getCamera()->getViewport();
}
const osgEarth::SpatialReference* OEScene::GetSrs() {
dyt_check(nullptr != g_srs_);
return g_srs_;
}
void OEScene::Init() {
QString earthFile = QString("%1/earth/triton.earth").arg(Application::GetBinPath());
if (!FileUtils::IsExist(earthFile)) {
LOG_ERROR("earth file not found: {}", earthFile.toStdString());
return;
}
std::string earthPath(earthFile.toLocal8Bit().constData());
LOG_INFO("Loading earth file from: {}", earthPath);
// earthRootNode_ = osgDB::readNodeFile("triton.earth");
earthRootNode_ = osgDB::readNodeFile(earthPath);
dyt_check(nullptr != earthRootNode_);
addChild(earthRootNode_);
earthMapNode_ = osgEarth::MapNode::get(earthRootNode_);
dyt_check(nullptr != earthMapNode_);
LOG_INFO("earth map node get success: {}", earthMapNode_.valid());
g_srs_ = earthMapNode_->getMapSRS();
earthManipulator_ = new osgEarth::Util::EarthManipulator();
earthManipulator_->getSettings()->setMinMaxPitch(-90.0, -10.0);
entityRoot_ = new osg::Group;
addChild(entityRoot_);
}

View File

@ -1,56 +1,53 @@
#pragma once #pragma once
#include <osg/Switch> #include <osgEarth/MapNode>
#include <osg/TextureCubeMap> #include <osgEarthUtil/Sky>
#include <osgEarth/Viewpoint>
#include <osgText/Text>
#include <osgEarth/ModelNode>
#include <osgEarth/Sky>
#include <osgEarth/LogarithmicDepthBuffer>
//#include "scene/SkyDome.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "config.h" #include "config.h"
#include "scene/ui/OESceneUI.h" #include "scene/ui/OESceneUI.h"
class OsgView; namespace osgEarth {
namespace Util {
class EarthManipulator;
}
}
class OEScene : public osg::Referenced { class OEScene : public osg::Group {
public: public:
OEScene(); OEScene();
void InitEventHandle(OsgView* view); void AttachView(osgViewer::View* view);
void AttachView(OsgView* view); void DetachView(osgViewer::View* view);
void DetachView(OsgView* view);
osg::ref_ptr<osg::TextureCubeMap> LoadCubeMapTextures(const std::string& dir); bool AddToScene(osg::Node* node) const;
void SetHomeViewpoint(const osgEarth::Viewpoint& viewpoint, double duration_s);
inline osg::Vec4f IntColor(unsigned r, unsigned g, unsigned b, unsigned a = 255) { bool TrackEntity(osg::Node* entity, bool track) const;
float div = 1.f / 255.f;
return osg::Vec4f(div * (float)r, div * (float)g, div * float(b), div * (float)a);
}
osg::Group* GetData();
inline osg::Group* GetScene(void) {
return root_.get();
}
osgEarth::MapNode* GetMapNode(void) const { osgEarth::MapNode* GetMapNode(void) const {
dyt_check(earthMapNode_.valid()); dyt_check(earthMapNode_.valid());
return earthMapNode_; return earthMapNode_;
} }
void AddToScene(osg::Node* node);
OESceneUI* GetOrCreateSceneUI(); OESceneUI* GetOrCreateSceneUI();
osgEarth::Util::EarthManipulator* GetManipulater() const {
return earthManipulator_.get();
}
osg::Viewport* GetViewport() const;
static const osgEarth::SpatialReference* GetSrs();
private:
void Init();
private: private:
osg::ref_ptr<osg::Group> root_;
osg::ref_ptr<osg::Node> earthRootNode_; osg::ref_ptr<osg::Node> earthRootNode_;
osg::ref_ptr<osgEarth::Util::EarthManipulator> earthManipulator_;
osg::ref_ptr<osgEarth::MapNode> earthMapNode_; osg::ref_ptr<osgEarth::MapNode> earthMapNode_;
osg::ref_ptr<osg::Group> entityRoot_; osg::ref_ptr<osg::Group> entityRoot_;
osg::ref_ptr<osgEarth::SkyNode> skyDome_; osg::ref_ptr<osgEarth::Util::SkyNode> skyDome_;
std::unique_ptr<osgEarth::Util::LogarithmicDepthBuffer> logarithmicDepthBuffer_;
osg::ref_ptr<OESceneUI> sceneUI_; osg::ref_ptr<OESceneUI> sceneUI_;
osgViewer::View* curentView_ {nullptr};
bool homeViewpointSet_ {false}; // 跟踪home viewpoint是否已经设置
}; };

View File

@ -1,114 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonAPIWrapper.h"
#include <Triton.h>
#define LC "[TritonAPI] "
using namespace osgEarth::Triton;
#define SETGET_EXPLICIT(NS, SETTER, GETTER, TYPE) \
void NS :: SETTER (TYPE value) { HANDLE-> SETTER (value); } \
TYPE NS :: GETTER () const { return HANDLE -> GETTER (); }
#define SETGET(NS, FUNC, TYPE) \
SETGET_EXPLICIT(NS, Set##FUNC, Get##FUNC, TYPE)
#define TOVEC3(X) ::Triton::Vector3(X.x(),X.y(),X.z())
#define FROMVEC3(X) osg::Vec3(X.x,X.y,X.z)
//................................
#undef HANDLE
#define HANDLE ((::Triton::BreakingWavesParameters*)_handle)
SETGET(BreakingWavesParameters, Steepness, float);
SETGET(BreakingWavesParameters, Wavelength, float);
//................................
#undef HANDLE
#define HANDLE ((::Triton::Environment*)_handle)
BreakingWavesParameters Environment::GetBreakingWavesParameters() const {
return BreakingWavesParameters((uintptr_t)&HANDLE->GetBreakingWavesParameters());
}
void Environment::SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color) {
HANDLE->SetDirectionalLight(TOVEC3(dir), TOVEC3(color));
}
osg::Vec3 Environment::GetLightDirection() const {
const ::Triton::Vector3& v = HANDLE->GetLightDirection();
return FROMVEC3(v);
}
osg::Vec3 Environment::GetDirectionalLightColor() const {
const ::Triton::Vector3& v = HANDLE->GetDirectionalLightColor();
return FROMVEC3(v);
}
void Environment::SetAmbientLight(const osg::Vec3& color) {
HANDLE->SetAmbientLight(TOVEC3(color));
}
osg::Vec3 Environment::GetAmbientLightColor() const {
const ::Triton::Vector3& v = HANDLE->GetAmbientLightColor();
return FROMVEC3(v);
}
void Environment::SimulateSeaState(double bscale, double winddir) {
HANDLE->SimulateSeaState(bscale, winddir);
}
void Environment::SetAboveWaterVisibility(double visibility, osg::Vec3 fog_color) {
HANDLE->SetAboveWaterVisibility(visibility, TOVEC3(fog_color));
}
void Environment::GetAboveWaterVisibility(double &visibility, osg::Vec3 &fog_color) const {
::Triton::Vector3 triton_fog_col;
HANDLE->GetAboveWaterVisibility(visibility, triton_fog_col);
fog_color = FROMVEC3(triton_fog_col);
}
void Environment::SetEnvironmentMap(GLuint cubeMap, const osg::Matrixd &textureMatrix) {
::Triton::Matrix3 triton_tex_mat(
textureMatrix(0, 0), textureMatrix(0, 1), textureMatrix(0, 2),
textureMatrix(1, 0), textureMatrix(1, 1), textureMatrix(1, 2),
textureMatrix(2, 0), textureMatrix(2, 1), textureMatrix(2, 2));
::Triton::TextureHandle tex_handle = (::Triton::TextureHandle)(static_cast<size_t>(cubeMap));
HANDLE->SetEnvironmentMap(tex_handle, triton_tex_mat);
}
GLuint Environment::GetEnvironmentMap() const {
::Triton::TextureHandle tex_handle = HANDLE->GetEnvironmentMap();
return static_cast<GLuint>((size_t)tex_handle);
}
osg::Matrixd Environment::GetEnvironmentMapMatrix() const {
::Triton::Matrix3 m = HANDLE->GetEnvironmentMapMatrix();
osg::Matrixd env_map_matrix(
m.elem[0][0], m.elem[0][1], m.elem[0][2], 0,
m.elem[1][0], m.elem[1][1], m.elem[1][2], 0,
m.elem[2][0], m.elem[2][1], m.elem[2][2], 0,
0, 0, 0, 1);
return env_map_matrix;
}
SETGET(Environment, SunIntensity, float);
//................................
#undef HANDLE
#define HANDLE ((::Triton::Ocean*)_handle)
SETGET(Ocean, Choppiness, float);
//SETGET(Ocean, MaximumWavePeriod, double);
SETGET_EXPLICIT(Ocean, EnableSpray, SprayEnabled, bool);
SETGET_EXPLICIT(Ocean, EnableGodRays, GodRaysEnabled, bool);
SETGET(Ocean, GodRaysFade, float);
void Ocean::EnableWireframe(bool wireframe) { HANDLE->EnableWireframe(wireframe); }
void Ocean::SetQuality(OceanQuality value) { HANDLE->SetQuality((::Triton::OceanQuality)value); }
OceanQuality Ocean::GetQuality() const { return (OceanQuality)HANDLE->GetQuality(); }

View File

@ -1,112 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_API_WRAPPER
#define OSGEARTH_TRITON_API_WRAPPER 1
//#include "Common"
#include <osg/Vec3>
#include <osg/Matrix>
#include <osg/GL>
#include <stdint.h> // for uintptr_t
namespace osgEarth {
namespace Util {
class OceanNode;
}
}
namespace osgEarth { namespace Triton
{
/** Enumerates the ocean quality settings used in Ocean::SetQuality() */
enum OceanQuality {
GOOD,
BETTER,
BEST
};
class BreakingWavesParameters
{
public:
void SetSteepness(float);
float GetSteepness() const;
void SetWavelength(float);
float GetWavelength() const;
public:
BreakingWavesParameters(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
class Environment
{
public:
void SetDirectionalLight(const osg::Vec3& dir, const osg::Vec3& color);
osg::Vec3 GetLightDirection() const;
osg::Vec3 GetDirectionalLightColor() const;
void SetAmbientLight(const osg::Vec3& color);
osg::Vec3 GetAmbientLightColor() const;
void SetSunIntensity(float intensity);
float GetSunIntensity() const;
BreakingWavesParameters GetBreakingWavesParameters() const;
void SimulateSeaState(double bs, double winddir);
void SetAboveWaterVisibility(double visibility, osg::Vec3 fog_color);
void GetAboveWaterVisibility(double &visibility, osg::Vec3 &fog_color) const;
void SetEnvironmentMap(GLuint id, const osg::Matrixd &textureMatrix = osg::Matrixd());
GLuint GetEnvironmentMap() const;
osg::Matrixd GetEnvironmentMapMatrix() const;
public:
Environment(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
class Ocean
{
public:
void SetChoppiness(float);
float GetChoppiness() const;
void EnableWireframe(bool wireframe);
void SetQuality(OceanQuality value);
OceanQuality GetQuality() const;
void EnableSpray(bool enabled);
bool SprayEnabled() const;
void EnableGodRays(bool enabled);
bool GodRaysEnabled() const;
void SetGodRaysFade(float fadeAmount);
float GetGodRaysFade() const;
public:
Ocean(uintptr_t handle) : _handle(handle) { }
uintptr_t _handle;
};
} } // namespace osgEarth::SilverLining
#endif // OSGEARTH_TRITON_API_WRAPPER

View File

@ -1,39 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_CALLBACK_H
#define OSGEARTH_TRITON_CALLBACK_H 1
#include "TritonAPIWrapper.h"
namespace osgEarth { namespace Triton
{
/**
* A callback that lets you execute code in the proper context.
*/
class Callback : public osg::Referenced
{
public:
virtual void onInitialize(Environment& env, Ocean& ocean) { }
virtual void onDrawOcean(Environment& env, Ocean& ocean) { }
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_CALLBACK_H

View File

@ -1,229 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonContext.h"
#include <osg/GLExtensions>
#include <osg/Math>
#include <osgDB/FileNameUtils>
#include <osgEarth/SpatialReference>
#include <cstdlib>
#include <QApplication>
#define LC "[TritonContext] "
using namespace osgEarth::Triton;
TritonContext::TritonContext(const TritonLayer::Options& options) :
_options ( options ),
_initAttempted ( false ),
_initFailed ( false ),
_resourceLoader ( 0L ),
_environment ( 0L ),
_environmentWrapper ( 0L ),
_ocean ( 0L ),
_oceanWrapper ( 0L )
{
//nop
}
TritonContext::~TritonContext()
{
if (_oceanWrapper)
delete _oceanWrapper;
if (_environmentWrapper)
delete _environmentWrapper;
}
void
TritonContext::setSRS(const osgEarth::SpatialReference* srs)
{
_srs = srs;
}
void
TritonContext::setCallback(Callback* callback)
{
_callback = callback;
}
bool
TritonContext::passHeightMapToTriton() const
{
return _options.useHeightMap() == true;
}
int
TritonContext::getHeightMapSize() const
{
return osg::clampBetween(_options.heightMapSize().get(), 64u, 2048u);
}
const std::string&
TritonContext::getMaskLayerName() const
{
return _options.maskLayer().externalLayerName().get();
}
void
TritonContext::initialize(osg::RenderInfo& renderInfo)
{
if ( !_initAttempted && !_initFailed )
{
// lock/double-check:
std::lock_guard<std::mutex> excl(_initMutex);
if ( !_initAttempted && !_initFailed )
{
_initAttempted = true;
std::string resourcePath = _options.resourcePath().get();
if (resourcePath.empty() && ::getenv("TRITON_PATH"))
{
resourcePath = osgDB::concatPaths(::getenv("TRITON_PATH"), "Resources");
}
if ( resourcePath.empty() )
{
const QString dir = QString("%1/TritonResources").arg(QApplication::applicationDirPath());
resourcePath = dir.toStdString();
}
_resourceLoader = new ::Triton::ResourceLoader(resourcePath.c_str());
_environment = new ::Triton::Environment();
_environmentWrapper = new Environment((uintptr_t)_environment);
_environment->SetLicenseCode(
_options.user()->c_str(),
_options.licenseCode()->c_str() );
// "WGS84" is used to represent any ellipsoid.
::Triton::CoordinateSystem cs =
_srs->isGeographic() ? ::Triton::WGS84_ZUP :
::Triton::FLAT_ZUP;
// Set the ellipsoid to match the one in our map's SRS.
if ( _srs->isGeographic() )
{
const Ellipsoid& ellipsoid = _srs->getEllipsoid();
std::string eqRadius = Stringify() << ellipsoid.getRadiusEquator();
std::string poRadius = Stringify() << ellipsoid.getRadiusPolar();
_environment->SetConfigOption( "equatorial-earth-radius-meters", eqRadius.c_str() );
_environment->SetConfigOption( "polar-earth-radius-meters", poRadius.c_str() );
}
//_environment->SetConfigOption("avoid-opengl-stalls", "yes");
//_environment->SetConfigOption("fft-texture-update-frame-delayed", "yes");
float openGLVersion = osg::getGLVersionNumber();
enum ::Triton::Renderer tritonOpenGlVersion = ::Triton::OPENGL_2_0;
#ifndef OSG_GL_FIXED_FUNCTION_AVAILABLE
if( openGLVersion >= 4.1 )
tritonOpenGlVersion = ::Triton::OPENGL_4_1;
else if( openGLVersion >= 4.0 )
tritonOpenGlVersion = ::Triton::OPENGL_4_0;
else if( openGLVersion >= 3.2 )
tritonOpenGlVersion = ::Triton::OPENGL_3_2;
#endif
::Triton::EnvironmentError err = _environment->Initialize(
cs,
tritonOpenGlVersion,
_resourceLoader );
if ( err == ::Triton::SUCCEEDED )
{
::Triton::WindFetch wf;
wf.SetWind( 10.0, 0.0 );
_environment->AddWindFetch( wf );
_ocean = ::Triton::Ocean::Create(
_environment,
::Triton::JONSWAP,
true ); // enableHeightTests - activated GetHeight for intersections
}
if ( _ocean )
{
_oceanWrapper = new Ocean((uintptr_t)_ocean);
// fire init callback if available
if (_callback.valid())
{
_callback->onInitialize(getEnvironmentWrapper(), getOceanWrapper());
}
OE_INFO << LC << "Triton initialized OK!" << std::endl;
}
else
{
_initFailed = true;
OE_WARN << LC << "Triton initialization failed- err=" << err << std::endl;
}
}
}
}
bool
TritonContext::intersect(const osg::Vec3d& start, const osg::Vec3d& dir, float& out_height, osg::Vec3f& out_normal) const
{
::Triton::Vector3 p(start.ptr());
::Triton::Vector3 d(dir.ptr());
::Triton::Vector3 normal;
bool ok = _ocean->GetHeight(p, d, out_height, normal);
out_normal.set(normal.x, normal.y, normal.z);
return ok;
}
void
TritonContext::resizeGLObjectBuffers(unsigned maxSize)
{
osg::Object::resizeGLObjectBuffers(maxSize);
}
void
TritonContext::releaseGLObjects(osg::State* state) const
{
osg::Object::releaseGLObjects(state);
OE_DEBUG << LC << "Triton shutting down - releasing GL resources\n";
if (state)
{
if ( _ocean )
{
delete _ocean;
_ocean = 0L;
}
if ( _environment )
{
delete _environment;
_environment = 0L;
}
if ( _resourceLoader )
{
delete _resourceLoader;
_resourceLoader = 0L;
}
}
}

View File

@ -1,115 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_CONTEXT_H
#define OSGEARTH_TRITON_CONTEXT_H
#include <Triton.h>
#include <Camera.h> // Triton
#include "TritonLayer.h"
#include "TritonAPIWrapper.h"
#include "TritonCallback.h"
#include <osg/Referenced>
#include <osg/Light>
#include <osgEarth/Threading>
namespace osgEarth {
class SpatialReference;
}
namespace osgEarth { namespace Triton
{
/**
* Contains all the Triton SDK handles.
*/
class TritonContext : public osg::Object
{
public:
META_Object(osgEarth, TritonContext);
TritonContext(const TritonLayer::Options&);
/** Sets the spatial reference system of the map */
void setSRS(const osgEarth::SpatialReference* srs);
/** Sets the user callback */
void setCallback(Callback* callback);
Callback* getCallback() const { return _callback.get(); }
public: // accessors
bool ready() const { return _initAttempted && !_initFailed; }
/** Spatial reference of the map */
const osgEarth::SpatialReference* getSRS() const { return _srs.get(); }
void initialize(osg::RenderInfo& renderInfo);
bool intersect(const osg::Vec3d& start, const osg::Vec3d& dir, float& out_height, osg::Vec3f& out_normal) const;
::Triton::Environment* getEnvironment() { return _environment; }
Environment& getEnvironmentWrapper() const { return *_environmentWrapper; }
::Triton::Ocean* getOcean() { return _ocean; }
Ocean& getOceanWrapper() const { return *_oceanWrapper; }
bool passHeightMapToTriton() const;
int getHeightMapSize() const;
const std::string& getMaskLayerName() const;
public: // osg::Object
void resizeGLObjectBuffers(unsigned maxSize);
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objects
* for all graphics contexts. */
void releaseGLObjects(osg::State* state) const;
protected:
virtual ~TritonContext();
// hidden ctors (for META_Object)
TritonContext() { }
TritonContext(const TritonContext&, const osg::CopyOp&) { }
private:
TritonLayer::Options _options;
bool _initAttempted;
bool _initFailed;
std::mutex _initMutex;
osg::ref_ptr<const osgEarth::SpatialReference> _srs;
mutable ::Triton::ResourceLoader* _resourceLoader;
mutable ::Triton::Environment* _environment;
mutable ::Triton::Ocean* _ocean;
Environment* _environmentWrapper;
Ocean* _oceanWrapper;
osg::ref_ptr<Callback> _callback;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_CONTEXT_H

View File

@ -1,330 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonContext.h"
#include "TritonDrawable.h"
#include "TritonHeightMap.h"
#include <Version.h>
#include <osg/MatrixTransform>
#include <osg/FrameBufferObject>
#include <osg/Depth>
#include <osgEarth/SpatialReference>
#include <osgEarth/VirtualProgram>
#include <osgEarth/MapNode>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/Random>
#include <osgEarth/GLUtils>
#undef LC
#define LC "[TritonDrawable] "
//#define DEBUG_HEIGHTMAP
using namespace osgEarth::Triton;
TritonDrawable::TritonDrawable(TritonContext* TRITON) :
_TRITON(TRITON)
{
// call this to ensure draw() gets called every frame.
setSupportsDisplayList( false );
setUseVertexBufferObjects( false );
// dynamic variance prevents update/cull overlap when drawing this
setDataVariance( osg::Object::DYNAMIC );
_wgs84 = SpatialReference::get("wgs84");
_ecef = _wgs84->getGeocentricSRS();
}
TritonDrawable::~TritonDrawable()
{
//nop
}
void
TritonDrawable::setMaskLayer(const osgEarth::ImageLayer* layer)
{
_maskLayer = layer;
}
void
TritonDrawable::setHeightMapGenerator(TritonHeightMap* value)
{
_heightMapGenerator = value;
}
void
TritonDrawable::setPlanarReflectionMap(osg::Texture2D* map)
{
_planarReflectionMap = map;
}
void
TritonDrawable::setPlanarReflectionProjection(osg::RefMatrix* proj)
{
_planarReflectionProjection = proj;
}
osg::BoundingBox
TritonDrawable::computeBoundingBox() const
{
return osg::BoundingBox();
}
namespace {
// Wrapper around Ocean->GetShaderObject() to account for API changes from Triton 3.x to 4.x
GLint
getOceanShader(::Triton::Ocean* ocean, ::Triton::Shaders shaderProgram, void* context, const ::Triton::Camera* camera)
{
#if (TRITON_MAJOR_VERSION >= 4)
return (GLint)ocean->GetShaderObject( shaderProgram, context, camera );
#else
return (GLint)ocean->GetShaderObject( shaderProgram );
#endif
}
}
void
TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
{
OE_GL_ZONE;
osg::State* state = renderInfo.getState();
state->disableAllVertexArrays();
_TRITON->initialize( renderInfo );
if ( !_TRITON->ready() )
return;
// Configure the height map generator.
// If configuration fails, attempt to continue without a heightmap.
if (_heightMapGenerator.valid())
{
bool configOK = _heightMapGenerator->configure(_TRITON->getHeightMapSize(), *state);
if (configOK == false)
{
_heightMapGenerator = 0L;
OE_WARN << LC << "Failed to establish a legal FBO configuration; disabling height map generator!" << std::endl;
}
}
::Triton::Environment* environment = _TRITON->getEnvironment();
// Find or create the Triton camera for this OSG camera:
CameraLocal& local = _local.get(renderInfo.getCurrentCamera());
if (local._tritonCam == 0L)
{
local._tritonCam = environment->CreateCamera();
local._tritonCam->SetName(renderInfo.getCurrentCamera()->getName().c_str());
}
::Triton::Camera* tritonCam = local._tritonCam;
auto cid = GLUtils::getSharedContextID(*state);
osgEarth::NativeProgramAdapterCollection& adapters = _adapters[cid];
if ( adapters.empty() )
{
OE_DEBUG << LC << "Initializing Triton program adapters" << std::endl;
const std::vector<const char*> prefixes = { "osg_", "oe_" };
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE, 0L, tritonCam), prefixes, "WATER_SURFACE"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE_PATCH, 0L, tritonCam), prefixes, "WATER_SURFACE_PATCH"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::GOD_RAYS, 0L, tritonCam), prefixes, "GOD_RAYS"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::SPRAY_PARTICLES, 0L, tritonCam), prefixes, "SPRAY_PARTICLES"));
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WAKE_SPRAY_PARTICLES, 0L, tritonCam), prefixes, "WAKE_SPRAY_PARTICLES"));
#if 0
// In older Triton (3.91), this line causes problems in Core profile and prevents the ocean from drawing. In newer Triton (4.01),
// this line causes a crash because there is no context passed in to GetShaderObject(), resulting in multiple NULL references.
adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_DECALS, 0L, tritonCam), prefixes, "WATER_DECALS"));
#endif
}
adapters.apply( state );
// Pass the final view and projection matrices into Triton.
if ( environment )
{
tritonCam->SetCameraMatrix(state->getModelViewMatrix().ptr());
tritonCam->SetProjectionMatrix(state->getProjectionMatrix().ptr());
}
// Calculate sea level based on the camera:
if (_verticalDatum.valid())
{
GeoPoint cam(_ecef, osg::Vec3d(0, 0, 0) * state->getInitialInverseViewMatrix(), ALTMODE_ABSOLUTE);
cam.transformInPlace(_wgs84);
auto msl = _verticalDatum->hae2msl(cam.y(), cam.x(), 0.0);
environment->SetSeaLevel(-msl);
}
if (_heightMapGenerator.valid())
{
GLint texName;
osg::Matrix hMM;
if (_heightMapGenerator->getTextureAndMatrix(renderInfo, texName, hMM))
{
// copy the OSG matrix to a Triton matrix:
::Triton::Matrix4 texMat(
hMM(0, 0), hMM(0, 1), hMM(0, 2), hMM(0, 3),
hMM(1, 0), hMM(1, 1), hMM(1, 2), hMM(1, 3),
hMM(2, 0), hMM(2, 1), hMM(2, 2), hMM(2, 3),
hMM(3, 0), hMM(3, 1), hMM(3, 2), hMM(3, 3));
environment->SetHeightMap((::Triton::TextureHandle)texName, texMat, 0L, tritonCam);
//OE_DEBUG << LC << "Updating height map, FN=" << renderInfo.getState()->getFrameStamp()->getFrameNumber() << std::endl;
}
}
state->dirtyAllVertexArrays();
// Now light and draw the ocean:
if ( environment )
{
// User pre-draw callback:
if (_TRITON->getCallback())
{
_TRITON->getCallback()->onDrawOcean(
_TRITON->getEnvironmentWrapper(),
_TRITON->getOceanWrapper());
}
osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL;
// This is the light attached to View so there are no transformations above..
// But in general case you would need to accumulate all transforms above the light into this matrix
osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity();
// If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use
// following elaborate scheme to grab the light source while drawing Triton ocean:
// - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage
// I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ...
// - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL
// then just find proper infinite directional light by scanning renderStage->PositionalStateContainer.
// - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable
// - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params
// Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors
if ( light && light->getPosition().w() == 0 )
{
osg::Vec4 ambient = light->getAmbient();
osg::Vec4 diffuse = light->getDiffuse();
osg::Vec4 position = light->getPosition();
// Compute light position/direction in the world
position = position * lightLocalToWorldMatrix;
// Diffuse direction and color
environment->SetDirectionalLight(
::Triton::Vector3( position[0], position[1], position[2] ),
::Triton::Vector3( diffuse[0], diffuse[1], diffuse[2] ) );
// Sun-based ambient value:
osg::Vec3d up = osg::Vec3d(0,0,0) * renderInfo.getCurrentCamera()->getInverseViewMatrix();
up.normalize();
osg::Vec3d pos3 = osg::Vec3d(position.x(), position.y(), position.z());
pos3.normalize();
float dot = osg::clampAbove(up*pos3, 0.0); dot*=dot;
float sunAmbient = (float)osg::clampBetween( dot, 0.0f, 0.88f );
float fa = osg::maximum(sunAmbient, ambient[0]);
// Ambient color based on the zenith color in the cube map
environment->SetAmbientLight( ::Triton::Vector3(fa, fa, fa) );
}
else
{
environment->SetDirectionalLight( ::Triton::Vector3(0,0,1), ::Triton::Vector3(1,1,1) );
environment->SetAmbientLight( ::Triton::Vector3(0.88f, 0.88f, 0.88f) );
}
if ( _cubeMap.valid() )
{
// Build transform from our cube map orientation space to native Triton orientation
// See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down
osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap
::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords(
m(0,0), m(0,1), m(0,2),
m(1,0), m(1,1), m(1,2),
m(2,0), m(2,1), m(2,2) );
// Grab the cube map from our sky box and give it to Triton to use as an _environment map
// GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE );
environment->SetEnvironmentMap(
(::Triton::TextureHandle)_cubeMap->getTextureObject(cid)->id(),
transformFromYUpToZUpCubeMapCoords );
if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() )
{
osg::Matrix & p = *_planarReflectionProjection;
::Triton::Matrix3 planarProjection(
p(0,0), p(0,1), p(0,2),
p(1,0), p(1,1), p(1,2),
p(2,0), p(2,1), p(2,2) );
environment->SetPlanarReflectionMap(
(::Triton::TextureHandle)_planarReflectionMap->getTextureObject(cid)->id(),
planarProjection,
0.125 );
}
}
// Draw the ocean for the current time sample
if ( _TRITON->getOcean() )
{
osg::GLExtensions* ext = osg::GLExtensions::Get(cid, true);
bool writeDepth = true;
const osg::Depth* depth = static_cast<const osg::Depth*>(state->getLastAppliedAttribute(osg::StateAttribute::DEPTH));
if (depth)
writeDepth = depth->getWriteMask();
double simTime = renderInfo.getView()->getFrameStamp()->getSimulationTime();
simTime = fmod(simTime, 86400.0);
_TRITON->getOcean()->Draw(
simTime,
writeDepth, // depth writes
true, // draw water
true, // draw particles
NULL, // optional context
tritonCam);
}
}
// Put GL back in a state that won't confuse the OSG state tracking:
state->dirtyAllVertexArrays();
state->dirtyAllAttributes();
state->dirtyAllModes();
#ifndef OSG_GL_FIXED_FUNCTION_AVAILABLE
// Keep OSG from reapplying GL_LIGHTING on next state change after dirtyAllModes().
state->setModeValidity(GL_LIGHTING, false);
#endif
// Keep an eye on this.
// I had to remove something similar in another module (Rex engine) because it was causing
// positional attributes (like clip planes) to re-apply with an incorrect MVM. -gw
state->apply();
}

View File

@ -1,102 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_DRAWABLE_H
#define OSGEARTH_TRITON_DRAWABLE_H
#include <osg/Drawable>
#include <osg/RenderInfo>
#include <osg/TextureCubeMap>
#include <osg/Version>
#include <osg/Texture2D>
#include <osg/buffered_value>
#include <osgEarth/Terrain>
#include <osgEarth/NativeProgramAdapter>
#include <osgEarth/ImageLayer>
#include <osgEarth/VerticalDatum>
const unsigned int TRITON_OCEAN_MASK = 0x4; // 0100
namespace osgEarth { namespace Triton
{
class TritonContext;
class TritonHeightMap;
/**
* Custom drawable for rendering the Triton ocean effects
*/
class TritonDrawable : public osg::Drawable
{
public:
TritonDrawable(TritonContext* TRITON);
//! Layer to use as an ocean rendering mask
void setMaskLayer(const osgEarth::ImageLayer* maskLayer);
//! Height map generator to use to mask out the ocean where the
//! terrain has positive elevation
void setHeightMapGenerator(TritonHeightMap* heightMap);
//! Vertical datum to use to calculate sea level
void setVerticalDatum(VerticalDatum* value) {
_verticalDatum = value;
}
//! Gets the Triton Camera associated with an osg Camera
::Triton::Camera* getTritonCam(const osg::Camera* cam) {
return _local.get(cam)._tritonCam;
}
void setPlanarReflectionMap(osg::Texture2D* map);
void setPlanarReflectionProjection(osg::RefMatrix* proj);
public: // osg::Drawable
void drawImplementation(osg::RenderInfo& ri) const override;
osg::BoundingBox computeBoundingBox() const override;
protected:
virtual ~TritonDrawable();
osg::observer_ptr<TritonContext> _TRITON;
osg::observer_ptr<const osgEarth::ImageLayer> _maskLayer;
osg::ref_ptr<osg::TextureCubeMap> _cubeMap;
osg::ref_ptr<osg::Texture2D> _planarReflectionMap;
osg::ref_ptr<osg::RefMatrix> _planarReflectionProjection;
mutable osg::ref_ptr<TritonHeightMap> _heightMapGenerator;
osg::ref_ptr<VerticalDatum> _verticalDatum;
osg::ref_ptr<const SpatialReference> _wgs84, _ecef;
mutable osg::buffered_object<osgEarth::NativeProgramAdapterCollection> _adapters;
struct CameraLocal
{
::Triton::Camera* _tritonCam = nullptr;
};
mutable PerObjectFastMap<const osg::Camera*, CameraLocal> _local;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_DRAWABLE_H

View File

@ -1,434 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonHeightMap.h"
#include "TritonContext.h"
#include <osgEarth/CullingUtils>
#include <osgEarth/VirtualProgram>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/Utils>
#define LC "[TritonHeightMap] "
using namespace osgEarth::Triton;
namespace
{
const char* vertexShader =
"#pragma import_defines(OE_TRITON_MASK_MATRIX);\n"
"// terrain SDK:\n"
"float oe_terrain_getElevation(); \n"
"out float oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_MATRIX\n"
"out vec2 maskCoords;\n"
"uniform mat4 OE_TRITON_MASK_MATRIX;\n"
"vec4 oe_layer_tilec;\n"
"#endif\n"
"void oe_triton_setupHeightMap(inout vec4 unused) \n"
"{ \n"
" oe_triton_elev = oe_terrain_getElevation(); \n"
"#ifdef OE_TRITON_MASK_MATRIX\n"
" maskCoords = (OE_TRITON_MASK_MATRIX * oe_layer_tilec).st;\n"
"#endif\n"
"} \n";
// The fragment shader simply takes the texture index that we generated
// in the vertex shader and does a texture lookup. In this case we're
// just wholesale replacing the color, so if the map had any existing
// imagery, this will overwrite it.
const char* fragmentShader =
"#pragma import_defines(OE_TRITON_MASK_SAMPLER);\n"
"in float oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_SAMPLER\n"
"in vec2 maskCoords;\n"
"uniform sampler2D OE_TRITON_MASK_SAMPLER;\n"
"#endif\n"
"out vec4 out_height; \n"
"void oe_triton_drawHeightMap(inout vec4 unused) \n"
"{ \n"
#ifdef DEBUG_HEIGHTMAP
// Map to black = -500m, white = +500m
" float nHeight = clamp(oe_triton_elev / 1000.0 + 0.5, 0.0, 1.0);\n"
#else
" float nHeight = oe_triton_elev;\n"
"#ifdef OE_TRITON_MASK_SAMPLER\n"
" float mask = texture(OE_TRITON_MASK_SAMPLER, maskCoords).a;\n"
" nHeight *= mask; \n"
"#endif\n"
#endif
" out_height = vec4( nHeight, 0.0, 0.0, 1.0 ); \n"
"} \n";
struct TerrainDirtyCallback : public osgEarth::TerrainCallback
{
osg::observer_ptr<TritonHeightMap> _hm;
TerrainDirtyCallback(TritonHeightMap* hm) : _hm(hm) { }
void onTileUpdate(const osgEarth::TileKey&, osg::Node*, osgEarth::TerrainCallbackContext&)
{
osg::ref_ptr<TritonHeightMap> hm;
if (_hm.lock(hm))
hm->dirty();
}
};
}
TritonHeightMap::TritonHeightMap() :
_texSize(0u),
_internalFormat((GLint)0),
_sourceFormat((GLenum)0)
{
setCullingActive(false);
}
TritonHeightMap::~TritonHeightMap()
{
osgEarth::TerrainEngineNode* t = dynamic_cast<osgEarth::TerrainEngineNode*>(_terrain.get());
if (t)
{
t->getTerrain()->removeTerrainCallback(static_cast<TerrainDirtyCallback*>(_terrainCallback.get()));
_terrainCallback = NULL;
}
}
void
TritonHeightMap::setTerrain(osg::Node* node)
{
_terrain = node;
osgEarth::TerrainEngineNode* t = dynamic_cast<osgEarth::TerrainEngineNode*>(node);
if (t)
{
TerrainDirtyCallback* cb = new TerrainDirtyCallback(this);
t->getTerrain()->addTerrainCallback(cb);
_terrainCallback = cb;
}
}
void
TritonHeightMap::setMaskLayer(const osgEarth::ImageLayer* layer)
{
_maskLayer = layer;
}
void
TritonHeightMap::SetDirty::operator()(CameraLocal& local)
{
local._mvpw.makeIdentity();
}
void
TritonHeightMap::dirty()
{
SetDirty setDirty;
_local.forEach(setDirty);
}
bool
TritonHeightMap::configure(unsigned texSize, osg::State& state)
{
bool result = true;
if (_texSize == 0u)
{
// first time through, single-lane and set up FBO parameters.
static std::mutex s_mutex;
std::lock_guard<std::mutex> lock(s_mutex);
if (_texSize == 0u)
{
_texSize = texSize;
if (!getBestFBOConfig(state, _internalFormat, _sourceFormat))
{
result = false;
}
}
}
return result;
}
namespace {
struct Format {
Format(GLint i, GLenum s, const std::string& n) :
internalFormat(i), sourceFormat(s), name(n) { }
GLint internalFormat;
GLenum sourceFormat;
std::string name;
};
}
bool
TritonHeightMap::getBestFBOConfig(osg::State& state, GLint& out_internalFormat, GLenum& out_sourceFormat)
{
#ifdef GL_LUMINANCE_FLOAT16_ATI
# define GL_LUMINANCE_FLOAT16_ATI 0x881E
#endif
std::vector<Format> formats;
#ifdef GL_R16F
formats.push_back(Format(GL_R16F, GL_RED, "GL_R16F"));
#endif
#ifdef GL_LUMINANCE16F_ARB
formats.push_back(Format(GL_LUMINANCE16F_ARB, GL_LUMINANCE, "GL_LUMINANCE16F_ARB"));
#endif
#ifdef GL_LUMINANCE_FLOAT16_ATI
formats.push_back(Format(GL_LUMINANCE_FLOAT16_ATI, GL_LUMINANCE, "GL_LUMINANCE_FLOAT16_ATI"));
#endif
#ifdef GL_R32F
formats.push_back(Format(GL_R32F, GL_RED, "GL_R32F"));
#endif
#ifdef GL_LUMINANCE32F_ARB
formats.push_back(Format(GL_LUMINANCE32F_ARB, GL_LUMINANCE, "GL_LUMINANCE32F_ARB"));
#endif
#ifdef GL_RGB16F_ARB
formats.push_back(Format(GL_RGB16F_ARB, GL_RGB, "GL_RGB16F_ARB"));
#endif
#ifdef GL_RGBA16F_ARB
formats.push_back(Format(GL_RGBA16F_ARB, GL_RGBA, "GL_RGBA16F_ARB"));
#endif
#ifdef GL_RGB32F_ARB
formats.push_back(Format(GL_RGB32F_ARB, GL_RGB, "GL_RGB32F_ARB"));
#endif
#ifdef GL_RGBA32F_ARB
formats.push_back(Format(GL_RGBA32F_ARB, GL_RGBA, "GL_RGBA32F_ARB"));
#endif
auto cid = GLUtils::getSharedContextID(state);
osg::GLExtensions* ext = osg::GLExtensions::Get(cid, true);
osg::State::CheckForGLErrors check = state.getCheckForGLErrors();
state.setCheckForGLErrors(state.NEVER_CHECK_GL_ERRORS);
bool found = false;
for(int i=0; i<formats.size() && !found; ++i)
{
const Format& format = formats[i];
osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D();
tex->setTextureSize(1, 1);
tex->setInternalFormat( format.internalFormat );
tex->setSourceFormat ( format.sourceFormat );
osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject();
fbo->setAttachment( osg::Camera::COLOR_BUFFER0, osg::FrameBufferAttachment(tex.get()) );
fbo->apply( state );
GLenum status = ext->glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
fbo->releaseGLObjects( &state );
tex->releaseGLObjects( &state );
if ( status == GL_FRAMEBUFFER_COMPLETE_EXT )
{
out_internalFormat = format.internalFormat;
out_sourceFormat = format.sourceFormat;
found = true;
}
}
state.setCheckForGLErrors(check);
return found;
}
bool
TritonHeightMap::isConfigurationComplete() const
{
return
_texSize > 0u &&
_internalFormat != (GLint)0 &&
_sourceFormat != (GLenum)0;
}
void
TritonHeightMap::setup(CameraLocal& local, const std::string& name)
{
// make sure the FBO params are configured:
if (!isConfigurationComplete())
return;
local._frameNum = 0u;
local._tex = new osg::Texture2D();
local._tex->setName(Stringify() << "Triton HM (" << name << ")");
local._tex->setTextureSize(_texSize, _texSize);
local._tex->setInternalFormat( _internalFormat );
local._tex->setSourceFormat( _sourceFormat );
local._tex->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
local._tex->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
// Triton prob doesn't need this but it's good practice
if (_sourceFormat == GL_RED)
{
local._tex->setSwizzle(osg::Vec4i(GL_RED, GL_RED, GL_RED, GL_ONE));
}
local._rtt = new osg::Camera();
local._rtt->setName(local._tex->getName());
local._rtt->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
local._rtt->setClearMask(GL_COLOR_BUFFER_BIT); //GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
local._rtt->setClearColor(osg::Vec4(-1000.0, -1000.0, -1000.0, 1.0f));
local._rtt->setViewport(0, 0, _texSize, _texSize);
local._rtt->setRenderOrder(osg::Camera::PRE_RENDER);
local._rtt->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
local._rtt->setImplicitBufferAttachmentMask(0, 0);
local._rtt->attach(osg::Camera::COLOR_BUFFER0, local._tex.get());
//local._rtt->setCullMask( ~TRITON_OCEAN_MASK );
local._rtt->setAllowEventFocus(false);
local._rtt->setDrawBuffer(GL_FRONT);
local._rtt->setReadBuffer(GL_FRONT);
local._rtt->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
// TODO: create this once and just re-use it for all RTT cameras
osg::StateSet* rttSS = local._rtt->getOrCreateStateSet();
osgEarth::VirtualProgram* rttVP = osgEarth::VirtualProgram::getOrCreate(rttSS);
rttVP->setName("Triton Height Map");
rttVP->setFunction( "oe_triton_setupHeightMap", vertexShader, VirtualProgram::LOCATION_VERTEX_MODEL);
rttVP->setFunction( "oe_triton_drawHeightMap", fragmentShader, VirtualProgram::LOCATION_FRAGMENT_OUTPUT);
rttVP->setInheritShaders(false);
osg::StateAttribute::OverrideValue off = osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE;
rttSS->setDefine("OE_IS_DEPTH_CAMERA");
rttSS->setDefine("OE_TERRAIN_RENDER_IMAGERY", off);
rttSS->setDefine("OE_TERRAIN_RENDER_NORMAL_MAP", off);
rttSS->setDefine("OE_TERRAIN_BLEND_IMAGERY", off);
rttSS->setDefine("OE_TERRAIN_MORPH_GEOMETRY", off);
osg::ref_ptr<const osgEarth::ImageLayer> maskLayer;
if (_maskLayer.lock(maskLayer))
{
rttSS->setDefine("OE_TRITON_MASK_SAMPLER", maskLayer->getSharedTextureUniformName());
rttSS->setDefine("OE_TRITON_MASK_MATRIX", maskLayer->getSharedTextureMatrixUniformName());
OE_DEBUG << LC << "Using mask layer \"" << maskLayer->getName() << "\", sampler=" << maskLayer->getSharedTextureUniformName() << ", matrix=" << maskLayer->getSharedTextureMatrixUniformName() << std::endl;
}
if (_terrain.valid())
{
local._rtt->addChild(_terrain.get());
}
else
{
OE_WARN << LC << "Illegal: no terrain set (must call setTerrain)" << std::endl;
}
}
#define MAXABS4(A,B,C,D) \
osg::maximum(fabs(A), osg::maximum(fabs(B), osg::maximum(fabs(C),fabs(D))))
void
TritonHeightMap::update(CameraLocal& local, const osg::Camera* cam, osgEarth::Horizon* horizon)
{
osg::Vec3d eye = osg::Vec3d(0,0,0) * cam->getInverseViewMatrix();
double hd = horizon->getDistanceToVisibleHorizon();
local._rtt->setProjectionMatrix(osg::Matrix::ortho(-hd, hd, -hd, hd, 1.0, eye.length()));
local._rtt->setViewMatrixAsLookAt(eye, osg::Vec3d(0.0,0.0,0.0), osg::Vec3d(0.0,0.0,1.0));
static const osg::Matrixd scaleBias(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0);
// Matrix that Triton will use to position the heightmap for sampling.
local._texMatrix = local._rtt->getViewMatrix() * local._rtt->getProjectionMatrix() * scaleBias;
}
void
TritonHeightMap::traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType() == nv.CULL_VISITOR)
{
osgUtil::CullVisitor* cv = osgEarth::Culling::asCullVisitor(nv);
const osg::Camera* camera = cv->getCurrentCamera();
if (camera)
{
CameraLocal& local = _local.get(camera);
if (isConfigurationComplete())
{
// create the RTT for this camera on first encounter:
if (!local._rtt.valid())
{
setup(local, camera->getName());
}
// only update when the MVPW changes.
if (local._mvpw != *cv->getMVPW())
{
// update the RTT based on the current camera:
osg::ref_ptr<Horizon> horizon;
ObjectStorage::get(&nv, horizon);
update(local, camera, horizon);
// finally, traverse the camera to build the height map.
local._rtt->accept(nv);
local._frameNum = nv.getFrameStamp()->getFrameNumber();
local._mvpw = *cv->getMVPW();
}
}
else
{
//OE_DEBUG << LC << "Configuration not yet complete..." << std::endl;
}
}
}
}
bool
TritonHeightMap::getTextureAndMatrix(osg::RenderInfo& ri, GLint& out_texName, osg::Matrix& out_matrix)
{
if (!isConfigurationComplete())
return false;
CameraLocal& local = _local.get(ri.getCurrentCamera());
if (!local._tex.valid())
return false;
// did the texture change?
//OE_DEBUG << "FN=" << ri.getState()->getFrameStamp()->getFrameNumber() << "; localFN=" << local._frameNum << std::endl;
if (ri.getState()->getFrameStamp()->getFrameNumber() > local._frameNum)
return false;
auto cid = GLUtils::getSharedContextID(*ri.getState());
osg::Texture::TextureObject* obj = local._tex->getTextureObject(cid);
if (!obj)
return false;
out_texName = obj->id();
out_matrix = local._texMatrix;
return true;
}

View File

@ -1,109 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_HEIGHT_MAP
#define OSGEARTH_TRITON_HEIGHT_MAP 1
#include <osgEarth/Containers>
#include <osgEarth/ImageLayer>
#include <osg/Node>
#include <osg/Camera>
#include <osg/Texture2D>
namespace osgEarth {
class Horizon;
}
namespace osgEarth { namespace Triton
{
/**
* Creates a height map that Triton can use to mask out the ocean where
* the terrain is above sea level.
*/
class TritonHeightMap : public osg::Node
{
public:
TritonHeightMap();
//! Sets the root of the terrain scene graph
void setTerrain(osg::Node*);
//! Sets the masking layer
void setMaskLayer(const osgEarth::ImageLayer* layer);
//! Configure the generator; return success t/f
bool configure(unsigned texSize, osg::State& state);
//! Fetch the heightmap texture and matrix generated for a camera.
bool getTextureAndMatrix(osg::RenderInfo&, GLint& out_texName, osg::Matrix& out_matrix);
//! Mark all height maps (for all cameras) for regeneration
void dirty();
public: // osg::Node
void traverse(osg::NodeVisitor&);
protected:
virtual ~TritonHeightMap();
private:
struct CameraLocal
{
osg::ref_ptr<osg::Camera> _rtt;
osg::ref_ptr<osg::Texture2D> _tex;
osg::Matrix _texMatrix;
osg::Matrix _mvpw;
unsigned _frameNum;
};
typedef osgEarth::PerObjectFastMap<const osg::Camera*, CameraLocal> Locals;
struct SetDirty : public Locals::Functor
{
void operator()(CameraLocal&);
};
//! Sets up an RTT camera for the first time
void setup(CameraLocal& local, const std::string& name);
//! Updates an RTT camera for the new view/projection matrices of the camera
void update(CameraLocal& local, const osg::Camera*, osgEarth::Horizon*);
//! Whether FBO configuration has happened yet
bool isConfigurationComplete() const;
//! Figures out the best FBO format on this GPU
static bool getBestFBOConfig(osg::State& state, GLint& internalFormat, GLenum& sourceFormat);
Locals _local;
osg::observer_ptr<osg::Node> _terrain;
unsigned _texSize;
GLint _internalFormat;
GLenum _sourceFormat;
osg::observer_ptr<const osgEarth::ImageLayer> _maskLayer;
osg::ref_ptr<osg::Referenced> _terrainCallback;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_HEIGHT_MAP

View File

@ -1,51 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonIntersections.h"
using namespace osgEarth;
using namespace osgEarth::Triton;
TritonIntersections::TritonIntersections() :
_maxRange(1.0, Units::KILOMETERS)
{
}
void
TritonIntersections::setAnchor(const GeoPoint& value)
{
_anchor = value;
// zero out the other stuff:
_anchor.z() = 0.0;
_anchor.altitudeMode() = ALTMODE_ABSOLUTE;
}
void
TritonIntersections::addLocalPoint(const osg::Vec3d& p)
{
_input.push_back(p);
_heights.resize(_input.size());
_normals.resize(_input.size());
}
void
TritonIntersections::setMaxRange(const Distance& range)
{
_maxRange = range;
}

View File

@ -1,72 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_INTERSECTIONS
#define OSGEARTH_TRITON_INTERSECTIONS 1
#include <osgEarth/VisibleLayer>
#include <osgEarth/ImageLayer>
#include "TritonCallback.h"
namespace osgEarth { namespace Triton
{
/**
* Pass this structure to TritonLayer and it will automatically
* populate the results with ocean wave intersections (local coordinates
* and normals.)
*/
class TritonIntersections : public osg::Referenced
{
public:
//! Construct an empty set
TritonIntersections();
//! Anchor point for intersectsions in this set. Only the X and Y
//! components are used. Any local points you add to this set will
//! be in the local coordinate system (LTP) around this anchor point.
void setAnchor(const GeoPoint& p);
//! Adds a point to the intersection set. The point should be in the
//! local coordinate system of the anchor point.
void addLocalPoint(const osg::Vec3d& p);
//! Maximum range at which to perform intersections. Beyond this
//! range Triton will skip this set. Default is 2km.
void setMaxRange(const Distance& value);
const Distance& getMaxRange() const { return _maxRange; }
//! Vector of input local points added by addLocalPoint.
const std::vector<osg::Vec3d>& getInput() const { return _input; }
//! Vector of heights resulting from the intersection tests.
const std::vector<float>& getHeights() const { return _heights; }
//! Vector of normals resulting from the intersection tests.
const std::vector<osg::Vec3d>& getNormals() const { return _normals; }
private:
GeoPoint _anchor;
std::vector<osg::Vec3d> _input;
std::vector<float> _heights;
std::vector<osg::Vec3d> _normals;
Distance _maxRange;
friend class TritonLayerNode;
};
} }
#endif // OSGEARTH_TRITON_INTERSECTIONS

View File

@ -1,386 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include "TritonLayer.h"
#include "TritonContext.h"
#include "TritonDrawable.h"
#include "TritonHeightMap.h"
#include "TritonCallback.h"
#include <osgEarth/MapNode>
#include <osgEarth/ImageLayer>
#include <osgEarth/NodeUtils>
#include <osgEarth/ElevationLOD>
#include <osgEarth/TerrainEngineNode>
#include <osgEarth/VerticalDatum>
#include <osgUtil/CullVisitor>
#define LC "[TritonLayer] "
using namespace osgEarth::Triton;
namespace osgEarth { namespace Triton
{
class TritonLayerNode : public osg::Group
{
public:
TritonLayerNode(osgEarth::Triton::TritonLayer* layer,
LayerReference<osgEarth::ImageLayer>& mask) :
_tritonLayer(layer),
_maskLayer(mask),
_callback(0L),
_needsMapNode(true)
{
// To detect the map node:
ADJUST_UPDATE_TRAV_COUNT(this, +1);
// Disable bounds culling
setCullingActive(false);
}
~TritonLayerNode()
{
//nop
}
void setUserCallback(osgEarth::Triton::Callback* callback)
{
_callback = callback;
}
void dirty()
{
create();
}
/** MapNode to use; will be discovered automatically if not set here */
void setMapNode(osgEarth::MapNode* mapNode)
{
if (!mapNode)
{
this->removeChildren(0, this->getNumChildren());
_drawable = 0L;
_TRITON = 0L;
_needsMapNode = true;
}
else
{
_mapNode = mapNode;
create();
}
}
void create()
{
this->removeChildren(0, this->getNumChildren());
_drawable = 0L;
osg::ref_ptr<osgEarth::MapNode> mapNode;
if (!_mapNode.lock(mapNode))
return;
const osgEarth::Map* map = mapNode->getMap();
// create an object to house Triton data and resources.
if (!_TRITON.valid())
_TRITON = new TritonContext(_tritonLayer->options());
if (map)
_TRITON->setSRS(map->getSRS());
if (_callback.valid())
_TRITON->setCallback(_callback.get());
TritonDrawable* drawable = new TritonDrawable(_TRITON.get());
_drawable = drawable;
_drawable->setNodeMask(TRITON_OCEAN_MASK);
drawable->setMaskLayer(_maskLayer.getLayer());
this->addChild(_drawable);
// Place in the depth-sorted bin and set a rendering order.
// We want Triton to render after the terrain.
_drawable->getOrCreateStateSet()->setRenderBinDetails(
_tritonLayer->getRenderBinNumber(),
"DepthSortedBin");
// Install a vdatum for sea level calculations:
auto vdatum = VerticalDatum::get(_tritonLayer->options().vdatum().value());
if (vdatum)
drawable->setVerticalDatum(vdatum);
// If the user requested a height map, install it now.
// Configuration of the height map generator will take place later when
// we have a valid graphics context.
if (_tritonLayer->getUseHeightMap() == true)
{
TritonHeightMap* heightMapGen = new TritonHeightMap();
heightMapGen->setTerrain(mapNode->getTerrainEngine()->getNode());
if (_maskLayer.getLayer())
heightMapGen->setMaskLayer(_maskLayer.getLayer());
this->addChild(heightMapGen);
drawable->setHeightMapGenerator(heightMapGen);
}
}
void traverse(osg::NodeVisitor& nv)
{
if (nv.getVisitorType() == nv.UPDATE_VISITOR)
{
// Find a MapNode in the traversal path if necessary:
if (_needsMapNode)
{
osgEarth::MapNode* mapNode = osgEarth::findInNodePath<osgEarth::MapNode>(nv);
if (mapNode)
{
setMapNode(mapNode);
_needsMapNode = false;
ADJUST_UPDATE_TRAV_COUNT(this, -1);
}
}
}
else if (nv.getVisitorType() == nv.CULL_VISITOR && _drawable && _TRITON.valid() && _TRITON->getOcean())
{
// Update any intersections.
// For now this is running in the CULL traversal, which is not ideal.
// However the Triton Ocean::GetHeight method requires a pointer to the Triton "camera"
// and under our framework this is only available in CULL or DRAW.
// Running the intersection in eithe CULL or DRAW will result in a frame
// incoherency w.r.t the Triton update() call that updates the ocean state.
::Triton::Ocean* ocean = _TRITON->getOcean();
// Find the TritonCam associated with this osg Cam
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
::Triton::Camera* tritonCam = static_cast<TritonDrawable*>(_drawable)->getTritonCam(cv->getCurrentCamera());
osg::Vec3d eye = osg::Vec3d(0,0,0) * cv->getCurrentCamera()->getInverseViewMatrix();
for(std::vector<osg::ref_ptr<TritonIntersections> >::iterator i = _isect.begin();
i != _isect.end();
++i)
{
TritonIntersections* ir = i->get();
// allocate enough space for the output:
ir->_input.resize(ir->_input.size());
ir->_normals.resize(ir->_input.size());
osg::Matrix local2world;
ir->_anchor.createLocalToWorld(local2world);
// Make sure it's in range so as not to waste cycles:
osg::Vec3d anchor = osg::Vec3d(0,0,0) * local2world;
double m = ir->getMaxRange().as(Units::METERS);
if ((eye-anchor).length2() > (m))
{
continue;
}
osg::Matrix world2local;
world2local.invert(local2world);
for(unsigned i=0; i<ir->_input.size(); ++i)
{
const osg::Vec3d& local = ir->_input[i];
// transform the ray to world coordinates
osg::Vec3d start = local * local2world;
osg::Vec3d dir = osg::Matrix::transform3x3(local2world, osg::Vec3d(0,0,1));
// intersect the ocean
float& out_height = ir->_heights[i];
::Triton::Vector3 out_normalT;
bool ok = ocean->GetHeight(
::Triton::Vector3(start.x(), start.y(), start.z()),
::Triton::Vector3(dir.x(), dir.y(), dir.z()),
out_height,
out_normalT,
true, // visualCorrelation
true, // includeWakes
true, // highResolution
true, // threadSafe,
0L, // intersectionPoint,
true, // autoFlip
tritonCam);
if (ok)
{
// populate the output data in local coordinates
osg::Vec3d& normal = ir->_normals[i];
normal.set(out_normalT.x, out_normalT.y, out_normalT.z);
normal = osg::Matrix::transform3x3(normal, world2local);
}
else
{
// todo...what?
OE_WARN << "GetHeight returned false dude" << std::endl;
}
}
}
}
osg::Group::traverse(nv);
}
osg::ref_ptr<TritonContext> _TRITON;
osg::Drawable* _drawable;
LayerReference<osgEarth::ImageLayer>& _maskLayer;
osg::observer_ptr<osgEarth::MapNode> _mapNode;
osg::observer_ptr<osgEarth::Triton::TritonLayer> _tritonLayer;
osg::ref_ptr<Callback> _callback;
bool _needsMapNode;
std::vector<osg::ref_ptr<TritonIntersections> > _isect;
};
} }
//........................................................................
void
TritonLayer::Options::fromConfig(const osgEarth::Config& conf)
{
conf.get("user", _user);
conf.get("license_code", _licenseCode);
conf.get("resource_path", _resourcePath);
conf.get("use_height_map", _useHeightMap);
conf.get("height_map_size", _heightMapSize);
conf.get("render_bin_number", _renderBinNumber);
conf.get("max_altitude", _maxAltitude);
conf.get("vdatum", vdatum());
maskLayer().get(conf, "mask_layer");
}
osgEarth::Config
TritonLayer::Options::getConfig() const
{
osgEarth::Config conf = osgEarth::VisibleLayer::Options::getConfig();
conf.set("user", _user);
conf.set("license_code", _licenseCode);
conf.set("resource_path", _resourcePath);
conf.set("use_height_map", _useHeightMap);
conf.set("height_map_size", _heightMapSize);
conf.set("render_bin_number", _renderBinNumber);
conf.set("max_altitude", _maxAltitude);
conf.set("vdatum", vdatum());
maskLayer().set(conf, "mask_layer");
return conf;
}
//........................................................................
/** Register this layer so it can be used in an earth file */
namespace osgEarth { namespace Triton
{
REGISTER_OSGEARTH_LAYER(triton, TritonLayer);
REGISTER_OSGEARTH_LAYER(triton_ocean, TritonLayer);
} }
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, UserName, user);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, LicenseCode, licenseCode);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, ResourcePath, resourcePath);
OE_LAYER_PROPERTY_IMPL(TritonLayer, bool, UseHeightMap, useHeightMap);
OE_LAYER_PROPERTY_IMPL(TritonLayer, unsigned, HeightMapSize, heightMapSize);
OE_LAYER_PROPERTY_IMPL(TritonLayer, int, RenderBinNumber, renderBinNumber);
OE_LAYER_PROPERTY_IMPL(TritonLayer, float, MaxAltitude, maxAltitude);
OE_LAYER_PROPERTY_IMPL(TritonLayer, std::string, VerticalDatum, vdatum);
void
TritonLayer::init()
{
super::init();
_seaLevel = 0.0f;
// Trick to force the VisibleLayer to install its opacity shader,
// which a modified Triton user-functions.glsl shader needs in order to control
// sea surface opacity.
float opacity = getOpacity();
setOpacity(0.0f);
setOpacity(opacity);
this->setName("Triton");
setRenderType(RENDERTYPE_CUSTOM);
ElevationLOD* lod = new ElevationLOD();
_root = lod;
if (options().maxAltitude().isSet())
{
OE_DEBUG << LC << "Setting max altitude = " << options().maxAltitude().get() << std::endl;
lod->setMaxElevation(options().maxAltitude().get());
}
_tritonNode = new TritonLayerNode(this, options().maskLayer());
_root->addChild(_tritonNode.get());
}
void
TritonLayer::setUserCallback(Callback* callback)
{
static_cast<TritonLayerNode*>(_tritonNode.get())->setUserCallback(callback);
}
osg::Node*
TritonLayer::getNode() const
{
return _root.get();
}
void
TritonLayer::setMaskLayer(osgEarth::ImageLayer* maskLayer)
{
options().maskLayer().setLayer(maskLayer);
static_cast<TritonLayerNode*>(_tritonNode.get())->dirty();
}
osgEarth::ImageLayer*
TritonLayer::getMaskLayer() const
{
return options().maskLayer().getLayer();
}
void
TritonLayer::addedToMap(const osgEarth::Map* map)
{
VisibleLayer::addedToMap(map);
options().maskLayer().addedToMap(map);
}
void
TritonLayer::removedFromMap(const osgEarth::Map* map)
{
VisibleLayer::removedFromMap(map);
options().maskLayer().removedFromMap(map);
setMaskLayer(0L);
}
void
TritonLayer::addIntersections(TritonIntersections* value)
{
TritonLayerNode* node = static_cast<TritonLayerNode*>(_tritonNode.get());
node->_isect.push_back(value);
}
osgEarth::Config
TritonLayer::getConfig() const
{
osgEarth::Config c = osgEarth::VisibleLayer::getConfig();
return c;
}

View File

@ -1,125 +0,0 @@
/* -*-c++-*- */
/* osgEarth - Geospatial SDK for OpenSceneGraph
* Copyright 2020 Pelican Mapping
* http://osgearth.org
*
* osgEarth is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#ifndef OSGEARTH_TRITON_LAYER
#define OSGEARTH_TRITON_LAYER 1
#include <osgEarth/VisibleLayer>
#include <osgEarth/LayerReference>
#include <osgEarth/ImageLayer>
#include "TritonCallback.h"
#include "TritonIntersections.h"
namespace osgEarth { namespace Triton
{
/**
* Node that roots the Triton adapter.
*/
class TritonLayer : public osgEarth::VisibleLayer
{
public:
class Options : public osgEarth::VisibleLayer::Options {
public:
META_LayerOptions(osgEarth, Options, osgEarth::VisibleLayer::Options);
OE_OPTION(std::string, user);
OE_OPTION(std::string, licenseCode);
OE_OPTION(std::string, resourcePath);
OE_OPTION(bool, useHeightMap, true);
OE_OPTION(unsigned, heightMapSize, 1024);
OE_OPTION(int, renderBinNumber, 12);
OE_OPTION(float, maxAltitude, 50000.0f);
OE_OPTION(std::string, vdatum, "egm96");
OE_OPTION_LAYER(osgEarth::ImageLayer, maskLayer);
virtual Config getConfig() const;
private:
void fromConfig(const Config& conf);
};
public:
META_Layer(osgEarth, TritonLayer, Options, osgEarth::VisibleLayer, triton);
//! Sets the user callback that's invoked when Triton start up
void setUserCallback(Triton::Callback* callback);
//! User name for license
void setUserName(const std::string& value);
const std::string& getUserName() const;
//! License code
void setLicenseCode(const std::string& value);
const std::string& getLicenseCode() const;
//! Triton resource path
void setResourcePath(const std::string& value);
const std::string& getResourcePath() const;
//! Whether to use a height map to fade out the ocean at the coastline
void setUseHeightMap(const bool& value);
const bool& getUseHeightMap() const;
//! Size in texels of the height map (each dimension)
void setHeightMapSize(const unsigned& value);
const unsigned& getHeightMapSize() const;
//! Render bin number to use for the ocean rendering
void setRenderBinNumber(const int& value);
const int& getRenderBinNumber() const;
//! Masking layer for the ocean
void setMaskLayer(osgEarth::ImageLayer* maskLayer);
osgEarth::ImageLayer* getMaskLayer() const;
//! Maximum visibility altitude
void setMaxAltitude(const float& value);
const float& getMaxAltitude() const;
//! Vertical datum to use to calculate sea level
void setVerticalDatum(const std::string& value);
const std::string& getVerticalDatum() const;
//! Adds an intersection set.
//! Each frame, Triton will perform intersections against the ocean surface
//! (including the waves) and populate the set with the results.
void addIntersections(TritonIntersections*);
public: // Layer
virtual osg::Node* getNode() const;
//! Serialize
virtual Config getConfig() const;
protected: // Layer
virtual void init();
virtual void addedToMap(const class osgEarth::Map*);
virtual void removedFromMap(const class osgEarth::Map*);
private:
osg::ref_ptr<osg::Group> _root;
osg::ref_ptr<osg::Node> _tritonNode;
float _seaLevel;
float _opacity;
};
} } // namespace osgEarth::Triton
#endif // OSGEARTH_TRITON_LAYER

View File

@ -1,9 +1,33 @@
#include "CompositeHandle.h" #include "CompositeHandle.h"
#include <osgEarthUtil/EarthManipulator>
#include "CompositeWidgetManager.h" #include "CompositeWidgetManager.h"
#include <iostream> #include <iostream>
CompositeHandle::CompositeHandle(CompositeWidgetManager* cw) :_cw(cw), #define M_PI 3.14159265358979323846 /* mathematical constant pi */
///Radian to degree conversion factor
static const double RAD2DEG = 180.0 / M_PI;
///Degree to radian conversion factor
static const double DEG2RAD = M_PI / 180.0;
inline double angFix360(double in) {
in -= 45.0;
if ((in < 0.0) || (in >= 360.0)) {
in = fmod(in, 360.0);
if (in < 0.0)
in += 360.0;
}
return in;
}
inline bool areEqual(double a, double b, double t = 1.0e-6) {
return fabs(a - b) < t;
}
CompositeHandle::CompositeHandle(CompositeWidgetManager* cw)
: _cw(cw),
_operate(cw->GetcanvasO()), _operate(cw->GetcanvasO()),
_N(cw->GetcanvasN()), _N(cw->GetcanvasN()),
_light(cw->GetcanvasFX()), _light(cw->GetcanvasFX()),
@ -13,141 +37,37 @@ _move(false)
{ {
} }
CompositeHandle::~CompositeHandle(void)
{
}
bool CompositeHandle::handle(const osgGA::GUIEventAdapter&ea, osgGA::GUIActionAdapter& aa) bool CompositeHandle::handle(const osgGA::GUIEventAdapter&ea, osgGA::GUIActionAdapter& aa)
{ {
if (_num != 0) if (ea.getEventType() == osgGA::GUIEventAdapter::FRAME) {
constexpr double TWO_DECIMAL_PLACES = 1e-02;
double heading = 0.0;
osgViewer::View* activeView = static_cast<osgViewer::View*>(aa.asView());
const osgEarth::Util::EarthManipulator* manip = dynamic_cast<const osgEarth::Util::EarthManipulator*>(activeView->getCameraManipulator());
if (manip != NULL)
{ {
_cw->_local_y = sin(_angle); manip->getCompositeEulerAngles(&heading);
_cw->_local_x = cos(_angle); // Convert to degrees
heading = angFix360(heading * RAD2DEG);
_angle = _angle + _num;
_cw->SendPosition();
if ((_num >= 0 && _angle >= osg::PI_2) || (_num < 0 && _angle < osg::PI_2))
{
_cw->_local_y = sin(osg::PI_2);
_cw->_local_x = cos(osg::PI_2);
_cw->SendPosition();
_num = 0;
_cw->_autoHome = false;
_cw->_N = false;
}
return false;
}
else
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::DRAG:
{
if (_cw->_state == CompositeWidgetManager::MOUSE_DRAG)
{
_cw->SendPosition();
}
break;
}
case osgGA::GUIEventAdapter::PUSH:
{
_cw->_N = false;
break;
}
case osgGA::GUIEventAdapter::DOUBLECLICK:
{
if (_cw->_N == true)
{
_num = (45 - _N->getRotate())*osg::PI / (100 * 180);
if (_num != 0)
{
_angle = (_N->getRotate() - 45)*osg::PI / 180 + osg::PI_2;
_cw->_autoHome = true;
}
return true;
}
else if (ea.getX() >= _cw->_center_x - 42 &&
ea.getX() < _cw->_center_x + 42 &&
ea.getY() > _cw->_center_y - 42 &&
ea.getY() < _cw->_center_y + 42)
{
return true;
}
break;
}
default:
break;
}
switch (_cw->_state)
{
case CompositeWidgetManager::MOUSE_PUSH:
{
if (_cw->_N != true || _cw->_autoHome == false)
{
_cw->SendPosition();
if (_cw->_local_y < 0)
{
if (_cw->_local_x > 0)
{
_light->setRotate(45 - (180 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2));
}
else
{
_light->setRotate(45 - (-180 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2));
}
}
else
{
_light->setRotate(45 - 90 * asinf(_cw->_local_x / sqrtf(_cw->_local_x*_cw->_local_x + _cw->_local_y*_cw->_local_y)) / osg::PI_2);
}
_light->getByName("light")->setColor(1, 1, 1, 0.5);
_light->resize();
}
break;
}
case CompositeWidgetManager::MOUSE_RELEASE:
{
_cw->_state = CompositeWidgetManager::DEFAULT;
_light->getByName("light")->setColor(1, 1, 1, 0);
break;
}
case CompositeWidgetManager::MOUSE_DRAG:
{
break;
}
default:
{
if (ea.getX() > _cw->_center_x - 50 &&
ea.getY() > _cw->_center_y - 200)
{
if (_cw->_center == 1)
{
_operate->getByName("center")->setColor(1, 1, 1, 1);
}
_background->getByName("backGround4")->setColor(1, 1, 1, 1);
}
else {
if (_cw->_center == 1)
{
_operate->getByName("center")->setColor(1, 1, 1, 0.1);
}
_background->getByName("backGround4")->setColor(1, 1, 1, 0);
}
}
break;
}
} }
else
{
// Fall back to the viewpoint's heading
heading = angFix360(manip->getViewpoint().heading()->as(osgEarth::Units::DEGREES));
}
// make sure that anything equivalent to 0.00 is displayed as 0.00
if (areEqual(heading, 0.0, TWO_DECIMAL_PLACES) || areEqual(heading, 360.0, TWO_DECIMAL_PLACES)) {
heading = 0.0;
}
if (!areEqual(_N->getRotate(), -heading, TWO_DECIMAL_PLACES))
{
_N->setRotate(-heading);
_N->update();
}
}
// compass_->update_();
return false; return false;
} }

View File

@ -14,9 +14,9 @@ class CompositeHandle :public osgGA::GUIEventHandler
public: public:
CompositeHandle(CompositeWidgetManager* cw); CompositeHandle(CompositeWidgetManager* cw);
~CompositeHandle(void); ~CompositeHandle(void) override = default;
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&); bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter&) override;
private: private:
osgWidget::Canvas* _operate; osgWidget::Canvas* _operate;

View File

@ -1,5 +1,6 @@
#include "CompositeWidgetManager.h" #include "CompositeWidgetManager.h"
#include "BackGroundWidget.h"
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "viewer/OsgViewUI.h" #include "viewer/OsgViewUI.h"
@ -77,23 +78,7 @@ CompositeWidgetManager::CompositeWidgetManager(void)
_canvasFX->getBackground()->setColor(0, 0, 0, 0); _canvasFX->getBackground()->setColor(0, 0, 0, 0);
} }
CompositeWidgetManager::~CompositeWidgetManager(void) CompositeWidgetManager::~CompositeWidgetManager(void) {
{
delete _canvasN;
delete _canvasO;
delete _canvasBackGround;
delete _canvasFX;
delete _bgLayer1;
delete _bgLayer2;
delete _bgLayer3;
delete _bgLayer4;
delete _bgShadow;
delete _widgetCenter;
delete _widgetN;
delete _widgetFX;
} }
void CompositeWidgetManager::ResetCanvasPosition(double x, double y) void CompositeWidgetManager::ResetCanvasPosition(double x, double y)
@ -114,7 +99,7 @@ void CompositeWidgetManager::ResetCanvasPosition(double x, double y)
void CompositeWidgetManager::SendPosition() void CompositeWidgetManager::SendPosition()
{ {
_mouseDirection = osg::Vec2(_local_x, _local_y); _mouseDirection = osg::Vec2(static_cast<float>(_local_x), static_cast<float>(_local_y));
if (_center == 0 && _state != CompositeWidgetManager::MOUSE_DRAG && _autoHome != true) if (_center == 0 && _state != CompositeWidgetManager::MOUSE_DRAG && _autoHome != true)
{ {
QVariantList varList; QVariantList varList;
@ -127,13 +112,14 @@ void CompositeWidgetManager::SendPosition()
QVariantList varList; QVariantList varList;
varList.push_back(QVariant(_mouseDirection.x())); varList.push_back(QVariant(_mouseDirection.x()));
varList.push_back(QVariant(_mouseDirection.y())); varList.push_back(QVariant(_mouseDirection.y()));
//emit signalHeading(QVariant(varList)); //emit signalHeading(QVariant(varList));
} }
else else
{ {
osg::Vec2 pos = _mouseDirection; osg::Vec2 pos = _mouseDirection;
pos[0] = pos.x()* 0.2; pos[0] = pos.x()* 0.2f;
pos[1] = pos.y()* 0.1; pos[1] = pos.y()* 0.1f;
QVariantList varList; QVariantList varList;
varList.push_back(QVariant(pos.x())); varList.push_back(QVariant(pos.x()));
@ -142,8 +128,7 @@ void CompositeWidgetManager::SendPosition()
} }
} }
void CompositeWidgetManager::SetHeading(double angle) void CompositeWidgetManager::SetHeading(double angle) {
{
_canvasN->setRotate(angle + 45); _canvasN->setRotate(angle + 45);
_canvasN->update(); _canvasN->update();
} }
@ -156,6 +141,20 @@ void CompositeWidgetManager::AttachViewUI(OsgViewUI* ui) {
ui->addChild(_canvasBackGround); ui->addChild(_canvasBackGround);
} }
void CompositeWidgetManager::AttachViewUI(osgWidget::WindowManager* ui) {
ui->addChild(_canvasO);
ui->addChild(_canvasN);
ui->addChild(_canvasFX);
ui->addChild(_canvasBackGround);
}
void CompositeWidgetManager::DetachViewUI(OsgViewUI* ui) {
ui->removeChild(_canvasO);
ui->removeChild(_canvasN);
ui->removeChild(_canvasFX);
ui->removeChild(_canvasBackGround);
}
//void CompositeWidgetManager::slotHeading(double angle) //void CompositeWidgetManager::slotHeading(double angle)
//{ //{
// SetHeading(angle); // SetHeading(angle);

View File

@ -1,13 +1,9 @@
#ifndef CompositeWidgetManager_h__ #ifndef CompositeWidgetManager_h__
#define CompositeWidgetManager_h__ #define CompositeWidgetManager_h__
#include "BackGroundWidget.h"
#include "CompositeHandle.h"
#include "CompositeWidget.h" #include "CompositeWidget.h"
#include "ZoomWidget.h" #include "ZoomWidget.h"
#include "ZoomHandle.h"
#include <QObject>
#include <QVariant> #include <QVariant>
@ -35,6 +31,8 @@ public:
} }
void AttachViewUI(class OsgViewUI* ui); void AttachViewUI(class OsgViewUI* ui);
void AttachViewUI(osgWidget::WindowManager* ui);
void DetachViewUI(class OsgViewUI* ui);
// //
// //
@ -47,23 +45,22 @@ public slots:
void slotHeading(double angle); void slotHeading(double angle);
private: private:
osgWidget::Canvas* _canvasN; osg::ref_ptr<osgWidget::Canvas> _canvasN;
osgWidget::Canvas* _canvasO; osg::ref_ptr<osgWidget::Canvas> _canvasO;
osgWidget::Canvas* _canvasBackGround; osg::ref_ptr<osgWidget::Canvas> _canvasBackGround;
osgWidget::Canvas* _canvasFX; osg::ref_ptr<osgWidget::Canvas> _canvasFX;
CompositeWidget* _bgLayer1; osg::ref_ptr<CompositeWidget> _bgLayer1;
osgWidget::Widget* _bgLayer2; osg::ref_ptr<osgWidget::Widget> _bgLayer2;
osgWidget::Widget* _bgLayer3; osg::ref_ptr<osgWidget::Widget> _bgLayer3;
osgWidget::Widget* _bgLayer4; osg::ref_ptr<osgWidget::Widget> _bgLayer4;
osgWidget::Widget* _bgShadow; osg::ref_ptr<osgWidget::Widget> _bgShadow;
CompositeWidget* _widgetCenter; osg::ref_ptr<CompositeWidget> _widgetCenter;
osg::ref_ptr<CompositeWidget> _widgetN;
CompositeWidget* _widgetN; osg::ref_ptr<osgWidget::Widget> _widgetFX;
osg::ref_ptr<osgWidget::Widget> _widgetFXBackground;
osgWidget::Widget* _widgetFX;
osgWidget::Widget* _widgetFXBackground;
osg::Vec2 _mouseDirection; osg::Vec2 _mouseDirection;

View File

@ -18,6 +18,11 @@ OESceneUI::OESceneUI(OEScene* oeScene)
OESceneUI::~OESceneUI(void) { OESceneUI::~OESceneUI(void) {
LOG_INFO("dctor self={}", spdlog::fmt_lib::ptr(this)); LOG_INFO("dctor self={}", spdlog::fmt_lib::ptr(this));
/* if (compositeWidgetManager_) {
compositeWidgetManager_->DetachViewUI();
delete compositeWidgetManager_;
compositeWidgetManager_ = nullptr;
}*/
} }
void OESceneUI::InitUI(OsgViewUI* ui) { void OESceneUI::InitUI(OsgViewUI* ui) {
@ -29,24 +34,43 @@ void OESceneUI::InitUI(OsgViewUI* ui) {
compositeWidgetManager_ = new CompositeWidgetManager(); compositeWidgetManager_ = new CompositeWidgetManager();
compositeWidgetManager_->AttachViewUI(ui); compositeWidgetManager_->AttachViewUI(ui);
zoomManager_ = new ZoomManager(); //zoomManager_ = new ZoomManager(oeScene_);
zoomManager_->AttachViewUI(ui); //zoomManager_->AttachViewUI(ui);
queryElevationWidget_ = new QueryElevationWidget(oeScene_); queryElevationWidget_ = new QueryElevationWidget(oeScene_);
queryElevationWidget_->AttachViewUI(ui); queryElevationWidget_->AttachViewUI(ui);
ui->getView()->addEventHandler(new ZoomHandle(zoomManager_, compositeWidgetManager_)); //ui->getView()->addEventHandler(new ZoomHandle(zoomManager_, compositeWidgetManager_));
ui->getView()->addEventHandler(new CompositeHandle(compositeWidgetManager_)); ui->getView()->addEventHandler(new CompositeHandle(compositeWidgetManager_));
isInit_ = true; isInit_ = true;
LOG_INFO("exit"); LOG_INFO("exit");
} }
void OESceneUI::UninitUI(OsgViewUI* ui) {
LOG_INFO("enter");
if (!isInit_) {
LOG_INFO("not init");
return;
}
if (compositeWidgetManager_) {
compositeWidgetManager_->DetachViewUI(ui);
compositeWidgetManager_ = nullptr;
}
if (queryElevationWidget_) {
queryElevationWidget_->DetachViewUI(ui);
queryElevationWidget_ = nullptr;
}
isInit_ = false;
LOG_INFO("exit");
}
void OESceneUI::OnResize(double width, double height) { void OESceneUI::OnResize(double width, double height) {
dyt_check(compositeWidgetManager_); dyt_check(compositeWidgetManager_);
dyt_check(zoomManager_); //dyt_check(zoomManager_);
compositeWidgetManager_->ResetCanvasPosition(width, height); compositeWidgetManager_->ResetCanvasPosition(width, height);
zoomManager_->ResetCanvasPosition(width, height); //zoomManager_->ResetCanvasPosition(width, height);
queryElevationWidget_->ResetCanvasPosition(width, height); queryElevationWidget_->ResetCanvasPosition(width, height);
} }

View File

@ -16,12 +16,13 @@ public:
~OESceneUI(void) override; ~OESceneUI(void) override;
void InitUI(OsgViewUI* ui) override; void InitUI(OsgViewUI* ui) override;
void UninitUI(OsgViewUI* ui) override;
void OnResize(double width, double height) override; void OnResize(double width, double height) override;
private: private:
class OEScene* oeScene_; class OEScene* oeScene_;
bool isInit_{ false }; bool isInit_{ false };
osg::ref_ptr<class CompositeWidgetManager> compositeWidgetManager_{ nullptr }; osg::ref_ptr<class CompositeWidgetManager> compositeWidgetManager_{ nullptr };
osg::ref_ptr<class ZoomManager> zoomManager_{ nullptr }; //osg::ref_ptr<class ZoomManager> zoomManager_{ nullptr };
osg::ref_ptr<class QueryElevationWidget> queryElevationWidget_{ nullptr }; osg::ref_ptr<class QueryElevationWidget> queryElevationWidget_{ nullptr };
}; };

View File

@ -43,7 +43,17 @@ void QueryElevationWidget::AttachViewUI(OsgViewUI* ui) {
ui->addChild(this); ui->addChild(this);
dyt_check(nullptr != oeScene_); dyt_check(nullptr != oeScene_);
osgEarth::MapNode* mapNode = oeScene_->GetMapNode(); osgEarth::MapNode* mapNode = oeScene_->GetMapNode();
ui->getView()->addEventHandler(new QueryElevationEventHandler(mapNode, this)); eventHandler_ = new QueryElevationEventHandler(mapNode, this);
ui->getView()->addEventHandler(eventHandler_);
}
void QueryElevationWidget::DetachViewUI(OsgViewUI* ui) {
dyt_check(nullptr != ui);
ui->removeChild(this);
if (nullptr != eventHandler_) {
ui->getView()->removeEventHandler(eventHandler_);
eventHandler_ = nullptr;
}
} }

View File

@ -24,6 +24,7 @@ public:
~QueryElevationWidget() override; ~QueryElevationWidget() override;
void AttachViewUI(class OsgViewUI* ui); void AttachViewUI(class OsgViewUI* ui);
void DetachViewUI(class OsgViewUI* ui);
void OnUpdateGeoPoint(double x, double y, double z); void OnUpdateGeoPoint(double x, double y, double z);
void ResetCanvasPosition(double width, double height); void ResetCanvasPosition(double width, double height);
@ -34,6 +35,7 @@ private:
private: private:
class OEScene* oeScene_; class OEScene* oeScene_;
osg::ref_ptr<osgWidget::Label> label_; osg::ref_ptr<osgWidget::Label> label_;
osg::ref_ptr<QueryElevationEventHandler> eventHandler_;
}; };

View File

@ -1,11 +1,15 @@
#include "ZoomManager.h" #include "ZoomManager.h"
#include <osgEarthUtil/EarthManipulator>
#include "config.h" #include "config.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "viewer/OsgViewUI.h" #include "viewer/OsgViewUI.h"
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "scene/OEScene.h"
ZoomManager::ZoomManager(void) ZoomManager::ZoomManager(OEScene* oeScene)
: oeScene_(oeScene)
{ {
zoom = 0.0; zoom = 0.0;
state = ZoomManager::DEFAULT; state = ZoomManager::DEFAULT;
@ -17,12 +21,20 @@ ZoomManager::ZoomManager(void)
_canvasZoom->setStrata(osgWidget::Window::STRATA_FOREGROUND); _canvasZoom->setStrata(osgWidget::Window::STRATA_FOREGROUND);
const std::string texturePath = RecourceHelper::Get().GetResourcesPath().toStdString(); const std::string texturePath = RecourceHelper::Get().GetResourcesPath().toStdString();
_lessen = new ZoomWidget("lessen", 18, 20, texturePath + "/northarrow/zoom_down.png", "lessen", osgWidget::Widget::LAYER_TOP, this); _lessen = new ZoomWidget("lessen", 18, 20, texturePath + "/northarrow/zoom_down.png",
_enlargement = new ZoomWidget("enlargement", 18, 20, texturePath + "/northarrow/zoom_up.png", "enlargement", osgWidget::Widget::LAYER_TOP, this); "lessen", osgWidget::Widget::LAYER_TOP, this);
_zoomBackground = new BackGroundWidget("zoomBackground", 18, 144, texturePath + "/northarrow/zoomactive.png"); _enlargement = new ZoomWidget("enlargement", 18, 20,
_bar = new ZoomWidget("bar", 17, 10, texturePath + "/northarrow/zoombar_norm.png", "bar", osgWidget::Widget::LAYER_TOP, this); texturePath + "/northarrow/zoom_up.png", "enlargement",
_bar_ = new BackGroundWidget("bar_", 18, 12, texturePath + "/northarrow/zoombar_norm_.png"); osgWidget::Widget::LAYER_TOP, this);
_zoomBackground_shadow = new BackGroundWidget("background_shadow", 18, 144, texturePath + "/northarrow/zoombackground.png"); _zoomBackground = new BackGroundWidget("zoomBackground", 18, 144,
texturePath + "/northarrow/zoomactive.png");
_bar = new ZoomWidget("bar", 17, 10,
texturePath + "/northarrow/zoombar_norm.png", "bar",
osgWidget::Widget::LAYER_TOP, this);
_bar_ = new BackGroundWidget("bar_", 18, 12,
texturePath + "/northarrow/zoombar_norm_.png");
_zoomBackground_shadow = new BackGroundWidget("background_shadow", 18, 144,
texturePath + "/northarrow/zoombackground.png");
_canvasZoom->addWidget(_lessen, 0, 0); _canvasZoom->addWidget(_lessen, 0, 0);
_canvasZoom->addWidget(_enlargement, 0, 124); _canvasZoom->addWidget(_enlargement, 0, 124);
@ -54,7 +66,7 @@ void ZoomManager::ResetCanvasPosition(double x, double y)
void ZoomManager::SendZoom() void ZoomManager::SendZoom()
{ {
_zoomNum[0] = zoom; _zoomNum[0] = zoom;
slotZoom();
//emit signalZoom(QVariant(_zoomNum[0])); //emit signalZoom(QVariant(_zoomNum[0]));
} }
@ -63,3 +75,51 @@ void ZoomManager::AttachViewUI(OsgViewUI* ui) {
ui->addChild(_canvasZoom); ui->addChild(_canvasZoom);
} }
void ZoomManager::slotZoom() {
double val = _zoomNum[0];
double dx = val*(-1.0)*(0.0005);// dx不起作用
double dy = val*(-1.0)*(0.0005);
return;
// dx *= getSettings()->getMouseSensitivity();
// dy *= getSettings()->getMouseSensitivity();
double minAlt = 500.0;
double maxAlt = 35000000.0;
auto em = oeScene_->GetManipulater();
auto vp = em->getViewpoint();
vp.setRange(vp.getRange() * 1.1);
em->setViewpoint(vp);
//
// double scale = 1.0f + dy;
// double distance = em->getDistance() * scale;
// distance = std::max(distance, maxAlt);
//
// // if (!OEScene::GetSrs()->isGeographic())
// // {
// // osg::Viewport* vp = oeScene_->GetViewport();
// // if (vp)
// // {
// // double ar = vp->width() / vp->height();
// // double y = distance * tan(0.5*osg::DegreesToRadians(em->));
// // double x = y * ar;
// //
// // osgEarth::GeoExtent extentMap = oeScene_->getMap()->getProfile()->getExtent();
// //
// // if ((_center.y() - y) < extentMap.yMin())
// // {
// // return;
// // }
// // if ((_center.y() + y) > extentMap.yMax())
// // {
// // return;
// // }
// // }
// // }
//
// em->setDistance(distance);
}

View File

@ -12,7 +12,7 @@
class ZoomManager : public osg::Referenced { class ZoomManager : public osg::Referenced {
public: public:
ZoomManager(void); ZoomManager(class OEScene* oeScene);
~ZoomManager(void); ~ZoomManager(void);
void ResetCanvasPosition(double x, double y); void ResetCanvasPosition(double x, double y);
@ -21,12 +21,18 @@ public:
osgWidget::Canvas* GetCanvasZoom() { osgWidget::Canvas* GetCanvasZoom() {
return _canvasZoom; return _canvasZoom;
} }
osgWidget::Widget* GetBar() const {
return _bar;
}
void AttachViewUI(class OsgViewUI* ui); void AttachViewUI(class OsgViewUI* ui);
// //
//signals: //signals:
// void signalZoom(QVariant var); // void signalZoom(QVariant var);
protected:
void slotZoom();
private: private:
osgWidget::Canvas* _canvasZoom; osgWidget::Canvas* _canvasZoom;
@ -39,6 +45,8 @@ private:
int _zoomNum[1]; int _zoomNum[1];
class OEScene* oeScene_;
public: public:
enum STATE { enum STATE {
MOUSE_PUSH, MOUSE_PUSH,

View File

@ -30,10 +30,6 @@ ZoomWidget::ZoomWidget(std::string name,
_pZoomManager = pZoomManager; _pZoomManager = pZoomManager;
} }
ZoomWidget::~ZoomWidget(void)
{
}
bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager* wm) bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager* wm)
{ {
_pZoomManager->state = ZoomManager::MOUSE_PUSH; _pZoomManager->state = ZoomManager::MOUSE_PUSH;
@ -42,11 +38,14 @@ bool ZoomWidget::mousePush(double x, double y, const osgWidget::WindowManager*
if ("lessen" == _order) if ("lessen" == _order)
{ {
_pZoomManager->zoom = -43; _pZoomManager->zoom = -43;
UpdateBarPosition(_pZoomManager->zoom);
} }
else if ("enlargement" == _order) else if ("enlargement" == _order)
{ {
_pZoomManager->zoom = 43; _pZoomManager->zoom = 43;
UpdateBarPosition(_pZoomManager->zoom);
} }
setColor(1, 1, 1, 1); setColor(1, 1, 1, 1);
return false; return false;
} }
@ -55,48 +54,55 @@ bool ZoomWidget::mouseRelease(double x, double y, const osgWidget::WindowManager
{ {
_pZoomManager->state = ZoomManager::MOUSE_RELEASE; _pZoomManager->state = ZoomManager::MOUSE_RELEASE;
if ("bar" == _order) //if ("bar" == _order)
{ //{
setOrigin(0, 67); // setOrigin(0, 67);
getParent()->getByName("bar_")->setOrigin(0, 66); // getParent()->getByName("bar_")->setOrigin(0, 66);
getParent()->resize(); // getParent()->resize();
} //}
_pZoomManager->zoom = 0.0; _pZoomManager->zoom = 0.0;
UpdateBarPosition(_pZoomManager->zoom);
setColor(1, 1, 1, 0); setColor(1, 1, 1, 0);
return false; return false;
} }
//
//bool ZoomWidget::mouseDrag(double x, double y, const osgWidget::WindowManager* wm)
//{
// if (_order == "bar")
// {
// _pointX += x;
// _pointY += y;
//
// while (_pZoomManager->zoom > 43)
// _pZoomManager->zoom = 43;
// while (_pZoomManager->zoom < -43)
// _pZoomManager->zoom = -43;
//
// if (y > 43 - _pZoomManager->zoom)
// {
// y = 43 - _pZoomManager->zoom;
// }
// if (y < -43 - _pZoomManager->zoom)
// {
// y = -43 - _pZoomManager->zoom;
// }
//
// if (_pZoomManager->zoom >= -43 && _pZoomManager->zoom <= 43)
// {
// /*addOrigin(0, y);
// getParent()->getByName("bar_")->addOrigin(0, y);*/
// double y1 = _pZoomManager->GetBar()->getOrigin().y();
// UpdateBarPosition(y + y1);
// _pZoomManager->zoom += y;
// }
// else {
// _pZoomManager->zoom += y;
// }
// }
// return true;
//}
bool ZoomWidget::mouseDrag(double x, double y, const osgWidget::WindowManager* wm) void ZoomWidget::UpdateBarPosition(double y) {
{ _pZoomManager->GetBar()->setOrigin(0, 67 + y * 0.5);
if (_order == "bar") _pZoomManager->GetCanvasZoom()->update();
{
_pointX += x;
_pointY += y;
while (_pZoomManager->zoom > 43)
_pZoomManager->zoom = 43;
while (_pZoomManager->zoom < -43)
_pZoomManager->zoom = -43;
if (y > 43 - _pZoomManager->zoom)
{
y = 43 - _pZoomManager->zoom;
}
if (y < -43 - _pZoomManager->zoom)
{
y = -43 - _pZoomManager->zoom;
}
if (_pZoomManager->zoom >= -43 && _pZoomManager->zoom <= 43)
{
addOrigin(0, y);
getParent()->getByName("bar_")->addOrigin(0, y);
_pZoomManager->zoom += y;
}
else {
_pZoomManager->zoom += y;
}
getParent()->resize();
}
return true;
} }

View File

@ -21,15 +21,16 @@ public:
osgWidget::Widget::Layer layer, osgWidget::Widget::Layer layer,
ZoomManager *pZoomManager); ZoomManager *pZoomManager);
~ZoomWidget(void); ~ZoomWidget(void) override = default;
bool mousePush(double, double, const osgWidget::WindowManager*); bool mousePush(double, double, const osgWidget::WindowManager*);
bool mouseRelease(double, double, const osgWidget::WindowManager*); bool mouseRelease(double, double, const osgWidget::WindowManager*);
bool mouseDrag(double, double, const osgWidget::WindowManager*); //bool mouseDrag(double, double, const osgWidget::WindowManager*);
std::string GetOrder() { return _order; } std::string GetOrder() { return _order; }
double GetPointerX() { return _pointX; } double GetPointerX() { return _pointX; }
double GetpointerY() { return _pointY; } double GetpointerY() { return _pointY; }
void UpdateBarPosition(double y);
private: private:
double _pointX; double _pointX;

1
src/scutcheon Submodule

@ -0,0 +1 @@
Subproject commit 99fe4de63326ed57f80411289763eb4449778122

File diff suppressed because it is too large Load Diff

View File

@ -9,30 +9,28 @@
Dialog::Dialog(QWidget* parent) Dialog::Dialog(QWidget* parent)
: QDialog(parent) : QDialog(parent)
, delegate_(FramelessDelegate::Create(this)) { , ui_(new Ui::Dialog) {
setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
ui_->setupUi(this);
ui_->titleBar->SetMainWidget(this);
InitFrame(); InitFrame();
} }
Dialog::~Dialog() {
delete ui_;
}
void Dialog::DeleteThisOnClose() { void Dialog::DeleteThisOnClose() {
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
} }
void Dialog::SetTitleBar(FrameTitleBar* titleBar) { void Dialog::SetTitleBar(FrameTitleBar* titleBar) {
delegate_->SetTitleBar(titleBar);
QVBoxLayout* layout = reinterpret_cast<QVBoxLayout*>(this->layout());
layout->insertWidget(0, titleBar, 0);
} }
void Dialog::SetTitle(const QString& title) { void Dialog::SetTitle(const QString& title) {
if (!delegate_) { ui_->titleBar->SetTitle(title);
return;
}
delegate_->SetTitle(title);
} }
void Dialog::hideEvent(QHideEvent*) { void Dialog::hideEvent(QHideEvent*) {
@ -47,9 +45,7 @@ bool Dialog::nativeEvent(const QByteArray& eventType, void* message, long* resul
#else #else
bool Dialog::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) { bool Dialog::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) {
#endif #endif
if (!delegate_->nativeEvent(eventType, message, result)) {
return QDialog::nativeEvent(eventType, message, result); return QDialog::nativeEvent(eventType, message, result);
}
return true; return true;
} }
@ -62,20 +58,4 @@ void Dialog::paintEvent(QPaintEvent* event) {
} }
void Dialog::InitFrame() { void Dialog::InitFrame() {
FrameTitleBar* titleBar = new FrameTitleBar(this);
titleBar->SetMainWidget(this);
titleBar->SetSysButton(FrameTitleBar::FTB_ICON | FrameTitleBar::FTB_CLOSE | FrameTitleBar::FTB_TTILE);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
layout->setStretch(0, 0);
layout->setStretch(1, 1);
layout->setAlignment(Qt::AlignLeft | Qt::AlignTop);
SetTitleBar(titleBar);
mainDilag_ = new QWidget(this);
layout->addWidget(mainDilag_, 1);
} }

View File

@ -2,6 +2,8 @@
#include <QDialog> #include <QDialog>
#include "ui_Dialog.h"
class FrameTitleBar; class FrameTitleBar;
class FramelessDelegate; class FramelessDelegate;
@ -10,7 +12,7 @@ class Dialog : public QDialog {
public: public:
Dialog(QWidget* parent); Dialog(QWidget* parent);
~Dialog() override = default; ~Dialog() override;
void DeleteThisOnClose(); void DeleteThisOnClose();
void SetTitleBar(FrameTitleBar* titleBar); void SetTitleBar(FrameTitleBar* titleBar);
@ -27,16 +29,18 @@ protected:
#endif #endif
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
protected: protected:
template<typename UI> template<typename UI>
void SetupUI(UI* ui) { void SetupUI(UI* ui) {
ui->setupUi(mainDilag_); //ui->setupUi(mainDilag_);
ui->setupUi(ui_->mianWidget);
} }
private: private:
void InitFrame(); void InitFrame();
private: private:
Ui::Dialog* ui_;
FramelessDelegate* delegate_; FramelessDelegate* delegate_;
QWidget* mainDilag_{ nullptr };
}; };

65
src/ui/Dialog.ui Normal file
View File

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Dialog</class>
<widget class="QDialog" name="Dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>654</width>
<height>509</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</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="DialogTitleBar" name="titleBar" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>40</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="mianWidget" native="true"/>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>DialogTitleBar</class>
<extends>QWidget</extends>
<header>DialogTitleBar.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../Hydro.qrc"/>
</resources>
<connections/>
</ui>

74
src/ui/DialogTitleBar.cpp Normal file
View File

@ -0,0 +1,74 @@
#include "DialogTitleBar.h"
#include <QStyleOption>
#include <QPainter>
#include <QMouseEvent>
#include <QButtonGroup>
#include "common/RecourceHelper.h"
#include "ui/Dialog.h"
#include "ui_DialogTitleBar.h"
DialogTitleBar::DialogTitleBar(QWidget* parent)
: QWidget(parent)
, ui(new Ui::DialogTitleBar) {
ui->setupUi(this);
connect(ui->sys_close, &QPushButton::clicked, this, &DialogTitleBar::closeDialog);
}
DialogTitleBar::~DialogTitleBar() {
delete ui;
}
//QSize DockTitleBar::minimumSizeHint() const {
// QSize s = size();
// return s;
//}
void DialogTitleBar::SetTitle(const QString& title) {
ui->sys_title->setText(title);
}
void DialogTitleBar::paintEvent(QPaintEvent* event) {
QStyleOption opt;
opt.initFrom(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}
void DialogTitleBar::mouseReleaseEvent(QMouseEvent* event) {
if (pressed_) {
pressed_ = false;
point_ = event->pos();
}
QWidget::mouseReleaseEvent(event);
}
void DialogTitleBar::mousePressEvent(QMouseEvent* event) {
if (event->button() == Qt::LeftButton) {
pressed_ = true;
point_ = event->pos();
}
QWidget::mousePressEvent(event);
}
void DialogTitleBar::mouseMoveEvent(QMouseEvent* event) {
if (pressed_) {
QPoint movePoint = event->globalPos() - point_;
if (nullptr != mainDialog_) {
mainDialog_->move(movePoint);
}
}
QWidget::mouseMoveEvent(event);
}
void DialogTitleBar::closeDialog() {
if (nullptr != mainDialog_) {
mainDialog_->reject();
return;
}
close();
}

36
src/ui/DialogTitleBar.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <QWidget>
namespace Ui {
class DialogTitleBar;
}
class DialogTitleBar : public QWidget {
Q_OBJECT
public:
DialogTitleBar(QWidget* parent = 0);
~DialogTitleBar() override;
//QSize minimumSizeHint() const override;
void SetMainWidget(class Dialog* dialog) { mainDialog_ = dialog; }
void SetTitle(const QString& title);
protected:
void paintEvent(QPaintEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
protected:
void closeDialog();
private:
Ui::DialogTitleBar* ui;
class Dialog* mainDialog_{ nullptr };
bool pressed_{ false };
QPoint point_;
};

71
src/ui/DialogTitleBar.ui Normal file
View File

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogTitleBar</class>
<widget class="QWidget" name="DialogTitleBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>451</width>
<height>42</height>
</rect>
</property>
<property name="windowTitle">
<string>DialogTitleBar</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</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="QLabel" name="sys_title">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>612</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="sys_close">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../Hydro.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -4,10 +4,13 @@
#include <QPainter> #include <QPainter>
#include <QAction> #include <QAction>
#include <QButtonGroup> #include <QButtonGroup>
#include <QMouseEvent>
#include <qDebug> #include <qDebug>
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "common/SpdLogger.h"
#include "config.h"
#include "ui_FrameTitleBar.h" #include "ui_FrameTitleBar.h"
@ -20,11 +23,12 @@ FrameTitleBar::FrameTitleBar(QWidget* parent)
connect(ui->sys_close, &QPushButton::clicked, this, &FrameTitleBar::OnCloseBtnClicked); connect(ui->sys_close, &QPushButton::clicked, this, &FrameTitleBar::OnCloseBtnClicked);
connect(ui->sys_min, &QPushButton::clicked, this, &FrameTitleBar::OnMinBtnClicked); connect(ui->sys_min, &QPushButton::clicked, this, &FrameTitleBar::OnMinBtnClicked);
connect(ui->sys_max, &QPushButton::clicked, this, &FrameTitleBar::OnMaxBtnClicked); connect(ui->sys_max, &QPushButton::clicked, this, &FrameTitleBar::OnMaxBtnClicked);
connect(ui->sys_restore, &QPushButton::clicked, this, &FrameTitleBar::OnRestorClicked); //connect(ui->sys_restore, &QPushButton::clicked, this, &FrameTitleBar::OnRestorClicked);
//connect(this, &FrameTitleBar::doubleClick, this, &FrameTitleBar::OnDoubleClicked); //connect(this, &FrameTitleBar::doubleClick, this, &FrameTitleBar::OnDoubleClicked);
ui->sys_restore->hide(); /*ui->sys_close->setIcon(style()->standardPixmap(QStyle::SP_TitleBarCloseButton));
ui->sys_max->hide(); ui->sys_min->setIcon(style()->standardPixmap(QStyle::SP_TitleBarMinButton));
ui->sys_max->setIcon(style()->standardPixmap(QStyle::SP_TitleBarMaxButton));*/
SetSysButton(0); SetSysButton(0);
@ -44,10 +48,12 @@ void FrameTitleBar::SetTitle(const QString& title) {
void FrameTitleBar::SetMainWidget(QWidget* widget) { void FrameTitleBar::SetMainWidget(QWidget* widget) {
mainWidget_ = widget; mainWidget_ = widget;
if (nullptr == mainWidget_) {
qDebug() << __FUNCTION__ << "mainWidget is nullptr";
return;
}
} }
void FrameTitleBar::OnMaximized(bool maximized) { void FrameTitleBar::OnMaximized(bool maximized) {
ui->sys_restore->setVisible(maximized);
ui->sys_max->setVisible(!maximized); ui->sys_max->setVisible(!maximized);
} }
@ -72,6 +78,33 @@ void FrameTitleBar::paintEvent(QPaintEvent* event) {
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
} }
void FrameTitleBar::mouseReleaseEvent(QMouseEvent* event) {
Q_UNUSED(event);
pressed_ = false;
}
void FrameTitleBar::mousePressEvent(QMouseEvent* event) {
if (nullptr == mainWidget_ || mainWidget_->isMaximized()) {
return;
}
if (event->button() == Qt::LeftButton) {
pressed_ = true;
point_ = event->pos();
}
}
void FrameTitleBar::mouseMoveEvent(QMouseEvent* event) {
if (pressed_ && nullptr != mainWidget_) {
mainWidget_->move(event->pos() - point_ + mainWidget_->pos());
}
}
void FrameTitleBar::mouseDoubleClickEvent(QMouseEvent* event) {
Q_UNUSED(event);
OnMaxBtnClicked();
}
void FrameTitleBar::OnMinBtnClicked() { void FrameTitleBar::OnMinBtnClicked() {
if (nullptr == mainWidget_) { if (nullptr == mainWidget_) {
qDebug() << __FUNCTION__ << "mainWidget is nullptr"; qDebug() << __FUNCTION__ << "mainWidget is nullptr";
@ -82,22 +115,18 @@ void FrameTitleBar::OnMinBtnClicked() {
} }
void FrameTitleBar::OnMaxBtnClicked() { void FrameTitleBar::OnMaxBtnClicked() {
if (nullptr == mainWidget_) {
qDebug() << __FUNCTION__ << "mainWidget is nullptr";
return;
}
mainWidget_->showMaximized();
}
void FrameTitleBar::OnRestorClicked() {
if (nullptr == mainWidget_) { if (nullptr == mainWidget_) {
qDebug() << __FUNCTION__ << "mainWidget is nullptr"; qDebug() << __FUNCTION__ << "mainWidget is nullptr";
return; return;
} }
if (mainWidget_->isMaximized()) {
mainWidget_->showNormal(); mainWidget_->showNormal();
ui->sys_max->setIcon(QPixmap(":/res/sys_max.png"));
} else {
mainWidget_->showMaximized();
ui->sys_max->setIcon(QPixmap(":/res/sys_restore.png"));
}
} }
void FrameTitleBar::OnCloseBtnClicked() { void FrameTitleBar::OnCloseBtnClicked() {
@ -115,15 +144,22 @@ void FrameTitleBar::InitSkinMemu() {
QStringList values; QStringList values;
values << "default" << "silver" << "blue"; values << "default" << "silver" << "blue";
assert(values.count() == names.count()); dyt_check(values.count() == names.count());
ui->sys_skin->setPopupMode(QToolButton::InstantPopup); ui->sys_skin->setPopupMode(QToolButton::InstantPopup);
QActionGroup* skinActionGroup = new QActionGroup(this);
skinActionGroup->setExclusive(true);
for (int i = 0; i < names.count(); ++i) { for (int i = 0; i < names.count(); ++i) {
QAction* action = new QAction(names[i], this); QAction* action = new QAction(names[i], this);
action->setCheckable(true);
action->setData(values[i]); action->setData(values[i]);
ui->sys_skin->addAction(action); ui->sys_skin->addAction(action);
skinActionGroup->addAction(action);
connect(action, &QAction::triggered, &RecourceHelper::Get(), &RecourceHelper::OnChangeStyle); connect(action, &QAction::triggered, &RecourceHelper::Get(), &RecourceHelper::OnChangeStyle);
} }
ui->sys_skin->actions().first()->setChecked(true);
} }
void FrameTitleBar::InitMenuWidget() { void FrameTitleBar::InitMenuWidget() {

View File

@ -41,11 +41,14 @@ public:
protected: protected:
void paintEvent(QPaintEvent* event) override; void paintEvent(QPaintEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseDoubleClickEvent(QMouseEvent* event) override;
protected: protected:
void OnMinBtnClicked(); void OnMinBtnClicked();
void OnMaxBtnClicked(); void OnMaxBtnClicked();
void OnRestorClicked();
void OnCloseBtnClicked(); void OnCloseBtnClicked();
private: private:
@ -55,4 +58,7 @@ private:
class QBoxLayout* menuLayout_{ nullptr }; class QBoxLayout* menuLayout_{ nullptr };
class QButtonGroup* buttonCourp_{ nullptr }; class QButtonGroup* buttonCourp_{ nullptr };
unsigned int ftbButton_{ 0 }; unsigned int ftbButton_{ 0 };
bool pressed_{ false };
QPoint point_;
}; };

View File

@ -89,19 +89,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="sys_restore">
<property name="maximumSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="sys_close"> <widget class="QPushButton" name="sys_close">
<property name="maximumSize"> <property name="maximumSize">

View File

@ -32,7 +32,7 @@ bool FramelessDelegate::nativeEvent(const QByteArray & eventType, void* message,
} }
void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) { void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) {
if (nullptr == titleBar || titleBar_ == titleBar) { /* if (nullptr == titleBar || titleBar_ == titleBar) {
return; return;
} }
if (nullptr != titleBar_) { if (nullptr != titleBar_) {
@ -43,7 +43,7 @@ void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) {
if (nullptr != titleBar_) { if (nullptr != titleBar_) {
titleBar_->installEventFilter(this); titleBar_->installEventFilter(this);
} }*/
} }
void FramelessDelegate::SetTitle(const QString& title) { void FramelessDelegate::SetTitle(const QString& title) {

View File

@ -96,7 +96,8 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
auto rc = workRect_; auto rc = workRect_;
if (!rc) if (!rc)
return false; return false;
if (auto ret = DefWindowProcW(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam); ret) { auto ret = DefWindowProcW(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
if ( ret) {
*result = ret; *result = ret;
return true; return true;
} }
@ -108,7 +109,8 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
} else { } else {
const auto clientRect = reinterpret_cast<LPRECT>(msg->lParam); const auto clientRect = reinterpret_cast<LPRECT>(msg->lParam);
const auto before = *clientRect; const auto before = *clientRect;
if (auto ret = DefWindowProcW(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam); ret) { auto ret = DefWindowProcW(msg->hwnd, WM_NCCALCSIZE, msg->wParam, msg->lParam);
if ( ret) {
*result = ret; *result = ret;
return true; return true;
} }
@ -276,7 +278,7 @@ void FramelessDelegateWin::CheckMonitorChanged() {
auto newMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); auto newMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
if (newMonitor != monitor_) { if (newMonitor != monitor_) {
monitor_ = newMonitor; monitor_ = newMonitor;
auto ret = GetScreenNativeWorkRect(hwnd); std::optional<QRect> ret = GetScreenNativeWorkRect(hwnd);
if ( !!ret) if ( !!ret)
workRect_ = ret; workRect_ = ret;
} }

View File

@ -12,72 +12,209 @@ namespace std {
}; };
constexpr explicit nullopt_t(_Tag) {} constexpr explicit nullopt_t(_Tag) {}
}; };
inline constexpr nullopt_t nullopt{ nullopt_t::_Tag{} }; constexpr nullopt_t nullopt{ nullopt_t::_Tag{} };
class bad_optional_access : public std::exception
{
public:
const char* what() const noexcept override
{
return "bad optional access";
}
};
template<typename T> template <class T>
class optional { class optional {
public: public:
optional() : has_value_(false) {} constexpr optional() noexcept : _engaged(false) {}
optional(const T& value) : has_value_(true), value_(value) {} constexpr optional(nullopt_t) noexcept : _engaged(false) {}
optional(T&& value) : has_value_(true), value_(std::move(value)) {}
optional(nullopt_t) : has_value_(false) {}
bool has_value() const { optional(const optional& other) : _engaged(other._engaged) {
return has_value_; if (other._engaged) {
new (_storage) T(*other);
}
} }
T& value() { optional(optional&& other) noexcept : _engaged(other._engaged) {
if (!has_value_) { if (other._engaged) {
throw std::runtime_error("optional has no value"); new (_storage) T(std::move(*other));
other._engaged = false;
} }
return value_;
} }
const T& value() const { optional& operator=(const optional& other)
if (!has_value_) { {
throw std::runtime_error("optional has no value"); if(this == &other)
return *this;
if(_engaged && other._engaged)
{
**this = *other;
} }
return value_; else if(other._engaged)
{
new (_storage) T(*other);
_engaged = true;
} else if(_engaged)
{
reset();
} }
// 重载运算符 * 和 -> 使得使用更加方便 return *this;
T& operator*() {
return value();
} }
const T& operator*() const { optional& operator=(optional&& other) noexcept
return value(); {
if(this == &other)
return *this;
if(_engaged && other._engaged)
{
**this = std::move(*other);
} else if (other._engaged)
{
new(_storage) T(std::move(*other));
_engaged = true;
} else if(_engaged)
{
reset();
}
other._engaged = false;
return *this;
}
optional(const T& value) : _engaged(true) {
new (_storage) T(value);
}
optional(T&& value) : _engaged(true) {
new (_storage) T(std::move(value));
}
~optional() {
reset();
}
void reset() noexcept {
if (_engaged) {
reinterpret_cast<T*>(_storage)->~T();
_engaged = false;
}
}
constexpr bool has_value() const noexcept
{
return _engaged;
}
T& operator*() &
{
if(!_engaged)
throw std::bad_optional_access();
return *reinterpret_cast<T*>(_storage);
}
const T& operator*() const&
{
if(!_engaged)
throw std::bad_optional_access();
return *reinterpret_cast<const T*>(_storage);
}
T&& operator*() &&
{
if(!_engaged)
throw std::bad_optional_access();
return std::move(*reinterpret_cast<T*>(_storage));
}
const T&& operator*() const&&
{
if(!_engaged)
throw std::bad_optional_access();
return std::move(*reinterpret_cast<T*>(_storage));
} }
T* operator->() { T* operator->() {
return &value(); return reinterpret_cast<T*>(_storage);
} }
const T* operator->() const { const T* operator->() const {
return &value(); return reinterpret_cast<const T*>(_storage);
} }
bool operator==(const optional& other) const { explicit operator bool() const noexcept {
if (has_value_ && other.has_value_) { return _engaged;
return value_ == other.value_;
}
return has_value_ == other.has_value_;
}
bool operator!=(const optional& other) const {
return !(*this == other);
}
bool operator!() const {
return !has_value();
} }
private: private:
bool has_value_; bool _engaged;
T value_; char _storage[sizeof(T)];
}; };
//
// template<typename T>
// class optional {
// public:
// optional() : has_value_(false) {}
// optional(const T& value) : has_value_(true), value_(value) {}
// optional(T&& value) : has_value_(true), value_(std::move(value)) {}
// optional(nullopt_t) : has_value_(false) {}
//
// bool has_value() const {
// return has_value_;
// }
//
// T& value() {
// if (!has_value_) {
// throw std::runtime_error("optional has no value");
// }
// return value_;
// }
//
// const T& value() const {
// if (!has_value_) {
// throw std::runtime_error("optional has no value");
// }
// return value_;
// }
//
// T& operator*() {
// return value();
// }
//
// const T& operator*() const {
// return value();
// }
//
// T* operator->() {
// return &value();
// }
//
// const T* operator->() const {
// return &value();
// }
//
// bool operator==(const optional& other) const {
// if (has_value_ && other.has_value_) {
// return value_ == other.value_;
// }
// return has_value_ == other.has_value_;
// }
//
// bool operator!=(const optional& other) const {
// return !(*this == other);
// }
//
// bool operator!() const {
// return !has_value();
// }
//
// private:
// bool has_value_;
// T value_;
// };
} }
#endif #endif

View File

@ -5,9 +5,8 @@
FramelessWindow::FramelessWindow(QWidget* parent) FramelessWindow::FramelessWindow(QWidget* parent)
: QFrame(parent) : QFrame(parent) {
, delegate_(FramelessDelegate::Create(this)) { setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
//setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
} }
@ -15,7 +14,7 @@ FramelessWindow::~FramelessWindow() {
} }
void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) { void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) {
delegate_->SetTitleBar(titleBar); titleBar->SetMainWidget(this);
} }
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@ -23,8 +22,5 @@ bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qi
#else #else
bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) { bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) {
#endif #endif
if (!delegate_->nativeEvent(eventType, message, result)) {
return QFrame::nativeEvent(eventType, message, result); return QFrame::nativeEvent(eventType, message, result);
} }
return true;
}

View File

@ -22,5 +22,5 @@ protected:
#endif #endif
private: private:
FramelessDelegate* delegate_; FramelessDelegate* delegate_{ nullptr };
}; };

View File

@ -1,4 +1,4 @@
#include "CodeEdtUI.h" #include "CodeEdtUI.h"
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QMenuBar> #include <QMenuBar>
@ -25,7 +25,7 @@ CodeEdtUI::CodeEdtUI(QWidget *parent)
{ {
ui.setupUi(this); ui.setupUi(this);
// 创建代码编辑器 // 创建代码编辑器
editor = new QPlainTextEdit(this); editor = new QPlainTextEdit(this);
QFont serifFont("Times", 20, QFont::Bold); QFont serifFont("Times", 20, QFont::Bold);
@ -38,7 +38,7 @@ CodeEdtUI::CodeEdtUI(QWidget *parent)
InitBat(); InitBat();
// // 创建菜单 // // 创建菜单
// QMenu* fileMenu = menuBar()->addMenu(tr("&file")); // QMenu* fileMenu = menuBar()->addMenu(tr("&file"));
// QAction* openMainAction = new QAction(tr("&Import the template"), this); // QAction* openMainAction = new QAction(tr("&Import the template"), this);
///* QAction* openLDAction = new QAction(tr("&Import the LD template"), this); ///* QAction* openLDAction = new QAction(tr("&Import the LD template"), this);
@ -55,7 +55,7 @@ CodeEdtUI::CodeEdtUI(QWidget *parent)
// connect(saveAction, &QAction::triggered, this, &CodeEdtUI::saveFile); // connect(saveAction, &QAction::triggered, this, &CodeEdtUI::saveFile);
// // 状态栏 // // 状态栏
// statusBar(); // statusBar();
} }
@ -71,7 +71,7 @@ void CodeEdtUI::AttachDock(DockWidget* dockWidget)
DockTitleBar* dockTitleBar = new DockTitleBar; DockTitleBar* dockTitleBar = new DockTitleBar;
dockTitleBar->SetTitle(tr("matlab editor")); dockTitleBar->SetTitle(u8"bat文件");
dockWidget->SetDockWidgetTitleBar(dockTitleBar); dockWidget->SetDockWidgetTitleBar(dockTitleBar);
} }
@ -79,7 +79,7 @@ void CodeEdtUI::AttachDock(DockWidget* dockWidget)
void CodeEdtUI::InitBat() void CodeEdtUI::InitBat()
{ {
{ {
QMenu* fileMenu = menuBar()->addMenu(tr("&bat")); QMenu* fileMenu = menuBar()->addMenu(u8"文件");
QDir dir(RecourceHelper::Get().GetBasePath() + "/bat"); QDir dir(RecourceHelper::Get().GetBasePath() + "/bat");
QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks); QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks);
@ -99,12 +99,12 @@ void CodeEdtUI::InitBat()
} }
{ {
QMenu* ctrlMenu = menuBar()->addMenu(tr("&Control")); QMenu* ctrlMenu = menuBar()->addMenu(u8"控制");
QAction* runAction = new QAction(tr("&Run"), this); QAction* runAction = new QAction(tr(u8"执行"), this);
ctrlMenu->addAction(runAction); ctrlMenu->addAction(runAction);
QAction* saveAction = new QAction(tr("&Save"), this); QAction* saveAction = new QAction(u8"保存", this);
ctrlMenu->addAction(saveAction); ctrlMenu->addAction(saveAction);
connect(runAction, &QAction::triggered, this, &CodeEdtUI::runFile); connect(runAction, &QAction::triggered, this, &CodeEdtUI::runFile);
@ -182,20 +182,20 @@ void CodeEdtUI::runFile()
{ {
saveFile(); saveFile();
// 创建QProcess对象 // 创建QProcess对象
QProcess process; QProcess process;
// 启动批处理文件 // 启动批处理文件
process.start(m_strCurOpenFile); process.start(m_strCurOpenFile);
// 等待过程完成 // 等待过程完成
process.waitForFinished(); process.waitForFinished();
// 获取输出 // 获取输出
QString output = process.readAllStandardOutput(); QString output = process.readAllStandardOutput();
QString errorOutput = process.readAllStandardError(); QString errorOutput = process.readAllStandardError();
// 打印输出 // 打印输出
qDebug() << "Output:" << output; qDebug() << "Output:" << output;
qDebug() << "Error Output:" << errorOutput; qDebug() << "Error Output:" << errorOutput;
} }

View File

@ -4,6 +4,7 @@
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QGridLayout> #include <QGridLayout>
#include <QPainter> #include <QPainter>
#include <QFileInfo>
#include "../DockTitleBar.h" #include "../DockTitleBar.h"
#include "../DockWidget.h" #include "../DockWidget.h"
@ -15,6 +16,7 @@
#include "workspace/WorkSpace.h" #include "workspace/WorkSpace.h"
#include "workspace/Timestep.h" #include "workspace/Timestep.h"
#include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpaceManager.h"
#include "workspace/LampStatus.h"
SignalIndicatorLampUI::SignalIndicatorLampUI(QWidget* parent) SignalIndicatorLampUI::SignalIndicatorLampUI(QWidget* parent)
: QWidget(parent) : QWidget(parent)
@ -35,12 +37,21 @@ void SignalIndicatorLampUI::AttachDock(DockWidget* dockWidget)
return; return;
} }
if (nullptr != dockWidget) {
m_titleText = dockWidget->windowTitle();
}
dockWidget->SetDockWidgetTitleBar(nullptr); dockWidget->SetDockWidgetTitleBar(nullptr);
dockWidget->setWidget(this); dockWidget->setWidget(this);
DockTitleBar* dockTitleBar = new DockTitleBar; DockTitleBar* dockTitleBar = new DockTitleBar;
m_pDockTitleBar = dockTitleBar;
if (m_titleText.isEmpty()) {
dockTitleBar->SetTitle(tr("Signal Indicator Lamp")); dockTitleBar->SetTitle(tr("Signal Indicator Lamp"));
} else {
dockTitleBar->SetTitle(m_titleText);
}
dockWidget->SetDockWidgetTitleBar(dockTitleBar); dockWidget->SetDockWidgetTitleBar(dockTitleBar);
} }
@ -183,12 +194,16 @@ void SignalIndicatorLampUI::UpdateIndicatorLamp(QStringList& lamps, LayoutType t
void SignalIndicatorLampUI::InitLamp(const QString& strFile) void SignalIndicatorLampUI::InitLamp(const QString& strFile)
{ {
ParseLamp(strFile); bool bRet = ParseLamp(strFile);
if (nullptr != m_pDockTitleBar && bRet) {
QFileInfo fileInfo(strFile);
m_pDockTitleBar->SetTitle(tr("%1 -- %2").arg(m_titleText).arg(fileInfo.fileName()));
}
QStringList listLamp; QStringList listLamp;
for (size_t i = 0; i < m_iLampCount; i++) for (size_t i = 0; i < m_iLampCount; i++)
{ {
listLamp <<tr("light") + QString::number(i+1); // 指示灯 listLamp <<tr("light") + QString::number(i+1); // ָʾ<EFBFBD><EFBFBD>
} }
InitIndicatorLamp(listLamp, SignalIndicatorLampUI::HLyt, listLamp.size()); InitIndicatorLamp(listLamp, SignalIndicatorLampUI::HLyt, listLamp.size());
@ -240,6 +255,12 @@ void SignalIndicatorLampUI::OnWorkSpaceChanged(WorkSpace* worksapce) {
} }
connect(worksapce, &WorkSpace::TimestepChanged, this, &SignalIndicatorLampUI::OnTimestepChanged); connect(worksapce, &WorkSpace::TimestepChanged, this, &SignalIndicatorLampUI::OnTimestepChanged);
auto lamp = worksapce->GetLampStatus();
if (nullptr != lamp) {
InitLamp(lamp->GetPath());
}
// Initialize the lamp with the current workspace's lamp file
} }
void SignalIndicatorLampUI::OnTimestepChanged(Timestep* timestep) { void SignalIndicatorLampUI::OnTimestepChanged(Timestep* timestep) {
@ -263,12 +284,12 @@ void SignalIndicatorLampUI::paintEvent(QPaintEvent* event)
painter.drawRect(QRect(5,5,rect().width() - 10, rect().height() - 10)); painter.drawRect(QRect(5,5,rect().width() - 10, rect().height() - 10));
} }
void SignalIndicatorLampUI::ParseLamp(const QString& strFile) bool SignalIndicatorLampUI::ParseLamp(const QString& strFile)
{ {
if (strFile.isEmpty()) if (strFile.isEmpty())
{ {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查数据Lamp文件路径")); QMessageBox::information(nullptr, QString::fromLocal8Bit("<EFBFBD><EFBFBD>ʾ"), QString::fromLocal8Bit("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Lamp<EFBFBD>ļ<EFBFBD>·<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"));
return; return false;
} }
m_lampStatus.clear(); m_lampStatus.clear();
@ -293,4 +314,6 @@ void SignalIndicatorLampUI::ParseLamp(const QString& strFile)
file.close(); file.close();
} }
return true;
} }

View File

@ -13,11 +13,11 @@ class SignalIndicatorLampUI : public QWidget
Q_OBJECT Q_OBJECT
public: public:
enum LayoutType // 信号灯布局类型 enum LayoutType // <EFBFBD>źŵƲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{ {
HLyt, // ˮƽ HLyt, // ˮƽ
VLyt, // 垂直 VLyt, // <EFBFBD><EFBFBD>ֱ
GLyt, // 网格 GLyt, // <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}; };
SignalIndicatorLampUI( QWidget *parent = Q_NULLPTR); SignalIndicatorLampUI( QWidget *parent = Q_NULLPTR);
@ -42,7 +42,7 @@ protected slots:
protected: protected:
void paintEvent(QPaintEvent* event); void paintEvent(QPaintEvent* event);
void ParseLamp(const QString& strFile); bool ParseLamp(const QString& strFile);
private: private:
Ui::SignalIndicatorLampUI ui; Ui::SignalIndicatorLampUI ui;
@ -51,4 +51,7 @@ private:
QList<int> m_lampStatus; QList<int> m_lampStatus;
int m_iLampCount = 0; int m_iLampCount = 0;
QString m_titleText;
class DockTitleBar* m_pDockTitleBar { nullptr };
}; };

View File

@ -26,6 +26,7 @@
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
#include "ui_MainFrame.h" #include "ui_MainFrame.h"
#include "viewer/OsgWidget.h"
MainFrame* s_instance { nullptr }; MainFrame* s_instance { nullptr };
@ -115,9 +116,9 @@ void MainFrame::InitUI() {
MainWindow* mainWindow = new MainWindow(this); MainWindow* mainWindow = new MainWindow(this);
layout->addWidget(mainWindow); layout->addWidget(mainWindow);
QtOsgViewWidget* viewWidget = mainWindow->GetViewWidget(); OsgWidget* viewWidget = mainWindow->GetViewWidget();
connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &QtOsgViewWidget::OnLoadDyt); connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &OsgWidget::OnLoadDyt);
connect(viewWidget, &QtOsgViewWidget::signalResetWorkSpace, mainWindow, &MainWindow::slotResetWorkSpace); connect(viewWidget, &OsgWidget::signalResetWorkSpace, mainWindow, &MainWindow::slotResetWorkSpace);
connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting); connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting);

View File

@ -39,7 +39,6 @@ protected:
void OnMenuTrigged(); void OnMenuTrigged();
void SetCurrentMenu(int index); void SetCurrentMenu(int index);
private: private:
void InitUI(); void InitUI();
void AddMenuWidget(const QString& name, const QString& text, QWidget* widget); void AddMenuWidget(const QString& name, const QString& text, QWidget* widget);

View File

@ -1,12 +1,5 @@
#include "MainWindow.h" #include "MainWindow.h"
#include <QBoxLayout>
#include <QUrl>
#include <QFile>
#include <QFileInfo>
#include <QMimeDatabase>
#include <QDir>
#include <qtabwidget.h> #include <qtabwidget.h>
#include "PropertyBrowser.h" #include "PropertyBrowser.h"
@ -34,6 +27,7 @@
#include "Matlab/MatlabObject.h" #include "Matlab/MatlabObject.h"
#include "ui_MainWindow.h" #include "ui_MainWindow.h"
#include "viewer/OsgWidget.h"
MainWindow::MainWindow(QWidget* parent) MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent) : QMainWindow(parent)
@ -44,7 +38,7 @@ MainWindow::MainWindow(QWidget* parent)
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
OsgViewer::Get().Uninitialize(); UninitUI();
delete ui; delete ui;
} }
@ -83,9 +77,9 @@ void MainWindow::InitUI() {
connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange); connect(modelBrowser_, &ModelBrowser::WorkSpaceChange, propertyBrowser_, &PropertyBrowser::OnWorkSpaceChange);
connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange); connect(modelBrowser_, &ModelBrowser::EntityChange, propertyBrowser_, &PropertyBrowser::OnEntityChange);
qtOsgViewWidget_ = new QtOsgViewWidget; qtOsgViewWidget_ = new OsgWidget;
qtOsgViewWidget_->Initialize(); qtOsgViewWidget_->Initialize();
m_mapDockWidget.insert("PropertyBrowser", attribte); //m_mapDockWidget.insert("PropertyBrowser", attribte);
QString wavePath ="", speedPath = "", rdPath = "", matlabParam=""; QString wavePath ="", speedPath = "", rdPath = "", matlabParam="";
if (WorkSpaceManager::Get().GetCurrent()) if (WorkSpaceManager::Get().GetCurrent())
@ -138,14 +132,14 @@ void MainWindow::InitUI() {
targetUITable_ = new TargetListWgt; targetUITable_ = new TargetListWgt;
QStringList headerLabels; QStringList headerLabels;
headerLabels << tr("Target number") << tr("Signal-to-noise ratio") //QString::fromLocal8Bit("目标编号") << QString::fromLocal8Bit("信噪比") headerLabels << tr("Target number") << tr("Signal-to-noise ratio")
<< tr("Azimuth line of sight") << tr("Pitch gaze angle") // QString::fromLocal8Bit("方位视线角") << QString::fromLocal8Bit("俯仰视线角") << tr("Azimuth line of sight") << tr("Pitch gaze angle")
<< tr("azimuth") << tr("Pitch angle") // QString::fromLocal8Bit("方位角") << QString::fromLocal8Bit("俯仰角") << tr("azimuth") << tr("Pitch angle")
<< tr("attribute") << tr("Doppler") // QString::fromLocal8Bit("属性") << QString::fromLocal8Bit("多普勒") << tr("attribute") << tr("Doppler")
<< tr("course") << tr("Speed") // QString::fromLocal8Bit("航向") << QString::fromLocal8Bit("航速") << tr("course") << tr("Speed")
<< tr("longitude") << tr("latitude") // QString::fromLocal8Bit("经度") << QString::fromLocal8Bit("纬度") << tr("longitude") << tr("latitude")
<< tr("distance") << tr("velocity") // QString::fromLocal8Bit("距离") << QString::fromLocal8Bit("速度") << tr("distance") << tr("velocity")
<< tr("Radial dimensions") << tr("Target RCS"); // QString::fromLocal8Bit("径向尺寸") << QString::fromLocal8Bit("目标RCS"); << tr("Radial dimensions") << tr("Target RCS");
targetUITable_->SetHeader(headerLabels); targetUITable_->SetHeader(headerLabels);
//const QString reportPath = RecourceHelper::Get().GetBasePath() + "/workspace/Report.txt"; //const QString reportPath = RecourceHelper::Get().GetBasePath() + "/workspace/Report.txt";
@ -172,32 +166,42 @@ void MainWindow::InitUI() {
addParamDlg_->AttachDock(addParamSettingDock); addParamDlg_->AttachDock(addParamSettingDock);
m_mapDockWidget.insert("ParamSetting", addParamSettingDock); m_mapDockWidget.insert("ParamSetting", addParamSettingDock);
DockWidget* matlabDock = new DockWidget(tr("Matlab File"), 0); DockWidget* matlabDock = new DockWidget(tr("bat File"), 0);
matlabFileDlg_ = new CodeEdtUI; matlabFileDlg_ = new CodeEdtUI;
matlabFileDlg_->AttachDock(matlabDock); matlabFileDlg_->AttachDock(matlabDock);
m_mapDockWidget.insert("Matlab", matlabDock); m_mapDockWidget.insert("Matlab", matlabDock);
ui->discript->setText(tr("name: 5year 0412")); //ui->discript->setText(tr("name: 5year 0412"));
//ui->status->setText(tr("start: no start")); //ui->status->setText(tr("start: no start"));
InitDockLayout(); InitDockLayout();
//ui->viewWidget->layout()->addWidget(qtOsgViewWidget_); //ui->viewWidget->layout()->addWidget(qtOsgViewWidget_);
qtOsgViewWidget_->LoadDefaultScene(); qtOsgViewWidget_->LoadDefaultScene();
OsgViewer::Get().Initialize(); /*OsgViewer::Get().Initialize();
OsgViewer::Get().OnFrame(); OsgViewer::Get().OnFrame();*/
#if 1 #if 0
// MatlabObject* mtlb = new MatlabObject; // MatlabObject* mtlb = new MatlabObject;
MatlabObject::GetInstance()->RunMatlabFile(""); MatlabObject::GetInstance()->RunMatlabFile("");
#endif // 1 #endif // 1
} }
void MainWindow::UninitUI() {
if (qtOsgViewWidget_) {
qtOsgViewWidget_->Uninitialize();
delete qtOsgViewWidget_;
qtOsgViewWidget_ = nullptr;
}
}
void MainWindow::InitDockLayout() { void MainWindow::InitDockLayout() {
while (tabWidget_->count() > 0) { while (tabWidget_->count() > 0) {
tabWidget_->removeTab(0); tabWidget_->removeTab(0);
} }
tabWidget_->tabBar()->setExpanding(true);
QVariantList listTab = pSettingUI->GetAreaLayout().toList(); QVariantList listTab = pSettingUI->GetAreaLayout().toList();
for (int i = 0; i < listTab.size(); i++) { for (int i = 0; i < listTab.size(); i++) {
QVariantMap mapTab = listTab[i].toMap(); QVariantMap mapTab = listTab[i].toMap();
@ -211,8 +215,8 @@ void MainWindow::InitDockLayout() {
tabWidget_->insertTab(i, mainWindow_, strTabName); tabWidget_->insertTab(i, mainWindow_, strTabName);
if (listDocArea[0].toList().size() > 0) { if (listDocArea[0].toList().size() > 0) {
mainWindow_->setCentralWidget(qtOsgViewWidget_); mainWindow_->setCentralWidget(qtOsgViewWidget_);
OsgViewer::Get().Initialize(); //OsgViewer::Get().Initialize();
OsgViewer::Get().OnFrame(); //OsgViewer::Get().OnFrame();
} else { } else {
mainWindow_->takeCentralWidget(); mainWindow_->takeCentralWidget();
} }
@ -266,6 +270,7 @@ void MainWindow::InitDockLayout() {
} }
} }
tabWidget_->tabBar()->setMinimumWidth(500);
/* AddDockArea("DockLeftArea"); /* AddDockArea("DockLeftArea");
AddDockArea("DockTopArea"); AddDockArea("DockTopArea");
AddDockArea("DockRightArea"); AddDockArea("DockRightArea");
@ -331,14 +336,14 @@ void MainWindow::AddDockArea(const QString& strArea) {
} }
void MainWindow::OnTabifiedDockWidgetActivated(QDockWidget* dockWidget) { void MainWindow::OnTabifiedDockWidgetActivated(QDockWidget* dockWidget) {
if (dockWidget) { //if (dockWidget) {
QMainWindow* mainWindow = qobject_cast<QMainWindow*>(dockWidget->parentWidget()); // QMainWindow* mainWindow = qobject_cast<QMainWindow*>(dockWidget->parentWidget());
if (mainWindow) { // if (mainWindow) {
mainWindow->removeDockWidget(dockWidget); // mainWindow->removeDockWidget(dockWidget);
} // }
// tabWidget_->setCurrentWidget(dockWidget->parentWidget()); // // tabWidget_->setCurrentWidget(dockWidget->parentWidget());
} //}
} }
void MainWindow::slotShowUISetting() { void MainWindow::slotShowUISetting() {
@ -348,20 +353,16 @@ void MainWindow::slotShowUISetting() {
void MainWindow::slotResetWorkSpace() void MainWindow::slotResetWorkSpace()
{ {
QString wavePath = "", speedPath = "", rdPath = ""; QString wavePath = "", speedPath = "", rdPath = "";
if (WorkSpaceManager::Get().GetCurrent()) if (WorkSpaceManager::Get().GetCurrent()) {
{ if (!WorkSpaceManager::Get().GetCurrent()->GetWavePath().isEmpty()) {
if (!WorkSpaceManager::Get().GetCurrent()->GetWavePath().isEmpty())
{
wavePath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetWavePath(); wavePath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetWavePath();
} }
if (!WorkSpaceManager::Get().GetCurrent()->GetReportPath().isEmpty()) if (!WorkSpaceManager::Get().GetCurrent()->GetReportPath().isEmpty()) {
{
speedPath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetReportPath(); speedPath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetReportPath();
} }
if (!WorkSpaceManager::Get().GetCurrent()->GetRDPath().isEmpty()) if (!WorkSpaceManager::Get().GetCurrent()->GetRDPath().isEmpty()) {
{
rdPath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetRDPath(); rdPath = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetRDPath();
} }
} }

View File

@ -21,7 +21,7 @@ public:
class ModelBrowser* GetModelBrowser() const { class ModelBrowser* GetModelBrowser() const {
return modelBrowser_; return modelBrowser_;
} }
class QtOsgViewWidget* GetViewWidget() const { class OsgWidget* GetViewWidget() const {
return qtOsgViewWidget_; return qtOsgViewWidget_;
} }
@ -42,6 +42,7 @@ public slots:
private: private:
void InitUI(); void InitUI();
void UninitUI();
void InitDockLayout(); void InitDockLayout();
void AddDockArea(const QString& strArea); void AddDockArea(const QString& strArea);
@ -55,7 +56,7 @@ private:
class ModelBrowser* modelBrowser_{ nullptr }; class ModelBrowser* modelBrowser_{ nullptr };
class PropertyBrowser* propertyBrowser_{ nullptr }; class PropertyBrowser* propertyBrowser_{ nullptr };
class QWebEngineView* webEngineView_{ nullptr }; class QWebEngineView* webEngineView_{ nullptr };
class QtOsgViewWidget* qtOsgViewWidget_{ nullptr }; class OsgWidget* qtOsgViewWidget_{ nullptr };
class FitCurveDialog* fitCurveDlg_{ nullptr }; class FitCurveDialog* fitCurveDlg_{ nullptr };
class FitCurveDialog* fitYLgCurveDlg_{ nullptr }; class FitCurveDialog* fitYLgCurveDlg_{ nullptr };

View File

@ -1,11 +1,15 @@
#include "ChartPlotMenu.h" #include "ChartPlotMenu.h"
#include "../Matlab/MatlabObject.h" #include "../Matlab/MatlabObject.h"
#include "../../common/RecourceHelper.h" #include "../../common/RecourceHelper.h"
#include "workspace/WorkSpace.h" #include "workspace/WorkSpace.h"
#include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpaceManager.h"
#include "workspace/LampStatus.h"
#include "utils/FileUtils.h"
#include <qmessagebox.h> #include <qmessagebox.h>
#include <qfiledialog.h>
ChartPlotMenu::ChartPlotMenu(QWidget *parent) ChartPlotMenu::ChartPlotMenu(QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
@ -24,19 +28,214 @@ void ChartPlotMenu::InitMenu()
connect(ui.toolButton, &QToolButton::clicked, this, [=] { connect(ui.toolButton, &QToolButton::clicked, this, [=] {
if (WorkSpaceManager::Get().GetCurrent()) if (WorkSpaceManager::Get().GetCurrent())
{ {
QString strFile = WorkSpaceManager::Get().GetCurrent()->GetSimMatlab(); QString strFile = WorkSpaceManager::Get().GetCurrent()->GetSimMatlab();
if (!strFile.isEmpty()) if (!strFile.isEmpty())
{ {
strFile = RecourceHelper::Get().GetBasePath() + "/" + WorkSpaceManager::Get().GetCurrent()->GetSimMatlab();
//MatlabObject::GetInstance()->RunMatlabFile("D:\\DYT\\TestGUI\\xierutest.m");
MatlabObject::GetInstance()->RunMatlabFile(strFile); MatlabObject::GetInstance()->RunMatlabFile(strFile);
} }
else else
{ {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查仿真文件路径是否存在!")); QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查仿真文件路径是否存在!"));
} }
} }
}); });
connect(ui.toolButton_2, &QToolButton::clicked, this, [=] {
auto current = WorkSpaceManager::Get().GetCurrent();
if (nullptr == current) {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先创建空间!"));
return;
}
QString strSel = QFileDialog::getOpenFileName(this, u8"选择仿真运行文件", RecourceHelper::Get().GetBasePath() + "/workspace/", "*.m");
if (strSel.isEmpty()) {
LOG_WARN("选择文件为空");
return;
}
const QString old = current->GetSimMatlab();
if (old == strSel) {
LOG_INFO("选择文件与当前文件相同");
return;
} else if (!old.isEmpty()) {
if (QFileInfo(old).isFile() && QFile::exists(old)) {
if (QMessageBox::Yes == QMessageBox::question(nullptr,
QString::fromLocal8Bit("询问"),
QString::fromLocal8Bit("替换当前仿真文件!"),
QMessageBox::Yes | QMessageBox::No)
) {
if (!QFile::remove(old)) {
LOG_WARN("删除文件失败");
QMessageBox::information(nullptr,
QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("删除文件失败!"));
return;
}
}
}
}
current->SetSimMatlab(strSel);
});
connect(ui.toolButton_5, &QToolButton::clicked, this, [=] {
auto current = WorkSpaceManager::Get().GetCurrent();
if (nullptr == current) {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先创建空间!"));
return;
}
QString strSel = QFileDialog::getOpenFileName(this, u8"选择Wave文件", RecourceHelper::Get().GetBasePath() + "/workspace/", "*.txt");
if (strSel.isEmpty()) {
LOG_WARN("选择文件为空");
return;
}
const QString old = current->GetWavePath();
if (old == strSel) {
LOG_INFO("选择文件与当前文件相同");
return;
}
else if (!old.isEmpty()) {
if (QFileInfo(old).isFile() && QFile::exists(old)) {
if (QMessageBox::Yes == QMessageBox::question(nullptr,
QString::fromLocal8Bit("询问"),
QString::fromLocal8Bit("替换当前Wave文件"),
QMessageBox::Yes | QMessageBox::No)
) {
if (!QFile::remove(old)) {
LOG_WARN("删除文件失败");
QMessageBox::information(nullptr,
QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("删除文件失败!"));
return;
}
}
}
}
current->SetWavePath(strSel);
});
connect(ui.toolButton_3, &QToolButton::clicked, this, [=] {
auto current = WorkSpaceManager::Get().GetCurrent();
if (nullptr == current) {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先创建空间!"));
return;
}
QString strSel = QFileDialog::getOpenFileName(this, u8"选择RD文件", RecourceHelper::Get().GetBasePath() + "/workspace/", "*.txt");
if (strSel.isEmpty()) {
LOG_WARN("选择文件为空");
return;
}
const QString old = current->GetRDPath();
if (old == strSel) {
LOG_INFO("选择文件与当前文件相同");
return;
}
else if (!old.isEmpty()) {
if (QFileInfo(old).isFile() && QFile::exists(old)) {
if (QMessageBox::Yes == QMessageBox::question(nullptr,
QString::fromLocal8Bit("询问"),
QString::fromLocal8Bit("替换当前RD文件"),
QMessageBox::Yes | QMessageBox::No)
) {
if (!QFile::remove(old)) {
LOG_WARN("删除文件失败");
QMessageBox::information(nullptr,
QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("删除文件失败!"));
return;
}
}
}
}
current->SetRDPath(strSel);
});
connect(ui.toolButton_4, &QToolButton::clicked, this, [=] {
auto current = WorkSpaceManager::Get().GetCurrent();
if (nullptr == current) {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先创建空间!"));
return;
}
QString strSel = QFileDialog::getOpenFileName(this, u8"选择Report文件", RecourceHelper::Get().GetBasePath() + "/workspace/", "*.txt");
if (strSel.isEmpty()) {
LOG_WARN("选择文件为空");
return;
}
const QString old = current->GetReportPath();
if (old == strSel) {
LOG_INFO("选择文件与当前文件相同");
return;
}
else if (!old.isEmpty()) {
if (QFileInfo(old).isFile() && QFile::exists(old)) {
if (QMessageBox::Yes == QMessageBox::question(nullptr,
QString::fromLocal8Bit("询问"),
QString::fromLocal8Bit("替换当前Report文件"),
QMessageBox::Yes | QMessageBox::No)
) {
if (!QFile::remove(old)) {
LOG_WARN("删除文件失败");
QMessageBox::information(nullptr,
QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("删除文件失败!"));
return;
}
}
}
}
current->SetReportPath(strSel);
});
connect(ui.toolButton_6, &QToolButton::clicked, this, [=] {
auto current = WorkSpaceManager::Get().GetCurrent();
if (nullptr == current) {
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先创建空间!"));
return;
}
QString strSel = QFileDialog::getOpenFileName(this, u8"选择Lamp文件", RecourceHelper::Get().GetBasePath() + "/workspace/", "*.txt");
if (strSel.isEmpty()) {
LOG_WARN("选择文件为空");
return;
}
auto lampStatus = current->GetLampStatus();
if (nullptr != lampStatus) {
const QString& old = lampStatus->GetPath();
if (old == strSel) {
LOG_INFO("选择文件与当前文件相同");
return;
}
else if (!old.isEmpty()) {
if (QFileInfo(old).isFile() && QFile::exists(old)) {
if (QMessageBox::Yes == QMessageBox::question(nullptr,
QString::fromLocal8Bit("询问"),
QString::fromLocal8Bit("替换当前Lamp文件"),
QMessageBox::Yes | QMessageBox::No)
) {
if (!QFile::remove(old)) {
LOG_WARN("删除文件失败");
QMessageBox::information(nullptr,
QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("删除文件失败!"));
return;
}
}
}
}
}
QFileInfo fileInfo(strSel);
QString dirPath = QString("%1/%2").arg(current->GetDir(), fileInfo.fileName());
bool sucess = FileUtils::CopyFileToPath(strSel, dirPath, true);
LOG_INFO("copy Wave file {}: {} to {}",
strSel.toLocal8Bit().data(),
dirPath.toLocal8Bit().data(),
sucess);
current->SetLampPath(dirPath);
});
} }

View File

@ -16,6 +16,71 @@
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="toolButton_5">
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Wave文件</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_4">
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Report文件</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_3">
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>RD文件</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_2">
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Matlab文件</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="toolButton_6">
<property name="minimumSize">
<size>
<width>60</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Lamp文件</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QToolButton" name="toolButton"> <widget class="QToolButton" name="toolButton">
<property name="minimumSize"> <property name="minimumSize">

View File

@ -38,7 +38,7 @@ void PlayManagerMenu::OnPlay() {
} }
Timestep* timestep = workSpace_->GetTimestep(); Timestep* timestep = workSpace_->GetTimestep();
if (nullptr == timestep) { if (nullptr == timestep) {
QMessageBox::warning(&MainFrame::Get(), tr("warning"), tr("has not workspace"), QMessageBox::warning(&MainFrame::Get(), tr("warning"), tr("not timestep"),
QMessageBox::Ok); QMessageBox::Ok);
LOG_INFO("current is nullptr"); LOG_INFO("current is nullptr");
return; return;

View File

@ -37,7 +37,7 @@
<item> <item>
<widget class="QToolButton" name="menu_window_manager"> <widget class="QToolButton" name="menu_window_manager">
<property name="toolTip"> <property name="toolTip">
<string>ui setting</string> <string>windows setting</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>

View File

@ -5,7 +5,7 @@
#include <QVariant> #include <QVariant>
#include <QMenu> #include <QMenu>
#include <osgEarth/EarthManipulator> #include <osgEarthUtil/EarthManipulator>
#include "common/RecourceHelper.h" #include "common/RecourceHelper.h"
#include "common/SpdLogger.h" #include "common/SpdLogger.h"
@ -16,6 +16,7 @@
#include "viewer/OsgCameraManipulator.h" #include "viewer/OsgCameraManipulator.h"
#include "viewer/CameraControlManipulator.h" #include "viewer/CameraControlManipulator.h"
#include "ui/ModelBrowser/EntityConstent.h" #include "ui/ModelBrowser/EntityConstent.h"
#include "workspace/WorkSpaceManager.h"
ModelTreeWidget::ModelTreeWidget(QWidget* parent) ModelTreeWidget::ModelTreeWidget(QWidget* parent)
@ -91,25 +92,18 @@ void ModelTreeWidget::OnEntityRemoved(Entity* entity) {
void ModelTreeWidget::contextMenuEvent(QContextMenuEvent* event) { void ModelTreeWidget::contextMenuEvent(QContextMenuEvent* event) {
QTreeWidgetItem* item = itemAt(event->pos()); QTreeWidgetItem* item = itemAt(event->pos());
if (nullptr == item) { if (nullptr != item) {
QMenu menu(this); QVariant value = item->data(0, E_Entity);
QAction* addEntiy = new QAction(tr("Release Track"), this); if (!value.isValid()) {
connect(addEntiy, &QAction::triggered, [this]() { LOG_WARN("unknown data E_Entity");
OnTrackEntity(nullptr);
}
);
menu.addAction(addEntiy);
menu.exec(event->globalPos());
return; return;
} }
QVariant value = item->data(0, E_Entity);
if (nullptr != item && value.isValid()) {
Entity* entity = value.value<Entity*>(); Entity* entity = value.value<Entity*>();
PopupEntityMenu(event, entity); PopupEntityMenu(event, entity);
} else { } else {
QMenu menu(this); QMenu menu(this);
// 警속꽉데淃
QAction* addEntiy = new QAction(tr("Add boke Entity"), this); QAction* addEntiy = new QAction(tr("Add boke Entity"), this);
connect(addEntiy, &QAction::triggered, [this]() { connect(addEntiy, &QAction::triggered, [this]() {
OnAddMeshEntity("boke/boke.ive", "boke"); OnAddMeshEntity("boke/boke.ive", "boke");
@ -152,7 +146,7 @@ void ModelTreeWidget::contextMenuEvent(QContextMenuEvent* event) {
); );
menu.addAction(addEntiy); menu.addAction(addEntiy);
// 鞫刻꽉데 // <EFBFBD><EFBFBD>ʾ<EFBFBD>˵<EFBFBD>
menu.exec(event->globalPos()); menu.exec(event->globalPos());
} }
@ -214,6 +208,8 @@ void ModelTreeWidget::OnAddMeshEntity(const QString& mesh, const QString& name)
int count = currentWorkSpace_->GetEntities().size(); int count = currentWorkSpace_->GetEntities().size();
entity->SetName(QString("%1_%2").arg(name).arg(count)); entity->SetName(QString("%1_%2").arg(name).arg(count));
currentWorkSpace_->AddEntity(entity); currentWorkSpace_->AddEntity(entity);
OnAddComponent("LabelComponent", entity);
} }
SceneComponent* ModelTreeWidget::OnAddComponent(const QString& typeName, Entity* entity) { SceneComponent* ModelTreeWidget::OnAddComponent(const QString& typeName, Entity* entity) {
@ -247,33 +243,68 @@ void ModelTreeWidget::OnDeleteEntity(Entity* entity) {
void ModelTreeWidget::PopupEntityMenu(QContextMenuEvent* event, Entity* entity) { void ModelTreeWidget::PopupEntityMenu(QContextMenuEvent* event, Entity* entity) {
QMenu menu(this); QMenu menu(this);
if (nullptr != entity) {
auto workspace = entity->GetWorkspace();
if (nullptr == workspace) {
LOG_WARN("workspace is nullptr");
return;
}
if (workspace->GetTrackEntity() == entity) {
QAction* releaseTrack = new QAction(tr("Release Track"), this);
connect(releaseTrack, &QAction::triggered, [this]() {
OnTrackEntity(nullptr);
}
);
menu.addAction(releaseTrack);
}
else {
QAction* addEntiy = new QAction(tr("Track"), this); QAction* addEntiy = new QAction(tr("Track"), this);
menu.addAction(addEntiy); menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() { connect(addEntiy, &QAction::triggered, [this, entity]() {
OnTrackEntity(entity); OnTrackEntity(entity);
} }
); );
}
}
// 警속꽉데淃 bool hasLableComponent = entity->HasComponent("LabelComponent");
addEntiy = new QAction(tr("Add Mesh Component"), this); if (!hasLableComponent) {
QAction* addEntiy = new QAction(tr("Add Label Component"), this);
menu.addAction(addEntiy); menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("LabelComponent", entity);
}
);
}
// 쉥꽉데淃警속돕꽉데櫓 bool hasMeshComponent = entity->HasComponent("MeshComponent");
addEntiy = new QAction(tr("Add Path Component"), this); if (!hasMeshComponent) {
QAction* addEntiy = new QAction(tr("Add Mesh Component"), this);
menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("MeshComponent", entity);
}
);
}
bool hasPathComponent = entity->HasComponent("PathComponent");
if (!hasPathComponent) {
QAction* addEntiy = new QAction(tr("Add Path Component"), this);
menu.addAction(addEntiy); menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() { connect(addEntiy, &QAction::triggered, [this, entity]() {
OnAddComponent("PathComponent", entity); OnAddComponent("PathComponent", entity);
} }
); );
}
addEntiy = new QAction(tr("Delete"), this); QAction* addEntiy = new QAction(tr("Delete"), this);
menu.addAction(addEntiy); menu.addAction(addEntiy);
connect(addEntiy, &QAction::triggered, [this, entity]() { connect(addEntiy, &QAction::triggered, [this, entity]() {
OnDeleteEntity(entity); OnDeleteEntity(entity);
} }
); );
// 鞫刻꽉데
menu.exec(event->globalPos()); menu.exec(event->globalPos());
} }
@ -324,35 +355,20 @@ void ModelTreeWidget::OnAddSatelliteEntity() {
} }
void ModelTreeWidget::OnTrackEntity(Entity* entity) { void ModelTreeWidget::OnTrackEntity(Entity* entity) {
OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator(); auto workspace = WorkSpaceManager::Get().GetCurrent();
if (nullptr == manipulator) { if (!workspace){
LOG_WARN("manipulator is nullptr"); LOG_WARN("scene is nullptr");
return; return;
} }
if (nullptr == entity) {
osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator(); LOG_INFO("clear track entity");
osgEarth::Util::EarthManipulator* ccm = dynamic_cast<osgEarth::Util::EarthManipulator*>(gaManipulator); workspace->UntrackEntity();
if (nullptr != ccm) { return;
if (nullptr != entity) {
osg::MatrixTransform* mt = entity->GetRootComponent()->GetMatrixTransform();
ccm->setNode(mt);
ccm->getSettings()->setTetherMode(osgEarth::Util::EarthManipulator::TETHER_CENTER);
osgEarth::Util::Viewpoint newVP;
newVP.setNode(mt);
double range = mt->getBound().radius() * 10.0;
newVP.range()->set(range, osgEarth::Units::METERS);
const osg::Vec3 rotation = entity->GetRootComponent()->GetTransform()->GetRotation();
newVP.heading()->set(rotation.x(), osgEarth::Units::DEGREES);
newVP.pitch()->set(rotation.y() - 15.0, osgEarth::Units::DEGREES);
//newVP.roll()->set(rotation.z(), osgEarth::Units::DEGREES);
ccm->setViewpoint(newVP, 1.5);
//ccm->setTetherMode(osgGA::CameraManipulator::TETHER_CENTER_AND_ROTATION);
} else {
ccm->clearViewpoint();
}
} }
LOG_INFO("track entity: {}", entity->GetName().toStdString());
workspace->TrackEntity(entity);
} }
void ModelTreeWidget::AddEntity(class QTreeWidgetItem* parent, Entity* entity) { void ModelTreeWidget::AddEntity(class QTreeWidgetItem* parent, Entity* entity) {

View File

@ -91,6 +91,11 @@ void PropertyBrowser::OnEntityChange(const QVariant& value) {
std::vector<SceneComponent*> children = component->GetChildren(); std::vector<SceneComponent*> children = component->GetChildren();
for (auto child : children) { for (auto child : children) {
componentManager = GetCompononetPropertyManager(child->GetSelfTypeName().c_str()); componentManager = GetCompononetPropertyManager(child->GetSelfTypeName().c_str());
if (nullptr == componentManager) {
LOG_WARN("component is nullptr id {}", child->GetSelfTypeName());
continue;
}
if (nullptr == child) { if (nullptr == child) {
LOG_WARN("component is nullptr id {}", child->GetSelfTypeName()); LOG_WARN("component is nullptr id {}", child->GetSelfTypeName());
return; return;
@ -115,6 +120,8 @@ void PropertyBrowser::InitUI() {
} }
void PropertyBrowser::InitPropertyManager() { void PropertyBrowser::InitPropertyManager() {
intManager_ = new QtIntPropertyManager(this);
boolManager_ = new QtBoolPropertyManager(this);
doubleManager_ = new QtDoublePropertyManager(this); doubleManager_ = new QtDoublePropertyManager(this);
stringManager_ = new QtStringPropertyManager(this); stringManager_ = new QtStringPropertyManager(this);
colorManager_ = new QtColorPropertyManager(this); colorManager_ = new QtColorPropertyManager(this);
@ -133,6 +140,8 @@ void PropertyBrowser::InitPropertyManager() {
QtFilePathFactory* filePathFactory = new QtFilePathFactory(this); QtFilePathFactory* filePathFactory = new QtFilePathFactory(this);
//QtTransfromEditorFactory* transformFactory = new QtTransfromEditorFactory(this); //QtTransfromEditorFactory* transformFactory = new QtTransfromEditorFactory(this);
browser_->setFactoryForManager(intManager_, spinBoxFactory);
browser_->setFactoryForManager(boolManager_, checkBoxFactory);
browser_->setFactoryForManager(doubleManager_, doubleSpinBoxFactory); browser_->setFactoryForManager(doubleManager_, doubleSpinBoxFactory);
browser_->setFactoryForManager(stringManager_, lineEditFactory); browser_->setFactoryForManager(stringManager_, lineEditFactory);
browser_->setFactoryForManager(colorManager_->subIntPropertyManager(), spinBoxFactory); browser_->setFactoryForManager(colorManager_->subIntPropertyManager(), spinBoxFactory);
@ -144,6 +153,7 @@ void PropertyBrowser::InitPropertyManager() {
browser_->setFactoryForManager(workSpaceManager_->subStringProperyManager(), lineEditFactory); browser_->setFactoryForManager(workSpaceManager_->subStringProperyManager(), lineEditFactory);
browser_->setFactoryForManager(workSpaceManager_->subFilesProperyManager(), filePathFactory); browser_->setFactoryForManager(workSpaceManager_->subFilesProperyManager(), filePathFactory);
browser_->setFactoryForManager(entityManager_->subStringProperyManager(), lineEditFactory); browser_->setFactoryForManager(entityManager_->subStringProperyManager(), lineEditFactory);
browser_->setFactoryForManager(entityManager_->subBoolProperyManager(), checkBoxFactory);
browser_->setFactoryForManager( browser_->setFactoryForManager(
entityManager_->subTransfromProperyManager()->subVec3TPropertyManager()->subDoublePropertyManager(), entityManager_->subTransfromProperyManager()->subVec3TPropertyManager()->subDoublePropertyManager(),
doubleSpinBoxFactory); doubleSpinBoxFactory);
@ -205,7 +215,7 @@ void PropertyBrowser::Test() {
QtProperty* property; QtProperty* property;
property = modelBaseManager_->addProperty(tr("ModelBase")); property = modelBaseManager_->addProperty(tr("ModelBase"));
QModelAttbute modelAttr(QString("test"), QString("test222"), true, 1.0 ); QModelAttbute modelAttr(QString("test"), QString("test222"), true, 1.0 , true);
modelBaseManager_->setValue(property, modelAttr); modelBaseManager_->setValue(property, modelAttr);
addProperty(property, QLatin1String("brush")); addProperty(property, QLatin1String("brush"));

View File

@ -32,6 +32,8 @@ private:
private: private:
class QtTreePropertyBrowser* browser_{ nullptr }; class QtTreePropertyBrowser* browser_{ nullptr };
class QtIntPropertyManager* intManager_{ nullptr };
class QtBoolPropertyManager* boolManager_{ nullptr };
class QtDoublePropertyManager* doubleManager_{ nullptr }; class QtDoublePropertyManager* doubleManager_{ nullptr };
class QtStringPropertyManager* stringManager_{ nullptr }; class QtStringPropertyManager* stringManager_{ nullptr };
class QtColorPropertyManager* colorManager_{ nullptr }; class QtColorPropertyManager* colorManager_{ nullptr };

Some files were not shown because too many files have changed in this diff Show More