removing platform abstract class, use ifdef instead

This commit is contained in:
Noel Berry 2022-11-19 17:53:21 -08:00
parent 1b41632991
commit 2c45b8b2f2
14 changed files with 443 additions and 559 deletions

View File

@ -12,14 +12,6 @@
using namespace Blah; using namespace Blah;
#define BLAH_ASSERT_RUNNING() BLAH_ASSERT(app_is_running, "The App is not running (call App::run)")
// Internal Platform Pointer
Platform* Internal::platform = nullptr;
// Internal Renderer Pointer
Renderer* Internal::renderer = nullptr;
// Internal Audio bool // Internal Audio bool
bool Internal::audio_is_init = false; bool Internal::audio_is_init = false;
@ -33,15 +25,16 @@ namespace
u64 app_time_accumulator = 0; u64 app_time_accumulator = 0;
u32 app_flags = 0; u32 app_flags = 0;
TargetRef app_backbuffer; TargetRef app_backbuffer;
Renderer* app_renderer_api;
void get_drawable_size(int* w, int* h) void get_drawable_size(int* w, int* h)
{ {
// Some renderer implementations might return their own size // Some renderer implementations might return their own size
if (Internal::renderer->get_draw_size(w, h)) if (app_renderer_api->get_draw_size(w, h))
return; return;
// otherwise fallback to the platform size // otherwise fallback to the platform size
Internal::platform->get_draw_size(w, h); Platform::get_draw_size(w, h);
} }
// A dummy Target that represents the Back Buffer. // A dummy Target that represents the Back Buffer.
@ -57,8 +50,8 @@ namespace
void clear(Color color, float depth, u8 stencil, ClearMask mask) override void clear(Color color, float depth, u8 stencil, ClearMask mask) override
{ {
BLAH_ASSERT_RENDERER(); BLAH_ASSERT_RENDERER();
if (Internal::renderer) if (app_renderer_api)
Internal::renderer->clear_backbuffer(color, depth, stencil, mask); app_renderer_api->clear_backbuffer(color, depth, stencil, mask);
} }
}; };
} }
@ -99,15 +92,7 @@ bool App::run(const Config* c)
// initialize the system // initialize the system
{ {
Internal::platform = Platform::try_make_platform(app_config); if (!Platform::init(app_config))
if (!Internal::platform)
{
Log::error("Failed to create Platform module");
Internal::app_shutdown();
return false;
}
if (!Internal::platform->init(app_config))
{ {
Log::error("Failed to initialize Platform module"); Log::error("Failed to initialize Platform module");
Internal::app_shutdown(); Internal::app_shutdown();
@ -117,26 +102,26 @@ bool App::run(const Config* c)
// initialize audio // initialize audio
{ {
if (!Blah::Internal::audio_is_init) { if (!Internal::audio_is_init) {
int more_on_emscripten = 1; int more_on_emscripten = 1;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
more_on_emscripten = 4; more_on_emscripten = 4;
#endif #endif
Blah::Internal::audio_is_init = Blah::Internal::audio_init(c->audio_frequency_in_Hz, 1024 * more_on_emscripten); Internal::audio_is_init = Internal::audio_init(c->audio_frequency_in_Hz, 1024 * more_on_emscripten);
} }
} }
// initialize graphics // initialize graphics
{ {
Internal::renderer = Renderer::try_make_renderer(app_config.renderer_type); app_renderer_api = Renderer::try_make_renderer(app_config.renderer_type);
if (Internal::renderer == nullptr) if (app_renderer_api == nullptr)
{ {
Log::error("Renderer module was not found"); Log::error("Renderer module was not found");
Internal::app_shutdown(); Internal::app_shutdown();
return false; return false;
} }
if (!Internal::renderer->init()) if (!app_renderer_api->init())
{ {
Log::error("Failed to initialize Renderer module"); Log::error("Failed to initialize Renderer module");
Internal::app_shutdown(); Internal::app_shutdown();
@ -145,22 +130,22 @@ bool App::run(const Config* c)
} }
// apply default flags // apply default flags
Internal::platform->set_app_flags(app_flags); Platform::set_app_flags(app_flags);
Internal::renderer->set_app_flags(app_flags); app_renderer_api->set_app_flags(app_flags);
// input + poll the platform once // input + poll the platform once
Internal::input_init(); Internal::input_init();
Internal::input_step_state(); Internal::input_step_state();
Internal::platform->update(Input::state); Platform::update(Input::state);
// startup // startup
if (app_config.on_startup != nullptr) if (app_config.on_startup != nullptr)
app_config.on_startup(); app_config.on_startup();
app_time_last = Internal::platform->ticks(); app_time_last = Platform::ticks();
app_time_accumulator = 0; app_time_accumulator = 0;
// display window // display window
Internal::platform->ready(); Platform::ready();
// Begin main loop // Begin main loop
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
@ -187,9 +172,9 @@ void Internal::app_step()
static const auto step = []() static const auto step = []()
{ {
Internal::input_step_state(); Internal::input_step_state();
platform->update(Input::state); Platform::update(Input::state);
Internal::input_step_bindings(); Internal::input_step_bindings();
renderer->update(); app_renderer_api->update();
if (app_config.on_update != nullptr) if (app_config.on_update != nullptr)
app_config.on_update(); app_config.on_update();
}; };
@ -200,7 +185,7 @@ void Internal::app_step()
if (is_fixed_timestep) if (is_fixed_timestep)
{ {
u64 time_target = (u64)((1.0 / app_config.target_framerate) * Time::ticks_per_second); u64 time_target = (u64)((1.0 / app_config.target_framerate) * Time::ticks_per_second);
u64 ticks_curr = Internal::platform->ticks(); u64 ticks_curr = Platform::ticks();
u64 ticks_diff = ticks_curr - app_time_last; u64 ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; app_time_last = ticks_curr;
app_time_accumulator += ticks_diff; app_time_accumulator += ticks_diff;
@ -209,9 +194,9 @@ void Internal::app_step()
while (app_time_accumulator < time_target) while (app_time_accumulator < time_target)
{ {
int milliseconds = (int)(time_target - app_time_accumulator) / (Time::ticks_per_second / 1000); int milliseconds = (int)(time_target - app_time_accumulator) / (Time::ticks_per_second / 1000);
Internal::platform->sleep(milliseconds); Platform::sleep(milliseconds);
ticks_curr = Internal::platform->ticks(); ticks_curr = Platform::ticks();
ticks_diff = ticks_curr - app_time_last; ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; app_time_last = ticks_curr;
app_time_accumulator += ticks_diff; app_time_accumulator += ticks_diff;
@ -250,7 +235,7 @@ void Internal::app_step()
// Update with Variable Timestep // Update with Variable Timestep
else else
{ {
u64 ticks_curr = Internal::platform->ticks(); u64 ticks_curr = Platform::ticks();
u64 ticks_diff = ticks_curr - app_time_last; u64 ticks_diff = ticks_curr - app_time_last;
app_time_last = ticks_curr; app_time_last = ticks_curr;
app_time_accumulator += ticks_diff; app_time_accumulator += ticks_diff;
@ -274,14 +259,15 @@ void Internal::app_step()
// Draw Frame // Draw Frame
{ {
renderer->before_render(); app_renderer_api->before_render();
if (app_config.on_render != nullptr) if (app_config.on_render != nullptr)
app_config.on_render(); app_config.on_render();
renderer->after_render(); app_renderer_api->after_render();
platform->present(); Platform::present();
} }
// Update audio // Update audio
if (Internal::audio_is_init)
Blah::Internal::audio_update(); Blah::Internal::audio_update();
} }
@ -289,22 +275,20 @@ void Internal::app_shutdown()
{ {
Internal::input_shutdown(); Internal::input_shutdown();
if (renderer) if (app_renderer_api)
renderer->shutdown(); {
app_renderer_api->shutdown();
delete app_renderer_api;
}
app_renderer_api = nullptr;
if (platform) if (Internal::audio_is_init)
platform->shutdown(); {
Internal::audio_shutdown();
Internal::audio_is_init = false;
}
if (renderer) Platform::shutdown();
delete renderer;
renderer = nullptr;
if (platform)
delete platform;
platform = nullptr;
Blah::Internal::audio_shutdown();
Blah::Internal::audio_is_init = false;
// clear static App state // clear static App state
app_config = Config(); app_config = Config();
@ -322,6 +306,12 @@ void Internal::app_shutdown()
Time::delta = 0; Time::delta = 0;
} }
Renderer* Internal::app_renderer()
{
BLAH_ASSERT_RUNNING();
return app_renderer_api;
}
void App::exit() void App::exit()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
@ -338,59 +328,59 @@ const Config& App::config()
const char* App::path() const char* App::path()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
return Internal::platform->app_path(); return Platform::app_path();
} }
const char* App::user_path() const char* App::user_path()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
return Internal::platform->user_path(); return Platform::user_path();
} }
const char* App::get_title() const char* App::get_title()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
return Internal::platform->get_title(); return Platform::get_title();
} }
void App::set_title(const char* title) void App::set_title(const char* title)
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Internal::platform->set_title(title); Platform::set_title(title);
} }
Point App::get_position() Point App::get_position()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Point result; Point result;
Internal::platform->get_position(&result.x, &result.y); Platform::get_position(&result.x, &result.y);
return result; return result;
} }
void App::set_position(Point point) void App::set_position(Point point)
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Internal::platform->set_position(point.x, point.y); Platform::set_position(point.x, point.y);
} }
Point App::get_size() Point App::get_size()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Point result; Point result;
Internal::platform->get_size(&result.x, &result.y); Platform::get_size(&result.x, &result.y);
return result; return result;
} }
void App::set_size(Point point) void App::set_size(Point point)
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Internal::platform->set_size(point.x, point.y); Platform::set_size(point.x, point.y);
} }
Point App::get_backbuffer_size() Point App::get_backbuffer_size()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
if (Internal::renderer) if (app_renderer_api)
return Point(app_backbuffer->width(), app_backbuffer->height()); return Point(app_backbuffer->width(), app_backbuffer->height());
return Point(0, 0); return Point(0, 0);
} }
@ -398,13 +388,13 @@ Point App::get_backbuffer_size()
float App::content_scale() float App::content_scale()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
return Internal::platform->get_content_scale(); return Platform::get_content_scale();
} }
bool App::focused() bool App::focused()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
return Internal::platform->get_focused(); return Platform::get_focused();
} }
void App::set_flag(u32 flag, bool enabled) void App::set_flag(u32 flag, bool enabled)
@ -420,10 +410,9 @@ void App::set_flag(u32 flag, bool enabled)
if (was != app_flags) if (was != app_flags)
{ {
if (Internal::platform) Platform::set_app_flags(app_flags);
Internal::platform->set_app_flags(app_flags); if (app_renderer_api)
if (Internal::renderer) app_renderer_api->set_app_flags(app_flags);
Internal::renderer->set_app_flags(app_flags);
} }
} }
@ -437,7 +426,7 @@ const RendererInfo& App::renderer()
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
BLAH_ASSERT_RENDERER(); BLAH_ASSERT_RENDERER();
return Internal::renderer->info; return app_renderer_api->info;
} }
const TargetRef& App::backbuffer() const TargetRef& App::backbuffer()
@ -449,5 +438,5 @@ const TargetRef& App::backbuffer()
void System::open_url(const char* url) void System::open_url(const char* url)
{ {
BLAH_ASSERT_RUNNING(); BLAH_ASSERT_RUNNING();
Internal::platform->open_url(url); Platform::open_url(url);
} }

