Merge branch 'new_osg' of http://brigecode.icu:16623/PM/DYTSrouce into new_osg
This commit is contained in:
commit
c580fed0b4
@ -1,6 +1,6 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.21)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.21)
|
||||||
|
|
||||||
PROJECT(Dyt)
|
project(Dyt VERSION 1.0.0)
|
||||||
|
|
||||||
option(USE_HOST_EVENT_LOOP
|
option(USE_HOST_EVENT_LOOP
|
||||||
"Enable the integration of CEF message loop thread into host event loop"
|
"Enable the integration of CEF message loop thread into host event loop"
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
PROJECT(Dyt)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
@ -19,7 +17,22 @@ FILE(GLOB_RECURSE CPP_FILES ./*.cpp common/*.cpp model/*.cpp app/*.cpp utils/*.c
|
|||||||
FILE(GLOB_RECURSE CC_FILES ./*.cc)
|
FILE(GLOB_RECURSE CC_FILES ./*.cc)
|
||||||
FILE(GLOB_RECURSE UI_FILES ./*.ui)
|
FILE(GLOB_RECURSE UI_FILES ./*.ui)
|
||||||
FILE(GLOB_RECURSE QRC_FILES ./*.qrc)
|
FILE(GLOB_RECURSE QRC_FILES ./*.qrc)
|
||||||
FILE(GLOB_RECURSE RC_FILES ./res/*.rc)
|
## Configure Windows resource file with version info (exposed to cmake-gui)
|
||||||
|
set(DYT_COMPANY_NAME "DYT" CACHE STRING "Company name for version resource")
|
||||||
|
set(DYT_PRODUCT_NAME "DYT" CACHE STRING "Product name for version resource")
|
||||||
|
set(DYT_FILE_DESCRIPTION "Dyt Application" CACHE STRING "File description for version resource")
|
||||||
|
set(DYT_COPYRIGHT "(C) 2025 DYT" CACHE STRING "Legal copyright for version resource")
|
||||||
|
|
||||||
|
# Read version from top-level project definition and expose as editable cache entries
|
||||||
|
set(DYT_VERSION_MAJOR "${Dyt_VERSION_MAJOR}" CACHE STRING "Major version for version resource")
|
||||||
|
set(DYT_VERSION_MINOR "${Dyt_VERSION_MINOR}" CACHE STRING "Minor version for version resource")
|
||||||
|
set(DYT_VERSION_PATCH "${Dyt_VERSION_PATCH}" CACHE STRING "Patch version for version resource")
|
||||||
|
set(DYT_VERSION "${Dyt_VERSION}" CACHE STRING "Product version string for version resource")
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/res/dyt.rc.in
|
||||||
|
${PROJECT_BINARY_DIR}/dyt.rc
|
||||||
|
)
|
||||||
|
|
||||||
SET(
|
SET(
|
||||||
TS_FILES
|
TS_FILES
|
||||||
@ -77,7 +90,7 @@ SET(
|
|||||||
)
|
)
|
||||||
|
|
||||||
configure_file(
|
configure_file(
|
||||||
${PROJECT_SOURCE_DIR}/config.cpp.in
|
${CMAKE_CURRENT_SOURCE_DIR}/config.cpp.in
|
||||||
${PROJECT_BINARY_DIR}/config.cpp
|
${PROJECT_BINARY_DIR}/config.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -88,10 +101,10 @@ SET(
|
|||||||
${CC_FILES}
|
${CC_FILES}
|
||||||
${UI_FILES}
|
${UI_FILES}
|
||||||
${QRC_FILES}
|
${QRC_FILES}
|
||||||
${RC_FILES}
|
${PROJECT_BINARY_DIR}/dyt.rc
|
||||||
${QM_FILES}
|
${QM_FILES}
|
||||||
${PROJECT_BINARY_DIR}/config.cpp
|
${PROJECT_BINARY_DIR}/config.cpp
|
||||||
${PROJECT_SOURCE_DIR}/${PROJECT_NAME}.manifest
|
${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.manifest
|
||||||
)
|
)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(
|
INCLUDE_DIRECTORIES(
|
||||||
|
|||||||
@ -62,7 +62,6 @@ void PathComponent::Begin() {
|
|||||||
|
|
||||||
animationPath_->clear();
|
animationPath_->clear();
|
||||||
|
|
||||||
// 优先使用路径文件的时间列;若不存在则按当前时间范围等间距生成时间点
|
|
||||||
std::vector<double> mappedSteps;
|
std::vector<double> mappedSteps;
|
||||||
const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty();
|
const bool hasPathTimes = transformPath_ && !transformPath_->GetTimes().empty();
|
||||||
double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0;
|
double rangeMin = 0.0, rangeMax = 0.0, rangeStep = 0.0;
|
||||||
@ -70,7 +69,6 @@ void PathComponent::Begin() {
|
|||||||
if (hasPathTimes) {
|
if (hasPathTimes) {
|
||||||
const auto& times = transformPath_->GetTimes();
|
const auto& times = transformPath_->GetTimes();
|
||||||
if (timeStep_->HasManualRange()) {
|
if (timeStep_->HasManualRange()) {
|
||||||
// 使用文件时间为主:仅截取手动范围内的原始时间点
|
|
||||||
double dstMin = timeStep_->GetManualStart();
|
double dstMin = timeStep_->GetManualStart();
|
||||||
double dstMax = timeStep_->GetManualEnd();
|
double dstMax = timeStep_->GetManualEnd();
|
||||||
mappedSteps.reserve(times.size());
|
mappedSteps.reserve(times.size());
|
||||||
@ -79,7 +77,6 @@ void PathComponent::Begin() {
|
|||||||
mappedSteps.push_back(t);
|
mappedSteps.push_back(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 若截取后为空,回退为原始时间列,避免动画路径为空
|
|
||||||
if (mappedSteps.empty()) {
|
if (mappedSteps.empty()) {
|
||||||
mappedSteps = times;
|
mappedSteps = times;
|
||||||
}
|
}
|
||||||
@ -94,7 +91,6 @@ void PathComponent::Begin() {
|
|||||||
double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin;
|
double start = timeStep_->HasManualRange() ? timeStep_->GetManualStart() : rangeMin;
|
||||||
double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax;
|
double end = timeStep_->HasManualRange() ? timeStep_->GetManualEnd() : rangeMax;
|
||||||
double step = rangeStep;
|
double step = rangeStep;
|
||||||
// 若步长无效,则回退为均匀分布
|
|
||||||
if (step <= 0.0) {
|
if (step <= 0.0) {
|
||||||
step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0;
|
step = (num > 1) ? std::max(0.0, (end - start)) / double(num - 1) : 0.0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,15 +70,10 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
MainFrame mainWindow;
|
MainFrame mainWindow;
|
||||||
splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt:: white);
|
splash.showMessage(("正在创建主窗口..."), Qt::AlignHCenter | Qt::AlignBottom, Qt:: white);
|
||||||
// 先显示窗口,再在事件循环启动后最大化,避免首次显示时原生窗口放置未就绪导致尺寸异常
|
mainWindow.show();
|
||||||
mainWindow.showMaximized();
|
QTimer::singleShot(20, &mainWindow, &MainFrame::showMaximized);
|
||||||
// QTimer::singleShot(0, &mainWindow, &MainFrame::showMaximized);
|
|
||||||
splash.finish(&mainWindow);
|
splash.finish(&mainWindow);
|
||||||
|
|
||||||
|
|
||||||
int ret = app.exec();
|
int ret = app.exec();
|
||||||
// app.Uninit();
|
|
||||||
Sleep(200);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
IDI_ICON ICON DISCARDABLE ".\\res\\sys_icon.ico"
|
|
||||||
36
src/res/dyt.rc.in
Normal file
36
src/res/dyt.rc.in
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
IDI_ICON ICON DISCARDABLE "@CMAKE_CURRENT_SOURCE_DIR@/res/sys_icon.ico"
|
||||||
|
|
||||||
|
#include <winver.h>
|
||||||
|
|
||||||
|
VS_VERSION_INFO VERSIONINFO
|
||||||
|
FILEVERSION @DYT_VERSION_MAJOR@,@DYT_VERSION_MINOR@,@DYT_VERSION_PATCH@,0
|
||||||
|
PRODUCTVERSION @DYT_VERSION_MAJOR@,@DYT_VERSION_MINOR@,@DYT_VERSION_PATCH@,0
|
||||||
|
FILEFLAGSMASK 0x3fL
|
||||||
|
#ifdef _DEBUG
|
||||||
|
FILEFLAGS VS_FF_DEBUG
|
||||||
|
#else
|
||||||
|
FILEFLAGS 0x0L
|
||||||
|
#endif
|
||||||
|
FILEOS VOS__WINDOWS32
|
||||||
|
FILETYPE VFT_APP
|
||||||
|
FILESUBTYPE VFT2_UNKNOWN
|
||||||
|
BEGIN
|
||||||
|
BLOCK "StringFileInfo"
|
||||||
|
BEGIN
|
||||||
|
BLOCK "040904B0"
|
||||||
|
BEGIN
|
||||||
|
VALUE "CompanyName", "@DYT_COMPANY_NAME@\0"
|
||||||
|
VALUE "FileDescription", "@DYT_FILE_DESCRIPTION@\0"
|
||||||
|
VALUE "FileVersion", "@DYT_VERSION@\0"
|
||||||
|
VALUE "InternalName", "@PROJECT_NAME@\0"
|
||||||
|
VALUE "OriginalFilename", "@PROJECT_NAME@.exe\0"
|
||||||
|
VALUE "ProductName", "@DYT_PRODUCT_NAME@\0"
|
||||||
|
VALUE "ProductVersion", "@DYT_VERSION@\0"
|
||||||
|
VALUE "LegalCopyright", "@DYT_COPYRIGHT@\0"
|
||||||
|
END
|
||||||
|
END
|
||||||
|
BLOCK "VarFileInfo"
|
||||||
|
BEGIN
|
||||||
|
VALUE "Translation", 0x0409, 1200
|
||||||
|
END
|
||||||
|
END
|
||||||
@ -54,7 +54,6 @@ void FrameTitleBar::SetMainWidget(QWidget* widget) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void FrameTitleBar::OnMaximized(bool maximized) {
|
void FrameTitleBar::OnMaximized(bool maximized) {
|
||||||
// 根据配置位决定是否显示最大/还原按钮,并切换图标
|
|
||||||
const bool hasMaxButton = (ftbButton_ & FTB_MAX) != 0;
|
const bool hasMaxButton = (ftbButton_ & FTB_MAX) != 0;
|
||||||
ui->sys_max->setVisible(hasMaxButton);
|
ui->sys_max->setVisible(hasMaxButton);
|
||||||
if (!hasMaxButton) {
|
if (!hasMaxButton) {
|
||||||
|
|||||||
@ -41,7 +41,6 @@ void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) {
|
|||||||
titleBar_ = titleBar;
|
titleBar_ = titleBar;
|
||||||
|
|
||||||
if (nullptr != titleBar_) {
|
if (nullptr != titleBar_) {
|
||||||
// 跟踪标题栏显示/隐藏,以便在显示时注册为可移动区域
|
|
||||||
titleBar_->installEventFilter(this);
|
titleBar_->installEventFilter(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -172,6 +172,16 @@ bool FramelessDelegateWin::nativeEvent(const QByteArray & eventType, void* messa
|
|||||||
|
|
||||||
mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2;
|
mmi->ptMaxTrackSize.x = (rcMon.right - rcMon.left) + frameX * 2;
|
||||||
mmi->ptMaxTrackSize.y = (rcMon.bottom - rcMon.top) + frameY * 2;
|
mmi->ptMaxTrackSize.y = (rcMon.bottom - rcMon.top) + frameY * 2;
|
||||||
|
|
||||||
|
const QSize minSize = mainWidget_->minimumSize();
|
||||||
|
const double dpr = mainWidget_->devicePixelRatioF();
|
||||||
|
const int minWpx = static_cast<int>(std::round(minSize.width() * dpr));
|
||||||
|
const int minHpx = static_cast<int>(std::round(minSize.height() * dpr));
|
||||||
|
// Guard against zero/negative values
|
||||||
|
const int clampedMinW = std::max(1, minWpx) + frameX * 2;
|
||||||
|
const int clampedMinH = std::max(1, minHpx) + frameY * 2;
|
||||||
|
mmi->ptMinTrackSize.x = clampedMinW;
|
||||||
|
mmi->ptMinTrackSize.y = clampedMinH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (::IsZoomed(msg->hwnd)) {
|
if (::IsZoomed(msg->hwnd)) {
|
||||||
|
|||||||
@ -11,10 +11,10 @@ FramelessWindow::FramelessWindow(QWidget* parent)
|
|||||||
| Qt::FramelessWindowHint
|
| Qt::FramelessWindowHint
|
||||||
| Qt::WindowSystemMenuHint
|
| Qt::WindowSystemMenuHint
|
||||||
| Qt::WindowMaximizeButtonHint
|
| Qt::WindowMaximizeButtonHint
|
||||||
| Qt::WindowMinimizeButtonHint);
|
| Qt::WindowMinimizeButtonHint
|
||||||
|
);
|
||||||
|
|
||||||
delegate_ = FramelessDelegate::Create(this);
|
delegate_ = FramelessDelegate::Create(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FramelessWindow::~FramelessWindow() {
|
FramelessWindow::~FramelessWindow() {
|
||||||
@ -23,7 +23,6 @@ FramelessWindow::~FramelessWindow() {
|
|||||||
void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) {
|
void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) {
|
||||||
titleBar->SetMainWidget(this);
|
titleBar->SetMainWidget(this);
|
||||||
if (delegate_) {
|
if (delegate_) {
|
||||||
// 通知委托当前标题栏,以便把它作为可拖动区域处理。
|
|
||||||
delegate_->SetTitleBar(titleBar);
|
delegate_->SetTitleBar(titleBar);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,7 +32,6 @@ 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
|
||||||
// 先让无边框委托处理原生事件(如 WM_NCHITTEST 以支持边缘拖动缩放)。
|
|
||||||
if (delegate_ && delegate_->nativeEvent(eventType, message, result)) {
|
if (delegate_ && delegate_->nativeEvent(eventType, message, result)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,6 +37,8 @@ MainFrame::MainFrame(QWidget *parent) :
|
|||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
setMinimumSize(800, 600);
|
||||||
|
|
||||||
assert(nullptr == s_instance);
|
assert(nullptr == s_instance);
|
||||||
s_instance = this;
|
s_instance = this;
|
||||||
|
|
||||||
@ -102,13 +104,6 @@ void MainFrame::InitUI() {
|
|||||||
FileManagerMenu* fileMenu = new FileManagerMenu(this);
|
FileManagerMenu* fileMenu = new FileManagerMenu(this);
|
||||||
AddMenuWidget("file_manager", tr("file manager"), fileMenu);
|
AddMenuWidget("file_manager", tr("file manager"), fileMenu);
|
||||||
|
|
||||||
//AddMenuWidget("view_manager", tr("view manager"), new ViewManagerMenu(this));
|
|
||||||
//AddMenuWidget("plan_manager", tr("plan manager"), new PlanManagerMenu(this));
|
|
||||||
//AddMenuWidget("dynamic_display", tr("dynamic display"), new DynamicDisplayMenu(this));
|
|
||||||
// ChartPlotMenu* chartMenu = new ChartPlotMenu(this);
|
|
||||||
// AddMenuWidget("simu_manager", tr("simu manager"), chartMenu);
|
|
||||||
|
|
||||||
// Command buttons menu based on parsed commands
|
|
||||||
SimuRunMenu* simuRunMenu = new SimuRunMenu(this);
|
SimuRunMenu* simuRunMenu = new SimuRunMenu(this);
|
||||||
AddMenuWidget("simu_manager", tr("simu manager"), simuRunMenu);
|
AddMenuWidget("simu_manager", tr("simu manager"), simuRunMenu);
|
||||||
|
|
||||||
@ -123,11 +118,6 @@ void MainFrame::InitUI() {
|
|||||||
|
|
||||||
simuRunMenu->SetMainWindow(mainWindow);
|
simuRunMenu->SetMainWindow(mainWindow);
|
||||||
|
|
||||||
/*OsgWidget* viewWidget = mainWindow->GetViewWidget();
|
|
||||||
connect(fileMenu, &FileManagerMenu::LoadDyt, viewWidget, &OsgWidget::OnLoadDyt);*/
|
|
||||||
|
|
||||||
//connect(system_, &SystemManagerMenu::signalShowUISetting, mainWindow, &MainWindow::slotShowUISetting);
|
|
||||||
|
|
||||||
if (ui->menuWidget->count() > 0) {
|
if (ui->menuWidget->count() > 0) {
|
||||||
ui->menuWidget->setCurrentIndex(0);
|
ui->menuWidget->setCurrentIndex(0);
|
||||||
menuWidget_.isEmpty() ? assert(false) : menuWidget_.key(0)->setChecked(true);
|
menuWidget_.isEmpty() ? assert(false) : menuWidget_.key(0)->setChecked(true);
|
||||||
|
|||||||
@ -38,6 +38,7 @@ MainWindow::MainWindow(QWidget* parent)
|
|||||||
: QMainWindow(parent)
|
: QMainWindow(parent)
|
||||||
, ui(new Ui::MainWindow) {
|
, ui(new Ui::MainWindow) {
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
setMinimumSize(800, 600);
|
||||||
|
|
||||||
LOG_INFO("MainWindow::MainWindow - Constructor called, about to call InitUI");
|
LOG_INFO("MainWindow::MainWindow - Constructor called, about to call InitUI");
|
||||||
InitUI();
|
InitUI();
|
||||||
@ -70,7 +71,6 @@ void MainWindow::InitUI() {
|
|||||||
mapDockWidget_.insert("ModelBrowser", model);
|
mapDockWidget_.insert("ModelBrowser", model);
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, model);
|
addDockWidget(Qt::LeftDockWidgetArea, model);
|
||||||
|
|
||||||
// 创建预制模型面板
|
|
||||||
DockWidget* presetModel = new DockWidget(tr("preset models"), 0);
|
DockWidget* presetModel = new DockWidget(tr("preset models"), 0);
|
||||||
presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel));
|
presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel));
|
||||||
presetModel->setObjectName("Dock.PresetModelPanel");
|
presetModel->setObjectName("Dock.PresetModelPanel");
|
||||||
@ -82,11 +82,8 @@ void MainWindow::InitUI() {
|
|||||||
DockWidget* attribte = new DockWidget(tr("attribte"), 0);
|
DockWidget* attribte = new DockWidget(tr("attribte"), 0);
|
||||||
attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte));
|
attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte));
|
||||||
attribte->setObjectName("Dock.PropertyBrowser");
|
attribte->setObjectName("Dock.PropertyBrowser");
|
||||||
//addDockWidget(pSettingUI->GetArea("PropertyBrowser"), attribte);
|
|
||||||
propertyBrowser_ = new PropertyBrowser(0);
|
propertyBrowser_ = new PropertyBrowser(0);
|
||||||
propertyBrowser_->AttachDock(attribte);
|
propertyBrowser_->AttachDock(attribte);
|
||||||
// Ensure property panel has a reasonable minimum width; no maximum limit
|
|
||||||
attribte->setMinimumWidth(240);
|
|
||||||
mapDockWidget_.insert("PropertyBrowser", attribte);
|
mapDockWidget_.insert("PropertyBrowser", attribte);
|
||||||
addDockWidget(Qt::RightDockWidgetArea, attribte);
|
addDockWidget(Qt::RightDockWidgetArea, attribte);
|
||||||
|
|
||||||
@ -106,23 +103,18 @@ void MainWindow::InitUI() {
|
|||||||
connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange);
|
connect(modelBrowser_, &ModelBrowser::FileEntryChange, propertyBrowser_, &PropertyBrowser::OnFileEntryChange);
|
||||||
connect(modelBrowser_, &ModelBrowser::GroupChange, propertyBrowser_, &PropertyBrowser::OnGroupChange);
|
connect(modelBrowser_, &ModelBrowser::GroupChange, propertyBrowser_, &PropertyBrowser::OnGroupChange);
|
||||||
|
|
||||||
qtOsgViewWidget_ = new OsgWidget;
|
qtOsgViewWidget_ = new OsgWidget(0);
|
||||||
qtOsgViewWidget_->Initialize();
|
qtOsgViewWidget_->Initialize();
|
||||||
|
|
||||||
DockWidget* viewDock = new DockWidget(tr("Main View"), 0);
|
DockWidget* mainView = new DockWidget(tr("Main View"), 0);
|
||||||
viewDock->SetDockWidgetTitleBar(new DockTitleBar(viewDock));
|
mainView->SetDockWidgetTitleBar(new DockTitleBar(mainView));
|
||||||
viewDock->setObjectName("Dock.MainView");
|
mainView->setObjectName("Dock.MainView");
|
||||||
viewDock->setWidget(qtOsgViewWidget_);
|
qtOsgViewWidget_->AttachDock(mainView);
|
||||||
// Ensure main view has a reasonable minimum size to avoid being squeezed
|
mapDockWidget_.insert("MainView", mainView);
|
||||||
// Use smaller minimum size to support smaller displays
|
addDockWidget(Qt::RightDockWidgetArea, mainView);
|
||||||
qtOsgViewWidget_->setMinimumSize(640, 480);
|
|
||||||
viewDock->setMinimumSize(640, 480);
|
|
||||||
addDockWidget(Qt::LeftDockWidgetArea, viewDock);
|
|
||||||
mapDockWidget_.insert("MainView", viewDock);
|
|
||||||
|
|
||||||
splitDockWidget(model, viewDock, Qt::Horizontal);
|
splitDockWidget(model, mainView, Qt::Horizontal);
|
||||||
|
|
||||||
// 将预制模型面板与模型浏览器标签化
|
|
||||||
tabifyDockWidget(model, presetModel);
|
tabifyDockWidget(model, presetModel);
|
||||||
|
|
||||||
dataPanelManager_ = new DataPanelManager(this, this);
|
dataPanelManager_ = new DataPanelManager(this, this);
|
||||||
|
|||||||
@ -48,6 +48,7 @@ private:
|
|||||||
class PropertyBrowser* propertyBrowser_{ nullptr };
|
class PropertyBrowser* propertyBrowser_{ nullptr };
|
||||||
class QWebEngineView* webEngineView_{ nullptr };
|
class QWebEngineView* webEngineView_{ nullptr };
|
||||||
class OsgWidget* qtOsgViewWidget_{ nullptr };
|
class OsgWidget* qtOsgViewWidget_{ nullptr };
|
||||||
|
//QWidget* qtOsgViewWidget_{ nullptr };
|
||||||
|
|
||||||
class SignalIndicatorLampUI* signalIndicatorLampUI_{ nullptr };
|
class SignalIndicatorLampUI* signalIndicatorLampUI_{ nullptr };
|
||||||
class CodeEdtUI* matlabFileDlg_{ nullptr };
|
class CodeEdtUI* matlabFileDlg_{ nullptr };
|
||||||
|
|||||||
@ -118,7 +118,6 @@ void PlayManagerMenu::OnWorkspaceChange(WorkSpace* workSpace) {
|
|||||||
}
|
}
|
||||||
workSpace_ = workSpace;
|
workSpace_ = workSpace;
|
||||||
connect(workSpace, &WorkSpace::TimestepChanged, this, &PlayManagerMenu::OnTimestepChanged);
|
connect(workSpace, &WorkSpace::TimestepChanged, this, &PlayManagerMenu::OnTimestepChanged);
|
||||||
// 若当前 workspace 已有 timestep,则立即刷新一次 UI
|
|
||||||
if (auto* timestep = workSpace->GetTimestep()) {
|
if (auto* timestep = workSpace->GetTimestep()) {
|
||||||
OnTimestepChanged(timestep);
|
OnTimestepChanged(timestep);
|
||||||
}
|
}
|
||||||
@ -140,12 +139,10 @@ void PlayManagerMenu::OnTimestepChanged(Timestep* timestep) {
|
|||||||
ui->horizontalSlider->setValue(int(dt));
|
ui->horizontalSlider->setValue(int(dt));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// 监听倍速改变(SpeedChanged):更新显示为 x倍速
|
|
||||||
connect(timestep, &Timestep::StepChanged, [this](double speed) {
|
connect(timestep, &Timestep::StepChanged, [this](double speed) {
|
||||||
ui->lbUp->setText(QString("x%1").arg(speed));
|
ui->lbUp->setText(QString("x%1").arg(speed));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// 当时间范围更新(例如用户在属性面板设置了起止时间)时,刷新显示与滑条范围
|
|
||||||
connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step, double speed) {
|
connect(timestep, &Timestep::RangeChanged, [this](double minTime, double maxTime, double step, double speed) {
|
||||||
minTime_ = minTime;
|
minTime_ = minTime;
|
||||||
maxTime_ = maxTime;
|
maxTime_ = maxTime;
|
||||||
|
|||||||
@ -3,8 +3,8 @@
|
|||||||
#include <QBoxLayout>
|
#include <QBoxLayout>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
#include "DockTitleBar.h"
|
#include "ui/DockTitleBar.h"
|
||||||
#include "DockWidget.h"
|
#include "ui/DockWidget.h"
|
||||||
#include "ModelBrowser/ModelTreeWidget.h"
|
#include "ModelBrowser/ModelTreeWidget.h"
|
||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
|
|||||||
WorkSpace* workspace = value.value<WorkSpace*>();
|
WorkSpace* workspace = value.value<WorkSpace*>();
|
||||||
if (nullptr == workspace) {
|
if (nullptr == workspace) {
|
||||||
LOG_WARN("workspace is nullptr");
|
LOG_WARN("workspace is nullptr");
|
||||||
// 如果没有属性对象,清空属性面板
|
|
||||||
browser_->clear();
|
browser_->clear();
|
||||||
propertyToId_.clear();
|
propertyToId_.clear();
|
||||||
idToProperty_.clear();
|
idToProperty_.clear();
|
||||||
@ -57,7 +56,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 点击根项目需要清空属性面板,不展示工作区属性
|
|
||||||
browser_->clear();
|
browser_->clear();
|
||||||
propertyToId_.clear();
|
propertyToId_.clear();
|
||||||
idToProperty_.clear();
|
idToProperty_.clear();
|
||||||
@ -71,7 +69,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
|
|||||||
workSpaceManager_->setValue(property, worksapceAttribute);
|
workSpaceManager_->setValue(property, worksapceAttribute);
|
||||||
addProperty(property, tr("WorkSpace"));
|
addProperty(property, tr("WorkSpace"));
|
||||||
|
|
||||||
// 保持对运行时工作区变更的监听(树刷新所需),但属性面板保持清空
|
|
||||||
if (currentWorkspace_) {
|
if (currentWorkspace_) {
|
||||||
QObject::disconnect(currentWorkspace_, nullptr, this, nullptr);
|
QObject::disconnect(currentWorkspace_, nullptr, this, nullptr);
|
||||||
}
|
}
|
||||||
@ -79,7 +76,6 @@ void PropertyBrowser::OnWorkSpaceChange(const QVariant& value) {
|
|||||||
QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged,
|
QObject::connect(currentWorkspace_, &WorkSpace::FilesChanged,
|
||||||
this, &PropertyBrowser::OnWorkspaceFilesChanged);
|
this, &PropertyBrowser::OnWorkspaceFilesChanged);
|
||||||
|
|
||||||
// 属性面板清空,文件项属性由 FileEntry 点击时单独处理
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PropertyBrowser::OnEntityChange(const QVariant& value) {
|
void PropertyBrowser::OnEntityChange(const QVariant& value) {
|
||||||
@ -87,7 +83,6 @@ void PropertyBrowser::OnEntityChange(const QVariant& value) {
|
|||||||
Entity* entity = value.value<Entity*>();
|
Entity* entity = value.value<Entity*>();
|
||||||
if (nullptr == entity) {
|
if (nullptr == entity) {
|
||||||
LOG_WARN("engity is nullptr");
|
LOG_WARN("engity is nullptr");
|
||||||
// 如果没有属性对象,清空属性面板
|
|
||||||
browser_->clear();
|
browser_->clear();
|
||||||
propertyToId_.clear();
|
propertyToId_.clear();
|
||||||
idToProperty_.clear();
|
idToProperty_.clear();
|
||||||
@ -141,7 +136,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
FileEntry* entry = value.value<FileEntry*>();
|
FileEntry* entry = value.value<FileEntry*>();
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
LOG_WARN("file entry is nullptr");
|
LOG_WARN("file entry is nullptr");
|
||||||
// 如果没有属性对象,清空属性面板
|
|
||||||
inFileEntryView_ = false;
|
inFileEntryView_ = false;
|
||||||
browser_->clear();
|
browser_->clear();
|
||||||
propertyToId_.clear();
|
propertyToId_.clear();
|
||||||
@ -173,7 +167,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
//if (!curve)
|
//if (!curve)
|
||||||
{
|
{
|
||||||
LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str());
|
LOG_WARN("file entry not a curve: %s", entry->GetFileName().toStdString().c_str());
|
||||||
// 基础信息组
|
|
||||||
const QString idBasic = QString("FileEntry:%1").arg(entry->GetFileName());
|
const QString idBasic = QString("FileEntry:%1").arg(entry->GetFileName());
|
||||||
const QString titleBasic = QString("File Entry - %1").arg(entry->GetName());
|
const QString titleBasic = QString("File Entry - %1").arg(entry->GetName());
|
||||||
QtProperty* groupBasic = groupManager_->addProperty(tr("Basic"));
|
QtProperty* groupBasic = groupManager_->addProperty(tr("Basic"));
|
||||||
@ -205,7 +198,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
|
|
||||||
addProperty(groupBasic, idBasic);
|
addProperty(groupBasic, idBasic);
|
||||||
|
|
||||||
// 类型专属属性显示
|
|
||||||
switch (entry->GetType())
|
switch (entry->GetType())
|
||||||
{
|
{
|
||||||
case FileEntryType::Curve:
|
case FileEntryType::Curve:
|
||||||
@ -453,7 +445,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
const QString titleChart = QString("Surface Chart - %1").arg(entry->GetName());
|
const QString titleChart = QString("Surface Chart - %1").arg(entry->GetName());
|
||||||
const QString titleItems = QString("Surfaces - %1").arg(entry->GetName());
|
const QString titleItems = QString("Surfaces - %1").arg(entry->GetName());
|
||||||
|
|
||||||
// Chart 属性
|
|
||||||
QtProperty* chartGroup = groupManager_->addProperty(tr("Chart"));
|
QtProperty* chartGroup = groupManager_->addProperty(tr("Chart"));
|
||||||
const auto& chart = surf->GetChartProperties();
|
const auto& chart = surf->GetChartProperties();
|
||||||
QtProperty* xCountProp = intManager_->addProperty(tr("xCount"));
|
QtProperty* xCountProp = intManager_->addProperty(tr("xCount"));
|
||||||
@ -600,7 +591,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
|
|
||||||
addProperty(chartGroup, idChart);
|
addProperty(chartGroup, idChart);
|
||||||
|
|
||||||
// Surface 列表
|
|
||||||
QtProperty* itemsGroup = groupManager_->addProperty(tr("SurfacesProp"));
|
QtProperty* itemsGroup = groupManager_->addProperty(tr("SurfacesProp"));
|
||||||
const auto& items = surf->GetSurfaceProperties();
|
const auto& items = surf->GetSurfaceProperties();
|
||||||
for (int i = 0; i < items.size(); ++i)
|
for (int i = 0; i < items.size(); ++i)
|
||||||
@ -626,7 +616,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
QtProperty* col = colorManager_->addProperty(tr("color"));
|
QtProperty* col = colorManager_->addProperty(tr("color"));
|
||||||
colorManager_->setValue(col, s.color);
|
colorManager_->setValue(col, s.color);
|
||||||
itemGroup->addSubProperty(col);
|
itemGroup->addSubProperty(col);
|
||||||
// 写回 Surface 条目颜色
|
|
||||||
colorSetters_[col] = [surf, entry, i](const QColor& c)
|
colorSetters_[col] = [surf, entry, i](const QColor& c)
|
||||||
{
|
{
|
||||||
auto props = surf->GetSurfaceProperties();
|
auto props = surf->GetSurfaceProperties();
|
||||||
@ -768,7 +757,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
// QtProperty* col = colorManager_->addProperty(tr("color"));
|
// QtProperty* col = colorManager_->addProperty(tr("color"));
|
||||||
// colorManager_->setValue(col, t.color);
|
// colorManager_->setValue(col, t.color);
|
||||||
// itemGroup->addSubProperty(col);
|
// itemGroup->addSubProperty(col);
|
||||||
// // 写回 Table 条目颜色
|
|
||||||
// colorSetters_[col] = [tbl, entry, i](const QColor& c){
|
// colorSetters_[col] = [tbl, entry, i](const QColor& c){
|
||||||
// auto props = tbl->GetTableProperties();
|
// auto props = tbl->GetTableProperties();
|
||||||
// if (i >= 0 && i < props.size()) {
|
// if (i >= 0 && i < props.size()) {
|
||||||
@ -778,7 +766,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
// if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
|
// if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
|
||||||
// }
|
// }
|
||||||
// };
|
// };
|
||||||
// // datas 展示为拼接字符串
|
|
||||||
// QStringList values;
|
// QStringList values;
|
||||||
// for (const auto& v : t.datas) values << QString::number(v);
|
// for (const auto& v : t.datas) values << QString::number(v);
|
||||||
// QtProperty* ds = stringManager_->addProperty(tr("datas"));
|
// QtProperty* ds = stringManager_->addProperty(tr("datas"));
|
||||||
@ -800,7 +787,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
const QString titleColor = QString("Light Colors - %1").arg(entry->GetName());
|
const QString titleColor = QString("Light Colors - %1").arg(entry->GetName());
|
||||||
const QString titleRows = QString("Light Rows - %1").arg(entry->GetName());
|
const QString titleRows = QString("Light Rows - %1").arg(entry->GetName());
|
||||||
|
|
||||||
// 颜色与时间
|
|
||||||
QtProperty* colorGroup = groupManager_->addProperty(tr("Chart"));
|
QtProperty* colorGroup = groupManager_->addProperty(tr("Chart"));
|
||||||
const auto& colorProps = lt->GetColorProperties();
|
const auto& colorProps = lt->GetColorProperties();
|
||||||
QtProperty* oc = colorManager_->addProperty(tr("openColor"));
|
QtProperty* oc = colorManager_->addProperty(tr("openColor"));
|
||||||
@ -822,7 +808,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
addProperty(colorGroup, idColor);
|
addProperty(colorGroup, idColor);
|
||||||
// 写回处理:颜色变化更新到 FileEntryLight 并通知 Workspace
|
|
||||||
colorSetters_[oc] = [lt, entry](const QColor& c)
|
colorSetters_[oc] = [lt, entry](const QColor& c)
|
||||||
{
|
{
|
||||||
auto props = lt->GetColorProperties();
|
auto props = lt->GetColorProperties();
|
||||||
@ -838,7 +823,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
|
if (auto ws = WorkSpaceManager::Get().GetCurrent()) ws->NotifyFileEntryUpdated(entry->GetType());
|
||||||
};
|
};
|
||||||
|
|
||||||
// 行数据
|
|
||||||
QtProperty* rowsGroup = groupManager_->addProperty(tr("Light Rows"));
|
QtProperty* rowsGroup = groupManager_->addProperty(tr("Light Rows"));
|
||||||
const auto& rows = lt->GetLightProperties();
|
const auto& rows = lt->GetLightProperties();
|
||||||
for (int i = 0; i < rows.size(); ++i)
|
for (int i = 0; i < rows.size(); ++i)
|
||||||
@ -987,7 +971,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
QtProperty* col = colorManager_->addProperty(tr("color"));
|
QtProperty* col = colorManager_->addProperty(tr("color"));
|
||||||
colorManager_->setValue(col, ln.color);
|
colorManager_->setValue(col, ln.color);
|
||||||
line->addSubProperty(col);
|
line->addSubProperty(col);
|
||||||
// 写回 Polar 线颜色
|
|
||||||
colorSetters_[col] = [pl, entry, i](const QColor& c)
|
colorSetters_[col] = [pl, entry, i](const QColor& c)
|
||||||
{
|
{
|
||||||
auto props = pl->GetLineProperties();
|
auto props = pl->GetLineProperties();
|
||||||
@ -1165,7 +1148,6 @@ void PropertyBrowser::OnFileEntryChange(const QVariant& value) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 聚焦基础信息组
|
|
||||||
if (groupBasic) {
|
if (groupBasic) {
|
||||||
QtBrowserItem* item = browser_->topLevelItem(groupBasic);
|
QtBrowserItem* item = browser_->topLevelItem(groupBasic);
|
||||||
if (item) {
|
if (item) {
|
||||||
@ -1270,7 +1252,6 @@ void PropertyBrowser::InitPropertyManager() {
|
|||||||
browser_->setFactoryForManager(curveEntryManager_->subDoubleProperyManager(), doubleSpinBoxFactory);
|
browser_->setFactoryForManager(curveEntryManager_->subDoubleProperyManager(), doubleSpinBoxFactory);
|
||||||
browser_->setFactoryForManager(curveEntryManager_->subColorProperyManager(), colorFactory);
|
browser_->setFactoryForManager(curveEntryManager_->subColorProperyManager(), colorFactory);
|
||||||
|
|
||||||
// 颜色属性变更信号:触发对应写回处理器
|
|
||||||
connect(colorManager_, &QtColorPropertyManager::valueChanged, this,
|
connect(colorManager_, &QtColorPropertyManager::valueChanged, this,
|
||||||
[this](QtProperty* prop, const QColor& color){
|
[this](QtProperty* prop, const QColor& color){
|
||||||
if (colorSetters_.contains(prop)) {
|
if (colorSetters_.contains(prop)) {
|
||||||
|
|||||||
@ -61,9 +61,6 @@ const QString QWorkspaceAttribute::GetDescription() const {
|
|||||||
return workspace_->GetDescribe();
|
return workspace_->GetDescribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 已移除:时间步长文件路径设置/获取(不再从文件读取)
|
|
||||||
|
|
||||||
void QWorkspaceAttribute::SetSimulationStart(double start) {
|
void QWorkspaceAttribute::SetSimulationStart(double start) {
|
||||||
if (!workspace_) return;
|
if (!workspace_) return;
|
||||||
Timestep* t = workspace_->GetTimestep();
|
Timestep* t = workspace_->GetTimestep();
|
||||||
|
|||||||
@ -62,8 +62,6 @@ public:
|
|||||||
void SetDescription(const QString& desc);
|
void SetDescription(const QString& desc);
|
||||||
const QString GetDescription() const;
|
const QString GetDescription() const;
|
||||||
|
|
||||||
// 已移除:时间步长文件路径(不再从文件读取)
|
|
||||||
|
|
||||||
// Simulation time (manual range) for playback
|
// Simulation time (manual range) for playback
|
||||||
void SetSimulationStart(double start);
|
void SetSimulationStart(double start);
|
||||||
double GetSimulationStart() const;
|
double GetSimulationStart() const;
|
||||||
|
|||||||
@ -53,7 +53,6 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
// 解析各字段
|
|
||||||
const double time = parts[0].toDouble(&ok); if (!ok) { LOG_WARN("invalid time: {}", parts[0].toStdString()); return {}; }
|
const double time = parts[0].toDouble(&ok); if (!ok) { LOG_WARN("invalid time: {}", parts[0].toStdString()); return {}; }
|
||||||
const double longitude= parts[1].toDouble(&ok); if (!ok) { LOG_WARN("invalid longitude: {}", parts[1].toStdString()); return {}; }
|
const double longitude= parts[1].toDouble(&ok); if (!ok) { LOG_WARN("invalid longitude: {}", parts[1].toStdString()); return {}; }
|
||||||
const double latitude = parts[2].toDouble(&ok); if (!ok) { LOG_WARN("invalid latitude: {}", parts[2].toStdString()); return {}; }
|
const double latitude = parts[2].toDouble(&ok); if (!ok) { LOG_WARN("invalid latitude: {}", parts[2].toStdString()); return {}; }
|
||||||
@ -63,13 +62,9 @@ TransformPath* TransformPath::LoadFromFile(const QString& path, QObject* parent)
|
|||||||
const double roll = parts[6].toDouble(&ok); if (!ok) { LOG_WARN("invalid roll: {}", parts[6].toStdString()); return {}; }
|
const double roll = parts[6].toDouble(&ok); if (!ok) { LOG_WARN("invalid roll: {}", parts[6].toStdString()); return {}; }
|
||||||
|
|
||||||
Transform transform;
|
Transform transform;
|
||||||
// 位置映射:经度->x,纬度->y,高度->z
|
|
||||||
transform.GetLocation().set(longitude, latitude, altitude);
|
transform.GetLocation().set(longitude, latitude, altitude);
|
||||||
// 旋转向量采用代码库约定顺序(Pitch, Roll, Heading),与 OsgUtils::HPRToQuat/QuatToHPR 保持一致
|
|
||||||
transform.GetRotation().set(pitch, roll, heading);
|
transform.GetRotation().set(pitch, roll, heading);
|
||||||
|
|
||||||
// 当前 PathComponent 使用 WorkSpace 的 Timestep 作为时间轴,这里暂不保存 time 字段
|
|
||||||
// 现在记录时间以支持按路径文件驱动回放
|
|
||||||
times.push_back(time);
|
times.push_back(time);
|
||||||
|
|
||||||
transforms.push_back(transform);
|
transforms.push_back(transform);
|
||||||
|
|||||||
@ -21,7 +21,6 @@
|
|||||||
#include "OsgViewer.h"
|
#include "OsgViewer.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "scene/OEScene.h"
|
#include "scene/OEScene.h"
|
||||||
#include "ui/MainFrame.h"
|
|
||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
#include "workspace/WorkSpace.h"
|
#include "workspace/WorkSpace.h"
|
||||||
#include "scutcheon/osgScutcheon.h"
|
#include "scutcheon/osgScutcheon.h"
|
||||||
@ -33,6 +32,10 @@
|
|||||||
#include "entities/Entity.h"
|
#include "entities/Entity.h"
|
||||||
#include "entities/Component.h"
|
#include "entities/Component.h"
|
||||||
|
|
||||||
|
#include "ui/DockTitleBar.h"
|
||||||
|
#include "ui/DockWidget.h"
|
||||||
|
#include "ui/MainFrame.h"
|
||||||
|
|
||||||
static void ConfigureView( osgViewer::View* view ) {
|
static void ConfigureView( osgViewer::View* view ) {
|
||||||
view->addEventHandler(new osgViewer::StatsHandler());
|
view->addEventHandler(new osgViewer::StatsHandler());
|
||||||
view->addEventHandler(new osgViewer::WindowSizeHandler());
|
view->addEventHandler(new osgViewer::WindowSizeHandler());
|
||||||
@ -56,13 +59,12 @@ OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f)
|
|||||||
setMouseTracking(true);
|
setMouseTracking(true);
|
||||||
setKeyEventSetsDone(0);
|
setKeyEventSetsDone(0);
|
||||||
|
|
||||||
// 启用拖拽接收
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) );
|
connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) );
|
||||||
timer_.start( 10 );
|
timer_.start( 10 );
|
||||||
|
|
||||||
setMinimumSize(100, 100);
|
//setMinimumSize(800, 100);
|
||||||
LOG_INFO("OsgWidget::OsgWidget");
|
LOG_INFO("OsgWidget::OsgWidget");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +133,19 @@ void OsgWidget::LoadDefaultScene() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OsgWidget::AttachDock(DockWidget* dockWidget) {
|
||||||
|
if (nullptr == dockWidget) {
|
||||||
|
qDebug() << __FUNCTION__ << "dockwidget is nullptr";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dockWidget->SetDockWidgetTitleBar(nullptr);
|
||||||
|
dockWidget->setWidget(this);
|
||||||
|
|
||||||
|
DockTitleBar* dockTitleBar = new DockTitleBar;
|
||||||
|
dockWidget->SetDockWidgetTitleBar(dockTitleBar);
|
||||||
|
}
|
||||||
|
|
||||||
osgQt::GraphicsWindowQt* OsgWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name,
|
osgQt::GraphicsWindowQt* OsgWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name,
|
||||||
bool windowDecoration) {
|
bool windowDecoration) {
|
||||||
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
|
||||||
@ -199,7 +214,6 @@ void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
|
void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
|
||||||
// 检查是否是预制模型拖拽
|
|
||||||
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
} else {
|
} else {
|
||||||
@ -249,11 +263,9 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
osg::Viewport* vp = view_->getCamera()->getViewport();
|
osg::Viewport* vp = view_->getCamera()->getViewport();
|
||||||
// 将屏幕坐标转换为世界坐标
|
|
||||||
double longitude, latitude, height;
|
double longitude, latitude, height;
|
||||||
if (!ScreenToWorldCoordinate(static_cast<int>(position.x()), static_cast<int>(vp->height() - position.y()), longitude, latitude, height)) {
|
if (!ScreenToWorldCoordinate(static_cast<int>(position.x()), static_cast<int>(vp->height() - position.y()), longitude, latitude, height)) {
|
||||||
LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates");
|
LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates");
|
||||||
// 使用默认位置
|
|
||||||
longitude = 0.0;
|
longitude = 0.0;
|
||||||
latitude = 0.0;
|
latitude = 0.0;
|
||||||
height = 0.0;
|
height = 0.0;
|
||||||
|
|||||||
@ -17,6 +17,8 @@ public:
|
|||||||
void Uninitialize(void);
|
void Uninitialize(void);
|
||||||
void LoadDefaultScene(void);
|
void LoadDefaultScene(void);
|
||||||
|
|
||||||
|
void AttachDock(class DockWidget* dockWidget);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void signalScaleInfo(const QString&);
|
void signalScaleInfo(const QString&);
|
||||||
|
|
||||||
@ -28,18 +30,11 @@ protected:
|
|||||||
void resizeEvent(QResizeEvent* event) override;
|
void resizeEvent(QResizeEvent* event) override;
|
||||||
void paintEvent( QPaintEvent* /*event*/ ) override;
|
void paintEvent( QPaintEvent* /*event*/ ) override;
|
||||||
|
|
||||||
// 拖拽事件处理
|
|
||||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||||
void dragMoveEvent(QDragMoveEvent* event) override;
|
void dragMoveEvent(QDragMoveEvent* event) override;
|
||||||
void dropEvent(QDropEvent* event) override;
|
void dropEvent(QDropEvent* event) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
|
||||||
* @brief 处理预制模型拖拽
|
|
||||||
* @param modelType 模型类型
|
|
||||||
* @param modelName 模型名称
|
|
||||||
* @param position 屏幕位置(可选)
|
|
||||||
*/
|
|
||||||
void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
|
void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
|
||||||
|
|
||||||
bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude);
|
bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude);
|
||||||
|
|||||||
@ -25,7 +25,6 @@ void Timestep::SetManualRange(double start, double end) {
|
|||||||
manualStart_ = start;
|
manualStart_ = start;
|
||||||
manualEnd_ = end;
|
manualEnd_ = end;
|
||||||
maxTime_ = end;
|
maxTime_ = end;
|
||||||
// 通知 UI 更新范围与步进
|
|
||||||
double minTime = 0.0, maxTime = 0.0, step = 1.0;
|
double minTime = 0.0, maxTime = 0.0, step = 1.0;
|
||||||
GetRange(minTime, maxTime, step);
|
GetRange(minTime, maxTime, step);
|
||||||
emit RangeChanged(minTime, maxTime, step, currentSpeed_);
|
emit RangeChanged(minTime, maxTime, step, currentSpeed_);
|
||||||
@ -126,7 +125,6 @@ void Timestep::Stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Timestep::Up() {
|
void Timestep::Up() {
|
||||||
// 提升到下一个倍率(封顶)
|
|
||||||
if (speedIndex_ < int(speedLevels_.size()) - 1) {
|
if (speedIndex_ < int(speedLevels_.size()) - 1) {
|
||||||
++speedIndex_;
|
++speedIndex_;
|
||||||
}
|
}
|
||||||
@ -168,7 +166,6 @@ void Timestep::SetSpeed(double speed) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Timestep::SetStep(double step) {
|
void Timestep::SetStep(double step) {
|
||||||
// 更新时间轴步进间隔,并通知 UI 范围与步进发生变化
|
|
||||||
stepInterval_ = step;
|
stepInterval_ = step;
|
||||||
double minTime = 0.0, maxTime = 0.0, s = 0.0;
|
double minTime = 0.0, maxTime = 0.0, s = 0.0;
|
||||||
GetRange(minTime, maxTime, s);
|
GetRange(minTime, maxTime, s);
|
||||||
|
|||||||
@ -367,13 +367,11 @@ void WorkSpace::ExecuteCommands(CommandWhen when) {
|
|||||||
cmdMgr_->Execute(this, when);
|
cmdMgr_->Execute(this, when);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统一属性更新通知:不改变数量,仅提升序号并广播 FilesChanged
|
|
||||||
void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) {
|
void WorkSpace::NotifyFileEntryUpdated(FileEntryType type, std::shared_ptr<FileEntry> fileEntry) {
|
||||||
++filesSeq_;
|
++filesSeq_;
|
||||||
emit FilesChanged(type, fileEntry);
|
emit FilesChanged(type, fileEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除指定指针的文件条目(不删除物理文件,仅移出工作空间管理)
|
|
||||||
bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
|
bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
LOG_WARN("RemoveFileEntry: entry is nullptr");
|
LOG_WARN("RemoveFileEntry: entry is nullptr");
|
||||||
@ -397,7 +395,6 @@ bool WorkSpace::RemoveFileEntry(FileEntryType type, FileEntry* entry) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按索引删除文件条目
|
|
||||||
bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
|
bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
|
||||||
auto it = files_.find(type);
|
auto it = files_.find(type);
|
||||||
if (it == files_.end()) {
|
if (it == files_.end()) {
|
||||||
@ -416,7 +413,6 @@ bool WorkSpace::RemoveFileEntryAt(FileEntryType type, int index) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按文件名删除文件条目(匹配工作空间内记录的文件名)
|
|
||||||
bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) {
|
bool WorkSpace::RemoveFileEntryByName(FileEntryType type, const QString& fileName) {
|
||||||
auto it = files_.find(type);
|
auto it = files_.find(type);
|
||||||
if (it == files_.end()) {
|
if (it == files_.end()) {
|
||||||
|
|||||||
@ -60,14 +60,13 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
|
|||||||
LOG_WARN("element is nullptr");
|
LOG_WARN("element is nullptr");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 确保存在 Timestep 实例
|
|
||||||
workSpace_->EnsureTimestep();
|
workSpace_->EnsureTimestep();
|
||||||
Timestep* t = workSpace_->GetTimestep();
|
Timestep* t = workSpace_->GetTimestep();
|
||||||
if (!t) {
|
if (!t) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析属性:manual(0/1)、start、end、step
|
|
||||||
int manualFlag = 0;
|
int manualFlag = 0;
|
||||||
element->QueryIntAttribute("manual", &manualFlag);
|
element->QueryIntAttribute("manual", &manualFlag);
|
||||||
double start = 0.0;
|
double start = 0.0;
|
||||||
@ -85,7 +84,6 @@ bool WorkSpaceXMLParse::ParseTimestep(const tinyxml2::XMLElement* element) {
|
|||||||
t->SetStep(step);
|
t->SetStep(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 若标记为手动或具有完整的 start/end,则设置手动范围;否则按数据最大时间设置边界
|
|
||||||
if (manualFlag != 0 || (hasStart && hasEnd)) {
|
if (manualFlag != 0 || (hasStart && hasEnd)) {
|
||||||
t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0);
|
t->SetManualRange(hasStart ? start : 0.0, hasEnd ? end : 0.0);
|
||||||
} else if (hasEnd) {
|
} else if (hasEnd) {
|
||||||
@ -122,7 +120,6 @@ bool WorkSpaceXMLParse::ParseCommond(const tinyxml2::XMLElement* element) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the command file path using the filename stored in XML
|
|
||||||
workSpace_->commondPath_ = path;
|
workSpace_->commondPath_ = path;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -133,19 +130,15 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首先处理新的Chart元素结构
|
|
||||||
const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart");
|
const tinyxml2::XMLElement* chartElement = element->FirstChildElement("Chart");
|
||||||
while (nullptr != chartElement) {
|
while (nullptr != chartElement) {
|
||||||
// 创建FileEntryCurve对象来解析Chart数据
|
|
||||||
auto curveEntry = CreateEmptyFileEntryCurve();
|
auto curveEntry = CreateEmptyFileEntryCurve();
|
||||||
if (curveEntry && curveEntry->ParseFiles(chartElement)) {
|
if (curveEntry && curveEntry->ParseFiles(chartElement)) {
|
||||||
// 添加解析后的FileEntry到workspace
|
|
||||||
workSpace_->SetFileEntry(curveEntry, false);
|
workSpace_->SetFileEntry(curveEntry, false);
|
||||||
}
|
}
|
||||||
chartElement = chartElement->NextSiblingElement("Chart");
|
chartElement = chartElement->NextSiblingElement("Chart");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保持向后兼容:处理旧的type元素结构
|
|
||||||
const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type");
|
const tinyxml2::XMLElement* typeElement = element->FirstChildElement("type");
|
||||||
while (nullptr != typeElement) {
|
while (nullptr != typeElement) {
|
||||||
const char* name = typeElement->Attribute("name");
|
const char* name = typeElement->Attribute("name");
|
||||||
@ -155,17 +148,14 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
|
|||||||
if (nullptr != name && count > 0) {
|
if (nullptr != name && count > 0) {
|
||||||
QString typeName = QString::fromLocal8Bit(name);
|
QString typeName = QString::fromLocal8Bit(name);
|
||||||
|
|
||||||
// Create FileEntry objects and call their ParseFiles method
|
|
||||||
FileEntryType enumType;
|
FileEntryType enumType;
|
||||||
if (FileEntryTypeFromString(name, enumType)) {
|
if (FileEntryTypeFromString(name, enumType)) {
|
||||||
|
|
||||||
const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart");
|
const tinyxml2::XMLElement* chartElement = typeElement->FirstChildElement("chart");
|
||||||
while (nullptr != chartElement) {
|
while (nullptr != chartElement) {
|
||||||
auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing
|
auto fileEntry = CreateEmptyFileEntry(enumType);
|
||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
// Call the FileEntry's ParseFiles method to parse detailed data
|
|
||||||
if (fileEntry->ParseFiles(chartElement)) {
|
if (fileEntry->ParseFiles(chartElement)) {
|
||||||
// Add the parsed FileEntry to workspace
|
|
||||||
workSpace_->SetFileEntry(fileEntry, false);
|
workSpace_->SetFileEntry(fileEntry, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,19 +163,6 @@ bool WorkSpaceXMLParse::ParseFiles(const tinyxml2::XMLElement* element) {
|
|||||||
chartElement = chartElement->NextSiblingElement();
|
chartElement = chartElement->NextSiblingElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create FileEntry objects for this type
|
|
||||||
//for (int i = 0; i < count; ++i) {
|
|
||||||
// auto fileEntry = CreateEmptyFileEntry(enumType); // Create empty FileEntry for XML parsing
|
|
||||||
// if (fileEntry) {
|
|
||||||
// // Call the FileEntry's ParseFiles method to parse detailed data
|
|
||||||
// if (fileEntry->ParseFiles(typeElement)) {
|
|
||||||
// // Add the parsed FileEntry to workspace
|
|
||||||
// workSpace_->SetFileEntry(fileEntry, false);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Also set file entry count for backward compatibility
|
|
||||||
workSpace_->SetFileEntryCount(enumType, count);
|
workSpace_->SetFileEntryCount(enumType, count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,15 +66,12 @@ bool WorkSpaceXMLWrite::SaveScene(tinyxml2::XMLElement* scene) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removed: SaveTimeStep — timestep is no longer file-based
|
|
||||||
// 新增:保存 Timestep 的手动范围与步长倍率
|
|
||||||
bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) {
|
bool WorkSpaceXMLWrite::SaveTimeStep(tinyxml2::XMLElement* scene) {
|
||||||
if (nullptr == workSpace_) {
|
if (nullptr == workSpace_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto* t = workSpace_->GetTimestep();
|
auto* t = workSpace_->GetTimestep();
|
||||||
if (!t) {
|
if (!t) {
|
||||||
// 若尚未创建,确保存在一个默认实例,以保证文件的一致性
|
|
||||||
workSpace_->EnsureTimestep();
|
workSpace_->EnsureTimestep();
|
||||||
t = workSpace_->GetTimestep();
|
t = workSpace_->GetTimestep();
|
||||||
}
|
}
|
||||||
@ -114,7 +111,6 @@ bool WorkSpaceXMLWrite::SaveCommond(tinyxml2::XMLElement* scene) {
|
|||||||
const QString commondPath = workSpace_->GetCommondFilePath();
|
const QString commondPath = workSpace_->GetCommondFilePath();
|
||||||
if (!commondPath.isEmpty()) {
|
if (!commondPath.isEmpty()) {
|
||||||
tinyxml2::XMLElement* commond = scene->InsertNewChildElement("commond");
|
tinyxml2::XMLElement* commond = scene->InsertNewChildElement("commond");
|
||||||
// Extract just the filename from the full path for storage
|
|
||||||
QFileInfo fileInfo(commondPath);
|
QFileInfo fileInfo(commondPath);
|
||||||
commond->SetAttribute("path", fileInfo.fileName().toStdString().c_str());
|
commond->SetAttribute("path", fileInfo.fileName().toStdString().c_str());
|
||||||
}
|
}
|
||||||
@ -129,7 +125,6 @@ bool WorkSpaceXMLWrite::SaveEntities(tinyxml2::XMLElement* scene, tinyxml2::XMLD
|
|||||||
|
|
||||||
bool WorkSpaceXMLWrite::SaveChart(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc)
|
bool WorkSpaceXMLWrite::SaveChart(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc)
|
||||||
{
|
{
|
||||||
// charts section retained for compatibility, but deprecated entries (Wave, Report, RD, SimMatlab) are no longer saved
|
|
||||||
tinyxml2::XMLElement* charts = doc->NewElement("charts");
|
tinyxml2::XMLElement* charts = doc->NewElement("charts");
|
||||||
scene->LinkEndChild(charts);
|
scene->LinkEndChild(charts);
|
||||||
|
|
||||||
@ -137,7 +132,6 @@ bool WorkSpaceXMLWrite::SaveChart(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) {
|
||||||
// Persist multi-file entries per type as counts
|
|
||||||
tinyxml2::XMLElement* files = doc->NewElement("files");
|
tinyxml2::XMLElement* files = doc->NewElement("files");
|
||||||
scene->LinkEndChild(files);
|
scene->LinkEndChild(files);
|
||||||
|
|
||||||
@ -149,7 +143,6 @@ bool WorkSpaceXMLWrite::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocu
|
|||||||
typeElem->SetAttribute("count", static_cast<int>(vec.size()));
|
typeElem->SetAttribute("count", static_cast<int>(vec.size()));
|
||||||
files->LinkEndChild(typeElem);
|
files->LinkEndChild(typeElem);
|
||||||
|
|
||||||
// Call SaveFiles method for each FileEntry to save detailed data
|
|
||||||
for (const auto& fileEntry : vec) {
|
for (const auto& fileEntry : vec) {
|
||||||
if (fileEntry) {
|
if (fileEntry) {
|
||||||
fileEntry->SaveFiles(typeElem, doc);
|
fileEntry->SaveFiles(typeElem, doc);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user