Initial engine repository
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
template <typename T, typename RefPolicy>
|
||||
class RefBasePtr : protected RefPolicy {
|
||||
public:
|
||||
using value_type = T;
|
||||
using pointer_type = T*;
|
||||
using const_pointer_type = const T*;
|
||||
using reference_type = T&;
|
||||
using const_reference_type = const T&;
|
||||
|
||||
RefBasePtr() noexcept : ptr_(nullptr) {}
|
||||
RefBasePtr(std::nullptr_t) noexcept : ptr_(nullptr) {}
|
||||
|
||||
RefBasePtr(pointer_type p) : ptr_(p) {
|
||||
RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
RefBasePtr(const RefBasePtr& other) : ptr_(other.ptr_) {
|
||||
RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
RefBasePtr(RefBasePtr&& other) noexcept : ptr_(nullptr) {
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
~RefBasePtr() {
|
||||
Tidy();
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
typename std::enable_if<std::is_convertible<U*, T*>::value, int>::type = 0>
|
||||
RefBasePtr(const RefBasePtr<U, RefPolicy>& other) {
|
||||
ptr_ = dynamic_cast<pointer_type>(other.Get());
|
||||
RefPolicy::Retain(ptr_);
|
||||
}
|
||||
|
||||
pointer_type Get() const noexcept { return ptr_; }
|
||||
|
||||
pointer_type* GetAddressOfAndRelease() {
|
||||
Tidy();
|
||||
return &ptr_;
|
||||
}
|
||||
|
||||
void Reset(pointer_type ptr = nullptr) {
|
||||
if (ptr) {
|
||||
RefBasePtr(ptr).Swap(*this);
|
||||
} else {
|
||||
Tidy();
|
||||
}
|
||||
}
|
||||
|
||||
void Swap(RefBasePtr& other) noexcept {
|
||||
std::swap(ptr_, other.ptr_);
|
||||
}
|
||||
|
||||
pointer_type operator->() { return ptr_; }
|
||||
const_pointer_type operator->() const { return ptr_; }
|
||||
reference_type operator*() { return *ptr_; }
|
||||
const_reference_type operator*() const { return *ptr_; }
|
||||
pointer_type* operator&() { return this->GetAddressOfAndRelease(); }
|
||||
|
||||
operator bool() const noexcept { return ptr_ != nullptr; }
|
||||
bool operator!() const noexcept { return ptr_ == nullptr; }
|
||||
|
||||
RefBasePtr& operator=(const RefBasePtr& other) {
|
||||
if (other.ptr_ != ptr_) {
|
||||
RefBasePtr(other).Swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefBasePtr& operator=(RefBasePtr&& other) noexcept {
|
||||
if (other.ptr_ != ptr_) {
|
||||
other.Swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefBasePtr& operator=(pointer_type p) {
|
||||
if (p != ptr_) {
|
||||
RefBasePtr(p).Swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
typename std::enable_if<std::is_convertible<U*, T*>::value, int>::type = 0>
|
||||
RefBasePtr& operator=(const RefBasePtr<U, RefPolicy>& other) {
|
||||
if (other.Get() != ptr_) {
|
||||
RefBasePtr(dynamic_cast<pointer_type>(other.Get())).Swap(*this);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
RefBasePtr& operator=(std::nullptr_t) {
|
||||
Tidy();
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
void Tidy() {
|
||||
RefPolicy::Release(ptr_);
|
||||
ptr_ = nullptr;
|
||||
}
|
||||
|
||||
pointer_type ptr_;
|
||||
};
|
||||
|
||||
template <class T, class U, class RefPolicy>
|
||||
bool operator==(const RefBasePtr<T, RefPolicy>& lhs,
|
||||
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
|
||||
return lhs.Get() == rhs.Get();
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator==(const RefBasePtr<T, RefPolicy>& lhs, T* rhs) noexcept {
|
||||
return lhs.Get() == rhs;
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator==(T* lhs, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
|
||||
return lhs == rhs.Get();
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator==(const RefBasePtr<T, RefPolicy>& lhs, std::nullptr_t) noexcept {
|
||||
return !static_cast<bool>(lhs);
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator==(std::nullptr_t, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
|
||||
return !static_cast<bool>(rhs);
|
||||
}
|
||||
|
||||
template <class T, class U, class RefPolicy>
|
||||
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs,
|
||||
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs, T* rhs) noexcept {
|
||||
return lhs.Get() != rhs;
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator!=(T* lhs, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
|
||||
return lhs != rhs.Get();
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator!=(const RefBasePtr<T, RefPolicy>& lhs, std::nullptr_t) noexcept {
|
||||
return static_cast<bool>(lhs);
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
bool operator!=(std::nullptr_t, const RefBasePtr<T, RefPolicy>& rhs) noexcept {
|
||||
return static_cast<bool>(rhs);
|
||||
}
|
||||
|
||||
template <class T, class U, class RefPolicy>
|
||||
bool operator<(const RefBasePtr<T, RefPolicy>& lhs,
|
||||
const RefBasePtr<U, RefPolicy>& rhs) noexcept {
|
||||
return lhs.Get() < rhs.Get();
|
||||
}
|
||||
|
||||
template <class T, class RefPolicy>
|
||||
void swap(RefBasePtr<T, RefPolicy>& lhs, RefBasePtr<T, RefPolicy>& rhs) noexcept {
|
||||
lhs.Swap(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
#pragma once
|
||||
|
||||
#include <frostbite2D/core/window.h>
|
||||
#include <frostbite2D/graphics/camera.h>
|
||||
#include <frostbite2D/graphics/render_style.h>
|
||||
#include <frostbite2D/graphics/render_resolution.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/event/event.h>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
/**
|
||||
* @brief 应用配置结构体
|
||||
* 仅包含应用级别的配置项,模块配置由各模块自行管理
|
||||
*/
|
||||
struct AppConfig {
|
||||
/**
|
||||
* @brief 应用名称
|
||||
*/
|
||||
std::string appName = "frostbite2D App";
|
||||
/**
|
||||
* @brief 应用版本号
|
||||
*/
|
||||
std::string appVersion = "1.0.0";
|
||||
/**
|
||||
* @brief 组织名称
|
||||
*/
|
||||
std::string organization = "frostbite";
|
||||
|
||||
/**
|
||||
* @brief 窗口配置
|
||||
*/
|
||||
WindowConfig windowConfig;
|
||||
|
||||
/**
|
||||
* @brief 目标平台
|
||||
*/
|
||||
PlatformType targetPlatform = PlatformType::Auto;
|
||||
|
||||
/**
|
||||
* @brief 是否启用虚拟分辨率
|
||||
*/
|
||||
bool useVirtualResolution = false;
|
||||
|
||||
/**
|
||||
* @brief 虚拟分辨率宽度
|
||||
*/
|
||||
int virtualWidth = 0;
|
||||
|
||||
/**
|
||||
* @brief 虚拟分辨率高度
|
||||
*/
|
||||
int virtualHeight = 0;
|
||||
|
||||
/**
|
||||
* @brief 虚拟分辨率缩放模式
|
||||
*/
|
||||
ResolutionScaleMode resolutionMode = ResolutionScaleMode::Fit;
|
||||
bool useSeparateUIVirtualResolution = false;
|
||||
int uiVirtualWidth = 0;
|
||||
int uiVirtualHeight = 0;
|
||||
ResolutionScaleMode uiResolutionMode = ResolutionScaleMode::Fit;
|
||||
|
||||
/**
|
||||
* @brief 默认 2D 渲染风格预设
|
||||
* 启动时作为世界/UI 渲染的基础风格,Scene 可按需覆盖
|
||||
*/
|
||||
RenderStyleProfileId renderStyleProfile = RenderStyleProfileId::Hybrid2D;
|
||||
/**
|
||||
* @brief 最大帧率,0 表示不限制
|
||||
*/
|
||||
int maxFps = 0;
|
||||
|
||||
/**
|
||||
* @brief 创建默认配置
|
||||
* @return 默认的应用配置实例
|
||||
*/
|
||||
static AppConfig createDefault() {
|
||||
AppConfig config;
|
||||
config.appName = "Frostbite2D App";
|
||||
config.appVersion = "1.0.0";
|
||||
config.organization = "frostbite";
|
||||
config.targetPlatform = PlatformType::Auto;
|
||||
config.windowConfig = WindowConfig();
|
||||
config.renderStyleProfile = RenderStyleProfileId::Hybrid2D;
|
||||
config.useSeparateUIVirtualResolution = false;
|
||||
config.uiVirtualWidth = 0;
|
||||
config.uiVirtualHeight = 0;
|
||||
config.uiResolutionMode = ResolutionScaleMode::Fit;
|
||||
config.maxFps = 0;
|
||||
return config;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 应用程序类
|
||||
*/
|
||||
class Application {
|
||||
public:
|
||||
using StartCallback = Function<void()>;
|
||||
|
||||
/**
|
||||
* @brief 获取单例实例
|
||||
* @return 应用程序实例引用
|
||||
*/
|
||||
static Application& get();
|
||||
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
|
||||
/**
|
||||
* @brief 使用默认配置初始化
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool init();
|
||||
|
||||
/**
|
||||
* @brief 使用指定配置初始化
|
||||
* @param config 应用配置
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool init(const AppConfig& config);
|
||||
|
||||
/**
|
||||
* @brief 关闭应用程序
|
||||
*/
|
||||
void shutdown();
|
||||
|
||||
/**
|
||||
* @brief 运行主循环
|
||||
* @param callback 主循环开始前执行一次的启动回调
|
||||
*/
|
||||
void run(StartCallback callback);
|
||||
|
||||
/**
|
||||
* @brief 请求退出
|
||||
*/
|
||||
void quit();
|
||||
|
||||
/**
|
||||
* @brief 暂停应用程序
|
||||
*/
|
||||
void pause();
|
||||
|
||||
/**
|
||||
* @brief 恢复应用程序
|
||||
*/
|
||||
void resume();
|
||||
|
||||
/**
|
||||
* @brief 检查是否暂停
|
||||
* @return 暂停状态返回 true
|
||||
*/
|
||||
bool isPaused() const { return paused_; }
|
||||
|
||||
/**
|
||||
* @brief 检查是否运行中
|
||||
* @return 运行中返回 true
|
||||
*/
|
||||
bool isRunning() const { return running_; }
|
||||
|
||||
/**
|
||||
* @brief 获取总运行时间
|
||||
* @return 总运行时间(秒)
|
||||
*/
|
||||
float totalTime() const { return totalTime_; }
|
||||
|
||||
/**
|
||||
* @brief 获取当前帧率
|
||||
* @return 帧率
|
||||
*/
|
||||
int fps() const { return currentFps_; }
|
||||
|
||||
/**
|
||||
* @brief 设置最大帧率
|
||||
* @param maxFps 0 表示不限制,>0 表示帧率上限
|
||||
*/
|
||||
void setMaxFps(int maxFps);
|
||||
|
||||
/**
|
||||
* @brief 获取最大帧率设置
|
||||
* @return 0 表示不限制,>0 表示帧率上限
|
||||
*/
|
||||
int maxFps() const { return maxFps_; }
|
||||
|
||||
void setTextInputEnabled(bool enabled);
|
||||
bool isTextInputEnabled() const { return textInputEnabled_; }
|
||||
void requestTextInput();
|
||||
void releaseTextInput();
|
||||
void setImmEnabled(bool enabled);
|
||||
bool isImmEnabled() const;
|
||||
|
||||
/**
|
||||
* @brief 获取应用配置
|
||||
* @return 应用配置常量引用
|
||||
*/
|
||||
const AppConfig& getConfig() const;
|
||||
|
||||
/**
|
||||
* @brief 获取窗口
|
||||
* @return 窗口指针
|
||||
*/
|
||||
Window* getWindow() const { return window_; }
|
||||
|
||||
/**
|
||||
* @brief 获取渲染器
|
||||
* @return 渲染器指针
|
||||
*/
|
||||
class Renderer* getRenderer() const { return renderer_; }
|
||||
|
||||
/**
|
||||
* @brief 获取 delta time
|
||||
* @return 帧间隔时间(秒)
|
||||
*/
|
||||
float deltaTime() const { return deltaTime_; }
|
||||
|
||||
private:
|
||||
Application() = default;
|
||||
~Application();
|
||||
|
||||
/**
|
||||
* @brief 初始化核心模块
|
||||
* @return 初始化成功返回 true
|
||||
*/
|
||||
bool initCoreModules();
|
||||
|
||||
/**
|
||||
* @brief 主循环
|
||||
*/
|
||||
void mainLoop();
|
||||
|
||||
/**
|
||||
* @brief 更新
|
||||
*/
|
||||
void update();
|
||||
|
||||
/**
|
||||
* @brief 渲染
|
||||
*/
|
||||
void render();
|
||||
|
||||
std::unique_ptr<Event> convertSDLEvent(const SDL_Event& sdlEvent);
|
||||
void dispatchEvent(const Event& event);
|
||||
|
||||
Window* window_ = nullptr;
|
||||
class Renderer* renderer_ = nullptr;
|
||||
Camera* camera_ = nullptr;
|
||||
AppConfig config_;
|
||||
|
||||
bool initialized_ = false;
|
||||
bool running_ = false;
|
||||
bool paused_ = false;
|
||||
bool shouldQuit_ = false;
|
||||
bool textInputEnabled_ = false;
|
||||
bool immEnabled_ = false;
|
||||
int textInputRequestCount_ = 0;
|
||||
|
||||
float deltaTime_ = 0.0f;
|
||||
float totalTime_ = 0.0f;
|
||||
double lastFrameTime_ = 0.0;
|
||||
int frameCount_ = 0;
|
||||
float fpsTimer_ = 0.0f;
|
||||
int currentFps_ = 0;
|
||||
int maxFps_ = 0;
|
||||
double targetFrameDuration_ = 0.0;
|
||||
const float fpsUpdateInterval_ = 1.0f;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <exception>
|
||||
#include <future>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
struct TaskSystemConfig {
|
||||
uint32 workerCount = 0;
|
||||
uint32 maxMainThreadCallbacksPerFrame = 0;
|
||||
uint32 threadStackSize = 0;
|
||||
};
|
||||
|
||||
class TaskSystem {
|
||||
public:
|
||||
static TaskSystem& get();
|
||||
|
||||
TaskSystem(const TaskSystem&) = delete;
|
||||
TaskSystem& operator=(const TaskSystem&) = delete;
|
||||
|
||||
bool init(const TaskSystemConfig& config = {});
|
||||
void shutdown();
|
||||
|
||||
bool isInitialized() const { return initialized_; }
|
||||
bool isMainThread() const;
|
||||
size_t workerCount() const;
|
||||
uint32 maxMainThreadCallbacksPerFrame() const;
|
||||
|
||||
template <typename F>
|
||||
void post(F&& task) {
|
||||
enqueueWorkerTask(Function<void()>(std::forward<F>(task)));
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
auto submit(F&& task) -> std::future<std::invoke_result_t<F>> {
|
||||
using Result = std::invoke_result_t<F>;
|
||||
|
||||
auto packagedTask =
|
||||
std::make_shared<std::packaged_task<Result()>>(std::forward<F>(task));
|
||||
std::future<Result> future = packagedTask->get_future();
|
||||
|
||||
enqueueWorkerTask([packagedTask]() mutable { (*packagedTask)(); });
|
||||
return future;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
void postToMainThread(F&& callback) {
|
||||
enqueueMainThreadTask(Function<void()>(std::forward<F>(callback)));
|
||||
}
|
||||
|
||||
template <typename Task, typename OnComplete>
|
||||
void submitThen(Task&& task, OnComplete&& onComplete) {
|
||||
using Result = std::invoke_result_t<Task>;
|
||||
using Storage = std::decay_t<Result>;
|
||||
|
||||
auto taskFn = std::make_shared<std::decay_t<Task>>(std::forward<Task>(task));
|
||||
auto completeFn =
|
||||
std::make_shared<std::decay_t<OnComplete>>(std::forward<OnComplete>(onComplete));
|
||||
|
||||
enqueueWorkerTask([this, taskFn, completeFn]() mutable {
|
||||
try {
|
||||
if constexpr (std::is_void_v<Result>) {
|
||||
std::invoke(*taskFn);
|
||||
enqueueMainThreadTask([completeFn]() mutable { std::invoke(*completeFn); });
|
||||
} else {
|
||||
auto result = std::make_shared<Storage>(std::invoke(*taskFn));
|
||||
enqueueMainThreadTask([completeFn, result]() mutable {
|
||||
std::invoke(*completeFn, std::move(*result));
|
||||
});
|
||||
}
|
||||
} catch (...) {
|
||||
logUnhandledTaskException(std::current_exception());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Task, typename OnComplete, typename OnError>
|
||||
void submitThen(Task&& task, OnComplete&& onComplete, OnError&& onError) {
|
||||
using Result = std::invoke_result_t<Task>;
|
||||
using Storage = std::decay_t<Result>;
|
||||
|
||||
auto taskFn = std::make_shared<std::decay_t<Task>>(std::forward<Task>(task));
|
||||
auto completeFn =
|
||||
std::make_shared<std::decay_t<OnComplete>>(std::forward<OnComplete>(onComplete));
|
||||
auto errorFn =
|
||||
std::make_shared<std::decay_t<OnError>>(std::forward<OnError>(onError));
|
||||
|
||||
enqueueWorkerTask([this, taskFn, completeFn, errorFn]() mutable {
|
||||
try {
|
||||
if constexpr (std::is_void_v<Result>) {
|
||||
std::invoke(*taskFn);
|
||||
enqueueMainThreadTask([completeFn]() mutable { std::invoke(*completeFn); });
|
||||
} else {
|
||||
auto result = std::make_shared<Storage>(std::invoke(*taskFn));
|
||||
enqueueMainThreadTask([completeFn, result]() mutable {
|
||||
std::invoke(*completeFn, std::move(*result));
|
||||
});
|
||||
}
|
||||
} catch (...) {
|
||||
auto error = std::make_shared<std::exception_ptr>(std::current_exception());
|
||||
enqueueMainThreadTask([errorFn, error]() mutable { std::invoke(*errorFn, *error); });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void drainMainThreadTasks(uint32 maxTasks = 0);
|
||||
|
||||
private:
|
||||
TaskSystem() = default;
|
||||
~TaskSystem();
|
||||
|
||||
void enqueueWorkerTask(Function<void()> task);
|
||||
void enqueueMainThreadTask(Function<void()> task);
|
||||
size_t resolveWorkerCount(uint32 requestedCount) const;
|
||||
static void logUnhandledTaskException(std::exception_ptr error);
|
||||
|
||||
TaskSystemConfig config_;
|
||||
std::vector<std::thread> workers_;
|
||||
std::queue<Function<void()>> workerTasks_;
|
||||
std::queue<Function<void()>> mainThreadTasks_;
|
||||
|
||||
mutable std::mutex workerMutex_;
|
||||
mutable std::mutex mainThreadMutex_;
|
||||
std::condition_variable workerCondition_;
|
||||
|
||||
std::atomic<bool> initialized_ = false;
|
||||
std::atomic<bool> acceptingTasks_ = false;
|
||||
std::thread::id mainThreadId_;
|
||||
};
|
||||
|
||||
} // namespace frostbite2D
|
||||
@@ -0,0 +1,137 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <frostbite2D/types/type_alias.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace frostbite2D {
|
||||
|
||||
enum class CursorType {
|
||||
Arrow,
|
||||
TextInput,
|
||||
Hand,
|
||||
SizeAll,
|
||||
SizeWE,
|
||||
SizeNS,
|
||||
SizeNESW,
|
||||
SizeNWSE,
|
||||
No,
|
||||
};
|
||||
|
||||
struct Resolution {
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t refresh_rate = 0;
|
||||
|
||||
Resolution() = default;
|
||||
|
||||
Resolution(uint32_t width, uint32_t height, uint32_t refresh_rate)
|
||||
: width(width), height(height), refresh_rate(refresh_rate) {}
|
||||
};
|
||||
|
||||
struct Icon {
|
||||
Icon() = default;
|
||||
|
||||
Icon(std::string file_path) : file_path(file_path) {}
|
||||
|
||||
std::string file_path;
|
||||
|
||||
#if defined(_WIN32)
|
||||
uint32_t resource_id = 0;
|
||||
|
||||
Icon(uint32_t resource_id) : resource_id(resource_id) {}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct WindowConfig {
|
||||
uint32_t width = 640;
|
||||
uint32_t height = 480;
|
||||
std::string title = "frostbite2D Game";
|
||||
Icon icon;
|
||||
bool resizable = false;
|
||||
bool fullscreen = false;
|
||||
bool borderless = false;
|
||||
bool decorated = true;
|
||||
int multisamples = 0;
|
||||
bool centered = true;
|
||||
bool vsync = true;
|
||||
bool showCursor = true;
|
||||
};
|
||||
|
||||
class Window {
|
||||
public:
|
||||
Window() = default;
|
||||
~Window() = default;
|
||||
|
||||
virtual bool create(const WindowConfig& cfg);
|
||||
virtual void destroy();
|
||||
virtual void poll();
|
||||
virtual void swap();
|
||||
virtual void close();
|
||||
virtual void setTitle(const std::string& title);
|
||||
virtual void setSize(int w, int h);
|
||||
virtual void setPos(int x, int y);
|
||||
virtual void setFullscreen(bool fs);
|
||||
virtual void setVSync(bool vsync);
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
virtual int width() const;
|
||||
virtual int height() const;
|
||||
virtual int drawableWidth() const;
|
||||
virtual int drawableHeight() const;
|
||||
virtual Size size() const;
|
||||
virtual Vec2 pos() const;
|
||||
virtual bool fullscreen() const;
|
||||
virtual bool vsync() const;
|
||||
virtual bool focused() const;
|
||||
virtual bool minimized() const;
|
||||
virtual void setImmEnabled(bool enabled);
|
||||
virtual bool isImmEnabled() const;
|
||||
virtual float scaleX() const;
|
||||
virtual float scaleY() const;
|
||||
virtual bool refreshMetrics(bool emitResize = false);
|
||||
virtual void setCursor(CursorType cursor);
|
||||
virtual void showCursor(bool show);
|
||||
virtual void lockCursor(bool lock);
|
||||
|
||||
using ResizeCb = std::function<void(int, int)>;
|
||||
using CloseCb = std::function<void()>;
|
||||
using FocusCb = std::function<void(bool)>;
|
||||
|
||||
virtual void onResize(ResizeCb cb);
|
||||
virtual void onClose(CloseCb cb);
|
||||
virtual void onFocus(FocusCb cb);
|
||||
virtual void* native() const;
|
||||
|
||||
SDL_Window* sdlWindow() const { return sdlWindow_; }
|
||||
SDL_GLContext glContext() const { return glContext_; }
|
||||
|
||||
private:
|
||||
SDL_Window* sdlWindow_ = nullptr;
|
||||
SDL_GLContext glContext_ = nullptr;
|
||||
|
||||
int width_ = 1280;
|
||||
int height_ = 720;
|
||||
int drawableWidth_ = 1280;
|
||||
int drawableHeight_ = 720;
|
||||
bool fullscreen_ = false;
|
||||
bool vsync_ = true;
|
||||
bool focused_ = true;
|
||||
bool minimized_ = false;
|
||||
bool shouldClose_ = false;
|
||||
float scaleX_ = 1.0f;
|
||||
float scaleY_ = 1.0f;
|
||||
bool cursorVisible_ = true;
|
||||
bool cursorLocked_ = false;
|
||||
bool immEnabled_ = false;
|
||||
bool immDisabledByApp_ = false;
|
||||
void* immRestoreContext_ = nullptr;
|
||||
|
||||
ResizeCb resizeCb_;
|
||||
CloseCb closeCb_;
|
||||
FocusCb focusCb_;
|
||||
};
|
||||
|
||||
} // namespace frostbite2D
|
||||
Reference in New Issue
Block a user