Integrate XCUI shell state and runtime frame seams
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <XCEngine/Input/InputTypes.h>
|
||||
|
||||
#include "XCUIBackend/XCUIEditorCommandRouter.h"
|
||||
#include "panels/XCUIDemoPanel.h"
|
||||
#include "panels/XCUILayoutLabPanel.h"
|
||||
|
||||
@@ -10,10 +13,14 @@
|
||||
#include "XCUIBackend/XCUIInputBridge.h"
|
||||
#include "XCUIBackend/XCUILayoutLabRuntime.h"
|
||||
#include "XCUIBackend/XCUIRHIRenderBackend.h"
|
||||
#include "XCUIBackend/XCUIShellChromeState.h"
|
||||
#include "XCUIBackend/XCUIStandaloneTextAtlasProvider.h"
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -24,9 +31,252 @@ namespace NewEditor {
|
||||
|
||||
class Application {
|
||||
public:
|
||||
using ShellPanelId = ::XCEngine::Editor::XCUIBackend::XCUIShellPanelId;
|
||||
using ShellViewToggleId = ::XCEngine::Editor::XCUIBackend::XCUIShellViewToggleId;
|
||||
using ShellHostedPreviewMode = ::XCEngine::Editor::XCUIBackend::XCUIShellHostedPreviewMode;
|
||||
using ShellPanelChromeState = ::XCEngine::Editor::XCUIBackend::XCUIShellPanelChromeState;
|
||||
using ShellViewToggleState = ::XCEngine::Editor::XCUIBackend::XCUIShellViewToggleState;
|
||||
|
||||
struct ShellCommandIds {
|
||||
static constexpr const char* ToggleXCUIDemoPanel =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleXCUIDemoPanel;
|
||||
static constexpr const char* ToggleXCUILayoutLabPanel =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleXCUILayoutLabPanel;
|
||||
static constexpr const char* ToggleImGuiDemoWindow =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleImGuiDemoWindow;
|
||||
static constexpr const char* ToggleNativeBackdrop =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleNativeBackdrop;
|
||||
static constexpr const char* TogglePulseAccent =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::TogglePulseAccent;
|
||||
static constexpr const char* ToggleNativeXCUIOverlay =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleNativeXCUIOverlay;
|
||||
static constexpr const char* ToggleHostedPreviewHud =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleHostedPreviewHud;
|
||||
static constexpr const char* ToggleNativeDemoPanelPreview =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleNativeDemoPanelPreview;
|
||||
static constexpr const char* ToggleNativeLayoutLabPreview =
|
||||
::XCEngine::Editor::XCUIBackend::XCUIShellChromeCommandIds::ToggleNativeLayoutLabPreview;
|
||||
};
|
||||
|
||||
struct ShellCommandBindings {
|
||||
std::function<bool()> getXCUIDemoPanelVisible = {};
|
||||
std::function<void(bool)> setXCUIDemoPanelVisible = {};
|
||||
std::function<bool()> getXCUILayoutLabPanelVisible = {};
|
||||
std::function<void(bool)> setXCUILayoutLabPanelVisible = {};
|
||||
std::function<bool()> getImGuiDemoWindowVisible = {};
|
||||
std::function<void(bool)> setImGuiDemoWindowVisible = {};
|
||||
std::function<bool()> getNativeBackdropVisible = {};
|
||||
std::function<void(bool)> setNativeBackdropVisible = {};
|
||||
std::function<bool()> getPulseAccentEnabled = {};
|
||||
std::function<void(bool)> setPulseAccentEnabled = {};
|
||||
std::function<bool()> getNativeXCUIOverlayVisible = {};
|
||||
std::function<void(bool)> setNativeXCUIOverlayVisible = {};
|
||||
std::function<bool()> getHostedPreviewHudVisible = {};
|
||||
std::function<void(bool)> setHostedPreviewHudVisible = {};
|
||||
std::function<bool()> getNativeDemoPanelPreviewEnabled = {};
|
||||
std::function<void(bool)> setNativeDemoPanelPreviewEnabled = {};
|
||||
std::function<bool()> getNativeLayoutLabPreviewEnabled = {};
|
||||
std::function<void(bool)> setNativeLayoutLabPreviewEnabled = {};
|
||||
std::function<void()> onHostedPreviewModeChanged = {};
|
||||
};
|
||||
|
||||
static ::XCEngine::Editor::XCUIBackend::XCUIEditorCommandInputSnapshot BuildShellShortcutSnapshot(
|
||||
const ::XCEngine::Editor::XCUIBackend::XCUIInputBridgeFrameDelta& frameDelta) {
|
||||
::XCEngine::Editor::XCUIBackend::XCUIEditorCommandInputSnapshot snapshot = {};
|
||||
snapshot.modifiers = frameDelta.state.modifiers;
|
||||
snapshot.windowFocused = frameDelta.state.windowFocused;
|
||||
snapshot.wantCaptureKeyboard = frameDelta.state.wantCaptureKeyboard;
|
||||
snapshot.wantTextInput = frameDelta.state.wantTextInput;
|
||||
|
||||
snapshot.keys.reserve(
|
||||
frameDelta.keyboard.pressedKeys.size() +
|
||||
frameDelta.keyboard.repeatedKeys.size());
|
||||
|
||||
const auto appendKeyState =
|
||||
[&snapshot](std::int32_t keyCode, bool repeat) {
|
||||
for (auto& existing : snapshot.keys) {
|
||||
if (existing.keyCode != keyCode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
existing.down = true;
|
||||
existing.repeat = existing.repeat || repeat;
|
||||
return;
|
||||
}
|
||||
|
||||
::XCEngine::Editor::XCUIBackend::XCUIEditorCommandKeyState keyState = {};
|
||||
keyState.keyCode = keyCode;
|
||||
keyState.down = true;
|
||||
keyState.repeat = repeat;
|
||||
snapshot.keys.push_back(keyState);
|
||||
};
|
||||
|
||||
for (std::int32_t keyCode : frameDelta.keyboard.pressedKeys) {
|
||||
appendKeyState(keyCode, false);
|
||||
}
|
||||
for (std::int32_t keyCode : frameDelta.keyboard.repeatedKeys) {
|
||||
appendKeyState(keyCode, true);
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
static void RegisterShellViewCommands(
|
||||
::XCEngine::Editor::XCUIBackend::XCUIEditorCommandRouter& router,
|
||||
const ShellCommandBindings& bindings) {
|
||||
using ::XCEngine::Editor::XCUIBackend::XCUIEditorCommandAccelerator;
|
||||
using ::XCEngine::Editor::XCUIBackend::XCUIEditorCommandDefinition;
|
||||
using ::XCEngine::Input::KeyCode;
|
||||
using ModifierState = ::XCEngine::UI::UIInputModifiers;
|
||||
|
||||
const auto bindToggleCommand =
|
||||
[&router](
|
||||
const char* commandId,
|
||||
const std::function<bool()>& getter,
|
||||
const std::function<void(bool)>& setter,
|
||||
std::initializer_list<XCUIEditorCommandAccelerator> accelerators,
|
||||
const std::function<void()>& afterToggle = {}) {
|
||||
if (!getter || !setter) {
|
||||
return;
|
||||
}
|
||||
|
||||
XCUIEditorCommandDefinition definition = {};
|
||||
definition.commandId = commandId;
|
||||
definition.isEnabled = [getter, setter]() {
|
||||
return static_cast<bool>(getter) && static_cast<bool>(setter);
|
||||
};
|
||||
definition.invoke = [getter, setter, afterToggle]() {
|
||||
const bool nextValue = !getter();
|
||||
setter(nextValue);
|
||||
if (afterToggle) {
|
||||
afterToggle();
|
||||
}
|
||||
};
|
||||
definition.accelerators.assign(accelerators.begin(), accelerators.end());
|
||||
router.RegisterCommand(definition);
|
||||
};
|
||||
|
||||
const ModifierState ctrlOnly = { false, true, false, false };
|
||||
const ModifierState ctrlShift = { true, true, false, false };
|
||||
const ModifierState ctrlAlt = { false, true, true, false };
|
||||
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleXCUIDemoPanel,
|
||||
bindings.getXCUIDemoPanelVisible,
|
||||
bindings.setXCUIDemoPanelVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::One),
|
||||
ctrlOnly,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleXCUILayoutLabPanel,
|
||||
bindings.getXCUILayoutLabPanelVisible,
|
||||
bindings.setXCUILayoutLabPanelVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::Two),
|
||||
ctrlOnly,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleImGuiDemoWindow,
|
||||
bindings.getImGuiDemoWindowVisible,
|
||||
bindings.setImGuiDemoWindowVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::Three),
|
||||
ctrlOnly,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleNativeBackdrop,
|
||||
bindings.getNativeBackdropVisible,
|
||||
bindings.setNativeBackdropVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::B),
|
||||
ctrlShift,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::TogglePulseAccent,
|
||||
bindings.getPulseAccentEnabled,
|
||||
bindings.setPulseAccentEnabled,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::P),
|
||||
ctrlShift,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleNativeXCUIOverlay,
|
||||
bindings.getNativeXCUIOverlayVisible,
|
||||
bindings.setNativeXCUIOverlayVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::O),
|
||||
ctrlShift,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleHostedPreviewHud,
|
||||
bindings.getHostedPreviewHudVisible,
|
||||
bindings.setHostedPreviewHudVisible,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::H),
|
||||
ctrlShift,
|
||||
true,
|
||||
false } });
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleNativeDemoPanelPreview,
|
||||
bindings.getNativeDemoPanelPreviewEnabled,
|
||||
bindings.setNativeDemoPanelPreviewEnabled,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::One),
|
||||
ctrlAlt,
|
||||
true,
|
||||
false } },
|
||||
bindings.onHostedPreviewModeChanged);
|
||||
bindToggleCommand(
|
||||
ShellCommandIds::ToggleNativeLayoutLabPreview,
|
||||
bindings.getNativeLayoutLabPreviewEnabled,
|
||||
bindings.setNativeLayoutLabPreviewEnabled,
|
||||
{ XCUIEditorCommandAccelerator{
|
||||
static_cast<std::int32_t>(KeyCode::Two),
|
||||
ctrlAlt,
|
||||
true,
|
||||
false } },
|
||||
bindings.onHostedPreviewModeChanged);
|
||||
}
|
||||
|
||||
int Run(HINSTANCE instance, int nCmdShow);
|
||||
|
||||
private:
|
||||
using ShellPanelStateArray = std::array<ShellPanelChromeState, static_cast<std::size_t>(ShellPanelId::Count)>;
|
||||
|
||||
static constexpr std::size_t GetShellPanelIndex(ShellPanelId panelId) {
|
||||
return static_cast<std::size_t>(panelId);
|
||||
}
|
||||
|
||||
static ShellPanelStateArray CreateDefaultShellPanelStates() {
|
||||
ShellPanelStateArray panels = {};
|
||||
panels[GetShellPanelIndex(ShellPanelId::XCUIDemo)] = {
|
||||
ShellPanelId::XCUIDemo,
|
||||
"XCUI Demo",
|
||||
"XCUI Demo",
|
||||
"new_editor.panels.xcui_demo",
|
||||
true,
|
||||
true,
|
||||
ShellHostedPreviewMode::NativeOffscreen
|
||||
};
|
||||
panels[GetShellPanelIndex(ShellPanelId::XCUILayoutLab)] = {
|
||||
ShellPanelId::XCUILayoutLab,
|
||||
"XCUI Layout Lab",
|
||||
"XCUI Layout Lab",
|
||||
"new_editor.panels.xcui_layout_lab",
|
||||
true,
|
||||
true,
|
||||
ShellHostedPreviewMode::LegacyImGui
|
||||
};
|
||||
return panels;
|
||||
}
|
||||
|
||||
struct HostedPreviewPanelDiagnostics {
|
||||
std::string debugName = {};
|
||||
std::string debugSource = {};
|
||||
@@ -79,10 +329,16 @@ private:
|
||||
void ShutdownWindowCompositor();
|
||||
void ShutdownRenderer();
|
||||
void DestroyHostedPreviewSurfaces();
|
||||
void SyncShellChromePanelStateFromPanels();
|
||||
void SyncHostedPreviewSurfaces();
|
||||
std::unique_ptr<::XCEngine::Editor::XCUIBackend::IXCUIHostedPreviewPresenter> CreateHostedPreviewPresenter(
|
||||
bool nativePreview);
|
||||
void ConfigureHostedPreviewPresenters();
|
||||
ShellPanelChromeState* TryGetShellPanelState(ShellPanelId panelId);
|
||||
const ShellPanelChromeState* TryGetShellPanelState(ShellPanelId panelId) const;
|
||||
bool IsShellViewToggleEnabled(ShellViewToggleId toggleId) const;
|
||||
void SetShellViewToggleEnabled(ShellViewToggleId toggleId, bool enabled);
|
||||
bool IsNativeHostedPreviewEnabled(ShellPanelId panelId) const;
|
||||
HostedPreviewPanelDiagnostics BuildHostedPreviewPanelDiagnostics(
|
||||
const char* debugName,
|
||||
const char* fallbackDebugSource,
|
||||
@@ -102,6 +358,8 @@ private:
|
||||
HostedPreviewOffscreenSurface& previewSurface,
|
||||
const ::XCEngine::Rendering::RenderContext& renderContext,
|
||||
const ::XCEngine::UI::UIDrawData& drawData);
|
||||
void ConfigureShellCommandRouter();
|
||||
void DispatchShellShortcuts();
|
||||
void RenderShellChrome();
|
||||
void RenderHostedPreviewHud();
|
||||
void RenderQueuedHostedPreviews(
|
||||
@@ -115,20 +373,17 @@ private:
|
||||
std::unique_ptr<XCUIDemoPanel> m_demoPanel;
|
||||
std::unique_ptr<XCUILayoutLabPanel> m_layoutLabPanel;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIWin32InputSource m_xcuiInputSource;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIInputBridge m_shellInputBridge;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIEditorCommandRouter m_shellCommandRouter;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewQueue m_hostedPreviewQueue;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIHostedPreviewSurfaceRegistry m_hostedPreviewSurfaceRegistry;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIStandaloneTextAtlasProvider m_hostedPreviewTextAtlasProvider;
|
||||
::XCEngine::Editor::XCUIBackend::XCUIRHIRenderBackend m_hostedPreviewRenderBackend;
|
||||
ShellViewToggleState m_shellViewToggles = {};
|
||||
ShellPanelStateArray m_shellPanels = CreateDefaultShellPanelStates();
|
||||
std::vector<HostedPreviewOffscreenSurface> m_hostedPreviewSurfaces = {};
|
||||
::XCEngine::Editor::XCUIBackend::XCUILayoutLabRuntime m_nativeOverlayRuntime;
|
||||
MainWindowNativeBackdropRenderer m_nativeBackdropRenderer;
|
||||
bool m_showImGuiDemoWindow = false;
|
||||
bool m_showNativeBackdrop = true;
|
||||
bool m_pulseNativeBackdropAccent = true;
|
||||
bool m_showNativeXCUIOverlay = true;
|
||||
bool m_showHostedPreviewHud = true;
|
||||
bool m_showNativeDemoPanelPreview = true;
|
||||
bool m_showNativeLayoutLabPreview = false;
|
||||
bool m_running = false;
|
||||
bool m_renderReady = false;
|
||||
std::chrono::steady_clock::time_point m_startTime = {};
|
||||
|
||||
Reference in New Issue
Block a user