Files
hfut-bishe/client/gui/main_window/MainWindow.h
T
2026-05-23 20:49:32 +08:00

265 lines
9.6 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "core/workspace/ProjectWorkspace.h"
#include "main_window/RecentProjectHistory.h"
#include <QElapsedTimer>
#include <QMainWindow>
#include <QPointF>
#include <QFrame>
#include <QIcon>
#include <QTimer>
#include <QToolButton>
#include <QSet>
class ToolOptionPopup;
class QAction;
class QCheckBox;
class QComboBox;
class QDockWidget;
class QFormLayout;
class QLabel;
class QMenu;
class QFrame;
class QIcon;
class QPushButton;
class QListWidget;
class QSlider;
class QStackedWidget;
class QToolButton;
class QTreeWidget;
class QTreeWidgetItem;
class QWidget;
class EditorCanvas;
class TimelineWidget;
class TimelineEditorModel;
namespace gui {
class BackgroundPropertySection;
class BlackholePropertySection;
class EntityPropertySection;
class ToolPropertySection;
class CameraPropertySection;
class HotspotPropertySection;
class EntityIntroPopup;
class ResourceLibraryDock;
}
namespace core::library {
class ResourceLibraryProvider;
class FakeResourceLibraryProvider;
class OnlineResourceLibraryProvider;
}
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = nullptr);
protected:
bool eventFilter(QObject* watched, QEvent* event) override;
private slots:
// 文件菜单槽函数
void onNewProject();
void onOpenProject();
void onSaveProject();
void onCloseProject();
// 编辑菜单槽函数
void onUndo();
void onRedo();
void onCopyObject();
void onPasteObject();
// 帮助菜单槽函数
void onAbout();
void onComputeDepth();
void onTogglePlay(bool on);
void onInsertCombinedKey(); // 位置 + userScale
void onProjectTreeItemClicked(QTreeWidgetItem* item, int column);
private:
void computeDepthAsync();
// UI 状态分三种:
// - Welcome:未打开项目。只显示欢迎页,其它 dock 一律隐藏,视图开关禁用。
// - EntityEditor:静态实体编辑(activeAnimationId=none,不显示摄像机)。
// - AnimationEditor:动画编辑(真实动画方案,可编辑摄像机/时间轴)。
// - HotspotEditor:展示热点布点(要求:项目已打开且背景不为空)。
// - Preview:预览展示。用于全流程完成后的展示(要求:项目已打开且背景不为空)。
enum class UiMode { Welcome, EntityEditor, AnimationEditor, HotspotEditor, Preview };
void createMenus(); // 菜单和工具栏
void createFileMenu(); // 文件菜单
void createEditMenu(); // 编辑菜单
void createHelpMenu(); // 帮助菜单
void createViewMenu(); // 视图菜单
void createAnimationMenu();
void createWindowMenu(); // 窗口菜单(资源库等)
void createProjectTreeDock();
void createTimelineDock();
void createResourceLibraryDock();
void refreshProjectTree();
void updateUiEnabledState(); // 更新“可用性/勾选/默认显隐”,不要做业务逻辑
void applyUiMode(UiMode mode); // 统一控制 welcome/editor 两态的显隐策略
UiMode currentUiMode() const; // 根据 workspace 状态推导
void syncCanvasViewMenuFromState();
void showProjectRootContextMenu(const QPoint& globalPos);
void showBackgroundContextMenu(const QPoint& globalPos);
void showBlackholeContextMenu(const QPoint& globalPos, const QString& entityId);
void rebuildCentralPages();
void showWelcomePage();
void showEditorPage();
void showPreviewPage();
void refreshWelcomeRecentList();
void openProjectFromPath(const QString& dir);
/// 打开/新建工程后:模态「加载中」直至首张背景可显示(无背景则立即继续)
void presentWorkspaceEditorWithBlockingInitialLoad();
void refreshPreviewPage();
void refreshEditorPage();
void applyTimelineFromProject();
/// 时间轴当前帧 → 画布:求值并回灌实体/工具/摄像机(不经 TimelineWidget::setCurrentFrame,避免触发 frameScrubbed
void applyTimelineFrameToEditor(int frame);
void updateTimelineTracks();
void refreshDopeSheet();
void setPreviewRequested(bool preview);
void syncPreviewPlaybackBar();
void syncPreviewFloatingChrome();
void stopEditorPlayback();
void stopPreviewPlayback();
void startPreviewPlayback();
QString effectivePreviewAnimationId() const;
void requestPreviewSchemeSwitchTo(const QString& id, bool warmupDialog);
QVector<QString> previewAnimationSchemeIdsNonNone() const;
void syncHotspotEnterPreviewCombo();
void syncEditorRailForMode();
QStackedWidget* m_centerStack = nullptr;
QWidget* m_pageWelcome = nullptr;
QTreeWidget* m_welcomeRecentTree = nullptr;
QLabel* m_welcomeRecentEmptyLabel = nullptr;
QWidget* m_pageEditor = nullptr;
QWidget* m_canvasHost = nullptr;
QFrame* m_floatingModeDock = nullptr;
QFrame* m_floatingToolDock = nullptr;
QComboBox* m_modeSelector = nullptr;
QStackedWidget* m_propertyStack = nullptr;
gui::BackgroundPropertySection* m_bgPropertySection = nullptr;
gui::BlackholePropertySection* m_blackholePropertySection = nullptr;
gui::EntityPropertySection* m_entityPropertySection = nullptr;
gui::ToolPropertySection* m_toolPropertySection = nullptr;
gui::CameraPropertySection* m_cameraPropertySection = nullptr;
gui::HotspotPropertySection* m_hotspotPropertySection = nullptr;
QToolButton* m_btnCreateEntity = nullptr;
ToolOptionPopup* m_createEntityPopup = nullptr;
QToolButton* m_btnToggleDepthOverlay = nullptr;
EditorCanvas* m_editorCanvas = nullptr;
QTreeWidget* m_projectTree = nullptr;
QStackedWidget* m_rightTopDockStack = nullptr;
QListWidget* m_hotspotAnimationList = nullptr;
QDockWidget* m_dockProjectTree = nullptr;
QDockWidget* m_dockProperties = nullptr;
QDockWidget* m_dockTimeline = nullptr;
QDockWidget* m_dockResourceLibrary = nullptr;
QTreeWidgetItem* m_itemBackground = nullptr;
QAction* m_actionUndo = nullptr;
QAction* m_actionRedo = nullptr;
QAction* m_actionCopy = nullptr;
QAction* m_actionPaste = nullptr;
QAction* m_actionToggleProjectTree = nullptr;
QAction* m_actionToggleProperties = nullptr;
QAction* m_actionToggleTimeline = nullptr;
QAction* m_actionToggleResourceLibrary = nullptr;
QAction* m_actionEnterPreview = nullptr;
QAction* m_actionBackToEditor = nullptr;
QAction* m_actionAnimationSettings = nullptr;
QAction* m_actionCanvasWorldAxes = nullptr;
QAction* m_actionCanvasAxisValues = nullptr;
QAction* m_actionCanvasGrid = nullptr;
QAction* m_actionCanvasCheckerboard = nullptr;
QAction* m_actionCanvasDepthOverlay = nullptr;
QAction* m_actionCanvasGizmoLabels = nullptr;
core::ProjectWorkspace m_workspace;
RecentProjectHistory m_recentHistory;
bool m_previewRequested = false;
/// 因右侧栏过窄自动收起;用户通过视图菜单再次打开时清除
bool m_rightDocksNarrowHidden = false;
QPointF m_lastWorldPos;
int m_lastWorldZ = -1;
bool m_hasSelectedEntity = false;
bool m_hasSelectedTool = false;
bool m_hasSelectedCamera = false;
bool m_syncingTreeSelection = false;
int m_selectedEntityDepth = 0;
QPointF m_selectedEntityOrigin;
QString m_selectedEntityId;
QString m_selectedToolId;
QString m_selectedCameraId;
QString m_selectedBlackholeEntityId;
QString m_selectedEntityDisplayNameCache;
QString m_bgAbsCache;
QString m_bgSizeTextCache;
// 项目树“眼睛”:仅用于画布临时隐藏(不持久化、不进时间轴)
QSet<QString> m_tempHiddenEntityIds;
QSet<QString> m_tempHiddenToolIds;
QSet<QString> m_tempHiddenCameraIds;
void updateStatusBarText();
void syncCreateEntityToolButtonTooltip();
void refreshPropertyPanel();
void refreshEntityPropertyPanelFast();
void syncProjectTreeFromCanvasSelection();
/// 右侧项目树+属性列最小宽度:随当前属性页与树内容 minimumSizeHint 抬高,窄于内容时不再缩小。
void updateRightDockColumnMinimumWidthFromContent();
bool m_timelineScrubbing = false;
/// 限制 scrub 时全量回灌频率,避免每像素一次 evaluate + 磁盘读图导致时间轴极卡
QElapsedTimer m_timelineEditorApplyThrottle;
bool m_entityDragging = false;
QTimer* m_propertySyncTimer = nullptr;
int m_currentFrame = 0;
bool m_playing = false;
QTimer* m_playTimer = nullptr;
QString m_previewAnimationId;
bool m_animationRequested = false;
bool m_hotspotRequested = false;
QString m_selectedHotspotId;
QToolButton* m_railBtnMove = nullptr;
QToolButton* m_railBtnZoom = nullptr;
QToolButton* m_railBtnFit = nullptr;
QToolButton* m_btnRailAddHotspot = nullptr;
QToolButton* m_btnRailMoveHotspot = nullptr;
QToolButton* m_btnHotspotEnterPreview = nullptr;
int m_previewFrame = 0;
bool m_previewPlaying = false;
QTimer* m_previewPlayTimer = nullptr;
TimelineWidget* m_timeline = nullptr;
TimelineEditorModel* m_timelineModel = nullptr;
QToolButton* m_btnPlay = nullptr;
QComboBox* m_schemeSelector = nullptr;
// 时间轴区间选择(用于逐帧贴图动画)
int m_timelineRangeStart = -1;
int m_timelineRangeEnd = -1;
QCheckBox* m_chkAutoKeyframe = nullptr;
// 旧版 DopeSheet 已移除,这里保留占位便于后续扩展区间 UI(如自定义小部件)
QTreeWidget* m_dopeTree = nullptr;
QPushButton* m_btnDopeDeleteKey = nullptr;
gui::EntityIntroPopup* m_entityIntroPopup = nullptr;
QToolButton* m_previewBackToStaticBtn = nullptr;
gui::ResourceLibraryDock* m_resourceLibraryDockWidget = nullptr;
core::library::ResourceLibraryProvider* m_resourceLibraryProvider = nullptr;
};