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