Merge branch 'new_osg' of http://brigecode.icu:16623/PM/DYTSrouce into new_osg
This commit is contained in:
commit
44b3fb6dbe
@ -26,8 +26,6 @@ SET(
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/translations/Dyt_zh_CN.ts
|
${CMAKE_CURRENT_SOURCE_DIR}/translations/Dyt_zh_CN.ts
|
||||||
)
|
)
|
||||||
|
|
||||||
# 控制是否在构建时自动运行 lupdate 更新 TS 文件。
|
|
||||||
# 关闭时仅在 TS 变更后编译生成 QM,避免每次构建都重新创建翻译文件。
|
|
||||||
option(UPDATE_TRANSLATIONS "Run lupdate to refresh TS files during build" OFF)
|
option(UPDATE_TRANSLATIONS "Run lupdate to refresh TS files during build" OFF)
|
||||||
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
if(${QT_VERSION_MAJOR} GREATER_EQUAL 6)
|
||||||
if(UPDATE_TRANSLATIONS)
|
if(UPDATE_TRANSLATIONS)
|
||||||
@ -205,7 +203,7 @@ endif()
|
|||||||
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ProjectDIR}/bin)
|
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${ProjectDIR}/bin)
|
||||||
|
|
||||||
TARGET_LINK_LIBRARIES(${PROJECT_NAME})
|
TARGET_LINK_LIBRARIES(${PROJECT_NAME})
|
||||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE")
|
# SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE")
|
||||||
|
|
||||||
add_custom_command(TARGET ${PROJECT_NAME}
|
add_custom_command(TARGET ${PROJECT_NAME}
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
<file>res/sys_min.png</file>
|
<file>res/sys_min.png</file>
|
||||||
<file>res/sys_restore.png</file>
|
<file>res/sys_restore.png</file>
|
||||||
<file>res/sys_icon.png</file>
|
<file>res/sys_icon.png</file>
|
||||||
|
<file>res/sys_icon.ico</file>
|
||||||
<file>res/sys_down.png</file>
|
<file>res/sys_down.png</file>
|
||||||
<file>res/sys_up.png</file>
|
<file>res/sys_up.png</file>
|
||||||
<file>res/select_file.ico</file>
|
<file>res/select_file.ico</file>
|
||||||
|
|||||||
@ -18,6 +18,7 @@ Application::Application(int& argc, char** argv, int /*= ApplicationFlags*/)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
|
Uninit();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Application::GetWorkSpacePath() {
|
QString Application::GetWorkSpacePath() {
|
||||||
@ -30,6 +31,15 @@ QString Application::GetBinPath() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::Init() {
|
void Application::Init() {
|
||||||
|
// Set application/taskbar icon early so all top-level windows inherit it
|
||||||
|
QIcon appIcon(":/res/sys_icon.ico");
|
||||||
|
if (!appIcon.isNull()) {
|
||||||
|
setWindowIcon(appIcon);
|
||||||
|
} else {
|
||||||
|
// Fallback to PNG if ICO is not embedded
|
||||||
|
setWindowIcon(QIcon(":/res/sys_icon.png"));
|
||||||
|
}
|
||||||
|
|
||||||
Singleton<MeshManager>::Create(this);
|
Singleton<MeshManager>::Create(this);
|
||||||
Singleton<RecourceHelper>::Create(this);
|
Singleton<RecourceHelper>::Create(this);
|
||||||
Singleton<EntityFactory>::Create(this);
|
Singleton<EntityFactory>::Create(this);
|
||||||
@ -53,8 +63,8 @@ void Application::Uninit() {
|
|||||||
timer_.stop();
|
timer_.stop();
|
||||||
}
|
}
|
||||||
//Singleton<PythonModule>::Destory();
|
//Singleton<PythonModule>::Destory();
|
||||||
Singleton<NetDriver>::Destory();
|
|
||||||
Singleton<PresetModelConfigParser>::Destory();
|
Singleton<PresetModelConfigParser>::Destory();
|
||||||
|
Singleton<NetDriver>::Destory();
|
||||||
Singleton<WorkSpaceManager>::Destory();
|
Singleton<WorkSpaceManager>::Destory();
|
||||||
Singleton<EntitiesManager>::Destory();
|
Singleton<EntitiesManager>::Destory();
|
||||||
Singleton<EntityFactory>::Destory();
|
Singleton<EntityFactory>::Destory();
|
||||||
|
|||||||
@ -31,6 +31,10 @@ void EntitiesManager::OnDestory() {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
for (auto* entity : entities) {
|
for (auto* entity : entities) {
|
||||||
|
// Detach scene graph nodes before deletion
|
||||||
|
if (auto* root = entity->GetRootComponent()) {
|
||||||
|
root->OnDestroy();
|
||||||
|
}
|
||||||
RemoveEntity(entity);
|
RemoveEntity(entity);
|
||||||
// Delete entities immediately to release scene graph resources before exit
|
// Delete entities immediately to release scene graph resources before exit
|
||||||
delete entity;
|
delete entity;
|
||||||
@ -139,8 +143,16 @@ bool EntitiesManager::DeleteEntity(Entity* entity) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure scene graph nodes are detached before deleting the entity
|
||||||
|
if (auto* root = entity->GetRootComponent()) {
|
||||||
|
root->OnDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
RemoveEntity(entity);
|
RemoveEntity(entity);
|
||||||
entity->deleteLater();
|
// Immediate deletion to ensure scene graph resources are released
|
||||||
|
// before viewer/context teardown. Using deleteLater() may invoke
|
||||||
|
// QObject cleanup after OSG/GL objects are gone, causing crashes.
|
||||||
|
delete entity;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -210,13 +210,37 @@ void SceneComponent::RemoveRender() {
|
|||||||
if (nullptr == mt_) {
|
if (nullptr == mt_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int count = mt_->getNumParents();
|
|
||||||
for (int i = 0; i < count; ++i) {
|
for (auto child : children_) {
|
||||||
|
child->RemoveRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If attached via GeoTransform (osgEarth), remove the GeoTransform from the scene
|
||||||
|
#ifndef USE_OCEAN
|
||||||
|
if (geo_.valid()) {
|
||||||
|
for (int i = geo_->getNumParents() - 1; i >= 0; --i) {
|
||||||
|
osg::Group* parent = geo_->getParent(i)->asGroup();
|
||||||
|
if (nullptr != parent) {
|
||||||
|
parent->removeChild(geo_.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Break the child link to mt_ to avoid lingering references
|
||||||
|
geo_->removeChild(mt_.get());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = mt_->getNumParents() - 1; i >= 0; --i) {
|
||||||
osg::Group* parent = mt_->getParent(i)->asGroup();
|
osg::Group* parent = mt_->getParent(i)->asGroup();
|
||||||
if (nullptr != parent) {
|
if (nullptr != parent) {
|
||||||
parent->removeChild(mt_);
|
parent->removeChild(mt_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Release local references proactively
|
||||||
|
#ifndef USE_OCEAN
|
||||||
|
geo_ = nullptr;
|
||||||
|
#endif
|
||||||
|
mt_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneComponent::RemoveParent() {
|
void SceneComponent::RemoveParent() {
|
||||||
|
|||||||
403
src/main.cpp
403
src/main.cpp
@ -12,6 +12,10 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
|
#include <QSplashScreen>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QLockFile>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include <osgViewer/CompositeViewer>
|
#include <osgViewer/CompositeViewer>
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
@ -22,7 +26,6 @@
|
|||||||
#include <osgEarth/MapNode>
|
#include <osgEarth/MapNode>
|
||||||
#include <osgEarthUtil/ExampleResources>
|
#include <osgEarthUtil/ExampleResources>
|
||||||
#include <osgGA/StateSetManipulator>
|
#include <osgGA/StateSetManipulator>
|
||||||
// #include <osgEarth/GLUtils>
|
|
||||||
|
|
||||||
#include "osgqt/GraphicsWindowQt.h"
|
#include "osgqt/GraphicsWindowQt.h"
|
||||||
#include "scene/ui/CompositeWidgetManager.h"
|
#include "scene/ui/CompositeWidgetManager.h"
|
||||||
@ -32,370 +35,48 @@
|
|||||||
#define LC "DYT"
|
#define LC "DYT"
|
||||||
#endif
|
#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");
|
// Single-instance guard to avoid multiple launches from repeated clicks
|
||||||
|
const QString lockPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/Dyt_app.lock";
|
||||||
MainFrame mainWindow;
|
QLockFile lock(lockPath);
|
||||||
mainWindow.showMaximized();
|
lock.setStaleLockTime(0);
|
||||||
//
|
if (!lock.tryLock(1)) {
|
||||||
|
// Another instance is starting or running; exit quietly
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show splash screen immediately to improve perceived startup speed
|
||||||
|
QString splashPath = RecourceHelper::Get().GetBasePath() + "/resources/splash.png";
|
||||||
|
QPixmap splashPixmap = QPixmap(splashPath).scaled(640, 480, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||||
|
QSplashScreen splash(splashPixmap);
|
||||||
|
splash.showMessage(("正在启动..."), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
|
||||||
|
splash.show();
|
||||||
|
app.processEvents();
|
||||||
|
|
||||||
|
RecourceHelper::ChangeSkin("default");
|
||||||
|
splash.showMessage(("正在加载界面皮肤..."), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
|
||||||
|
app.processEvents();
|
||||||
|
|
||||||
|
splash.showMessage(("正在加载数据..."), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
|
||||||
|
app.processEvents();
|
||||||
|
|
||||||
|
|
||||||
|
MainFrame mainWindow;
|
||||||
|
splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt::white);
|
||||||
|
mainWindow.showMaximized();
|
||||||
|
splash.finish(&mainWindow);
|
||||||
|
|
||||||
int ret = app.exec();
|
int ret = app.exec();
|
||||||
app.Uninit();
|
// app.Uninit();
|
||||||
|
Sleep(200);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,16 +41,29 @@ MeshManager::~MeshManager(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MeshManager::OnDestory() {
|
void MeshManager::OnDestory() {
|
||||||
|
// Defer destruction of cached nodes to process exit to avoid
|
||||||
|
// shutdown-order crashes inside OSG ref_ptr/Drawable destructors.
|
||||||
|
// We intentionally leak the cache at exit; acceptable for application shutdown.
|
||||||
|
LOG_INFO("MeshManager::OnDestory - deferring cache release to process exit");
|
||||||
|
static NodeMap* leakedCache = nullptr;
|
||||||
|
if (!leakedCache) leakedCache = new NodeMap();
|
||||||
|
leakedCache->swap(nodes_);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::MatrixTransform* MeshManager::ReadNode(const std::string& file) {
|
osg::MatrixTransform* MeshManager::ReadNode(const std::string& file) {
|
||||||
LOG_INFO("load node:{}", file);
|
LOG_INFO("load node:{}", file);
|
||||||
const auto iter = nodes_.find(file);
|
const auto iter = nodes_.find(file);
|
||||||
if (nodes_.end() != iter) {
|
if (nodes_.end() != iter) {
|
||||||
osg::MatrixTransform* mt = new osg::MatrixTransform;
|
// Guard against previously cleared cache entries
|
||||||
mt->addChild(iter->second);
|
osg::ref_ptr<osg::Node> cached = iter->second;
|
||||||
return mt;
|
if (cached.valid()) {
|
||||||
|
osg::MatrixTransform* mt = new osg::MatrixTransform;
|
||||||
|
mt->addChild(cached.get());
|
||||||
|
return mt;
|
||||||
|
} else {
|
||||||
|
// Remove invalid entry and fall through to reload
|
||||||
|
nodes_.erase(iter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Node* node = osgDB::readNodeFile(file);
|
osg::Node* node = osgDB::readNodeFile(file);
|
||||||
|
|||||||
@ -59,6 +59,12 @@ void OEScene::DetachView(osgViewer::View* view) {
|
|||||||
|
|
||||||
// Remove sky dome from this group if present; SkyNode has no detach in osgEarth 2.8
|
// Remove sky dome from this group if present; SkyNode has no detach in osgEarth 2.8
|
||||||
if (skyDome_.valid()) {
|
if (skyDome_.valid()) {
|
||||||
|
// Proactively disable lighting/effects to reduce interactions with the View
|
||||||
|
skyDome_->setLighting(osg::StateAttribute::OFF);
|
||||||
|
skyDome_->setSunVisible(false);
|
||||||
|
skyDome_->setMoonVisible(false);
|
||||||
|
skyDome_->setStarsVisible(false);
|
||||||
|
skyDome_->setAtmosphereVisible(false);
|
||||||
removeChild(skyDome_.get());
|
removeChild(skyDome_.get());
|
||||||
skyDome_ = nullptr;
|
skyDome_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
OESceneUI* GetOrCreateSceneUI();
|
OESceneUI* GetOrCreateSceneUI();
|
||||||
|
// Read-only accessor to avoid creating UI during teardown
|
||||||
|
OESceneUI* GetSceneUI() const {
|
||||||
|
return sceneUI_.get();
|
||||||
|
}
|
||||||
osgEarth::Util::EarthManipulator* GetManipulater() const {
|
osgEarth::Util::EarthManipulator* GetManipulater() const {
|
||||||
return earthManipulator_.get();
|
return earthManipulator_.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -110,7 +110,13 @@ void OsgWidget::Initialize() {
|
|||||||
void OsgWidget::Uninitialize() {
|
void OsgWidget::Uninitialize() {
|
||||||
LOG_INFO("OsgWidget::Uninitialize");
|
LOG_INFO("OsgWidget::Uninitialize");
|
||||||
if (nullptr != viewUI_) {
|
if (nullptr != viewUI_) {
|
||||||
viewUI_->RemoveUI(activeScene_->GetOrCreateSceneUI());
|
// Avoid creating UI during teardown; only remove if it exists
|
||||||
|
if (activeScene_.valid()) {
|
||||||
|
OESceneUI* sceneUI = activeScene_->GetSceneUI();
|
||||||
|
if (sceneUI) {
|
||||||
|
viewUI_->RemoveUI(sceneUI);
|
||||||
|
}
|
||||||
|
}
|
||||||
viewUI_ = nullptr;
|
viewUI_ = nullptr;
|
||||||
}
|
}
|
||||||
if (nullptr != activeScene_) {
|
if (nullptr != activeScene_) {
|
||||||
|
|||||||
@ -25,11 +25,15 @@ void WorkSpaceManager::OnDestory() {
|
|||||||
WorkSpace* ws = kv.second;
|
WorkSpace* ws = kv.second;
|
||||||
if (ws) {
|
if (ws) {
|
||||||
ws->Unlaod();
|
ws->Unlaod();
|
||||||
ws->deleteLater();
|
// Delete workspaces immediately to prevent deferred Qt cleanup
|
||||||
|
// after viewer/context teardown, which can lead to crashes.
|
||||||
|
delete ws;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workSpaces_.clear();
|
workSpaces_.clear();
|
||||||
|
|
||||||
|
// Clear dangling pointers
|
||||||
|
current_ = nullptr;
|
||||||
scene_ = nullptr;
|
scene_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user