mirror of
				https://github.com/NoelFB/blah.git
				synced 2025-11-04 01:41:34 +08:00 
			
		
		
		
	removing platform abstract class, use ifdef instead
This commit is contained in:
		
							
								
								
									
										135
									
								
								src/blah_app.cpp
									
									
									
									
									
								
							
							
						
						
									
										135
									
								
								src/blah_app.cpp
									
									
									
									
									
								
							@ -12,14 +12,6 @@
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
bool Internal::audio_is_init = false;
 | 
			
		||||
 | 
			
		||||
@ -33,15 +25,16 @@ namespace
 | 
			
		||||
	u64        app_time_accumulator = 0;
 | 
			
		||||
	u32        app_flags = 0;
 | 
			
		||||
	TargetRef  app_backbuffer;
 | 
			
		||||
	Renderer*  app_renderer_api;
 | 
			
		||||
 | 
			
		||||
	void get_drawable_size(int* w, int* h)
 | 
			
		||||
	{
 | 
			
		||||
		// 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;
 | 
			
		||||
 | 
			
		||||
		// 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.
 | 
			
		||||
@ -57,8 +50,8 @@ namespace
 | 
			
		||||
		void clear(Color color, float depth, u8 stencil, ClearMask mask) override
 | 
			
		||||
		{
 | 
			
		||||
			BLAH_ASSERT_RENDERER();
 | 
			
		||||
			if (Internal::renderer)
 | 
			
		||||
				Internal::renderer->clear_backbuffer(color, depth, stencil, mask);
 | 
			
		||||
			if (app_renderer_api)
 | 
			
		||||
				app_renderer_api->clear_backbuffer(color, depth, stencil, mask);
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
@ -99,15 +92,7 @@ bool App::run(const Config* c)
 | 
			
		||||
 | 
			
		||||
	// initialize the system
 | 
			
		||||
	{
 | 
			
		||||
		Internal::platform = Platform::try_make_platform(app_config);
 | 
			
		||||
		if (!Internal::platform)
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("Failed to create Platform module");
 | 
			
		||||
			Internal::app_shutdown();
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!Internal::platform->init(app_config))
 | 
			
		||||
		if (!Platform::init(app_config))
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("Failed to initialize Platform module");
 | 
			
		||||
			Internal::app_shutdown();
 | 
			
		||||
@ -117,26 +102,26 @@ bool App::run(const Config* c)
 | 
			
		||||
 | 
			
		||||
	// initialize audio
 | 
			
		||||
	{
 | 
			
		||||
		if (!Blah::Internal::audio_is_init) {
 | 
			
		||||
		if (!Internal::audio_is_init) {
 | 
			
		||||
			int more_on_emscripten = 1;
 | 
			
		||||
			#ifdef __EMSCRIPTEN__
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
			more_on_emscripten = 4;
 | 
			
		||||
			#endif
 | 
			
		||||
			Blah::Internal::audio_is_init = Blah::Internal::audio_init(c->audio_frequency_in_Hz, 1024 * more_on_emscripten);
 | 
			
		||||
#endif
 | 
			
		||||
			Internal::audio_is_init = Internal::audio_init(c->audio_frequency_in_Hz, 1024 * more_on_emscripten);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// initialize graphics
 | 
			
		||||
	{
 | 
			
		||||
		Internal::renderer = Renderer::try_make_renderer(app_config.renderer_type);
 | 
			
		||||
		if (Internal::renderer == nullptr)
 | 
			
		||||
		app_renderer_api = Renderer::try_make_renderer(app_config.renderer_type);
 | 
			
		||||
		if (app_renderer_api == nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("Renderer module was not found");
 | 
			
		||||
			Internal::app_shutdown();
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!Internal::renderer->init())
 | 
			
		||||
		if (!app_renderer_api->init())
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("Failed to initialize Renderer module");
 | 
			
		||||
			Internal::app_shutdown();
 | 
			
		||||
@ -145,22 +130,22 @@ bool App::run(const Config* c)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// apply default flags
 | 
			
		||||
	Internal::platform->set_app_flags(app_flags);
 | 
			
		||||
	Internal::renderer->set_app_flags(app_flags);
 | 
			
		||||
	Platform::set_app_flags(app_flags);
 | 
			
		||||
	app_renderer_api->set_app_flags(app_flags);
 | 
			
		||||
 | 
			
		||||
	// input + poll the platform once
 | 
			
		||||
	Internal::input_init();
 | 
			
		||||
	Internal::input_step_state();
 | 
			
		||||
	Internal::platform->update(Input::state);
 | 
			
		||||
	Platform::update(Input::state);
 | 
			
		||||
 | 
			
		||||
	// startup
 | 
			
		||||
	if (app_config.on_startup != nullptr)
 | 
			
		||||
		app_config.on_startup();
 | 
			
		||||
	app_time_last = Internal::platform->ticks();
 | 
			
		||||
	app_time_last = Platform::ticks();
 | 
			
		||||
	app_time_accumulator = 0;
 | 
			
		||||
 | 
			
		||||
	// display window
 | 
			
		||||
	Internal::platform->ready();
 | 
			
		||||
	Platform::ready();
 | 
			
		||||
 | 
			
		||||
	// Begin main loop
 | 
			
		||||
#ifdef __EMSCRIPTEN__
 | 
			
		||||
@ -187,9 +172,9 @@ void Internal::app_step()
 | 
			
		||||
	static const auto step = []()
 | 
			
		||||
	{
 | 
			
		||||
		Internal::input_step_state();
 | 
			
		||||
		platform->update(Input::state);
 | 
			
		||||
		Platform::update(Input::state);
 | 
			
		||||
		Internal::input_step_bindings();
 | 
			
		||||
		renderer->update();
 | 
			
		||||
		app_renderer_api->update();
 | 
			
		||||
		if (app_config.on_update != nullptr)
 | 
			
		||||
			app_config.on_update();
 | 
			
		||||
	};
 | 
			
		||||
@ -200,7 +185,7 @@ void Internal::app_step()
 | 
			
		||||
	if (is_fixed_timestep)
 | 
			
		||||
	{
 | 
			
		||||
		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;
 | 
			
		||||
		app_time_last = ticks_curr;
 | 
			
		||||
		app_time_accumulator += ticks_diff;
 | 
			
		||||
@ -209,9 +194,9 @@ void Internal::app_step()
 | 
			
		||||
		while (app_time_accumulator < time_target)
 | 
			
		||||
		{
 | 
			
		||||
			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;
 | 
			
		||||
			app_time_last = ticks_curr;
 | 
			
		||||
			app_time_accumulator += ticks_diff;
 | 
			
		||||
@ -250,7 +235,7 @@ void Internal::app_step()
 | 
			
		||||
	// Update with Variable Timestep
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		u64 ticks_curr = Internal::platform->ticks();
 | 
			
		||||
		u64 ticks_curr = Platform::ticks();
 | 
			
		||||
		u64 ticks_diff = ticks_curr - app_time_last;
 | 
			
		||||
		app_time_last = ticks_curr;
 | 
			
		||||
		app_time_accumulator += ticks_diff;
 | 
			
		||||
@ -274,14 +259,15 @@ void Internal::app_step()
 | 
			
		||||
 | 
			
		||||
	// Draw Frame
 | 
			
		||||
	{
 | 
			
		||||
		renderer->before_render();
 | 
			
		||||
		app_renderer_api->before_render();
 | 
			
		||||
		if (app_config.on_render != nullptr)
 | 
			
		||||
			app_config.on_render();
 | 
			
		||||
		renderer->after_render();
 | 
			
		||||
		platform->present();
 | 
			
		||||
		app_renderer_api->after_render();
 | 
			
		||||
		Platform::present();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update audio
 | 
			
		||||
	if (Internal::audio_is_init)
 | 
			
		||||
		Blah::Internal::audio_update();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -289,22 +275,20 @@ void Internal::app_shutdown()
 | 
			
		||||
{
 | 
			
		||||
	Internal::input_shutdown();
 | 
			
		||||
 | 
			
		||||
	if (renderer)
 | 
			
		||||
		renderer->shutdown();
 | 
			
		||||
	if (app_renderer_api)
 | 
			
		||||
	{
 | 
			
		||||
		app_renderer_api->shutdown();
 | 
			
		||||
		delete app_renderer_api;
 | 
			
		||||
	}
 | 
			
		||||
	app_renderer_api = nullptr;
 | 
			
		||||
 | 
			
		||||
	if (platform)
 | 
			
		||||
		platform->shutdown();
 | 
			
		||||
	if (Internal::audio_is_init)
 | 
			
		||||
	{
 | 
			
		||||
		Internal::audio_shutdown();
 | 
			
		||||
		Internal::audio_is_init = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (renderer)
 | 
			
		||||
		delete renderer;
 | 
			
		||||
	renderer = nullptr;
 | 
			
		||||
 | 
			
		||||
	if (platform)
 | 
			
		||||
		delete platform;
 | 
			
		||||
	platform = nullptr;
 | 
			
		||||
 | 
			
		||||
	Blah::Internal::audio_shutdown();
 | 
			
		||||
	Blah::Internal::audio_is_init = false;
 | 
			
		||||
	Platform::shutdown();
 | 
			
		||||
 | 
			
		||||
	// clear static App state
 | 
			
		||||
	app_config = Config();
 | 
			
		||||
@ -322,6 +306,12 @@ void Internal::app_shutdown()
 | 
			
		||||
	Time::delta = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Renderer* Internal::app_renderer()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return app_renderer_api;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void App::exit()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
@ -338,59 +328,59 @@ const Config& App::config()
 | 
			
		||||
const char* App::path()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return Internal::platform->app_path();
 | 
			
		||||
	return Platform::app_path();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* App::user_path()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return Internal::platform->user_path();
 | 
			
		||||
	return Platform::user_path();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* App::get_title()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return Internal::platform->get_title();
 | 
			
		||||
	return Platform::get_title();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void App::set_title(const char* title)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Internal::platform->set_title(title);
 | 
			
		||||
	Platform::set_title(title);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point App::get_position()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Point result;
 | 
			
		||||
	Internal::platform->get_position(&result.x, &result.y);
 | 
			
		||||
	Platform::get_position(&result.x, &result.y);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void App::set_position(Point point)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Internal::platform->set_position(point.x, point.y);
 | 
			
		||||
	Platform::set_position(point.x, point.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point App::get_size()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Point result;
 | 
			
		||||
	Internal::platform->get_size(&result.x, &result.y);
 | 
			
		||||
	Platform::get_size(&result.x, &result.y);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void App::set_size(Point point)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Internal::platform->set_size(point.x, point.y);
 | 
			
		||||
	Platform::set_size(point.x, point.y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Point App::get_backbuffer_size()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (Internal::renderer)
 | 
			
		||||
	if (app_renderer_api)
 | 
			
		||||
		return Point(app_backbuffer->width(), app_backbuffer->height());
 | 
			
		||||
	return Point(0, 0);
 | 
			
		||||
}
 | 
			
		||||
@ -398,13 +388,13 @@ Point App::get_backbuffer_size()
 | 
			
		||||
float App::content_scale()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return Internal::platform->get_content_scale();
 | 
			
		||||
	return Platform::get_content_scale();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool App::focused()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	return Internal::platform->get_focused();
 | 
			
		||||
	return Platform::get_focused();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 (Internal::platform)
 | 
			
		||||
			Internal::platform->set_app_flags(app_flags);
 | 
			
		||||
		if (Internal::renderer)
 | 
			
		||||
			Internal::renderer->set_app_flags(app_flags);
 | 
			
		||||
		Platform::set_app_flags(app_flags);
 | 
			
		||||
		if (app_renderer_api)
 | 
			
		||||
			app_renderer_api->set_app_flags(app_flags);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -437,7 +426,7 @@ const RendererInfo& App::renderer()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	BLAH_ASSERT_RENDERER();
 | 
			
		||||
	return Internal::renderer->info;
 | 
			
		||||
	return app_renderer_api->info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TargetRef& App::backbuffer()
 | 
			
		||||
@ -449,5 +438,5 @@ const TargetRef& App::backbuffer()
 | 
			
		||||
void System::open_url(const char* url)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	Internal::platform->open_url(url);
 | 
			
		||||
	Platform::open_url(url);
 | 
			
		||||
}
 | 
			
		||||
@ -18,7 +18,7 @@ namespace Blah
 | 
			
		||||
	{
 | 
			
		||||
		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) {
 | 
			
		||||
				Log::error(cs_error_as_string(err));
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
@ -282,7 +282,8 @@ void Batch::render(const TargetRef& target, const Mat4x4f& matrix)
 | 
			
		||||
		if (!m_default_material)
 | 
			
		||||
		{
 | 
			
		||||
			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);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,11 @@ using namespace Blah;
 | 
			
		||||
 | 
			
		||||
FileRef File::open(const FilePath& path, FileMode mode)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
 | 
			
		||||
	FileRef ref;
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		ref = Internal::platform->file_open(path.cstr(), mode);
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		ref = Platform::file_open(path.cstr(), mode);
 | 
			
		||||
	if (ref)
 | 
			
		||||
		ref->m_mode = mode;
 | 
			
		||||
	return ref;
 | 
			
		||||
@ -17,17 +17,17 @@ FileRef File::open(const FilePath& path, FileMode mode)
 | 
			
		||||
 | 
			
		||||
bool File::exists(const FilePath& path)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->file_exists(path.cstr());
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::file_exists(path.cstr());
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool File::destroy(const FilePath& path)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->file_delete(path.cstr());
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::file_delete(path.cstr());
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -38,37 +38,37 @@ FileMode File::mode() const
 | 
			
		||||
 | 
			
		||||
bool Directory::create(const FilePath& path)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->dir_create(path.cstr());
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::dir_create(path.cstr());
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Directory::exists(const FilePath& path)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->dir_exists(path.cstr());
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::dir_exists(path.cstr());
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Directory::destroy(const FilePath& path)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->dir_delete(path.cstr());
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::dir_delete(path.cstr());
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Vector<FilePath> Directory::enumerate(const FilePath& path, bool recursive)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
 | 
			
		||||
	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 (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)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_PLATFORM();
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		Internal::platform->dir_explore(path);
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		Platform::dir_explore(path);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FilePath Path::get_file_name(const FilePath& path)
 | 
			
		||||
 | 
			
		||||
@ -88,8 +88,8 @@ ShaderRef Shader::create(const ShaderData& data)
 | 
			
		||||
 | 
			
		||||
	ShaderRef shader;
 | 
			
		||||
 | 
			
		||||
	if (Internal::renderer)
 | 
			
		||||
		shader = Internal::renderer->create_shader(&data);
 | 
			
		||||
	if (auto renderer = Internal::app_renderer())
 | 
			
		||||
		shader = renderer->create_shader(&data);
 | 
			
		||||
 | 
			
		||||
	// validate the 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((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)
 | 
			
		||||
			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(color_count <= Attachments::capacity - 1, "Exceeded maximum Color texture count");
 | 
			
		||||
 | 
			
		||||
	if (Internal::renderer)
 | 
			
		||||
		return Internal::renderer->create_target(width, height, textures.data(), textures.size());
 | 
			
		||||
	if (auto renderer = Internal::app_renderer())
 | 
			
		||||
		return renderer->create_target(width, height, textures.data(), textures.size());
 | 
			
		||||
 | 
			
		||||
	return TargetRef();
 | 
			
		||||
}
 | 
			
		||||
@ -224,8 +224,8 @@ MeshRef Mesh::create()
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RENDERER();
 | 
			
		||||
 | 
			
		||||
	if (Internal::renderer)
 | 
			
		||||
		return Internal::renderer->create_mesh();
 | 
			
		||||
	if (auto renderer = Internal::app_renderer())
 | 
			
		||||
		return renderer->create_mesh();
 | 
			
		||||
 | 
			
		||||
	return MeshRef();
 | 
			
		||||
}
 | 
			
		||||
@ -623,7 +623,7 @@ void DrawCall::perform()
 | 
			
		||||
	BLAH_ASSERT(material->shader(), "Trying to draw with an invalid Shader");
 | 
			
		||||
	BLAH_ASSERT(mesh, "Trying to draw with an invalid Mesh");
 | 
			
		||||
 | 
			
		||||
	if (!Internal::renderer)
 | 
			
		||||
	if (!Internal::app_renderer())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	// copy call
 | 
			
		||||
@ -685,5 +685,5 @@ void DrawCall::perform()
 | 
			
		||||
		pass.scissor = pass.scissor.overlap_rect(Rectf(0, 0, draw_size.x, draw_size.y));
 | 
			
		||||
 | 
			
		||||
	// perform render
 | 
			
		||||
	Internal::renderer->render(pass);
 | 
			
		||||
	Internal::app_renderer()->render(pass);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -78,8 +78,7 @@ void Internal::input_step_state()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get clipboard
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		g_clipboard = Internal::platform->get_clipboard();
 | 
			
		||||
	g_clipboard = Platform::get_clipboard();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Internal::input_step_bindings()
 | 
			
		||||
@ -397,9 +396,9 @@ const String& Input::get_clipboard()
 | 
			
		||||
 | 
			
		||||
void Input::set_clipboard(const String& text)
 | 
			
		||||
{
 | 
			
		||||
	BLAH_ASSERT_RUNNING();
 | 
			
		||||
	g_clipboard = text;
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		Internal::platform->set_clipboard(text);
 | 
			
		||||
	Platform::set_clipboard(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ButtonBindingRef Input::register_binding(const ButtonBinding& binding_data)
 | 
			
		||||
 | 
			
		||||
@ -12,8 +12,8 @@ float Time::pause_timer = 0;
 | 
			
		||||
 | 
			
		||||
u64 Time::get_ticks()
 | 
			
		||||
{
 | 
			
		||||
	if (Internal::platform)
 | 
			
		||||
		return Internal::platform->ticks();
 | 
			
		||||
	if (App::is_running())
 | 
			
		||||
		return Platform::ticks();
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,19 +2,18 @@
 | 
			
		||||
#include "blah_renderer.h"
 | 
			
		||||
#include "blah_platform.h"
 | 
			
		||||
 | 
			
		||||
#define BLAH_ASSERT_RENDERER() BLAH_ASSERT(Blah::Internal::renderer, "Renderer has not been created")
 | 
			
		||||
#define BLAH_ASSERT_PLATFORM() BLAH_ASSERT(Blah::Internal::platform, "Platform has not been created")
 | 
			
		||||
#define BLAH_ASSERT_RENDERER() BLAH_ASSERT(Blah::Internal::app_renderer(), "Renderer 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 Internal
 | 
			
		||||
	{
 | 
			
		||||
		extern Platform* platform;
 | 
			
		||||
		extern Renderer* renderer;
 | 
			
		||||
		extern bool audio_is_init;
 | 
			
		||||
 | 
			
		||||
		void app_step();
 | 
			
		||||
		void app_shutdown();
 | 
			
		||||
		Renderer* app_renderer();
 | 
			
		||||
 | 
			
		||||
		void input_init();
 | 
			
		||||
		void input_step_state();
 | 
			
		||||
 | 
			
		||||
@ -8,112 +8,105 @@ namespace Blah
 | 
			
		||||
{
 | 
			
		||||
	struct Config;
 | 
			
		||||
 | 
			
		||||
	class Platform
 | 
			
		||||
	namespace Platform
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		virtual ~Platform() = default;
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual void ready() = 0;
 | 
			
		||||
		void ready();
 | 
			
		||||
 | 
			
		||||
		// Called during shutdown
 | 
			
		||||
		virtual void shutdown() = 0;
 | 
			
		||||
		void shutdown();
 | 
			
		||||
 | 
			
		||||
		// The time, in ticks (microseconds) since the Application was started
 | 
			
		||||
		virtual u64 ticks() = 0;
 | 
			
		||||
		u64 ticks();
 | 
			
		||||
 | 
			
		||||
		// Called every frame
 | 
			
		||||
		virtual void update(InputState& state) = 0;
 | 
			
		||||
		void update(InputState& state);
 | 
			
		||||
 | 
			
		||||
		// Sleeps the current thread
 | 
			
		||||
		virtual void sleep(int milliseconds) = 0;
 | 
			
		||||
		void sleep(int milliseconds);
 | 
			
		||||
 | 
			
		||||
		// Called to present the window contents
 | 
			
		||||
		virtual void present() = 0;
 | 
			
		||||
		void present();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual const char* get_title() = 0;
 | 
			
		||||
		const char* get_title();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual void get_position(int* x, int* y) = 0;
 | 
			
		||||
		void get_position(int* x, int* y);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual bool get_focused() = 0;
 | 
			
		||||
		bool get_focused();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		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.
 | 
			
		||||
		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
 | 
			
		||||
		virtual float get_content_scale() = 0;
 | 
			
		||||
		float get_content_scale();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
		virtual bool dir_create(const char* path) = 0;
 | 
			
		||||
		bool dir_create(const char* path);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		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
 | 
			
		||||
		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
 | 
			
		||||
		virtual void dir_explore(const char* path) = 0;
 | 
			
		||||
		void dir_explore(const char* path);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual const char* get_clipboard() = 0;
 | 
			
		||||
		const char* get_clipboard();
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		virtual void* gl_get_func(const char* name) = 0;
 | 
			
		||||
		virtual void* gl_context_create() = 0;
 | 
			
		||||
		virtual void gl_context_make_current(void* context) = 0;
 | 
			
		||||
		virtual void gl_context_destroy(void* context) = 0;
 | 
			
		||||
		void* gl_get_func(const char* name);
 | 
			
		||||
		void* gl_context_create();
 | 
			
		||||
		void gl_context_make_current(void* context);
 | 
			
		||||
		void gl_context_destroy(void* context);
 | 
			
		||||
 | 
			
		||||
		// D3D11 Methods
 | 
			
		||||
		virtual void* d3d11_get_hwnd() = 0;
 | 
			
		||||
 | 
			
		||||
		// Instantiates the Platform object
 | 
			
		||||
		static Platform* try_make_platform(const Config& config);
 | 
			
		||||
		void* d3d11_get_hwnd();
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
@ -71,67 +71,18 @@ namespace Blah
 | 
			
		||||
		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* window = nullptr;
 | 
			
		||||
		SDL_Joystick* joysticks[Input::max_controllers];
 | 
			
		||||
		SDL_GameController* gamepads[Input::max_controllers];
 | 
			
		||||
		char* base_path_value = nullptr;
 | 
			
		||||
		char* user_path_value = nullptr;
 | 
			
		||||
		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;
 | 
			
		||||
	};
 | 
			
		||||
	SDL_Window* sdl2_window = nullptr;
 | 
			
		||||
	SDL_Joystick* sdl2_joysticks[Input::max_controllers];
 | 
			
		||||
	SDL_GameController* sdl2_gamepads[Input::max_controllers];
 | 
			
		||||
	char* sdl2_base_path_value = nullptr;
 | 
			
		||||
	char* sdl2_user_path_value = nullptr;
 | 
			
		||||
	char* sdl2_clipboard_text = nullptr;
 | 
			
		||||
	bool sdl2_displayed = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
 | 
			
		||||
SDL2_Platform::SDL2_Platform()
 | 
			
		||||
{
 | 
			
		||||
	for (int i = 0; i < Input::max_controllers; i++)
 | 
			
		||||
	{
 | 
			
		||||
		joysticks[i] = nullptr;
 | 
			
		||||
		gamepads[i] = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SDL2_Platform::init(const Config& config)
 | 
			
		||||
bool Platform::init(const Config& config)
 | 
			
		||||
{
 | 
			
		||||
	// TODO:
 | 
			
		||||
	// control this via some kind of config flag
 | 
			
		||||
@ -185,54 +136,60 @@ bool SDL2_Platform::init(const Config& config)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// create the window
 | 
			
		||||
	window = SDL_CreateWindow(config.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config.width, config.height, flags);
 | 
			
		||||
	if (window == nullptr)
 | 
			
		||||
	sdl2_window = SDL_CreateWindow(config.name, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, config.width, config.height, flags);
 | 
			
		||||
	if (sdl2_window == nullptr)
 | 
			
		||||
	{
 | 
			
		||||
		Log::error("Failed to create a Window");
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < Input::max_controllers; i++)
 | 
			
		||||
	{
 | 
			
		||||
		sdl2_joysticks[i] = nullptr;
 | 
			
		||||
		sdl2_gamepads[i] = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::ready()
 | 
			
		||||
void Platform::ready()
 | 
			
		||||
{
 | 
			
		||||
	
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::shutdown()
 | 
			
		||||
void Platform::shutdown()
 | 
			
		||||
{
 | 
			
		||||
	if (window != nullptr)
 | 
			
		||||
		SDL_DestroyWindow(window);
 | 
			
		||||
	window = nullptr;
 | 
			
		||||
	displayed = false;
 | 
			
		||||
	if (sdl2_window != nullptr)
 | 
			
		||||
		SDL_DestroyWindow(sdl2_window);
 | 
			
		||||
	sdl2_window = nullptr;
 | 
			
		||||
	sdl2_displayed = false;
 | 
			
		||||
 | 
			
		||||
	if (base_path_value != nullptr)
 | 
			
		||||
		SDL_free(base_path_value);
 | 
			
		||||
	if (sdl2_base_path_value != nullptr)
 | 
			
		||||
		SDL_free(sdl2_base_path_value);
 | 
			
		||||
 | 
			
		||||
	if (user_path_value != nullptr)
 | 
			
		||||
		SDL_free(user_path_value);
 | 
			
		||||
	if (sdl2_user_path_value != nullptr)
 | 
			
		||||
		SDL_free(sdl2_user_path_value);
 | 
			
		||||
 | 
			
		||||
	if (clipboard_text != nullptr)
 | 
			
		||||
		SDL_free(clipboard_text);
 | 
			
		||||
	if (sdl2_clipboard_text != nullptr)
 | 
			
		||||
		SDL_free(sdl2_clipboard_text);
 | 
			
		||||
 | 
			
		||||
	SDL_Quit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 SDL2_Platform::ticks()
 | 
			
		||||
u64 Platform::ticks()
 | 
			
		||||
{
 | 
			
		||||
	auto counter = SDL_GetPerformanceCounter();
 | 
			
		||||
	auto per_second = (double)SDL_GetPerformanceFrequency();
 | 
			
		||||
	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
 | 
			
		||||
	{
 | 
			
		||||
		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);
 | 
			
		||||
 | 
			
		||||
		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)
 | 
			
		||||
			{
 | 
			
		||||
				auto ptr = joysticks[index] = SDL_JoystickOpen(index);
 | 
			
		||||
				auto ptr = sdl2_joysticks[index] = SDL_JoystickOpen(index);
 | 
			
		||||
				auto name = SDL_JoystickName(ptr);
 | 
			
		||||
				auto button_count = SDL_JoystickNumButtons(ptr);
 | 
			
		||||
				auto axis_count = SDL_JoystickNumAxes(ptr);
 | 
			
		||||
@ -314,19 +271,19 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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 (SDL_IsGameController(index) == SDL_FALSE)
 | 
			
		||||
				{
 | 
			
		||||
					state.controllers[index].on_disconnect();
 | 
			
		||||
					SDL_JoystickClose(joysticks[index]);
 | 
			
		||||
					SDL_JoystickClose(sdl2_joysticks[index]);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		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 (SDL_IsGameController(index) == SDL_FALSE)
 | 
			
		||||
@ -335,7 +292,7 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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 (SDL_IsGameController(index) == SDL_FALSE)
 | 
			
		||||
@ -344,7 +301,7 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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 (SDL_IsGameController(index) == SDL_FALSE)
 | 
			
		||||
@ -364,7 +321,7 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
			auto index = event.cdevice.which;
 | 
			
		||||
			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 vendor = SDL_GameControllerGetVendor(ptr);
 | 
			
		||||
				auto product = SDL_GameControllerGetProduct(ptr);
 | 
			
		||||
@ -375,16 +332,16 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
			{
 | 
			
		||||
				state.controllers[index].on_disconnect();
 | 
			
		||||
				SDL_GameControllerClose(gamepads[index]);
 | 
			
		||||
				SDL_GameControllerClose(sdl2_gamepads[index]);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
			{
 | 
			
		||||
				Button button = Button::None;
 | 
			
		||||
@ -396,7 +353,7 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
			{
 | 
			
		||||
				Button button = Button::None;
 | 
			
		||||
@ -408,7 +365,7 @@ void SDL2_Platform::update(InputState& state)
 | 
			
		||||
		}
 | 
			
		||||
		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)
 | 
			
		||||
			{
 | 
			
		||||
				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)
 | 
			
		||||
		SDL_Delay((u32)milliseconds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::present()
 | 
			
		||||
void Platform::present()
 | 
			
		||||
{
 | 
			
		||||
	if (App::renderer().type == RendererType::OpenGL)
 | 
			
		||||
		SDL_GL_SwapWindow(window);
 | 
			
		||||
		SDL_GL_SwapWindow(sdl2_window);
 | 
			
		||||
 | 
			
		||||
	// display the window
 | 
			
		||||
	// this avoids a short black screen on macOS
 | 
			
		||||
	if (!displayed)
 | 
			
		||||
	if (!sdl2_displayed)
 | 
			
		||||
	{
 | 
			
		||||
		SDL_ShowWindow(window);
 | 
			
		||||
		displayed = true;
 | 
			
		||||
		SDL_ShowWindow(sdl2_window);
 | 
			
		||||
		sdl2_displayed = true;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::set_app_flags(u32 flags)
 | 
			
		||||
void Platform::set_app_flags(u32 flags)
 | 
			
		||||
{
 | 
			
		||||
	// 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
 | 
			
		||||
	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
 | 
			
		||||
#ifndef __EMSCRIPTEN__
 | 
			
		||||
@ -462,57 +419,57 @@ void SDL2_Platform::set_app_flags(u32 flags)
 | 
			
		||||
#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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	{
 | 
			
		||||
	case RendererType::OpenGL:
 | 
			
		||||
		SDL_GL_GetDrawableSize(window, width, height);
 | 
			
		||||
		SDL_GL_GetDrawableSize(sdl2_window, width, height);
 | 
			
		||||
		break;
 | 
			
		||||
	case RendererType::None:
 | 
			
		||||
	case RendererType::D3D11:
 | 
			
		||||
		SDL_GetWindowSize(window, width, height);
 | 
			
		||||
		SDL_GetWindowSize(sdl2_window, width, height);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float SDL2_Platform::get_content_scale()
 | 
			
		||||
float Platform::get_content_scale()
 | 
			
		||||
{
 | 
			
		||||
	// TODO:
 | 
			
		||||
	// 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
 | 
			
		||||
	const float hidpi_res = 96;
 | 
			
		||||
 | 
			
		||||
	int index = SDL_GetWindowDisplayIndex(window);
 | 
			
		||||
	int index = SDL_GetWindowDisplayIndex(sdl2_window);
 | 
			
		||||
	if (index < 0)
 | 
			
		||||
	{
 | 
			
		||||
		Log::error(SDL_GetError());
 | 
			
		||||
@ -542,25 +499,25 @@ float SDL2_Platform::get_content_scale()
 | 
			
		||||
	return (ddpi / hidpi_res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* SDL2_Platform::app_path()
 | 
			
		||||
const char* Platform::app_path()
 | 
			
		||||
{
 | 
			
		||||
	if (base_path_value == nullptr)
 | 
			
		||||
		base_path_value = SDL_GetBasePath();
 | 
			
		||||
	return base_path_value;
 | 
			
		||||
	if (sdl2_base_path_value == nullptr)
 | 
			
		||||
		sdl2_base_path_value = SDL_GetBasePath();
 | 
			
		||||
	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();
 | 
			
		||||
		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 = "";
 | 
			
		||||
 | 
			
		||||
@ -587,32 +544,32 @@ FileRef SDL2_Platform::file_open(const char* path, FileMode mode)
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SDL2_Platform::file_delete(const char* path)
 | 
			
		||||
bool Platform::file_delete(const char* 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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SDL2_Platform::dir_exists(const char* path)
 | 
			
		||||
bool Platform::dir_exists(const char* 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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))
 | 
			
		||||
	{
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -646,64 +603,59 @@ void SDL2_Platform::dir_explore(const char* path)
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::set_clipboard(const char* text)
 | 
			
		||||
void Platform::set_clipboard(const char* text)
 | 
			
		||||
{
 | 
			
		||||
	SDL_SetClipboardText(text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* SDL2_Platform::get_clipboard()
 | 
			
		||||
const char* Platform::get_clipboard()
 | 
			
		||||
{
 | 
			
		||||
	// free previous clipboard text
 | 
			
		||||
	if (clipboard_text != nullptr)
 | 
			
		||||
		SDL_free(clipboard_text);
 | 
			
		||||
	if (sdl2_clipboard_text != nullptr)
 | 
			
		||||
		SDL_free(sdl2_clipboard_text);
 | 
			
		||||
 | 
			
		||||
	clipboard_text = SDL_GetClipboardText();
 | 
			
		||||
	return clipboard_text;
 | 
			
		||||
	sdl2_clipboard_text = SDL_GetClipboardText();
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
		Log::error("SDL_GL_CreateContext failed: %s", SDL_GetError());
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* SDL2_Platform::d3d11_get_hwnd()
 | 
			
		||||
void* Platform::d3d11_get_hwnd()
 | 
			
		||||
{
 | 
			
		||||
#if _WIN32
 | 
			
		||||
	SDL_SysWMinfo info;
 | 
			
		||||
	SDL_VERSION(&info.version);
 | 
			
		||||
	SDL_GetWindowWMInfo(window, &info);
 | 
			
		||||
	SDL_GetWindowWMInfo(sdl2_window, &info);
 | 
			
		||||
	return info.info.win.window;
 | 
			
		||||
#else
 | 
			
		||||
	return nullptr;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SDL2_Platform::open_url(const char* url)
 | 
			
		||||
void Platform::open_url(const char* url)
 | 
			
		||||
{
 | 
			
		||||
	SDL_OpenURL(url);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Platform* Platform::try_make_platform(const Config& config)
 | 
			
		||||
{
 | 
			
		||||
	return new SDL2_Platform();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BLAH_PLATFORM_SDL2
 | 
			
		||||
 | 
			
		||||
@ -48,17 +48,15 @@ namespace Blah
 | 
			
		||||
		size_t write(const void* buffer, size_t length) override;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct Win32_Platform : public Platform
 | 
			
		||||
	{
 | 
			
		||||
	// Main State
 | 
			
		||||
		HWND         hwnd;
 | 
			
		||||
		FilePath     working_directory;
 | 
			
		||||
		FilePath     user_directory;
 | 
			
		||||
		Duration     start_time;
 | 
			
		||||
		RECT         windowed_position;
 | 
			
		||||
		bool         fullscreen = false;
 | 
			
		||||
		InputState*  input_state = nullptr;
 | 
			
		||||
		String       clipboard;
 | 
			
		||||
	HWND         win32_hwnd;
 | 
			
		||||
	FilePath     win32_working_directory;
 | 
			
		||||
	FilePath     win32_user_directory;
 | 
			
		||||
	Duration     win32_start_time;
 | 
			
		||||
	RECT         win32_windowed_position;
 | 
			
		||||
	bool         win32_fullscreen = false;
 | 
			
		||||
	InputState*  win32_input_state = nullptr;
 | 
			
		||||
	String       win32_clipboard;
 | 
			
		||||
 | 
			
		||||
	// XInput
 | 
			
		||||
	struct
 | 
			
		||||
@ -66,7 +64,7 @@ namespace Blah
 | 
			
		||||
		HMODULE dll;
 | 
			
		||||
		XInputGetCapabilities_fn get_capabilities;
 | 
			
		||||
		XInputGetState_fn get_state;
 | 
			
		||||
		} xinput;
 | 
			
		||||
	} win32_xinput;
 | 
			
		||||
 | 
			
		||||
	struct Joystick
 | 
			
		||||
	{
 | 
			
		||||
@ -74,7 +72,7 @@ namespace Blah
 | 
			
		||||
		bool accounted = false;
 | 
			
		||||
		GUID dinstance = GUID_NULL;
 | 
			
		||||
		DWORD xindex = 0;
 | 
			
		||||
		} joysticks[Input::max_controllers];
 | 
			
		||||
	} win32_joysticks[Input::max_controllers];
 | 
			
		||||
 | 
			
		||||
	// OpenGL Methods
 | 
			
		||||
	// These are only loaded if built using the OpenGL Backend
 | 
			
		||||
@ -85,52 +83,15 @@ namespace Blah
 | 
			
		||||
		wglCreateContext_fn create_context;
 | 
			
		||||
		wglDeleteContext_fn delete_context;
 | 
			
		||||
		wglMakeCurrent_fn make_current;
 | 
			
		||||
		} 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();
 | 
			
		||||
	};
 | 
			
		||||
	} win32_gl;
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	Key win32_scancode_to_key(WPARAM wParam, LPARAM lParam);
 | 
			
		||||
 | 
			
		||||
	void win32_detect_joysticks();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
using namespace Blah;
 | 
			
		||||
@ -194,7 +155,7 @@ size_t Win32File::read(void* buffer, size_t length)
 | 
			
		||||
			to_read = (DWORD)(length - read);
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
		if (moved < to_read)
 | 
			
		||||
@ -217,7 +178,7 @@ size_t Win32File::write(const void* buffer, size_t length)
 | 
			
		||||
			to_write = (DWORD)(length - written);
 | 
			
		||||
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
		if (moved < to_write)
 | 
			
		||||
@ -227,7 +188,7 @@ size_t Win32File::write(const void* buffer, size_t length)
 | 
			
		||||
	return written;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Win32_Platform::init(const Config& config)
 | 
			
		||||
bool Platform::init(const Config& config)
 | 
			
		||||
{
 | 
			
		||||
	// Required to call this for Windows
 | 
			
		||||
	SetProcessDPIAware();
 | 
			
		||||
@ -252,10 +213,10 @@ bool Win32_Platform::init(const Config& config)
 | 
			
		||||
	RegisterClass(&wc);
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	if (hwnd == NULL)
 | 
			
		||||
	if (win32_hwnd == NULL)
 | 
			
		||||
	{
 | 
			
		||||
		Log::error("Window Creation Failed");
 | 
			
		||||
		return false;
 | 
			
		||||
@ -273,18 +234,18 @@ bool Win32_Platform::init(const Config& config)
 | 
			
		||||
	if (config.renderer_type == RendererType::OpenGL)
 | 
			
		||||
	{
 | 
			
		||||
		// Load the DLL
 | 
			
		||||
		gl.dll = LoadLibraryA("opengl32.dll");
 | 
			
		||||
		if (gl.dll == NULL)
 | 
			
		||||
		win32_gl.dll = LoadLibraryA("opengl32.dll");
 | 
			
		||||
		if (win32_gl.dll == NULL)
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("OpenGL Instantiation Failed - unable to fine opengl32.dll");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Get the Windows GL functions we need
 | 
			
		||||
		gl.get_proc_address = (wglGetProcAddress_fn)GetProcAddress(gl.dll, "wglGetProcAddress");
 | 
			
		||||
		gl.create_context = (wglCreateContext_fn)GetProcAddress(gl.dll, "wglCreateContext");
 | 
			
		||||
		gl.delete_context = (wglDeleteContext_fn)GetProcAddress(gl.dll, "wglDeleteContext");
 | 
			
		||||
		gl.make_current = (wglMakeCurrent_fn)GetProcAddress(gl.dll, "wglMakeCurrent");
 | 
			
		||||
		win32_gl.get_proc_address = (wglGetProcAddress_fn)GetProcAddress(win32_gl.dll, "wglGetProcAddress");
 | 
			
		||||
		win32_gl.create_context = (wglCreateContext_fn)GetProcAddress(win32_gl.dll, "wglCreateContext");
 | 
			
		||||
		win32_gl.delete_context = (wglDeleteContext_fn)GetProcAddress(win32_gl.dll, "wglDeleteContext");
 | 
			
		||||
		win32_gl.make_current = (wglMakeCurrent_fn)GetProcAddress(win32_gl.dll, "wglMakeCurrent");
 | 
			
		||||
 | 
			
		||||
		// TODO:
 | 
			
		||||
		// 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  
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		HDC hdc = GetDC(hwnd);
 | 
			
		||||
		HDC hdc = GetDC(win32_hwnd);
 | 
			
		||||
 | 
			
		||||
		// get the best available match of pixel format for the device context   
 | 
			
		||||
		int pixel_format = ChoosePixelFormat(hdc, &pfd);
 | 
			
		||||
@ -327,17 +288,17 @@ bool Win32_Platform::init(const Config& config)
 | 
			
		||||
 | 
			
		||||
		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");
 | 
			
		||||
				xinput.get_state = (XInputGetState_fn)GetProcAddress(xinput.dll, "XInputGetState");
 | 
			
		||||
				win32_xinput.get_capabilities = (XInputGetCapabilities_fn)GetProcAddress(win32_xinput.dll, "XInputGetCapabilities");
 | 
			
		||||
				win32_xinput.get_state = (XInputGetState_fn)GetProcAddress(win32_xinput.dll, "XInputGetState");
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!xinput.dll)
 | 
			
		||||
		if (!win32_xinput.dll)
 | 
			
		||||
			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 end = normalized.last_index_of('/');;
 | 
			
		||||
		if (end >= 0)
 | 
			
		||||
			working_directory = FilePath(normalized.begin(), normalized.begin() + end);
 | 
			
		||||
			win32_working_directory = FilePath(normalized.begin(), normalized.begin() + end);
 | 
			
		||||
		else
 | 
			
		||||
			working_directory = normalized;
 | 
			
		||||
		working_directory.append("/");
 | 
			
		||||
			win32_working_directory = normalized;
 | 
			
		||||
		win32_working_directory.append("/");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Get Application User Directory
 | 
			
		||||
@ -366,56 +327,56 @@ bool Win32_Platform::init(const Config& config)
 | 
			
		||||
			FilePath result;
 | 
			
		||||
			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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	fullscreen = false;
 | 
			
		||||
	// Not currently win32_fullscreen
 | 
			
		||||
	win32_fullscreen = false;
 | 
			
		||||
 | 
			
		||||
	// Finished Platform Setup
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::ready()
 | 
			
		||||
void Platform::ready()
 | 
			
		||||
{
 | 
			
		||||
	// Display the game window
 | 
			
		||||
	ShowWindow(hwnd, SW_SHOW);
 | 
			
		||||
	ShowWindow(win32_hwnd, SW_SHOW);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::shutdown()
 | 
			
		||||
void Platform::shutdown()
 | 
			
		||||
{
 | 
			
		||||
	if (xinput.dll)
 | 
			
		||||
		FreeLibrary(xinput.dll);
 | 
			
		||||
	if (win32_xinput.dll)
 | 
			
		||||
		FreeLibrary(win32_xinput.dll);
 | 
			
		||||
 | 
			
		||||
	if (gl.dll)
 | 
			
		||||
		FreeLibrary(gl.dll);
 | 
			
		||||
	if (win32_gl.dll)
 | 
			
		||||
		FreeLibrary(win32_gl.dll);
 | 
			
		||||
 | 
			
		||||
	DestroyWindow(hwnd);
 | 
			
		||||
	DestroyWindow(win32_hwnd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 Win32_Platform::ticks()
 | 
			
		||||
u64 Platform::ticks()
 | 
			
		||||
{
 | 
			
		||||
	// Todo:
 | 
			
		||||
	// This should account for whatever Time::ticks_per_second is set to
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
	bool first_update = input_state == nullptr;
 | 
			
		||||
	input_state = &state;
 | 
			
		||||
	bool first_update = win32_input_state == nullptr;
 | 
			
		||||
	win32_input_state = &state;
 | 
			
		||||
 | 
			
		||||
	// if this is the first update, poll joysticks that are already connected
 | 
			
		||||
	if (first_update)
 | 
			
		||||
		detect_joysticks();
 | 
			
		||||
		win32_detect_joysticks();
 | 
			
		||||
 | 
			
		||||
	// Catch & Dispatch Window Messages
 | 
			
		||||
	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)
 | 
			
		||||
		Sleep(milliseconds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::present()
 | 
			
		||||
void Platform::present()
 | 
			
		||||
{
 | 
			
		||||
	if (App::renderer().type == RendererType::OpenGL)
 | 
			
		||||
	{
 | 
			
		||||
		HDC hdc = GetDC(hwnd);
 | 
			
		||||
		HDC hdc = GetDC(win32_hwnd);
 | 
			
		||||
		SwapBuffers(hdc);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* Win32_Platform::get_title()
 | 
			
		||||
const char* Platform::get_title()
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
	if (GetWindowRect(hwnd, &rect))
 | 
			
		||||
	if (GetWindowRect(win32_hwnd, &rect))
 | 
			
		||||
	{
 | 
			
		||||
		*x = rect.left;
 | 
			
		||||
		*y = rect.top;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::set_position(int x, int y)
 | 
			
		||||
void Platform::set_position(int x, int y)
 | 
			
		||||
{
 | 
			
		||||
	int 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");
 | 
			
		||||
	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;
 | 
			
		||||
		if (fullscreen == enabled)
 | 
			
		||||
		if (win32_fullscreen == enabled)
 | 
			
		||||
			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 h = GetSystemMetrics(SM_CYSCREEN);
 | 
			
		||||
			SetWindowLongPtr(hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
 | 
			
		||||
			SetWindowPos(hwnd, HWND_TOP, 0, 0, w, h, 0);
 | 
			
		||||
			ShowWindow(hwnd, SW_SHOW);
 | 
			
		||||
			SetWindowLongPtr(win32_hwnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
 | 
			
		||||
			SetWindowPos(win32_hwnd, HWND_TOP, 0, 0, w, h, 0);
 | 
			
		||||
			ShowWindow(win32_hwnd, SW_SHOW);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
 | 
			
		||||
			SetWindowPos(hwnd, HWND_TOP,
 | 
			
		||||
				windowed_position.left,
 | 
			
		||||
				windowed_position.top,
 | 
			
		||||
				windowed_position.right - windowed_position.left,
 | 
			
		||||
				windowed_position.bottom - windowed_position.top, 0);
 | 
			
		||||
			ShowWindow(hwnd, SW_SHOW);
 | 
			
		||||
			SetWindowLongPtr(win32_hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
 | 
			
		||||
			SetWindowPos(win32_hwnd, HWND_TOP,
 | 
			
		||||
				win32_windowed_position.left,
 | 
			
		||||
				win32_windowed_position.top,
 | 
			
		||||
				win32_windowed_position.right - win32_windowed_position.left,
 | 
			
		||||
				win32_windowed_position.bottom - win32_windowed_position.top, 0);
 | 
			
		||||
			ShowWindow(win32_hwnd, SW_SHOW);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -509,88 +470,88 @@ void Win32_Platform::set_app_flags(u32 flags)
 | 
			
		||||
	// TODO: ...
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::get_size(int* width, int* height)
 | 
			
		||||
void Platform::get_size(int* width, int* height)
 | 
			
		||||
{
 | 
			
		||||
	RECT rect;
 | 
			
		||||
	if (GetClientRect(hwnd, &rect))
 | 
			
		||||
	if (GetClientRect(win32_hwnd, &rect))
 | 
			
		||||
	{
 | 
			
		||||
		*width = rect.right - rect.left;
 | 
			
		||||
		*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 border_rect;
 | 
			
		||||
 | 
			
		||||
	GetClientRect(hwnd, &client_rect);
 | 
			
		||||
	GetWindowRect(hwnd, &border_rect);
 | 
			
		||||
	GetClientRect(win32_hwnd, &client_rect);
 | 
			
		||||
	GetWindowRect(win32_hwnd, &border_rect);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
	if (GetClientRect(hwnd, &rect))
 | 
			
		||||
	if (GetClientRect(win32_hwnd, &rect))
 | 
			
		||||
	{
 | 
			
		||||
		*width = rect.right - rect.left;
 | 
			
		||||
		*height = rect.bottom - rect.top;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float Win32_Platform::get_content_scale()
 | 
			
		||||
float Platform::get_content_scale()
 | 
			
		||||
{
 | 
			
		||||
	// base value of Windows DPI
 | 
			
		||||
	// as seen here: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdpiforwindow
 | 
			
		||||
	constexpr float base_raw_value = 96.0f;
 | 
			
		||||
 | 
			
		||||
	UINT raw_value = GetDpiForWindow(hwnd);
 | 
			
		||||
	UINT raw_value = GetDpiForWindow(win32_hwnd);
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Win32_Platform::file_delete(const char* path)
 | 
			
		||||
bool Platform::file_delete(const char* 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;
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Win32_Platform::dir_delete(const char* path)
 | 
			
		||||
bool Platform::dir_delete(const char* path)
 | 
			
		||||
{
 | 
			
		||||
	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))
 | 
			
		||||
	{
 | 
			
		||||
@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileRef Win32_Platform::file_open(const char* path, FileMode mode)
 | 
			
		||||
FileRef Platform::file_open(const char* path, FileMode mode)
 | 
			
		||||
{
 | 
			
		||||
	int access = 0;
 | 
			
		||||
	int creation = 0;
 | 
			
		||||
@ -645,52 +606,52 @@ FileRef Win32_Platform::file_open(const char* path, FileMode mode)
 | 
			
		||||
	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
 | 
			
		||||
	// 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) ||
 | 
			
		||||
		(p == (void*)0x1) ||
 | 
			
		||||
		(p == (void*)0x2) ||
 | 
			
		||||
		(p == (void*)0x3) ||
 | 
			
		||||
		(p == (void*)-1))
 | 
			
		||||
	{
 | 
			
		||||
		p = (void*)GetProcAddress(gl.dll, name);
 | 
			
		||||
		p = (void*)GetProcAddress(win32_gl.dll, name);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* Win32_Platform::gl_context_create()
 | 
			
		||||
void* Platform::gl_context_create()
 | 
			
		||||
{
 | 
			
		||||
	HDC hdc = GetDC(hwnd);
 | 
			
		||||
	return gl.create_context(hdc);
 | 
			
		||||
	HDC hdc = GetDC(win32_hwnd);
 | 
			
		||||
	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)
 | 
			
		||||
	{
 | 
			
		||||
		HDC hdc = GetDC(hwnd);
 | 
			
		||||
		gl.make_current(hdc, (HGLRC)context);
 | 
			
		||||
		HDC hdc = GetDC(win32_hwnd);
 | 
			
		||||
		win32_gl.make_current(hdc, (HGLRC)context);
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
	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))
 | 
			
		||||
	{
 | 
			
		||||
@ -720,44 +681,42 @@ const char* Win32_Platform::get_clipboard()
 | 
			
		||||
		{
 | 
			
		||||
			auto text = static_cast<const char*>(GlobalLock(data));
 | 
			
		||||
			if (text)
 | 
			
		||||
				clipboard = text;
 | 
			
		||||
				win32_clipboard = text;
 | 
			
		||||
			GlobalUnlock(data);
 | 
			
		||||
		}
 | 
			
		||||
		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;
 | 
			
		||||
	system(cmd.cstr());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Win32_Platform::detect_joysticks()
 | 
			
		||||
void win32_detect_joysticks()
 | 
			
		||||
{
 | 
			
		||||
	auto platform = ((Win32_Platform*)Internal::platform);
 | 
			
		||||
 | 
			
		||||
	// mark all joysticks as unnacounted for
 | 
			
		||||
	for (int i = 0; i < Input::max_controllers; i++)
 | 
			
		||||
		platform->joysticks[i].accounted = false;
 | 
			
		||||
		win32_joysticks[i].accounted = false;
 | 
			
		||||
 | 
			
		||||
	// check for xinput controllers
 | 
			
		||||
	if (platform->xinput.dll)
 | 
			
		||||
	if (win32_xinput.dll)
 | 
			
		||||
	{
 | 
			
		||||
		for (DWORD index = 0; index < XUSER_MAX_COUNT; index++)
 | 
			
		||||
		{
 | 
			
		||||
			// can't get capabilities; not connected
 | 
			
		||||
			XINPUT_CAPABILITIES xic;
 | 
			
		||||
			if (platform->xinput.get_capabilities(index, 0, &xic) != ERROR_SUCCESS)
 | 
			
		||||
			if (win32_xinput.get_capabilities(index, 0, &xic) != ERROR_SUCCESS)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			// already connected
 | 
			
		||||
			bool already_connected = false;
 | 
			
		||||
			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)
 | 
			
		||||
				{
 | 
			
		||||
					it.accounted = true;
 | 
			
		||||
@ -772,7 +731,7 @@ void Win32_Platform::detect_joysticks()
 | 
			
		||||
			// find an empty slot and mark connected
 | 
			
		||||
			for (int i = 0; i < Input::max_controllers; i++)
 | 
			
		||||
			{
 | 
			
		||||
				auto& it = platform->joysticks[i];
 | 
			
		||||
				auto& it = win32_joysticks[i];
 | 
			
		||||
				if (!it.connected)
 | 
			
		||||
				{
 | 
			
		||||
					it.connected = it.accounted = true;
 | 
			
		||||
@ -783,7 +742,7 @@ void Win32_Platform::detect_joysticks()
 | 
			
		||||
 | 
			
		||||
					// TODO:
 | 
			
		||||
					// 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;
 | 
			
		||||
				}
 | 
			
		||||
@ -794,21 +753,18 @@ void Win32_Platform::detect_joysticks()
 | 
			
		||||
	// call disconnect on joysticks that aren't accounted for
 | 
			
		||||
	for (int i = 0; i < Input::max_controllers; i++)
 | 
			
		||||
	{
 | 
			
		||||
		auto& it = platform->joysticks[i];
 | 
			
		||||
		auto& it = win32_joysticks[i];
 | 
			
		||||
		if (it.connected && !it.accounted)
 | 
			
		||||
		{
 | 
			
		||||
			Log::info("Disconnected [%i]", i);
 | 
			
		||||
			platform->input_state->controllers[i].on_disconnect();
 | 
			
		||||
			it = Win32_Platform::Joystick();
 | 
			
		||||
			win32_input_state->controllers[i].on_disconnect();
 | 
			
		||||
			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)
 | 
			
		||||
	{
 | 
			
		||||
	case WM_CLOSE:
 | 
			
		||||
@ -829,41 +785,41 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
 | 
			
		||||
		// DBT_DEVNODES_CHANGED = 0x0007
 | 
			
		||||
		// https://docs.microsoft.com/en-us/windows/win32/devio/wm-devicechange
 | 
			
		||||
		if (wParam == 0x0007)
 | 
			
		||||
			platform->detect_joysticks();
 | 
			
		||||
			win32_detect_joysticks();
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Mouse Input
 | 
			
		||||
	case WM_LBUTTONDOWN:
 | 
			
		||||
		input_state->mouse.on_press(MouseButton::Left);
 | 
			
		||||
		win32_input_state->mouse.on_press(MouseButton::Left);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_LBUTTONUP:
 | 
			
		||||
		input_state->mouse.on_release(MouseButton::Left);
 | 
			
		||||
		win32_input_state->mouse.on_release(MouseButton::Left);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_RBUTTONDOWN:
 | 
			
		||||
		input_state->mouse.on_press(MouseButton::Right);
 | 
			
		||||
		win32_input_state->mouse.on_press(MouseButton::Right);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_RBUTTONUP:
 | 
			
		||||
		input_state->mouse.on_release(MouseButton::Right);
 | 
			
		||||
		win32_input_state->mouse.on_release(MouseButton::Right);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_MBUTTONDOWN:
 | 
			
		||||
		input_state->mouse.on_press(MouseButton::Middle);
 | 
			
		||||
		win32_input_state->mouse.on_press(MouseButton::Middle);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	case WM_MBUTTONUP:
 | 
			
		||||
		input_state->mouse.on_release(MouseButton::Middle);
 | 
			
		||||
		win32_input_state->mouse.on_release(MouseButton::Middle);
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
		// Text Input
 | 
			
		||||
@ -875,7 +831,7 @@ LRESULT CALLBACK Blah::win32_window_procedure(HWND hwnd, UINT msg, WPARAM wParam
 | 
			
		||||
		String result;
 | 
			
		||||
		result.append((u32)wParam);
 | 
			
		||||
		if (result.length() > 0)
 | 
			
		||||
			input_state->keyboard.text += result.cstr();
 | 
			
		||||
			win32_input_state->keyboard.text += result.cstr();
 | 
			
		||||
		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);
 | 
			
		||||
			if (key != Key::Unknown)
 | 
			
		||||
				input_state->keyboard.on_press(key);
 | 
			
		||||
				win32_input_state->keyboard.on_press(key);
 | 
			
		||||
		}
 | 
			
		||||
		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);
 | 
			
		||||
		if (key != Key::Unknown)
 | 
			
		||||
			input_state->keyboard.on_release(key);
 | 
			
		||||
			win32_input_state->keyboard.on_release(key);
 | 
			
		||||
		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)
 | 
			
		||||
@ -1086,9 +1042,4 @@ Blah::Key Blah::win32_scancode_to_key(WPARAM wParam, LPARAM lParam)
 | 
			
		||||
	return Key::Unknown;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Platform* Platform::try_make_platform(const Config& config)
 | 
			
		||||
{
 | 
			
		||||
	return new Win32_Platform();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BLAH_PLATFORM_WIN32
 | 
			
		||||
 | 
			
		||||
@ -9,10 +9,10 @@ namespace Blah
 | 
			
		||||
	{
 | 
			
		||||
	public:
 | 
			
		||||
 | 
			
		||||
		// Renderer Info
 | 
			
		||||
		// Renderer Info, should be assigned during init
 | 
			
		||||
		RendererInfo info;
 | 
			
		||||
 | 
			
		||||
		// Default Shader for the Batcher
 | 
			
		||||
		// Default Shader for the Batcher, should be created in init
 | 
			
		||||
		ShaderRef default_batcher_shader;
 | 
			
		||||
 | 
			
		||||
		virtual ~Renderer() = default;
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
#include <d3dcompiler.h>
 | 
			
		||||
 | 
			
		||||
// shorthand to our internal state
 | 
			
		||||
#define RENDERER ((Renderer_D3D11*)Internal::renderer)
 | 
			
		||||
#define RENDERER ((Renderer_D3D11*)Internal::app_renderer())
 | 
			
		||||
 | 
			
		||||
namespace Blah
 | 
			
		||||
{
 | 
			
		||||
@ -776,7 +776,7 @@ namespace Blah
 | 
			
		||||
		desc.SampleDesc.Quality = 0;
 | 
			
		||||
		desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 | 
			
		||||
		desc.BufferCount = 1;
 | 
			
		||||
		desc.OutputWindow = (HWND)Internal::platform->d3d11_get_hwnd();
 | 
			
		||||
		desc.OutputWindow = (HWND)Platform::d3d11_get_hwnd();
 | 
			
		||||
		desc.Windowed = true;
 | 
			
		||||
 | 
			
		||||
		// Creation Flags
 | 
			
		||||
 | 
			
		||||
@ -340,7 +340,7 @@ typedef void (APIENTRY* DEBUGPROC)(GLenum source,
 | 
			
		||||
	const void* userParam);
 | 
			
		||||
 | 
			
		||||
// shorthand to our internal state
 | 
			
		||||
#define RENDERER ((Renderer_OpenGL*)Internal::renderer)
 | 
			
		||||
#define RENDERER ((Renderer_OpenGL*)Internal::app_renderer())
 | 
			
		||||
 | 
			
		||||
namespace Blah
 | 
			
		||||
{
 | 
			
		||||
@ -1176,16 +1176,16 @@ namespace Blah
 | 
			
		||||
	bool Renderer_OpenGL::init()
 | 
			
		||||
	{
 | 
			
		||||
		// create gl context
 | 
			
		||||
		context = Internal::platform->gl_context_create();
 | 
			
		||||
		context = Platform::gl_context_create();
 | 
			
		||||
		if (context == nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			Log::error("Failed to create OpenGL Context");
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		Internal::platform->gl_context_make_current(context);
 | 
			
		||||
		Platform::gl_context_make_current(context);
 | 
			
		||||
 | 
			
		||||
		// 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
 | 
			
		||||
		#undef GL_FUNC
 | 
			
		||||
 | 
			
		||||
@ -1229,7 +1229,7 @@ namespace Blah
 | 
			
		||||
 | 
			
		||||
	void Renderer_OpenGL::shutdown()
 | 
			
		||||
	{
 | 
			
		||||
		Internal::platform->gl_context_destroy(context);
 | 
			
		||||
		Platform::gl_context_destroy(context);
 | 
			
		||||
		context = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user