/
Mr.Stalin
/
FOnline-Engine
Обзор
Документация
Войти
/
Mr.Stalin
/
FOnline-Engine
Код
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
Source/Frontend/ApplicationStub.cpp
351 строка
11 KB
cvet
Code coverage (#203)
10 авг 2026, 15:25
Не верифицирован
10 авг 2026, 15:25
d73ed92
Код
Авторство
О чём код?
// __________ ___ ______ _ // / ____/ __ \____ / (_)___ ___ / ____/___ ____ _(_)___ ___ // / /_ / / / / __ \/ / / __ \/ _ \ / __/ / __ \/ __ `/ / __ \/ _ \ // / __/ / /_/ / / / / / / / / / __/ / /___/ / / / /_/ / / / / / __/ // /_/ \____/_/ /_/_/_/_/ /_/\___/ /_____/_/ /_/\__, /_/_/ /_/\___/ // /____/ // FOnline Engine // https://fonline.ru // https://github.com/cvet/fonline // // MIT License // // Copyright (c) 2006 - 2026, Anton Tsvetinskiy aka cvet <cvet@tut.by> // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // #include "Application.h" FO_BEGIN_NAMESPACE class StubAppRender final : public IAppRender { public: explicit StubAppRender(ptr<GlobalSettings> settings) { FO_STACK_TRACE_ENTRY(); _renderer.Init(*settings, nullptr); } [[nodiscard]] auto GetRenderTarget() -> nptr<RenderTexture> override { return _renderTarget; } [[nodiscard]] auto CreateTexture(isize32 size, bool linear_filtered, bool with_depth) -> unique_ptr<RenderTexture> override { return _renderer.CreateTexture(size, linear_filtered, with_depth); } [[nodiscard]] auto CreateDrawBuffer(bool is_static) -> unique_ptr<RenderDrawBuffer> override { return _renderer.CreateDrawBuffer(is_static); } [[nodiscard]] auto CreateEffect(EffectUsage usage, string_view name, const RenderEffectLoader& loader) -> unique_ptr<RenderEffect> override { return _renderer.CreateEffect(usage, name, loader); } [[nodiscard]] auto CreateOrthoMatrix(float32_t left, float32_t right, float32_t bottom, float32_t top, float32_t nearp, float32_t farp) const -> mat44 override { return _renderer.CreateOrthoMatrix(left, right, bottom, top, nearp, farp); } [[nodiscard]] auto IsRenderTargetFlipped() const -> bool override { return _renderer.IsRenderTargetFlipped(); } [[nodiscard]] auto GetProjMatrix() const -> mat44 override { return _renderer.GetProjMatrix(); } void SetRenderTarget(nptr<RenderTexture> tex) override { FO_STACK_TRACE_ENTRY(); _renderTarget = tex; _renderer.SetRenderTarget(tex); } void SetOrthoDepthRange(float32_t nearp, float32_t farp) noexcept override { FO_STACK_TRACE_ENTRY(); _renderer.SetOrthoDepthRange(nearp, farp); } void ClearRenderTarget(optional<ucolor> color, bool depth = false, bool stencil = false) override { FO_STACK_TRACE_ENTRY(); _renderer.ClearRenderTarget(color, depth, stencil); } void EnableScissor(irect32 rect) override { FO_STACK_TRACE_ENTRY(); _renderer.EnableScissor(rect); } void DisableScissor() override { FO_STACK_TRACE_ENTRY(); _renderer.DisableScissor(); } private: Null_Renderer _renderer; nptr<RenderTexture> _renderTarget {}; }; class StubAppInput final : public IAppInput { public: explicit StubAppInput(ptr<GlobalSettings> settings) { FO_STACK_TRACE_ENTRY(); ignore_unused(settings); } [[nodiscard]] auto IsMouseAvailable() const noexcept -> bool override { return false; } [[nodiscard]] auto GetMousePosition() const -> ipos32 override { return _lastMousePos; } [[nodiscard]] auto GetGamepadState() const noexcept -> GamepadState override { return {}; } [[nodiscard]] auto GetClipboardText() -> const string& override { return _clipboardTextStorage; } [[nodiscard]] auto IsShiftDown() const noexcept -> bool override { return _shiftDown; } [[nodiscard]] auto IsCtrlDown() const noexcept -> bool override { return _ctrlDown; } [[nodiscard]] auto IsAltDown() const noexcept -> bool override { return _altDown; } auto PollEvent(InputEvent& ev) -> bool override { FO_STACK_TRACE_ENTRY(); if (_eventsQueue.empty() && !_nextFrameEventsQueue.empty()) { _eventsQueue.swap(_nextFrameEventsQueue); } if (_eventsQueue.empty()) { return false; } ev = _eventsQueue.front(); _eventsQueue.pop_front(); return true; } void ClearEvents() override { FO_STACK_TRACE_ENTRY(); _eventsQueue.clear(); _nextFrameEventsQueue.clear(); } void SetMousePosition(ipos32 pos, nptr<const IAppWindow> relative_to = nullptr) override { FO_STACK_TRACE_ENTRY(); ignore_unused(relative_to); _lastMousePos = pos; } void PushEvent(const InputEvent& ev, bool push_to_this_frame = false) override { FO_STACK_TRACE_ENTRY(); UpdateModifierState(ev); if (push_to_this_frame) { _eventsQueue.emplace_back(ev); } else { _nextFrameEventsQueue.emplace_back(ev); } } void SetScreenKeyboardEnabled(bool enabled) override { FO_STACK_TRACE_ENTRY(); ignore_unused(enabled); } void SetClipboardText(string_view text) override { FO_STACK_TRACE_ENTRY(); _clipboardTextStorage = string(text); } private: void UpdateModifierState(const InputEvent& ev) { FO_STACK_TRACE_ENTRY(); auto update_key_state = [this](KeyCode key, bool pressed) { if (key == KeyCode::Lshift || key == KeyCode::Rshift) { _shiftDown = pressed; } else if (key == KeyCode::Lcontrol || key == KeyCode::Rcontrol) { _ctrlDown = pressed; } else if (key == KeyCode::Lmenu || key == KeyCode::Rmenu) { _altDown = pressed; } }; if (ev.Type == InputEvent::EventType::KeyDownEvent) { update_key_state(ev.KeyDown.Code, true); } else if (ev.Type == InputEvent::EventType::KeyUpEvent) { update_key_state(ev.KeyUp.Code, false); } } string _clipboardTextStorage {}; ipos32 _lastMousePos {}; deque<InputEvent> _eventsQueue {}; deque<InputEvent> _nextFrameEventsQueue {}; bool _shiftDown {}; bool _ctrlDown {}; bool _altDown {}; }; class StubAppAudio final : public IAppAudio { public: [[nodiscard]] auto IsEnabled() const -> bool override { return false; } auto ConvertAudio(int32_t format, int32_t channels, int32_t rate, vector<uint8_t>& buf) -> bool override { FO_STACK_TRACE_ENTRY(); ignore_unused(format, channels, rate, buf); return false; } void SetSource(AudioStreamCallback stream_callback) override { FO_STACK_TRACE_ENTRY(); ignore_unused(stream_callback); } void MixAudio(span<uint8_t> output, const_span<uint8_t> buf, int32_t volume) override { FO_STACK_TRACE_ENTRY(); ignore_unused(output, buf, volume); } void LockDevice() override { FO_STACK_TRACE_ENTRY(); } void UnlockDevice() override { FO_STACK_TRACE_ENTRY(); } }; class StubAppWindow final : public IAppWindow { public: explicit StubAppWindow(ptr<GlobalSettings> settings) : _render {settings}, _input {settings} { FO_STACK_TRACE_ENTRY(); _state.Size = {settings->ScreenWidth, settings->ScreenHeight}; } [[nodiscard]] auto GetSize() const -> isize32 override { return _state.Size; } [[nodiscard]] auto GetScreenSize() const -> isize32 override { return _state.Size; } [[nodiscard]] auto GetPosition() const -> ipos32 override { return _state.Position; } [[nodiscard]] auto IsFocused() const -> bool override { return !_state.Minimized; } [[nodiscard]] auto IsFullscreen() const -> bool override { return _state.Fullscreen; } [[nodiscard]] auto IsVirtual() const noexcept -> bool override { return false; } [[nodiscard]] auto GetRender() noexcept -> ptr<IAppRender> override { return &_render; } [[nodiscard]] auto GetInput() noexcept -> ptr<IAppInput> override { return &_input; } [[nodiscard]] auto GetAudio() noexcept -> ptr<IAppAudio> override { return &_audio; } [[nodiscard]] auto GetOnWindowSizeChanged() noexcept -> ptr<EventObserver<>> override { return &OnWindowSizeChanged; } [[nodiscard]] auto GetOnScreenSizeChanged() noexcept -> ptr<EventObserver<>> override { return &OnScreenSizeChanged; } [[nodiscard]] auto GetOnLowMemory() noexcept -> ptr<EventObserver<>> override { return &OnLowMemory; } [[nodiscard]] auto GetWindowHandleForInput() const -> nptr<WindowInternalHandle> override { return nullptr; } void GrabInput(bool enable) override { FO_STACK_TRACE_ENTRY(); _grabbed = enable; } void SetSize(isize32 size) override { FO_STACK_TRACE_ENTRY(); if (_state.Size != size) { _state.Size = size; _onWindowSizeChangedDispatcher(); } } void SetScreenSize(isize32 size) override { FO_STACK_TRACE_ENTRY(); if (_state.Size != size) { _state.Size = size; _onScreenSizeChangedDispatcher(); } } void SetPosition(ipos32 pos) override { FO_STACK_TRACE_ENTRY(); _state.Position = pos; } void Minimize() override { FO_STACK_TRACE_ENTRY(); _state.Minimized = true; } auto ToggleFullscreen(bool enable) -> bool override { FO_STACK_TRACE_ENTRY(); // The interface reports whether the state changed, not the resulting state bool changed = _state.Fullscreen != enable; _state.Fullscreen = enable; return changed; } void Blink() override { FO_STACK_TRACE_ENTRY(); } void AlwaysOnTop(bool enable) override { FO_STACK_TRACE_ENTRY(); _state.AlwaysOnTop = enable; } void Destroy() override { FO_STACK_TRACE_ENTRY(); } EventObserver<> OnWindowSizeChanged {}; EventObserver<> OnScreenSizeChanged {}; EventObserver<> OnLowMemory {}; private: HeadlessWindowStub _state {}; StubAppRender _render; StubAppInput _input; StubAppAudio _audio; bool _grabbed {}; EventDispatcher<> _onWindowSizeChangedDispatcher {&OnWindowSizeChanged}; EventDispatcher<> _onScreenSizeChangedDispatcher {&OnScreenSizeChanged}; }; auto GetAppWindowStub(GlobalSettings& settings) -> unique_ptr<IAppWindow> { FO_STACK_TRACE_ENTRY(); return SafeAlloc::MakeUnique<StubAppWindow>(&settings); } FO_END_NAMESPACE