View File

@ -18,7 +18,7 @@ namespace Blah
{ {
bool audio_init(unsigned play_frequency_in_Hz, int buffered_samples) bool audio_init(unsigned play_frequency_in_Hz, int buffered_samples)
{ {
cs_error_t err = cs_init(Internal::platform->d3d11_get_hwnd(), play_frequency_in_Hz, buffered_samples, NULL); cs_error_t err = cs_init(Platform::d3d11_get_hwnd(), play_frequency_in_Hz, buffered_samples, NULL);
if (err != CUTE_SOUND_ERROR_NONE) { if (err != CUTE_SOUND_ERROR_NONE) {
Log::error(cs_error_as_string(err)); Log::error(cs_error_as_string(err));
return false; return false;

View File

@ -282,7 +282,8 @@ void Batch::render(const TargetRef& target, const Mat4x4f& matrix)
if (!m_default_material) if (!m_default_material)
{ {
BLAH_ASSERT_RENDERER(); BLAH_ASSERT_RENDERER();
m_default_material = Material::create(Internal::renderer->default_batcher_shader); if (auto renderer = Internal::app_renderer())
m_default_material = Material::create(renderer->default_batcher_shader);
} }
} }

View File

@ -5,11 +5,11 @@ using namespace Blah;
FileRef File::open(const FilePath& path, FileMode mode) FileRef File::open(const FilePath& path, FileMode mode)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
FileRef ref; FileRef ref;
if (Internal::platform) if (App::is_running())
ref = Internal::platform->file_open(path.cstr(), mode); ref = Platform::file_open(path.cstr(), mode);
if (ref) if (ref)
ref->m_mode = mode; ref->m_mode = mode;
return ref; return ref;
@ -17,17 +17,17 @@ FileRef File::open(const FilePath& path, FileMode mode)
bool File::exists(const FilePath& path) bool File::exists(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
return Internal::platform->file_exists(path.cstr()); return Platform::file_exists(path.cstr());
return false; return false;
} }
bool File::destroy(const FilePath& path) bool File::destroy(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
return Internal::platform->file_delete(path.cstr()); return Platform::file_delete(path.cstr());
return false; return false;
} }
@ -38,37 +38,37 @@ FileMode File::mode() const
bool Directory::create(const FilePath& path) bool Directory::create(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
return Internal::platform->dir_create(path.cstr()); return Platform::dir_create(path.cstr());
return false; return false;
} }
bool Directory::exists(const FilePath& path) bool Directory::exists(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
return Internal::platform->dir_exists(path.cstr()); return Platform::dir_exists(path.cstr());
return false; return false;
} }
bool Directory::destroy(const FilePath& path) bool Directory::destroy(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
return Internal::platform->dir_delete(path.cstr()); return Platform::dir_delete(path.cstr());
return false; return false;
} }
Vector<FilePath> Directory::enumerate(const FilePath& path, bool recursive) Vector<FilePath> Directory::enumerate(const FilePath& path, bool recursive)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
Vector<FilePath> list; Vector<FilePath> list;
if (Internal::platform) if (App::is_running())
{ {
Internal::platform->dir_enumerate(list, path.cstr(), recursive); Platform::dir_enumerate(list, path.cstr(), recursive);
for (auto& it : list) for (auto& it : list)
{ {
for (int n = 0; n < it.length(); n ++) for (int n = 0; n < it.length(); n ++)
@ -81,9 +81,9 @@ Vector<FilePath> Directory::enumerate(const FilePath& path, bool recursive)
void Directory::explore(const FilePath& path) void Directory::explore(const FilePath& path)
{ {
BLAH_ASSERT_PLATFORM(); BLAH_ASSERT_RUNNING();
if (Internal::platform) if (App::is_running())
Internal::platform->dir_explore(path); Platform::dir_explore(path);
} }
FilePath Path::get_file_name(const FilePath& path) FilePath Path::get_file_name(const FilePath& path)

View File

@ -88,8 +88,8 @@ ShaderRef Shader::create(const ShaderData& data)
ShaderRef shader; ShaderRef shader;
if (Internal::renderer) if (auto renderer = Internal::app_renderer())
shader = Internal::renderer->create_shader(&data); shader = renderer->create_shader(&data);
// validate the shader // validate the shader
if (shader) if (shader)
@ -130,9 +130,9 @@ TextureRef Texture::create(int width, int height, TextureFormat format, unsigned
BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0"); BLAH_ASSERT(width > 0 && height > 0, "Texture width and height must be larger than 0");
BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format"); BLAH_ASSERT((int)format > (int)TextureFormat::None && (int)format < (int)TextureFormat::Count, "Invalid texture format");
if (Internal::renderer) if (auto renderer = Internal::app_renderer())
{ {
auto tex = Internal::renderer->create_texture(width, height, format); auto tex = renderer->create_texture(width, height, format);
if (tex && data != nullptr) if (tex && data != nullptr)
tex->set_data(data); tex->set_data(data);
@ -194,8 +194,8 @@ TargetRef Target::create(int width, int height, const AttachmentFormats& texture
BLAH_ASSERT(depth_count <= 1, "Target can only have 1 Depth/Stencil Texture"); BLAH_ASSERT(depth_count <= 1, "Target can only have 1 Depth/Stencil Texture");
BLAH_ASSERT(color_count <= Attachments::capacity - 1, "Exceeded maximum Color texture count"); BLAH_ASSERT(color_count <= Attachments::capacity - 1, "Exceeded maximum Color texture count");
if (Internal::renderer) if (auto renderer = Internal::app_renderer())
return Internal::renderer->create_target(width, height, textures.data(), textures.size()); return renderer->create_target(width, height, textures.data(), textures.size());
return TargetRef(); return TargetRef();
} }
@ -224,8 +224,8 @@ MeshRef Mesh::create()
{ {
BLAH_ASSERT_RENDERER(); BLAH_ASSERT_RENDERER();
if (Internal::renderer) if (auto renderer = Internal::app_renderer())
return Internal::renderer->create_mesh(); return renderer->create_mesh();
return MeshRef(); return MeshRef();
} }
@ -623,7 +623,7 @@ void DrawCall::perform()
BLAH_ASSERT(material->shader(), "Trying to draw with an invalid Shader"); BLAH_ASSERT(material->shader(), "Trying to draw with an invalid Shader");
BLAH_ASSERT(mesh, "Trying to draw with an invalid Mesh"); BLAH_ASSERT(mesh, "Trying to draw with an invalid Mesh");
if (!Internal::renderer) if (!Internal::app_renderer())
return; return;
// copy call // copy call
@ -685,5 +685,5 @@ void DrawCall::perform()
pass.scissor = pass.scissor.overlap_rect(Rectf(0, 0, draw_size.x, draw_size.y)); pass.scissor = pass.scissor.overlap_rect(Rectf(0, 0, draw_size.x, draw_size.y));
// perform render // perform render
Internal::renderer->render(pass); Internal::app_renderer()->render(pass);
} }

View File

@ -78,8 +78,7 @@ void Internal::input_step_state()
} }
// get clipboard // get clipboard
if (Internal::platform) g_clipboard = Platform::get_clipboard();
g_clipboard = Internal::platform->get_clipboard();
} }
void Internal::input_step_bindings() void Internal::input_step_bindings()
@ -397,9 +396,9 @@ const String& Input::get_clipboard()
void Input::set_clipboard(const String& text) void Input::set_clipboard(const String& text)
{ {
BLAH_ASSERT_RUNNING();
g_clipboard = text; g_clipboard = text;
if (Internal::platform) Platform::set_clipboard(text);
Internal::platform->set_clipboard(text);
} }
ButtonBindingRef Input::register_binding(const ButtonBinding& binding_data) ButtonBindingRef Input::register_binding(const ButtonBinding& binding_data)

View File

@ -12,8 +12,8 @@ float Time::pause_timer = 0;
u64 Time::get_ticks() u64 Time::get_ticks()
{ {
if (Internal::platform) if (App::is_running())
return Internal::platform->ticks(); return Platform::ticks();
return 0; return 0;
} }

View File

