feat: expand editor scripting asset and viewport flow

This commit is contained in:
2026-04-03 13:22:30 +08:00
parent ed8c27fde2
commit a05d0b80a2
124 changed files with 10397 additions and 1737 deletions

View File

@@ -6,9 +6,25 @@
#include "Core/ISceneManager.h"
#include "Core/IUndoManager.h"
#include <XCEngine/Input/InputManager.h>
#include <XCEngine/Scripting/ScriptEngine.h>
namespace XCEngine {
namespace Editor {
namespace {
bool IsModifierKeyDown(const GameViewInputFrameEvent& input, XCEngine::Input::KeyCode key) {
const size_t index = static_cast<size_t>(key);
return index < input.keyDown.size() && input.keyDown[index];
}
bool IsGameViewInputActive(const GameViewInputFrameEvent& input) {
return input.hovered || input.focused;
}
} // namespace
void PlaySessionController::Attach(IEditorContext& context) {
if (m_playStartRequestedHandlerId == 0) {
m_playStartRequestedHandlerId = context.GetEventBus().Subscribe<PlayModeStartRequestedEvent>(
@@ -44,6 +60,14 @@ void PlaySessionController::Attach(IEditorContext& context) {
StepPlay(context);
});
}
if (m_gameViewInputFrameHandlerId == 0) {
m_gameViewInputFrameHandlerId = context.GetEventBus().Subscribe<GameViewInputFrameEvent>(
[this](const GameViewInputFrameEvent& event) {
m_pendingGameViewInput = event;
m_hasPendingGameViewInput = true;
});
}
}
void PlaySessionController::Detach(IEditorContext& context) {
@@ -73,6 +97,13 @@ void PlaySessionController::Detach(IEditorContext& context) {
context.GetEventBus().Unsubscribe<PlayModeStepRequestedEvent>(m_playStepRequestedHandlerId);
m_playStepRequestedHandlerId = 0;
}
if (m_gameViewInputFrameHandlerId != 0) {
context.GetEventBus().Unsubscribe<GameViewInputFrameEvent>(m_gameViewInputFrameHandlerId);
m_gameViewInputFrameHandlerId = 0;
}
ResetRuntimeInputBridge();
}
void PlaySessionController::Update(IEditorContext& context, float deltaTime) {
@@ -81,6 +112,7 @@ void PlaySessionController::Update(IEditorContext& context, float deltaTime) {
return;
}
ApplyGameViewInputFrame(deltaTime);
m_runtimeLoop.Tick(deltaTime);
}
@@ -104,6 +136,10 @@ bool PlaySessionController::StartPlay(IEditorContext& context) {
}
sceneManager.SetSceneDocumentDirtyTrackingEnabled(false);
XCEngine::Scripting::ScriptEngine::Get().SetRuntimeFixedDeltaTime(m_runtimeLoop.GetSettings().fixedDeltaTime);
ResetRuntimeInputBridge();
XCEngine::Input::InputManager::Get().Shutdown();
XCEngine::Input::InputManager::Get().Initialize(nullptr);
m_runtimeLoop.Start(sceneManager.GetScene());
context.GetUndoManager().ClearHistory();
context.SetRuntimeMode(EditorRuntimeMode::Play);
@@ -118,6 +154,8 @@ bool PlaySessionController::StopPlay(IEditorContext& context) {
auto& sceneManager = context.GetSceneManager();
m_runtimeLoop.Stop();
ResetRuntimeInputBridge();
XCEngine::Input::InputManager::Get().Shutdown();
sceneManager.SetSceneDocumentDirtyTrackingEnabled(true);
if (!sceneManager.RestoreSceneSnapshot(m_editorSnapshot)) {
@@ -162,5 +200,83 @@ bool PlaySessionController::StepPlay(IEditorContext& context) {
return true;
}
void PlaySessionController::ResetRuntimeInputBridge() {
m_pendingGameViewInput = {};
m_appliedGameViewInput = {};
m_hasPendingGameViewInput = false;
}
void PlaySessionController::ApplyGameViewInputFrame(float deltaTime) {
using XCEngine::Input::InputManager;
using XCEngine::Input::KeyCode;
using XCEngine::Input::MouseButton;
InputManager& inputManager = InputManager::Get();
inputManager.Update(deltaTime);
const GameViewInputFrameEvent input = m_hasPendingGameViewInput
? m_pendingGameViewInput
: GameViewInputFrameEvent{};
m_hasPendingGameViewInput = false;
const bool inputActive = IsGameViewInputActive(input);
const bool alt = inputActive &&
(IsModifierKeyDown(input, KeyCode::LeftAlt) || IsModifierKeyDown(input, KeyCode::RightAlt));
const bool ctrl = inputActive &&
(IsModifierKeyDown(input, KeyCode::LeftCtrl) || IsModifierKeyDown(input, KeyCode::RightCtrl));
const bool shift = inputActive &&
(IsModifierKeyDown(input, KeyCode::LeftShift) || IsModifierKeyDown(input, KeyCode::RightShift));
for (size_t index = 0; index < input.keyDown.size(); ++index) {
const bool wasDown = m_appliedGameViewInput.keyDown[index];
const bool isDown = inputActive && input.keyDown[index];
if (wasDown == isDown) {
continue;
}
const KeyCode key = static_cast<KeyCode>(index);
if (isDown) {
inputManager.ProcessKeyDown(key, false, alt, ctrl, shift, false);
} else {
inputManager.ProcessKeyUp(key, alt, ctrl, shift, false);
}
}
for (size_t index = 0; index < input.mouseButtonDown.size(); ++index) {
const bool wasDown = m_appliedGameViewInput.mouseButtonDown[index];
const bool isDown = inputActive && input.mouseButtonDown[index];
if (wasDown == isDown) {
continue;
}
inputManager.ProcessMouseButton(
static_cast<MouseButton>(index),
isDown,
static_cast<int>(input.mousePosition.x),
static_cast<int>(input.mousePosition.y));
}
if (inputActive &&
(input.mousePosition != m_appliedGameViewInput.mousePosition || input.mouseDelta != XCEngine::Math::Vector2::Zero())) {
inputManager.ProcessMouseMove(
static_cast<int>(input.mousePosition.x),
static_cast<int>(input.mousePosition.y),
static_cast<int>(input.mouseDelta.x),
static_cast<int>(input.mouseDelta.y));
}
if (inputActive && input.mouseWheel != 0.0f) {
inputManager.ProcessMouseWheel(
input.mouseWheel,
static_cast<int>(input.mousePosition.x),
static_cast<int>(input.mousePosition.y));
}
m_appliedGameViewInput = {};
if (inputActive) {
m_appliedGameViewInput = input;
}
}
} // namespace Editor
} // namespace XCEngine