@ -2,19 +2,18 @@
#include "blah_renderer.h" #include "blah_renderer.h"
#include "blah_platform.h" #include "blah_platform.h"
#define BLAH_ASSERT_RENDERER() BLAH_ASSERT(Blah::Internal::renderer, "Renderer has not been created") #define BLAH_ASSERT_RENDERER() BLAH_ASSERT(Blah::Internal::app_renderer(), "Renderer has not been created")
#define BLAH_ASSERT_PLATFORM() BLAH_ASSERT(Blah::Internal::platform, "Platform has not been created") #define BLAH_ASSERT_RUNNING() BLAH_ASSERT(Blah::App::is_running(), "The App is not running (call App::run)")
namespace Blah namespace Blah
{ {
namespace Internal namespace Internal
{ {
extern Platform* platform;
extern Renderer* renderer;
extern bool audio_is_init; extern bool audio_is_init;
void app_step(); void app_step();
void app_shutdown(); void app_shutdown();
Renderer* app_renderer();
void input_init(); void input_init();
void input_step_state(); void input_step_state();

View File

@ -8,112 +8,105 @@ namespace Blah
{ {
struct Config; struct Config;
class Platform namespace Platform
{ {
public:
virtual ~Platform() = default;
// Initialize the Graphics // Initialize the Graphics
virtual bool init(const Config& config) = 0; bool init(const Config& config);
// Called after the on_startup callback, but before the update loop begins // Called after the on_startup callback, but before the update loop begins
virtual void ready() = 0; void ready();
// Called during shutdown // Called during shutdown
virtual void shutdown() = 0; void shutdown();
// The time, in ticks (microseconds) since the Application was started // The time, in ticks (microseconds) since the Application was started
virtual u64 ticks() = 0; u64 ticks();
// Called every frame // Called every frame
virtual void update(InputState& state) = 0; void update(InputState& state);
// Sleeps the current thread // Sleeps the current thread
virtual void sleep(int milliseconds) = 0; void sleep(int milliseconds);
// Called to present the window contents // Called to present the window contents
virtual void present() = 0; void present();
// Called when the App sets flags // Called when the App sets flags
virtual void set_app_flags(u32 flags) = 0; void set_app_flags(u32 flags);
// Gets the Application Window Title in UTF-8 // Gets the Application Window Title in UTF-8
virtual const char* get_title() = 0; const char* get_title();
// Sets the Application Window Title in UTF-8 // Sets the Application Window Title in UTF-8
virtual void set_title(const char* title) = 0; void set_title(const char* title);
// Gets the Application Window Position, in Screen Coordinates // Gets the Application Window Position, in Screen Coordinates
virtual void get_position(int* x, int* y) = 0; void get_position(int* x, int* y);
// Sets the Application Window Position, in Screen Coordinates // Sets the Application Window Position, in Screen Coordinates
virtual void set_position(int x, int y) = 0; void set_position(int x, int y);
// Gets whether the Window has focus // Gets whether the Window has focus
virtual bool get_focused() = 0; bool get_focused();
// Gets the Application Window Size, in Screen Coordinates // Gets the Application Window Size, in Screen Coordinates
virtual void get_size(int* width, int* height) = 0; void get_size(int* width, int* height);
// Sets the Application Window Size, in Screen Coordinates // Sets the Application Window Size, in Screen Coordinates
virtual void set_size(int width, int height) = 0; void set_size(int width, int height);
// Gets the Application Window Drawing Size, in Pixels. This may differ from the Window Size on hi-dpi displays. // Gets the Application Window Drawing Size, in Pixels. This may differ from the Window Size on hi-dpi displays.
virtual void get_draw_size(int* width, int* height) = 0; void get_draw_size(int* width, int* height);
// Gets the Desktop Content Scale. Gui should be scaled by this value // Gets the Desktop Content Scale. Gui should be scaled by this value
virtual float get_content_scale() = 0; float get_content_scale();
// Returns the absolute path to the directory that the application was started from // Returns the absolute path to the directory that the application was started from
virtual const char* app_path() = 0; const char* app_path();
// Returns the absolute path to the user directory where save data and settings should be stored // Returns the absolute path to the user directory where save data and settings should be stored
virtual const char* user_path() = 0; const char* user_path();
// Opens a file and sets the handle, or returns an empty handle if it fails // Opens a file and sets the handle, or returns an empty handle if it fails
virtual FileRef file_open(const char* path, FileMode mode) = 0; FileRef file_open(const char* path, FileMode mode);
// Returns true if a file with the given path exists // Returns true if a file with the given path exists
virtual bool file_exists(const char* path) = 0; bool file_exists(const char* path);
// Returns true if a file with the given path was deleted // Returns true if a file with the given path was deleted
virtual bool file_delete(const char* path) = 0; bool file_delete(const char* path);
// Returns true if a directory with the given path was successfully created // Returns true if a directory with the given path was successfully created
virtual bool dir_create(const char* path) = 0; bool dir_create(const char* path);
// Returns true if a directory with the given path exists // Returns true if a directory with the given path exists
virtual bool dir_exists(const char* path) = 0; bool dir_exists(const char* path);
// Returns true if a directory with the given path was deleted // Returns true if a directory with the given path was deleted
virtual bool dir_delete(const char* path) = 0; bool dir_delete(const char* path);
// enumerates a directory and appends each file to the given list // enumerates a directory and appends each file to the given list
virtual void dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive) = 0; void dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive);
// opens a directory in the OS file explorer / finder // opens a directory in the OS file explorer / finder
virtual void dir_explore(const char* path) = 0; void dir_explore(const char* path);
// sets the contents of the clipboard // sets the contents of the clipboard
virtual void set_clipboard(const char* text) = 0; void set_clipboard(const char* text);
// gets the contents of the clipboard into the given string // gets the contents of the clipboard into the given string
virtual const char* get_clipboard() = 0; const char* get_clipboard();
// Tries to open a URL in a web browser // Tries to open a URL in a web browser
virtual void open_url(const char* url) = 0; void open_url(const char* url);
// OpenGL Methods // OpenGL Methods
virtual void* gl_get_func(const char* name) = 0; void* gl_get_func(const char* name);
virtual void* gl_context_create() = 0; void* gl_context_create();
virtual void gl_context_make_current(void* context) = 0; void gl_context_make_current(void* context);
virtual void gl_context_destroy(void* context) = 0; void gl_context_destroy(void* context);
// D3D11 Methods // D3D11 Methods
virtual void* d3d11_get_hwnd() = 0; void* d3d11_get_hwnd();
// Instantiates the Platform object
static Platform* try_make_platform(const Config& config);
}; };
} }

View File

@ -71,67 +71,18 @@ namespace Blah
size_t write(const void* buffer, size_t length) override { return SDL_RWwrite(handle, buffer, sizeof(char), length); } size_t write(const void* buffer, size_t length) override { return SDL_RWwrite(handle, buffer, sizeof(char), length); }
}; };
struct SDL2_Platform : public Platform SDL_Window* sdl2_window = nullptr;
{ SDL_Joystick* sdl2_joysticks[Input::max_controllers];
SDL_Window* window = nullptr; SDL_GameController* sdl2_gamepads[Input::max_controllers];
SDL_Joystick* joysticks[Input::max_controllers]; char* sdl2_base_path_value = nullptr;
SDL_GameController* gamepads[Input::max_controllers]; char* sdl2_user_path_value = nullptr;
char* base_path_value = nullptr; char* sdl2_clipboard_text = nullptr;
char* user_path_value = nullptr; bool sdl2_displayed = false;
char* clipboard_text = nullptr;
bool displayed = false;
SDL2_Platform();
bool init(const Config& config) override;
void ready() override;
void shutdown() override;
u64 ticks() override;
void update(InputState& state) override;
void sleep(int milliseconds) override;
void present() override;
void set_app_flags(u32 flags) override;
const char* get_title() override;
void set_title(const char* title) override;
void get_position(int* x, int* y) override;
void set_position(int x, int y) override;
bool get_focused() override;
void get_size(int* width, int* height) override;
void set_size(int width, int height) override;
void get_draw_size(int* width, int* height) override;
float get_content_scale() override;
const char* app_path() override;
const char* user_path() override;
FileRef file_open(const char* path, FileMode mode) override;
bool file_exists(const char* path) override;
bool file_delete(const char* path) override;
bool dir_create(const char* path) override;
bool dir_exists(const char* path) override;
bool dir_delete(const char* path) override;
void dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive) override;
void dir_explore(const char* path) override;
void set_clipboard(const char* text) override;
const char* get_clipboard() override;
void open_url(const char* url) override;
void* gl_get_func(const char* name) override;
void* gl_context_create() override;
void gl_context_make_current(void* context) override;
void gl_context_destroy(void* context) override;
void* d3d11_get_hwnd() override;
};
} }
using namespace Blah; using namespace Blah;
SDL2_Platform::SDL2_Platform() bool Platform::init(const Config& config)
{
for (int i = 0; i < Input::max_controllers; i++)
{
joysticks[i] = nullptr;
gamepads[i] = nullptr;
}
}
bool SDL2_Platform::init(const Config& config)
{ {
// TODO: // TODO:
// control this via some kind of config flag // control this via some kind of config flag
@ -185,54 +136,60 @@ bool SDL2_Platform::init(const Config& config)
} }
// create the window // create the window
window = SDL_CreateWindow(config.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config.width, config.height, flags); sdl2_window = SDL_CreateWindow(config.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config.width, config.height, flags);
if (window == nullptr) if (sdl2_window == nullptr)
{ {
Log::error("Failed to create a Window"); Log::error("Failed to create a Window");
return false; return false;
} }
for (int i = 0; i < Input::max_controllers; i++)
{
sdl2_joysticks[i] = nullptr;
sdl2_gamepads[i] = nullptr;
}
return true; return true;
} }
void SDL2_Platform::ready() void Platform::ready()
{ {
} }
void SDL2_Platform::shutdown() void Platform::shutdown()
{ {
if (window != nullptr) if (sdl2_window != nullptr)
SDL_DestroyWindow(window); SDL_DestroyWindow(sdl2_window);
window = nullptr; sdl2_window = nullptr;
displayed = false; sdl2_displayed = false;
if (base_path_value != nullptr) if (sdl2_base_path_value != nullptr)
SDL_free(base_path_value); SDL_free(sdl2_base_path_value);
if (user_path_value != nullptr) if (sdl2_user_path_value != nullptr)
SDL_free(user_path_value); SDL_free(sdl2_user_path_value);
if (clipboard_text != nullptr) if (sdl2_clipboard_text != nullptr)
SDL_free(clipboard_text); SDL_free(sdl2_clipboard_text);
SDL_Quit(); SDL_Quit();
} }
u64 SDL2_Platform::ticks() u64 Platform::ticks()
{ {
auto counter = SDL_GetPerformanceCounter(); auto counter = SDL_GetPerformanceCounter();
auto per_second = (double)SDL_GetPerformanceFrequency(); auto per_second = (double)SDL_GetPerformanceFrequency();
return (u64)(counter * (Time::ticks_per_second / per_second)); return (u64)(counter * (Time::ticks_per_second / per_second));
} }
void SDL2_Platform::update(InputState& state) void Platform::update(InputState& state)
{ {
// update the mouse every frame // update the mouse every frame
{ {
int win_x, win_y, x, y; int win_x, win_y, x, y;
SDL_GetWindowPosition(window, &win_x, &win_y); SDL_GetWindowPosition(sdl2_window, &win_x, &win_y);
SDL_GetGlobalMouseState(&x, &y); SDL_GetGlobalMouseState(&x, &y);
state.mouse.on_move( state.mouse.on_move(
@ -301,7 +258,7 @@ void SDL2_Platform::update(InputState& state)
if (SDL_IsGameController(index) == SDL_FALSE && index >= 0 && index < Input::max_controllers) if (SDL_IsGameController(index) == SDL_FALSE && index >= 0 && index < Input::max_controllers)
{ {
auto ptr = joysticks[index] = SDL_JoystickOpen(index); auto ptr = sdl2_joysticks[index] = SDL_JoystickOpen(index);
auto name = SDL_JoystickName(ptr); auto name = SDL_JoystickName(ptr);
auto button_count = SDL_JoystickNumButtons(ptr); auto button_count = SDL_JoystickNumButtons(ptr);
auto axis_count = SDL_JoystickNumAxes(ptr); auto axis_count = SDL_JoystickNumAxes(ptr);
@ -314,19 +271,19 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_JOYDEVICEREMOVED) else if (event.type == SDL_JOYDEVICEREMOVED)
{ {
auto index = blah_sdl_find_joystick_index(joysticks, event.jdevice.which); auto index = blah_sdl_find_joystick_index(sdl2_joysticks, event.jdevice.which);
if (index >= 0) if (index >= 0)
{ {
if (SDL_IsGameController(index) == SDL_FALSE) if (SDL_IsGameController(index) == SDL_FALSE)
{ {
state.controllers[index].on_disconnect(); state.controllers[index].on_disconnect();
SDL_JoystickClose(joysticks[index]); SDL_JoystickClose(sdl2_joysticks[index]);
} }
} }
} }
else if (event.type == SDL_JOYBUTTONDOWN) else if (event.type == SDL_JOYBUTTONDOWN)
{ {
auto index = blah_sdl_find_joystick_index(joysticks, event.jdevice.which); auto index = blah_sdl_find_joystick_index(sdl2_joysticks, event.jdevice.which);
if (index >= 0) if (index >= 0)
{ {
if (SDL_IsGameController(index) == SDL_FALSE) if (SDL_IsGameController(index) == SDL_FALSE)
@ -335,7 +292,7 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_JOYBUTTONUP) else if (event.type == SDL_JOYBUTTONUP)
{ {
auto index = blah_sdl_find_joystick_index(joysticks, event.jdevice.which); auto index = blah_sdl_find_joystick_index(sdl2_joysticks, event.jdevice.which);
if (index >= 0) if (index >= 0)
{ {
if (SDL_IsGameController(index) == SDL_FALSE) if (SDL_IsGameController(index) == SDL_FALSE)
@ -344,7 +301,7 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_JOYAXISMOTION) else if (event.type == SDL_JOYAXISMOTION)
{ {
auto index = blah_sdl_find_joystick_index(joysticks, event.jdevice.which); auto index = blah_sdl_find_joystick_index(sdl2_joysticks, event.jdevice.which);
if (index >= 0) if (index >= 0)
{ {
if (SDL_IsGameController(index) == SDL_FALSE) if (SDL_IsGameController(index) == SDL_FALSE)
@ -364,7 +321,7 @@ void SDL2_Platform::update(InputState& state)
auto index = event.cdevice.which; auto index = event.cdevice.which;
if (index >= 0 && index < Input::max_controllers) if (index >= 0 && index < Input::max_controllers)
{ {
auto ptr = gamepads[index] = SDL_GameControllerOpen(index); auto ptr = sdl2_gamepads[index] = SDL_GameControllerOpen(index);
auto name = SDL_GameControllerName(ptr); auto name = SDL_GameControllerName(ptr);
auto vendor = SDL_GameControllerGetVendor(ptr); auto vendor = SDL_GameControllerGetVendor(ptr);
auto product = SDL_GameControllerGetProduct(ptr); auto product = SDL_GameControllerGetProduct(ptr);
@ -375,16 +332,16 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_CONTROLLERDEVICEREMOVED) else if (event.type == SDL_CONTROLLERDEVICEREMOVED)
{ {
auto index = blah_sdl_find_gamepad_index(gamepads, event.cdevice.which); auto index = blah_sdl_find_gamepad_index(sdl2_gamepads, event.cdevice.which);
if (index >= 0) if (index >= 0)
{ {
state.controllers[index].on_disconnect(); state.controllers[index].on_disconnect();
SDL_GameControllerClose(gamepads[index]); SDL_GameControllerClose(sdl2_gamepads[index]);
} }
} }
else if (event.type == SDL_CONTROLLERBUTTONDOWN) else if (event.type == SDL_CONTROLLERBUTTONDOWN)
{ {
auto index = blah_sdl_find_gamepad_index(gamepads, event.cdevice.which); auto index = blah_sdl_find_gamepad_index(sdl2_gamepads, event.cdevice.which);
if (index >= 0) if (index >= 0)
{ {
Button button = Button::None; Button button = Button::None;
@ -396,7 +353,7 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_CONTROLLERBUTTONUP) else if (event.type == SDL_CONTROLLERBUTTONUP)
{ {
auto index = blah_sdl_find_gamepad_index(gamepads, event.cdevice.which); auto index = blah_sdl_find_gamepad_index(sdl2_gamepads, event.cdevice.which);
if (index >= 0) if (index >= 0)
{ {
Button button = Button::None; Button button = Button::None;
@ -408,7 +365,7 @@ void SDL2_Platform::update(InputState& state)
} }
else if (event.type == SDL_CONTROLLERAXISMOTION) else if (event.type == SDL_CONTROLLERAXISMOTION)
{ {
auto index = blah_sdl_find_gamepad_index(gamepads, event.cdevice.which); auto index = blah_sdl_find_gamepad_index(sdl2_gamepads, event.cdevice.which);
if (index >= 0) if (index >= 0)
{ {
Axis axis = Axis::None; Axis axis = Axis::None;
@ -427,33 +384,33 @@ void SDL2_Platform::update(InputState& state)
} }
} }
void SDL2_Platform::sleep(int milliseconds) void Platform::sleep(int milliseconds)
{ {
if (milliseconds >= 0) if (milliseconds >= 0)
SDL_Delay((u32)milliseconds); SDL_Delay((u32)milliseconds);
} }
void SDL2_Platform::present() void Platform::present()
{ {
if (App::renderer().type == RendererType::OpenGL) if (App::renderer().type == RendererType::OpenGL)
SDL_GL_SwapWindow(window); SDL_GL_SwapWindow(sdl2_window);
// display the window // display the window
// this avoids a short black screen on macOS // this avoids a short black screen on macOS
if (!displayed) if (!sdl2_displayed)
{ {
SDL_ShowWindow(window); SDL_ShowWindow(sdl2_window);
displayed = true; sdl2_displayed = true;
} }
} }
void SDL2_Platform::set_app_flags(u32 flags) void Platform::set_app_flags(u32 flags)
{ {
// Toggle Fullscreen // Toggle Fullscreen
SDL_SetWindowFullscreen(window, ((flags & Flags::Fullscreen) != 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); SDL_SetWindowFullscreen(sdl2_window, ((flags & Flags::Fullscreen) != 0) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
// Toggle Resizable // Toggle Resizable
SDL_SetWindowResizable(window, ((flags & Flags::Resizable) != 0) ? SDL_TRUE : SDL_FALSE); SDL_SetWindowResizable(sdl2_window, ((flags & Flags::Resizable) != 0) ? SDL_TRUE : SDL_FALSE);
// Toggle V-Sync for OpenGL // Toggle V-Sync for OpenGL
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
@ -462,57 +419,57 @@ void SDL2_Platform::set_app_flags(u32 flags)
#endif #endif
} }
const char* SDL2_Platform::get_title() const char* Platform::get_title()
{ {
return SDL_GetWindowTitle(window); return SDL_GetWindowTitle(sdl2_window);
} }
void SDL2_Platform::set_title(const char* title) void Platform::set_title(const char* title)
{ {
SDL_SetWindowTitle(window, title); SDL_SetWindowTitle(sdl2_window, title);
} }
void SDL2_Platform::get_position(int* x, int* y) void Platform::get_position(int* x, int* y)
{ {
SDL_GetWindowPosition(window, x, y); SDL_GetWindowPosition(sdl2_window, x, y);
} }
void SDL2_Platform::set_position(int x, int y) void Platform::set_position(int x, int y)
{ {
SDL_SetWindowPosition(window, x, y); SDL_SetWindowPosition(sdl2_window, x, y);
} }
bool SDL2_Platform::get_focused() bool Platform::get_focused()
{ {
auto flags = SDL_GetWindowFlags(window); auto flags = SDL_GetWindowFlags(sdl2_window);
return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 && (flags & SDL_WINDOW_MINIMIZED) == 0; return (flags & SDL_WINDOW_INPUT_FOCUS) != 0 && (flags & SDL_WINDOW_MINIMIZED) == 0;
} }
void SDL2_Platform::get_size(int* width, int* height) void Platform::get_size(int* width, int* height)
{ {
SDL_GetWindowSize(window, width, height); SDL_GetWindowSize(sdl2_window, width, height);
} }
void SDL2_Platform::set_size(int width, int height) void Platform::set_size(int width, int height)
{ {
SDL_SetWindowSize(window, width, height); SDL_SetWindowSize(sdl2_window, width, height);
} }
void SDL2_Platform::get_draw_size(int* width, int* height) void Platform::get_draw_size(int* width, int* height)
{ {
switch (App::renderer().type) switch (App::renderer().type)
{ {
case RendererType::OpenGL: case RendererType::OpenGL:
SDL_GL_GetDrawableSize(window, width, height); SDL_GL_GetDrawableSize(sdl2_window, width, height);
break; break;
case RendererType::None: case RendererType::None:
case RendererType::D3D11: case RendererType::D3D11:
SDL_GetWindowSize(window, width, height); SDL_GetWindowSize(sdl2_window, width, height);
break; break;
} }
} }
float SDL2_Platform::get_content_scale() float Platform::get_content_scale()
{ {
// TODO: // TODO:
// This is incorrect! but for some reason the scale // This is incorrect! but for some reason the scale
@ -525,7 +482,7 @@ float SDL2_Platform::get_content_scale()
// is there a way to get this value properly? My Windows & Linux PC's both seem to thing 96 is correct // is there a way to get this value properly? My Windows & Linux PC's both seem to thing 96 is correct
const float hidpi_res = 96; const float hidpi_res = 96;
int index = SDL_GetWindowDisplayIndex(window); int index = SDL_GetWindowDisplayIndex(sdl2_window);
if (index < 0) if (index < 0)
{ {
Log::error(SDL_GetError()); Log::error(SDL_GetError());
@ -542,25 +499,25 @@ float SDL2_Platform::get_content_scale()
return (ddpi / hidpi_res); return (ddpi / hidpi_res);
} }
const char* SDL2_Platform::app_path() const char* Platform::app_path()
{ {
if (base_path_value == nullptr) if (sdl2_base_path_value == nullptr)
base_path_value = SDL_GetBasePath(); sdl2_base_path_value = SDL_GetBasePath();
return base_path_value; return sdl2_base_path_value;
} }
const char* SDL2_Platform::user_path() const char* Platform::user_path()
{ {
if (user_path_value == nullptr) if (sdl2_user_path_value == nullptr)
{ {
auto& config = App::config(); auto& config = App::config();
user_path_value = SDL_GetPrefPath(nullptr, config.name); sdl2_user_path_value = SDL_GetPrefPath(nullptr, config.name);
} }
return user_path_value; return sdl2_user_path_value;
} }
FileRef SDL2_Platform::file_open(const char* path, FileMode mode) FileRef Platform::file_open(const char* path, FileMode mode)
{ {
const char* sdl_mode = ""; const char* sdl_mode = "";
@ -587,32 +544,32 @@ FileRef SDL2_Platform::file_open(const char* path, FileMode mode)
return FileRef(new SDL2_File(ptr)); return FileRef(new SDL2_File(ptr));
} }
bool SDL2_Platform::file_exists(const char* path) bool Platform::file_exists(const char* path)
{ {
return std::filesystem::is_regular_file(path); return std::filesystem::is_regular_file(path);
} }
bool SDL2_Platform::file_delete(const char* path) bool Platform::file_delete(const char* path)
{ {
return std::filesystem::remove(path); return std::filesystem::remove(path);
} }
bool SDL2_Platform::dir_create(const char* path) bool Platform::dir_create(const char* path)
{ {
return std::filesystem::create_directories(path); return std::filesystem::create_directories(path);
} }
bool SDL2_Platform::dir_exists(const char* path) bool Platform::dir_exists(const char* path)
{ {
return std::filesystem::is_directory(path); return std::filesystem::is_directory(path);
} }
bool SDL2_Platform::dir_delete(const char* path) bool Platform::dir_delete(const char* path)
{ {
return std::filesystem::remove_all(path) > 0; return std::filesystem::remove_all(path) > 0;
} }
void SDL2_Platform::dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive) void Platform::dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive)
{ {
if (std::filesystem::is_directory(path)) if (std::filesystem::is_directory(path))
{ {
@ -629,7 +586,7 @@ void SDL2_Platform::dir_enumerate(Vector<FilePath>& list, const char* path, bool
} }
} }
void SDL2_Platform::dir_explore(const char* path) void Platform::dir_explore(const char* path)
{ {
#if _WIN32 #if _WIN32
@ -646,64 +603,59 @@ void SDL2_Platform::dir_explore(const char* path)
#endif #endif
} }
void SDL2_Platform::set_clipboard(const char* text) void Platform::set_clipboard(const char* text)
{ {
SDL_SetClipboardText(text); SDL_SetClipboardText(text);
} }
const char* SDL2_Platform::get_clipboard() const char* Platform::get_clipboard()
{ {
// free previous clipboard text // free previous clipboard text
if (clipboard_text != nullptr) if (sdl2_clipboard_text != nullptr)
SDL_free(clipboard_text); SDL_free(sdl2_clipboard_text);
clipboard_text = SDL_GetClipboardText(); sdl2_clipboard_text = SDL_GetClipboardText();
return clipboard_text; return sdl2_clipboard_text;
} }
void* SDL2_Platform::gl_get_func(const char* name) void* Platform::gl_get_func(const char* name)
{ {
return SDL_GL_GetProcAddress(name); return SDL_GL_GetProcAddress(name);
} }
void* SDL2_Platform::gl_context_create() void* Platform::gl_context_create()
{ {
void* pointer = SDL_GL_CreateContext(window); void* pointer = SDL_GL_CreateContext(sdl2_window);
if (pointer == nullptr) if (pointer == nullptr)
Log::error("SDL_GL_CreateContext failed: %s", SDL_GetError()); Log::error("SDL_GL_CreateContext failed: %s", SDL_GetError());
return pointer; return pointer;
} }
void SDL2_Platform::gl_context_make_current(void* context) void Platform::gl_context_make_current(void* context)
{ {
SDL_GL_MakeCurrent(window, context); SDL_GL_MakeCurrent(sdl2_window, context);
} }
void SDL2_Platform::gl_context_destroy(void* context) void Platform::gl_context_destroy(void* context)
{ {
SDL_GL_DeleteContext(context); SDL_GL_DeleteContext(context);
} }
void* SDL2_Platform::d3d11_get_hwnd() void* Platform::d3d11_get_hwnd()
{ {
#if _WIN32 #if _WIN32
SDL_SysWMinfo info; SDL_SysWMinfo info;
SDL_VERSION(&info.version); SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(window, &info); SDL_GetWindowWMInfo(sdl2_window, &info);
return info.info.win.window; return info.info.win.window;
#else #else
return nullptr; return nullptr;
#endif #endif
} }
void SDL2_Platform::open_url(const char* url) void Platform::open_url(const char* url)
{ {
SDL_OpenURL(url); SDL_OpenURL(url);
} }
Platform* Platform::try_make_platform(const Config& config)
{
return new SDL2_Platform();
}
#endif // BLAH_PLATFORM_SDL2 #endif // BLAH_PLATFORM_SDL2

View File

@ -48,17 +48,15 @@ namespace Blah
size_t write(const void* buffer, size_t length) override; size_t write(const void* buffer, size_t length) override;
}; };
struct Win32_Platform : public Platform
{
// Main State // Main State
HWND hwnd; HWND win32_hwnd;
FilePath working_directory; FilePath win32_working_directory;
FilePath user_directory; FilePath win32_user_directory;
Duration start_time; Duration win32_start_time;
RECT windowed_position; RECT win32_windowed_position;
bool fullscreen = false; bool win32_fullscreen = false;
InputState* input_state = nullptr; InputState* win32_input_state = nullptr;
String clipboard; String win32_clipboard;
// XInput // XInput
struct struct
@ -66,7 +64,7 @@ namespace Blah
HMODULE dll; HMODULE dll;
XInputGetCapabilities_fn get_capabilities; XInputGetCapabilities_fn get_capabilities;
XInputGetState_fn get_state; XInputGetState_fn get_state;
} xinput; } win32_xinput;
struct Joystick struct Joystick
{ {
@ -74,7 +72,7 @@ namespace Blah
bool accounted = false; bool accounted = false;
GUID dinstance = GUID_NULL; GUID dinstance = GUID_NULL;
DWORD xindex = 0; DWORD xindex = 0;
} joysticks[Input::max_controllers]; } win32_joysticks[Input::max_controllers];
// OpenGL Methods // OpenGL Methods
// These are only loaded if built using the OpenGL Backend // These are only loaded if built using the OpenGL Backend
@ -85,52 +83,15 @@ namespace Blah
wglCreateContext_fn create_context; wglCreateContext_fn create_context;
wglDeleteContext_fn delete_context; wglDeleteContext_fn delete_context;
wglMakeCurrent_fn make_current; wglMakeCurrent_fn make_current;
} gl; } win32_gl;
bool init(const Config& config) override;
void ready() override;
void shutdown() override;
u64 ticks() override;
void update(InputState& state) override;
void sleep(int milliseconds) override;
void present() override;
const char* get_title() override;
void set_title(const char* title) override;
void get_position(int* x, int* y) override;
void set_position(int x, int y) override;
bool get_focused() override;
void set_app_flags(u32 flags) override;
void get_size(int* width, int* height) override;
void set_size(int width, int height) override;
void get_draw_size(int* width, int* height) override;
float get_content_scale() override;
const char* app_path() override;
const char* user_path() override;
FileRef file_open(const char* path, FileMode mode) override;
bool file_exists(const char* path) override;
bool file_delete(const char* path) override;
bool dir_create(const char* path) override;
bool dir_exists(const char* path) override;
bool dir_delete(const char* path) override;
void dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive) override;
void dir_explore(const char* path) override;
void set_clipboard(const char* text) override;
const char* get_clipboard() override;
void open_url(const char* url) override;
void* gl_get_func(const char* name) override;
void* gl_context_create() override;
void gl_context_make_current(void* context) override;
void gl_context_destroy(void* context) override;
void* d3d11_get_hwnd() override;
void detect_joysticks();
};
// Main Windows Procedure callback // Main Windows Procedure callback
LRESULT CALLBACK win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT CALLBACK win32_window_procedure(HWND win32_hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
// Converts Windows scancode to Blah key // Converts Windows scancode to Blah key
Key win32_scancode_to_key(WPARAM wParam, LPARAM lParam); Key win32_scancode_to_key(WPARAM wParam, LPARAM lParam);
void win32_detect_joysticks();
} }
using namespace Blah; using namespace Blah;
@ -194,7 +155,7 @@ size_t Win32File::read(void* buffer, size_t length)
to_read = (DWORD)(length - read); to_read = (DWORD)(length - read);
DWORD moved = 0; DWORD moved = 0;
if (ReadFile(m_handle, (char *)buffer + read, to_read, &moved, NULL)) if (ReadFile(m_handle, (char*)buffer + read, to_read, &moved, NULL))
read += moved; read += moved;
if (moved < to_read) if (moved < to_read)
@ -217,7 +178,7 @@ size_t Win32File::write(const void* buffer, size_t length)
to_write = (DWORD)(length - written); to_write = (DWORD)(length - written);
DWORD moved = 0; DWORD moved = 0;
if (WriteFile(m_handle, (char *)buffer + written, to_write, &moved, NULL)) if (WriteFile(m_handle, (char*)buffer + written, to_write, &moved, NULL))
written += moved; written += moved;
if (moved < to_write) if (moved < to_write)
@ -227,7 +188,7 @@ size_t Win32File::write(const void* buffer, size_t length)
return written; return written;
} }
bool Win32_Platform::init(const Config& config) bool Platform::init(const Config& config)
{ {
// Required to call this for Windows // Required to call this for Windows
SetProcessDPIAware(); SetProcessDPIAware();
@ -252,10 +213,10 @@ bool Win32_Platform::init(const Config& config)
RegisterClass(&wc); RegisterClass(&wc);
// Create the Window Instance // Create the Window Instance
hwnd = CreateWindow("BLAH WINDOW", config.name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 640, 480, NULL, NULL, hInstance, NULL); win32_hwnd = CreateWindow("BLAH WINDOW", config.name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 640, 480, NULL, NULL, hInstance, NULL);
// Failed to create the Window // Failed to create the Window
if (hwnd == NULL) if (win32_hwnd == NULL)
{ {
Log::error("Window Creation Failed"); Log::error("Window Creation Failed");
return false; return false;
@ -273,18 +234,18 @@ bool Win32_Platform::init(const Config& config)
if (config.renderer_type == RendererType::OpenGL) if (config.renderer_type == RendererType::OpenGL)
{ {
// Load the DLL // Load the DLL
gl.dll = LoadLibraryA("opengl32.dll"); win32_gl.dll = LoadLibraryA("opengl32.dll");
if (gl.dll == NULL) if (win32_gl.dll == NULL)
{ {
Log::error("OpenGL Instantiation Failed - unable to fine opengl32.dll"); Log::error("OpenGL Instantiation Failed - unable to fine opengl32.dll");
return false; return false;
} }
// Get the Windows GL functions we need // Get the Windows GL functions we need
gl.get_proc_address = (wglGetProcAddress_fn)GetProcAddress(gl.dll, "wglGetProcAddress"); win32_gl.get_proc_address = (wglGetProcAddress_fn)GetProcAddress(win32_gl.dll, "wglGetProcAddress");
gl.create_context = (wglCreateContext_fn)GetProcAddress(gl.dll, "wglCreateContext"); win32_gl.create_context = (wglCreateContext_fn)GetProcAddress(win32_gl.dll, "wglCreateContext");
gl.delete_context = (wglDeleteContext_fn)GetProcAddress(gl.dll, "wglDeleteContext"); win32_gl.delete_context = (wglDeleteContext_fn)GetProcAddress(win32_gl.dll, "wglDeleteContext");
gl.make_current = (wglMakeCurrent_fn)GetProcAddress(gl.dll, "wglMakeCurrent"); win32_gl.make_current = (wglMakeCurrent_fn)GetProcAddress(win32_gl.dll, "wglMakeCurrent");
// TODO: // TODO:
// Allow the user to apply (some of) these values before instantiation. // Allow the user to apply (some of) these values before instantiation.
@ -312,7 +273,7 @@ bool Win32_Platform::init(const Config& config)
0, 0, 0 // layer masks ignored 0, 0, 0 // layer masks ignored
}; };
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(win32_hwnd);
// get the best available match of pixel format for the device context // get the best available match of pixel format for the device context
int pixel_format = ChoosePixelFormat(hdc, &pfd); int pixel_format = ChoosePixelFormat(hdc, &pfd);
@ -327,17 +288,17 @@ bool Win32_Platform::init(const Config& config)
for (int i = 0; dlls[i]; i++) for (int i = 0; dlls[i]; i++)
{ {
xinput.dll = LoadLibraryA(dlls[i]); win32_xinput.dll = LoadLibraryA(dlls[i]);
if (xinput.dll) if (win32_xinput.dll)
{ {
xinput.get_capabilities = (XInputGetCapabilities_fn)GetProcAddress(xinput.dll, "XInputGetCapabilities"); win32_xinput.get_capabilities = (XInputGetCapabilities_fn)GetProcAddress(win32_xinput.dll, "XInputGetCapabilities");
xinput.get_state = (XInputGetState_fn)GetProcAddress(xinput.dll, "XInputGetState"); win32_xinput.get_state = (XInputGetState_fn)GetProcAddress(win32_xinput.dll, "XInputGetState");
break; break;
} }
} }
if (!xinput.dll) if (!win32_xinput.dll)
Log::warn("Failed to find XInput dll; No Controller Support"); Log::warn("Failed to find XInput dll; No Controller Support");
} }
@ -349,10 +310,10 @@ bool Win32_Platform::init(const Config& config)
auto normalized = Path::normalize(buffer); auto normalized = Path::normalize(buffer);
auto end = normalized.last_index_of('/');; auto end = normalized.last_index_of('/');;
if (end >= 0) if (end >= 0)
working_directory = FilePath(normalized.begin(), normalized.begin() + end); win32_working_directory = FilePath(normalized.begin(), normalized.begin() + end);
else else
working_directory = normalized; win32_working_directory = normalized;
working_directory.append("/"); win32_working_directory.append("/");
} }
// Get Application User Directory // Get Application User Directory
@ -366,56 +327,56 @@ bool Win32_Platform::init(const Config& config)
FilePath result; FilePath result;
result.append((u16*)path, (u16*)end); result.append((u16*)path, (u16*)end);
user_directory = Path::join(Path::normalize(result), config.name) + "/"; win32_user_directory = Path::join(Path::normalize(result), config.name) + "/";
} }
CoTaskMemFree(path); CoTaskMemFree(path);
} }
// Reset our game timer // Reset our game timer
start_time = std::chrono::system_clock::now().time_since_epoch(); win32_start_time = std::chrono::system_clock::now().time_since_epoch();
// Not currently fullscreen // Not currently win32_fullscreen
fullscreen = false; win32_fullscreen = false;
// Finished Platform Setup // Finished Platform Setup
return true; return true;
} }
void Win32_Platform::ready() void Platform::ready()
{ {
// Display the game window // Display the game window
ShowWindow(hwnd, SW_SHOW); ShowWindow(win32_hwnd, SW_SHOW);
} }
void Win32_Platform::shutdown() void Platform::shutdown()
{ {
if (xinput.dll) if (win32_xinput.dll)
FreeLibrary(xinput.dll); FreeLibrary(win32_xinput.dll);
if (gl.dll) if (win32_gl.dll)
FreeLibrary(gl.dll); FreeLibrary(win32_gl.dll);
DestroyWindow(hwnd); DestroyWindow(win32_hwnd);
} }
u64 Win32_Platform::ticks() u64 Platform::ticks()
{ {
// Todo: // Todo:
// This should account for whatever Time::ticks_per_second is set to // This should account for whatever Time::ticks_per_second is set to
auto now = std::chrono::system_clock::now().time_since_epoch(); auto now = std::chrono::system_clock::now().time_since_epoch();
return std::chrono::duration_cast<std::chrono::microseconds>(now - start_time).count(); return std::chrono::duration_cast<std::chrono::microseconds>(now - win32_start_time).count();
} }
void Win32_Platform::update(InputState& state) void Platform::update(InputState& state)
{ {
// store reference to input state // store reference to input state
bool first_update = input_state == nullptr; bool first_update = win32_input_state == nullptr;
input_state = &state; win32_input_state = &state;
// if this is the first update, poll joysticks that are already connected // if this is the first update, poll joysticks that are already connected
if (first_update) if (first_update)
detect_joysticks(); win32_detect_joysticks();
// Catch & Dispatch Window Messages // Catch & Dispatch Window Messages
MSG msg; MSG msg;
@ -426,82 +387,82 @@ void Win32_Platform::update(InputState& state)
} }
} }
void Win32_Platform::sleep(int milliseconds) void Platform::sleep(int milliseconds)
{ {
if (milliseconds > 0) if (milliseconds > 0)
Sleep(milliseconds); Sleep(milliseconds);
} }
void Win32_Platform::present() void Platform::present()
{ {
if (App::renderer().type == RendererType::OpenGL) if (App::renderer().type == RendererType::OpenGL)
{ {
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(win32_hwnd);
SwapBuffers(hdc); SwapBuffers(hdc);
} }
} }
const char* Win32_Platform::get_title() const char* Platform::get_title()
{ {
return nullptr; return nullptr;
} }
void Win32_Platform::set_title(const char* title) void Platform::set_title(const char* title)
{ {
SetWindowText(hwnd, title); SetWindowText(win32_hwnd, title);
} }
void Win32_Platform::get_position(int* x, int* y) void Platform::get_position(int* x, int* y)
{ {
RECT rect; RECT rect;
if (GetWindowRect(hwnd, &rect)) if (GetWindowRect(win32_hwnd, &rect))
{ {
*x = rect.left; *x = rect.left;
*y = rect.top; *y = rect.top;
} }
} }
void Win32_Platform::set_position(int x, int y) void Platform::set_position(int x, int y)
{ {
int w, h; int w, h;
get_size(&w, &h); get_size(&w, &h);
SetWindowPos(hwnd, NULL, x, y, w, h, 0); SetWindowPos(win32_hwnd, NULL, x, y, w, h, 0);
} }
bool Win32_Platform::get_focused() bool Platform::get_focused()
{ {
Log::warn("App::focused not implemented for Win32 yet"); Log::warn("App::focused not implemented for Win32 yet");
return true; return true;
} }
void Win32_Platform::set_app_flags(u32 flags) void Platform::set_app_flags(u32 flags)
{ {
// toggle fullscreen // toggle win32_fullscreen
{ {
bool enabled = (flags & Flags::Fullscreen) != 0; bool enabled = (flags & Flags::Fullscreen) != 0;
if (fullscreen == enabled) if (win32_fullscreen == enabled)
return; return;
fullscreen = enabled; win32_fullscreen = enabled;
if (fullscreen) if (win32_fullscreen)
{ {
GetWindowRect(hwnd, &windowed_position); GetWindowRect(win32_hwnd, &win32_windowed_position);
int w = GetSystemMetrics(SM_CXSCREEN); int w = GetSystemMetrics(SM_CXSCREEN);
int h = GetSystemMetrics(SM_CYSCREEN); int h = GetSystemMetrics(SM_CYSCREEN);
SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); SetWindowLongPtr(win32_hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
SetWindowPos(hwnd, HWND_TOP, 0, 0, w, h, 0); SetWindowPos(win32_hwnd, HWND_TOP, 0, 0, w, h, 0);
ShowWindow(hwnd, SW_SHOW); ShowWindow(win32_hwnd, SW_SHOW);
} }
else else
{ {
SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); SetWindowLongPtr(win32_hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
SetWindowPos(hwnd, HWND_TOP, SetWindowPos(win32_hwnd, HWND_TOP,
windowed_position.left, win32_windowed_position.left,
windowed_position.top, win32_windowed_position.top,
windowed_position.right - windowed_position.left, win32_windowed_position.right - win32_windowed_position.left,
windowed_position.bottom - windowed_position.top, 0); win32_windowed_position.bottom - win32_windowed_position.top, 0);
ShowWindow(hwnd, SW_SHOW); ShowWindow(win32_hwnd, SW_SHOW);
} }
} }
@ -509,88 +470,88 @@ void Win32_Platform::set_app_flags(u32 flags)
// TODO: ... // TODO: ...
} }
void Win32_Platform::get_size(int* width, int* height) void Platform::get_size(int* width, int* height)
{ {
RECT rect; RECT rect;
if (GetClientRect(hwnd, &rect)) if (GetClientRect(win32_hwnd, &rect))
{ {
*width = rect.right - rect.left; *width = rect.right - rect.left;
*height = rect.bottom - rect.top; *height = rect.bottom - rect.top;
} }
} }
void Win32_Platform::set_size(int width, int height) void Platform::set_size(int width, int height)
{ {
RECT client_rect; RECT client_rect;
RECT border_rect; RECT border_rect;
GetClientRect(hwnd, &client_rect); GetClientRect(win32_hwnd, &client_rect);
GetWindowRect(hwnd, &border_rect); GetWindowRect(win32_hwnd, &border_rect);
int border_width = (border_rect.right - border_rect.left) - (client_rect.right - client_rect.left); int border_width = (border_rect.right - border_rect.left) - (client_rect.right - client_rect.left);
int border_height = (border_rect.bottom - border_rect.top) - (client_rect.bottom - client_rect.top); int border_height = (border_rect.bottom - border_rect.top) - (client_rect.bottom - client_rect.top);
SetWindowPos(hwnd, NULL, border_rect.left, border_rect.top, width + border_width, height + border_height, 0); SetWindowPos(win32_hwnd, NULL, border_rect.left, border_rect.top, width + border_width, height + border_height, 0);
} }
void Win32_Platform::get_draw_size(int* width, int* height) void Platform::get_draw_size(int* width, int* height)
{ {
RECT rect; RECT rect;
if (GetClientRect(hwnd, &rect)) if (GetClientRect(win32_hwnd, &rect))
{ {
*width = rect.right - rect.left; *width = rect.right - rect.left;
*height = rect.bottom - rect.top; *height = rect.bottom - rect.top;
} }
} }
float Win32_Platform::get_content_scale() float Platform::get_content_scale()
{ {
// base value of Windows DPI // base value of Windows DPI
// as seen here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow // as seen here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow
constexpr float base_raw_value = 96.0f; constexpr float base_raw_value = 96.0f;
UINT raw_value = GetDpiForWindow(hwnd); UINT raw_value = GetDpiForWindow(win32_hwnd);
return (raw_value / base_raw_value); return (raw_value / base_raw_value);
} }
const char* Win32_Platform::app_path() const char* Platform::app_path()
{ {
return working_directory.cstr(); return win32_working_directory.cstr();
} }
const char* Win32_Platform::user_path() const char* Platform::user_path()
{ {
return user_directory.cstr(); return win32_user_directory.cstr();
} }
bool Win32_Platform::file_exists(const char* path) bool Platform::file_exists(const char* path)
{ {
return std::filesystem::is_regular_file(path); return std::filesystem::is_regular_file(path);
} }
bool Win32_Platform::file_delete(const char* path) bool Platform::file_delete(const char* path)
{ {
return std::filesystem::remove(path); return std::filesystem::remove(path);
} }
bool Win32_Platform::dir_create(const char* path) bool Platform::dir_create(const char* path)
{ {
std::error_code error; std::error_code error;
return std::filesystem::create_directories(path, error); return std::filesystem::create_directories(path, error);
} }
bool Win32_Platform::dir_exists(const char* path) bool Platform::dir_exists(const char* path)
{ {
return std::filesystem::is_directory(path); return std::filesystem::is_directory(path);
} }
bool Win32_Platform::dir_delete(const char* path) bool Platform::dir_delete(const char* path)
{ {
return std::filesystem::remove_all(path) > 0; return std::filesystem::remove_all(path) > 0;
} }
void Win32_Platform::dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive) void Platform::dir_enumerate(Vector<FilePath>& list, const char* path, bool recursive)
{ {
if (std::filesystem::is_directory(path)) if (std::filesystem::is_directory(path))
{ {
@ -607,12 +568,12 @@ void Win32_Platform::dir_enumerate(Vector<FilePath>& list, const char* path, boo
} }
} }
void Win32_Platform::dir_explore(const char* path) void Platform::dir_explore(const char* path)
{ {
ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT); ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT);
} }
FileRef Win32_Platform::file_open(const char* path, FileMode mode) FileRef Platform::file_open(const char* path, FileMode mode)
{ {
int access = 0; int access = 0;
int creation = 0; int creation = 0;
@ -645,52 +606,52 @@ FileRef Win32_Platform::file_open(const char* path, FileMode mode)
return FileRef(new Win32File(result)); return FileRef(new Win32File(result));
} }
void* Win32_Platform::gl_get_func(const char* name) void* Platform::gl_get_func(const char* name)
{ {
// this check is taken from https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions // this check is taken from https://www.khronos.org/opengl/wiki/Load_OpenGL_Functions
// wglGetProcAddress doesn't always return valid pointers for some specific methods? // wglGetProcAddress doesn't always return valid pointers for some specific methods?
void* p = (void*)gl.get_proc_address(name); void* p = (void*)win32_gl.get_proc_address(name);
if ((p == 0) || if ((p == 0) ||
(p == (void*)0x1) || (p == (void*)0x1) ||
(p == (void*)0x2) || (p == (void*)0x2) ||
(p == (void*)0x3) || (p == (void*)0x3) ||
(p == (void*)-1)) (p == (void*)-1))
{ {
p = (void*)GetProcAddress(gl.dll, name); p = (void*)GetProcAddress(win32_gl.dll, name);
} }
return p; return p;
} }
void* Win32_Platform::gl_context_create() void* Platform::gl_context_create()
{ {
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(win32_hwnd);
return gl.create_context(hdc); return win32_gl.create_context(hdc);
} }
void Win32_Platform::gl_context_make_current(void* context) void Platform::gl_context_make_current(void* context)
{ {
if (context != nullptr) if (context != nullptr)
{ {
HDC hdc = GetDC(hwnd); HDC hdc = GetDC(win32_hwnd);
gl.make_current(hdc, (HGLRC)context); win32_gl.make_current(hdc, (HGLRC)context);
} }
else else
gl.make_current(NULL, NULL); win32_gl.make_current(NULL, NULL);
} }
void Win32_Platform::gl_context_destroy(void* context) void Platform::gl_context_destroy(void* context)
{ {
gl.delete_context((HGLRC)context); win32_gl.delete_context((HGLRC)context);
} }
void* Win32_Platform::d3d11_get_hwnd() void* Platform::d3d11_get_hwnd()
{ {
return hwnd; return win32_hwnd;
} }
void Win32_Platform::set_clipboard(const char* text) void Platform::set_clipboard(const char* text)
{ {
auto len = strlen(text); auto len = strlen(text);
if (auto glob = GlobalAlloc(GMEM_MOVEABLE, len)) if (auto glob = GlobalAlloc(GMEM_MOVEABLE, len))
@ -711,7 +672,7 @@ void Win32_Platform::set_clipboard(const char* text)
} }
} }
const char* Win32_Platform::get_clipboard() const char* Platform::get_clipboard()
{ {
if (OpenClipboard(nullptr)) if (OpenClipboard(nullptr))
{ {
@ -720,44 +681,42 @@ const char* Win32_Platform::get_clipboard()
{ {
auto text = static_cast<const char*>(GlobalLock(data)); auto text = static_cast<const char*>(GlobalLock(data));
if (text) if (text)
clipboard = text; win32_clipboard = text;
GlobalUnlock(data); GlobalUnlock(data);
} }
CloseClipboard(); CloseClipboard();
} }
return clipboard.cstr(); return win32_clipboard.cstr();
} }
void Win32_Platform::open_url(const char* url) void Platform::open_url(const char* url)
{ {
auto cmd = String("start ") + url; auto cmd = String("start ") + url;
system(cmd.cstr()); system(cmd.cstr());
} }
void Win32_Platform::detect_joysticks() void win32_detect_joysticks()
{ {
auto platform = ((Win32_Platform*)Internal::platform);
// mark all joysticks as unnacounted for // mark all joysticks as unnacounted for
for (int i = 0; i < Input::max_controllers; i++) for (int i = 0; i < Input::max_controllers; i++)
platform->joysticks[i].accounted = false; win32_joysticks[i].accounted = false;
// check for xinput controllers // check for xinput controllers
if (platform->xinput.dll) if (win32_xinput.dll)
{ {
for (DWORD index = 0; index < XUSER_MAX_COUNT; index++) for (DWORD index = 0; index < XUSER_MAX_COUNT; index++)
{ {
// can't get capabilities; not connected // can't get capabilities; not connected
XINPUT_CAPABILITIES xic; XINPUT_CAPABILITIES xic;
if (platform->xinput.get_capabilities(index, 0, &xic) != ERROR_SUCCESS) if (win32_xinput.get_capabilities(index, 0, &xic) != ERROR_SUCCESS)
continue; continue;
// already connected // already connected
bool already_connected = false; bool already_connected = false;
for (int i = 0; i < Input::max_controllers; i++) for (int i = 0; i < Input::max_controllers; i++)
{ {
auto& it = platform->joysticks[i]; auto& it = win32_joysticks[i];
if (it.connected && it.dinstance == GUID_NULL && it.xindex == index) if (it.connected && it.dinstance == GUID_NULL && it.xindex == index)
{ {
it.accounted = true; it.accounted = true;
@ -772,7 +731,7 @@ void Win32_Platform::detect_joysticks()
// find an empty slot and mark connected // find an empty slot and mark connected
for (int i = 0; i < Input::max_controllers; i++) for (int i = 0; i < Input::max_controllers; i++)
{ {
auto& it = platform->joysticks[i]; auto& it = win32_joysticks[i];
if (!it.connected) if (!it.connected)
{ {
it.connected = it.accounted = true; it.connected = it.accounted = true;
@ -783,7 +742,7 @@ void Win32_Platform::detect_joysticks()
// TODO: // TODO:
// Get Product Info & Proper Name // Get Product Info & Proper Name
platform->input_state->controllers[i].on_connect("Xbox Controller", true, 15, 6, 0, 0, 0); win32_input_state->controllers[i].on_connect("Xbox Controller", true, 15, 6, 0, 0, 0);
break; break;
} }
@ -794,21 +753,18 @@ void Win32_Platform::detect_joysticks()
// call disconnect on joysticks that aren't accounted for // call disconnect on joysticks that aren't accounted for
for (int i = 0; i < Input::max_controllers; i++) for (int i = 0; i < Input::max_controllers; i++)
{ {
auto& it = platform->joysticks[i]; auto& it = win32_joysticks[i];
if (it.connected && !it.accounted) if (it.connected && !it.accounted)
{ {
Log::info("Disconnected [%i]", i); Log::info("Disconnected [%i]", i);
platform->input_state->controllers[i].on_disconnect(); win32_input_state->controllers[i].on_disconnect();
it = Win32_Platform::Joystick(); it = Joystick();
} }
} }
} }
LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) LRESULT CALLBACK Blah::win32_window_procedure(HWND win32_hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{ {
auto platform = ((Win32_Platform*)Internal::platform);
auto input_state = platform->input_state;
switch (msg) switch (msg)
{ {
case WM_CLOSE: case WM_CLOSE:
@ -829,41 +785,41 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
// DBT_DEVNODES_CHANGED = 0x0007 // DBT_DEVNODES_CHANGED = 0x0007
// https://docs.microsoft.com/en-us/windows/win32/devio/wm-devicechange // https://docs.microsoft.com/en-us/windows/win32/devio/wm-devicechange
if (wParam == 0x0007) if (wParam == 0x0007)
platform->detect_joysticks(); win32_detect_joysticks();
return 0; return 0;
} }
// Mouse Input // Mouse Input
case WM_LBUTTONDOWN: case WM_LBUTTONDOWN:
input_state->mouse.on_press(MouseButton::Left); win32_input_state->mouse.on_press(MouseButton::Left);
return 0; return 0;
case WM_LBUTTONUP: case WM_LBUTTONUP:
input_state->mouse.on_release(MouseButton::Left); win32_input_state->mouse.on_release(MouseButton::Left);
return 0; return 0;
case WM_RBUTTONDOWN: case WM_RBUTTONDOWN:
input_state->mouse.on_press(MouseButton::Right); win32_input_state->mouse.on_press(MouseButton::Right);
return 0; return 0;
case WM_RBUTTONUP: case WM_RBUTTONUP:
input_state->mouse.on_release(MouseButton::Right); win32_input_state->mouse.on_release(MouseButton::Right);
return 0; return 0;
case WM_MBUTTONDOWN: case WM_MBUTTONDOWN:
input_state->mouse.on_press(MouseButton::Middle); win32_input_state->mouse.on_press(MouseButton::Middle);
return 0; return 0;
case WM_MBUTTONUP: case WM_MBUTTONUP:
input_state->mouse.on_release(MouseButton::Middle); win32_input_state->mouse.on_release(MouseButton::Middle);
return 0; return 0;
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
input_state->mouse.on_move(Vec2f((float)((u16)lParam), (float)(lParam >> 16)), Vec2f::zero); win32_input_state->mouse.on_move(Vec2f((float)((u16)lParam), (float)(lParam >> 16)), Vec2f::zero);
return 0; return 0;
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
input_state->mouse.wheel = Point(0, GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA); win32_input_state->mouse.wheel = Point(0, GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA);
return 0; return 0;
// Text Input // Text Input
@ -875,7 +831,7 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
String result; String result;
result.append((u32)wParam); result.append((u32)wParam);
if (result.length() > 0) if (result.length() > 0)
input_state->keyboard.text += result.cstr(); win32_input_state->keyboard.text += result.cstr();
return 0; return 0;
} }
@ -888,7 +844,7 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
{ {
auto key = Blah::win32_scancode_to_key(wParam, lParam); auto key = Blah::win32_scancode_to_key(wParam, lParam);
if (key != Key::Unknown) if (key != Key::Unknown)
input_state->keyboard.on_press(key); win32_input_state->keyboard.on_press(key);
} }
return 0; return 0;
} }
@ -898,12 +854,12 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
{ {
auto key = Blah::win32_scancode_to_key(wParam, lParam); auto key = Blah::win32_scancode_to_key(wParam, lParam);
if (key != Key::Unknown) if (key != Key::Unknown)
input_state->keyboard.on_release(key); win32_input_state->keyboard.on_release(key);
return 0; return 0;
} }
} }
return DefWindowProc(hwnd, msg, wParam, lParam); return DefWindowProc(win32_hwnd, msg, wParam, lParam);
} }
Blah::Key Blah::win32_scancode_to_key(WPARAM wParam, LPARAM lParam) Blah::Key Blah::win32_scancode_to_key(WPARAM wParam, LPARAM lParam)
@ -1086,9 +1042,4 @@ Blah::Key Blah::win32_scancode_to_key(WPARAM wParam, LPARAM lParam)
return Key::Unknown; return Key::Unknown;
} }
Platform* Platform::try_make_platform(const Config& config)
{
return new Win32_Platform();
}
#endif // BLAH_PLATFORM_WIN32 #endif // BLAH_PLATFORM_WIN32

View File

@ -9,10 +9,10 @@ namespace Blah
{ {
public: public:
// Renderer Info // Renderer Info, should be assigned during init
RendererInfo info; RendererInfo info;
// Default Shader for the Batcher // Default Shader for the Batcher, should be created in init
ShaderRef default_batcher_shader; ShaderRef default_batcher_shader;
virtual ~Renderer() = default; virtual ~Renderer() = default;

View File

@ -17,7 +17,7 @@
#include <d3dcompiler.h> #include <d3dcompiler.h>
// shorthand to our internal state // shorthand to our internal state
#define RENDERER ((Renderer_D3D11*)Internal::renderer) #define RENDERER ((Renderer_D3D11*)Internal::app_renderer())
namespace Blah namespace Blah
{ {
@ -776,7 +776,7 @@ namespace Blah
desc.SampleDesc.Quality = 0; desc.SampleDesc.Quality = 0;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.BufferCount = 1; desc.BufferCount = 1;
desc.OutputWindow = (HWND)Internal::platform->d3d11_get_hwnd(); desc.OutputWindow = (HWND)Platform::d3d11_get_hwnd();
desc.Windowed = true; desc.Windowed = true;
// Creation Flags // Creation Flags

View File

@ -340,7 +340,7 @@ typedef void (APIENTRY* DEBUGPROC)(GLenum source,
const void* userParam); const void* userParam);
// shorthand to our internal state // shorthand to our internal state
#define RENDERER ((Renderer_OpenGL*)Internal::renderer) #define RENDERER ((Renderer_OpenGL*)Internal::app_renderer())
namespace Blah namespace Blah
{ {
@ -1176,16 +1176,16 @@ namespace Blah
bool Renderer_OpenGL::init() bool Renderer_OpenGL::init()
{ {
// create gl context // create gl context
context = Internal::platform->gl_context_create(); context = Platform::gl_context_create();
if (context == nullptr) if (context == nullptr)
{ {
Log::error("Failed to create OpenGL Context"); Log::error("Failed to create OpenGL Context");
return false; return false;
} }
Internal::platform->gl_context_make_current(context); Platform::gl_context_make_current(context);
// bind opengl functions // bind opengl functions
#define GL_FUNC(name, ...) gl.name = (Renderer_OpenGL::Bindings::name ## Func)(Internal::platform->gl_get_func("gl" #name)); #define GL_FUNC(name, ...) gl.name = (Renderer_OpenGL::Bindings::name ## Func)(Platform::gl_get_func("gl" #name));
GL_FUNCTIONS GL_FUNCTIONS
#undef GL_FUNC #undef GL_FUNC
@ -1229,7 +1229,7 @@ namespace Blah
void Renderer_OpenGL::shutdown() void Renderer_OpenGL::shutdown()
{ {
Internal::platform->gl_context_destroy(context); Platform::gl_context_destroy(context);
context = nullptr; context = nullptr;
} }