mirror of
https://github.com/Mr-Wiseguy/Zelda64Recomp.git
synced 2024-11-29 08:04:18 +01:00
Delayed game start, made UI hot reload include all files, passed input
events to UI
This commit is contained in:
parent
346e298eb1
commit
91611c9c33
9
include/recomp_ui.h
Normal file
9
include/recomp_ui.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef __RECOMP_UI__
|
||||||
|
#define __RECOMP_UI__
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
void queue_event(const SDL_Event& event);
|
||||||
|
bool try_deque_event(SDL_Event& out);
|
||||||
|
|
||||||
|
#endif
|
@ -95,6 +95,8 @@ extern "C" void osViSetEvent(RDRAM_ARG PTR(OSMesgQueue) mq_, OSMesg msg, u32 ret
|
|||||||
|
|
||||||
uint64_t total_vis = 0;
|
uint64_t total_vis = 0;
|
||||||
|
|
||||||
|
void set_dummy_vi();
|
||||||
|
|
||||||
void vi_thread_func() {
|
void vi_thread_func() {
|
||||||
Multilibultra::set_native_thread_name("VI Thread");
|
Multilibultra::set_native_thread_name("VI Thread");
|
||||||
// This thread should be prioritized over every other thread in the application, as it's what allows
|
// This thread should be prioritized over every other thread in the application, as it's what allows
|
||||||
@ -131,12 +133,25 @@ void vi_thread_func() {
|
|||||||
if (remaining_retraces == 0) {
|
if (remaining_retraces == 0) {
|
||||||
remaining_retraces = events_context.vi.retrace_count;
|
remaining_retraces = events_context.vi.retrace_count;
|
||||||
|
|
||||||
|
if (Multilibultra::is_game_started()) {
|
||||||
if (events_context.vi.mq != NULLPTR) {
|
if (events_context.vi.mq != NULLPTR) {
|
||||||
if (osSendMesg(PASS_RDRAM events_context.vi.mq, events_context.vi.msg, OS_MESG_NOBLOCK) == -1) {
|
if (osSendMesg(PASS_RDRAM events_context.vi.mq, events_context.vi.msg, OS_MESG_NOBLOCK) == -1) {
|
||||||
//printf("Game skipped a VI frame!\n");
|
//printf("Game skipped a VI frame!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
set_dummy_vi();
|
||||||
|
static bool swap = false;
|
||||||
|
uint32_t vi_origin = 0x400 + 0x280; // Skip initial RDRAM contents and add the usual origin offset
|
||||||
|
// Offset by one FB every other frame so RT64 continues drawing
|
||||||
|
if (swap) {
|
||||||
|
vi_origin += 0x25800;
|
||||||
|
}
|
||||||
|
osViSwapBuffer(rdram, vi_origin);
|
||||||
|
swap = !swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (events_context.ai.mq != NULLPTR) {
|
if (events_context.ai.mq != NULLPTR) {
|
||||||
if (osSendMesg(PASS_RDRAM events_context.ai.mq, events_context.ai.msg, OS_MESG_NOBLOCK) == -1) {
|
if (osSendMesg(PASS_RDRAM events_context.ai.mq, events_context.ai.msg, OS_MESG_NOBLOCK) == -1) {
|
||||||
//printf("Game skipped a AI frame!\n");
|
//printf("Game skipped a AI frame!\n");
|
||||||
@ -238,7 +253,6 @@ void task_thread_func(uint8_t* rdram, uint8_t* rom, std::atomic_flag* thread_rea
|
|||||||
|
|
||||||
void gfx_thread_func(uint8_t* rdram, uint8_t* rom, std::atomic_flag* thread_ready, Multilibultra::WindowHandle window_handle) {
|
void gfx_thread_func(uint8_t* rdram, uint8_t* rom, std::atomic_flag* thread_ready, Multilibultra::WindowHandle window_handle) {
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
Multilibultra::gfx_callbacks_t::gfx_data_t gfx_data{};
|
|
||||||
|
|
||||||
Multilibultra::set_native_thread_name("Gfx Thread");
|
Multilibultra::set_native_thread_name("Gfx Thread");
|
||||||
Multilibultra::set_native_thread_priority(Multilibultra::ThreadPriority::Normal);
|
Multilibultra::set_native_thread_priority(Multilibultra::ThreadPriority::Normal);
|
||||||
@ -291,6 +305,22 @@ uint32_t hstart = 0;
|
|||||||
uint32_t vi_origin_offset = 320 * sizeof(uint16_t);
|
uint32_t vi_origin_offset = 320 * sizeof(uint16_t);
|
||||||
bool vi_black = false;
|
bool vi_black = false;
|
||||||
|
|
||||||
|
void set_dummy_vi() {
|
||||||
|
VI_STATUS_REG = 0x311E;
|
||||||
|
VI_WIDTH_REG = 0x140;
|
||||||
|
VI_V_SYNC_REG = 0x20D;
|
||||||
|
VI_H_SYNC_REG = 0xC15;
|
||||||
|
VI_LEAP_REG = 0x0C150C15;
|
||||||
|
hstart = 0x006C02EC;
|
||||||
|
VI_X_SCALE_REG = 0x200;
|
||||||
|
VI_V_CURRENT_LINE_REG = 0x0;
|
||||||
|
vi_origin_offset = 0x280;
|
||||||
|
VI_Y_SCALE_REG = 0x400;
|
||||||
|
VI_V_START_REG = 0x2501FF;
|
||||||
|
VI_V_BURST_REG = 0xE0204;
|
||||||
|
VI_INTR_REG = 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void osViSwapBuffer(RDRAM_ARG PTR(void) frameBufPtr) {
|
extern "C" void osViSwapBuffer(RDRAM_ARG PTR(void) frameBufPtr) {
|
||||||
if (vi_black) {
|
if (vi_black) {
|
||||||
VI_H_START_REG = 0;
|
VI_H_START_REG = 0;
|
||||||
|
@ -123,14 +123,8 @@ struct gfx_callbacks_t {
|
|||||||
update_gfx_t* update_gfx;
|
update_gfx_t* update_gfx;
|
||||||
};
|
};
|
||||||
void start(WindowHandle window_handle, const audio_callbacks_t& audio_callbacks, const input_callbacks_t& input_callbacks, const gfx_callbacks_t& gfx_callbacks);
|
void start(WindowHandle window_handle, const audio_callbacks_t& audio_callbacks, const input_callbacks_t& input_callbacks, const gfx_callbacks_t& gfx_callbacks);
|
||||||
|
void start_game(int game);
|
||||||
class preemption_guard {
|
bool is_game_started();
|
||||||
public:
|
|
||||||
preemption_guard();
|
|
||||||
~preemption_guard();
|
|
||||||
private:
|
|
||||||
std::lock_guard<std::mutex> lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Multilibultra
|
} // namespace Multilibultra
|
||||||
|
|
||||||
|
@ -258,16 +258,6 @@ void enable_preemption() {
|
|||||||
#pragma warning( pop )
|
#pragma warning( pop )
|
||||||
}
|
}
|
||||||
|
|
||||||
// lock's constructor is called first, so can_preempt is set after locking
|
|
||||||
preemption_guard::preemption_guard() : lock{scheduler_context.premption_mutex} {
|
|
||||||
scheduler_context.can_preempt = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// lock's destructor is called last, so can_preempt is set before unlocking
|
|
||||||
preemption_guard::~preemption_guard() {
|
|
||||||
scheduler_context.can_preempt = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void notify_scheduler() {
|
void notify_scheduler() {
|
||||||
std::lock_guard lock{scheduler_context.mutex};
|
std::lock_guard lock{scheduler_context.mutex};
|
||||||
scheduler_context.notify_count.fetch_add(1);
|
scheduler_context.notify_count.fetch_add(1);
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "SDL2/SDL_syswm.h"
|
#include "SDL2/SDL_syswm.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "recomp_ui.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@ -138,6 +140,9 @@ int sdl_event_filter(void* userdata, SDL_Event* event) {
|
|||||||
case SDL_EventType::SDL_QUIT:
|
case SDL_EventType::SDL_QUIT:
|
||||||
std::quick_exit(EXIT_SUCCESS);
|
std::quick_exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
queue_event(*event);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -153,7 +158,7 @@ Multilibultra::gfx_callbacks_t::gfx_data_t create_gfx() {
|
|||||||
SDL_Window* window;
|
SDL_Window* window;
|
||||||
|
|
||||||
Multilibultra::WindowHandle create_window(Multilibultra::gfx_callbacks_t::gfx_data_t) {
|
Multilibultra::WindowHandle create_window(Multilibultra::gfx_callbacks_t::gfx_data_t) {
|
||||||
window = SDL_CreateWindow("Majora's Mask", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE);
|
window = SDL_CreateWindow("Recomp", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_RESIZABLE);
|
||||||
|
|
||||||
if (window == nullptr) {
|
if (window == nullptr) {
|
||||||
exit_error("Failed to create window: %s\n", SDL_GetError());
|
exit_error("Failed to create window: %s\n", SDL_GetError());
|
||||||
|
@ -183,11 +183,16 @@ EXPORT extern "C" void init() {
|
|||||||
MEM_W(osMemSize, 0) = 8 * 1024 * 1024; // 8MB
|
MEM_W(osMemSize, 0) = 8 * 1024 * 1024; // 8MB
|
||||||
}
|
}
|
||||||
|
|
||||||
// LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
std::atomic_int game_started = -1;
|
||||||
// return DefWindowProc(hwnd, uMsg, wParam, lParam);
|
|
||||||
// }
|
|
||||||
|
|
||||||
static Multilibultra::gfx_callbacks_t gfx_callbacks;
|
void Multilibultra::start_game(int game) {
|
||||||
|
game_started.store(game);
|
||||||
|
game_started.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Multilibultra::is_game_started() {
|
||||||
|
return game_started.load() != -1;
|
||||||
|
}
|
||||||
|
|
||||||
void set_audio_callbacks(const Multilibultra::audio_callbacks_t& callbacks);
|
void set_audio_callbacks(const Multilibultra::audio_callbacks_t& callbacks);
|
||||||
void set_input_callbacks(const Multilibultra::input_callbacks_t& callback);
|
void set_input_callbacks(const Multilibultra::input_callbacks_t& callback);
|
||||||
@ -220,7 +225,13 @@ void Multilibultra::start(WindowHandle window_handle, const audio_callbacks_t& a
|
|||||||
|
|
||||||
Multilibultra::preinit(rdram_buffer.get(), rom.get(), window_handle);
|
Multilibultra::preinit(rdram_buffer.get(), rom.get(), window_handle);
|
||||||
|
|
||||||
|
game_started.wait(-1);
|
||||||
|
|
||||||
|
switch (game_started.load()) {
|
||||||
|
case 0:
|
||||||
recomp_entrypoint(rdram_buffer.get(), &context);
|
recomp_entrypoint(rdram_buffer.get(), &context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
debug_printf("[Recomp] Quitting\n");
|
debug_printf("[Recomp] Quitting\n");
|
||||||
}, window_handle};
|
}, window_handle};
|
||||||
@ -229,7 +240,7 @@ void Multilibultra::start(WindowHandle window_handle, const audio_callbacks_t& a
|
|||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
std::this_thread::sleep_for(1ms);
|
std::this_thread::sleep_for(1ms);
|
||||||
if (gfx_callbacks.update_gfx != nullptr) {
|
if (gfx_callbacks.update_gfx != nullptr) {
|
||||||
gfx_callbacks.update_gfx(nullptr);
|
gfx_callbacks.update_gfx(gfx_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
74
src/ui.cpp
74
src/ui.cpp
@ -5,6 +5,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
#include "concurrentqueue.h"
|
||||||
|
|
||||||
#include "rt64_layer.h"
|
#include "rt64_layer.h"
|
||||||
#include "rt64_render_hooks.h"
|
#include "rt64_render_hooks.h"
|
||||||
#include "rt64_render_interface_builders.h"
|
#include "rt64_render_interface_builders.h"
|
||||||
@ -116,6 +118,8 @@ class RmlRenderInterface_RT64 : public Rml::RenderInterface {
|
|||||||
int scissor_y_ = 0;
|
int scissor_y_ = 0;
|
||||||
int scissor_width_ = 0;
|
int scissor_width_ = 0;
|
||||||
int scissor_height_ = 0;
|
int scissor_height_ = 0;
|
||||||
|
int window_width_ = 0;
|
||||||
|
int window_height_ = 0;
|
||||||
Rml::Matrix4f projection_mtx_ = Rml::Matrix4f::Identity();
|
Rml::Matrix4f projection_mtx_ = Rml::Matrix4f::Identity();
|
||||||
Rml::Matrix4f transform_ = Rml::Matrix4f::Identity();
|
Rml::Matrix4f transform_ = Rml::Matrix4f::Identity();
|
||||||
Rml::Matrix4f mvp_ = Rml::Matrix4f::Identity();
|
Rml::Matrix4f mvp_ = Rml::Matrix4f::Identity();
|
||||||
@ -274,11 +278,16 @@ public:
|
|||||||
uint32_t total_bytes = vert_size_bytes + index_size_bytes;
|
uint32_t total_bytes = vert_size_bytes + index_size_bytes;
|
||||||
uint32_t index_bytes_start = vert_size_bytes;
|
uint32_t index_bytes_start = vert_size_bytes;
|
||||||
|
|
||||||
if (textures_.size() == 0) {
|
|
||||||
|
if (!textures_.contains(texture)) {
|
||||||
|
if (texture == 0) {
|
||||||
// Create a 1x1 pixel white texture as the first handle
|
// Create a 1x1 pixel white texture as the first handle
|
||||||
Rml::byte white_pixel[] = { 255, 255, 255, 255 };
|
Rml::byte white_pixel[] = { 255, 255, 255, 255 };
|
||||||
Rml::TextureHandle dummy_handle;
|
create_texture(0, white_pixel, Rml::Vector2i{ 1,1 });
|
||||||
GenerateTexture(dummy_handle, white_pixel, Rml::Vector2i{ 1,1 });
|
}
|
||||||
|
else {
|
||||||
|
assert(false && "Rendered without texture!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t upload_buffer_offset = allocate_upload_data(total_bytes);
|
uint32_t upload_buffer_offset = allocate_upload_data(total_bytes);
|
||||||
@ -325,17 +334,19 @@ public:
|
|||||||
};
|
};
|
||||||
list_->barriers(usage_barriers, uint32_t(std::size(usage_barriers)));
|
list_->barriers(usage_barriers, uint32_t(std::size(usage_barriers)));
|
||||||
|
|
||||||
// TODO set scissor, viewport
|
list_->setViewports(RT64::RenderViewport{ 0, 0, float(window_width_), float(window_height_) });
|
||||||
//if (scissor_enabled_) {
|
if (scissor_enabled_) {
|
||||||
list_->setViewports(RT64::RenderViewport{ 0, 0, float(scissor_width_), float(scissor_height_) });
|
list_->setScissors(RT64::RenderRect{ scissor_x_, scissor_y_, scissor_width_, scissor_height_ });
|
||||||
list_->setScissors(RT64::RenderRect{ 0, 0, scissor_width_, scissor_height_ });
|
}
|
||||||
//}
|
else {
|
||||||
|
list_->setScissors(RT64::RenderRect{ 0, 0, window_width_, window_height_ });
|
||||||
|
}
|
||||||
|
|
||||||
RT64::RenderIndexBufferView index_view{index_buffer_->at(0), index_size_bytes, RT64::RenderFormat::R32_UINT};
|
RT64::RenderIndexBufferView index_view{index_buffer_->at(0), index_size_bytes, RT64::RenderFormat::R32_UINT};
|
||||||
list_->setIndexBuffer(&index_view);
|
list_->setIndexBuffer(&index_view);
|
||||||
RT64::RenderVertexBufferView vertex_view{vertex_buffer_->at(0), vert_size_bytes};
|
RT64::RenderVertexBufferView vertex_view{vertex_buffer_->at(0), vert_size_bytes};
|
||||||
list_->setVertexBuffers(0, &vertex_view, 1, &vertex_slot_);
|
list_->setVertexBuffers(0, &vertex_view, 1, &vertex_slot_);
|
||||||
list_->setGraphicsDescriptorHeap(textures_[texture].heap.get());
|
list_->setGraphicsDescriptorHeap(textures_.at(texture).heap.get());
|
||||||
|
|
||||||
RmlPushConstants constants{
|
RmlPushConstants constants{
|
||||||
.transform = mvp_,
|
.transform = mvp_,
|
||||||
@ -420,6 +431,7 @@ public:
|
|||||||
texture_dimensions.x = size_x;
|
texture_dimensions.x = size_x;
|
||||||
texture_dimensions.y = size_y;
|
texture_dimensions.y = size_y;
|
||||||
|
|
||||||
|
texture_handle = texture_count_++;
|
||||||
create_texture(texture_handle, reinterpret_cast<const Rml::byte*>(file_data.data() + 18), texture_dimensions, true);
|
create_texture(texture_handle, reinterpret_cast<const Rml::byte*>(file_data.data() + 18), texture_dimensions, true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -429,11 +441,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override {
|
bool GenerateTexture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions) override {
|
||||||
|
texture_handle = texture_count_++;
|
||||||
return create_texture(texture_handle, source, source_dimensions);
|
return create_texture(texture_handle, source, source_dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool create_texture(Rml::TextureHandle& texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions, bool flip_y = false) {
|
bool create_texture(Rml::TextureHandle texture_handle, const Rml::byte* source, const Rml::Vector2i& source_dimensions, bool flip_y = false) {
|
||||||
texture_handle = texture_count_++;
|
|
||||||
std::unique_ptr<RT64::RenderTexture> texture =
|
std::unique_ptr<RT64::RenderTexture> texture =
|
||||||
render_context_->device->createTexture(RT64::RenderTextureDesc::Texture2D(source_dimensions.x, source_dimensions.y, 1, RmlTextureFormat));
|
render_context_->device->createTexture(RT64::RenderTextureDesc::Texture2D(source_dimensions.x, source_dimensions.y, 1, RmlTextureFormat));
|
||||||
|
|
||||||
@ -524,6 +536,9 @@ public:
|
|||||||
list_->setPipeline(pipeline_.get());
|
list_->setPipeline(pipeline_.get());
|
||||||
list_->setGraphicsPipelineLayout(layout_.get());
|
list_->setGraphicsPipelineLayout(layout_.get());
|
||||||
|
|
||||||
|
window_width_ = image_width;
|
||||||
|
window_height_ = image_height;
|
||||||
|
|
||||||
projection_mtx_ = Rml::Matrix4f::ProjectOrtho(0.0f, static_cast<float>(image_width), static_cast<float>(image_height), 0.0f, -10000, 10000);
|
projection_mtx_ = Rml::Matrix4f::ProjectOrtho(0.0f, static_cast<float>(image_width), static_cast<float>(image_height), 0.0f, -10000, 10000);
|
||||||
recalculate_mvp();
|
recalculate_mvp();
|
||||||
|
|
||||||
@ -565,6 +580,10 @@ extern SDL_Window* window;
|
|||||||
|
|
||||||
void load_document() {
|
void load_document() {
|
||||||
if (UIContext.render.document) {
|
if (UIContext.render.document) {
|
||||||
|
UIContext.render.document->ReloadStyleSheet();
|
||||||
|
Rml::ReleaseTextures();
|
||||||
|
Rml::ReleaseMemoryPools();
|
||||||
|
UIContext.render.document->Hide();
|
||||||
UIContext.render.document->Close();
|
UIContext.render.document->Close();
|
||||||
// Documents are owned by RmlUi, so we don't have anything to free here.
|
// Documents are owned by RmlUi, so we don't have anything to free here.
|
||||||
UIContext.render.document = nullptr;
|
UIContext.render.document = nullptr;
|
||||||
@ -620,15 +639,17 @@ void init_hook(RT64::RenderInterface* interface, RT64::RenderDevice* device) {
|
|||||||
load_document();
|
load_document();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moodycamel::ConcurrentQueue<SDL_Event> ui_event_queue{};
|
||||||
|
|
||||||
|
void queue_event(const SDL_Event& event) {
|
||||||
|
ui_event_queue.enqueue(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool try_deque_event(SDL_Event& out) {
|
||||||
|
return ui_event_queue.try_dequeue(out);
|
||||||
|
}
|
||||||
|
|
||||||
void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_chain_texture) {
|
void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_chain_texture) {
|
||||||
command_list->barriers(RT64::RenderTextureBarrier::Transition(swap_chain_texture, RT64::RenderTextureState::RENDER_TARGET));
|
|
||||||
// command_list->setGraphicsPipelineLayout(UIContext.render.layout.get());
|
|
||||||
// command_list->setPipeline(UIContext.render.pipeline.get());
|
|
||||||
// command_list->setIndexBuffer(&UIContext.render.index_buffer_view);
|
|
||||||
// command_list->drawIndexedInstanced(6, 1, 0, 0, 0);
|
|
||||||
|
|
||||||
// TODO process SDL events
|
|
||||||
|
|
||||||
int num_keys;
|
int num_keys;
|
||||||
const Uint8* key_state = SDL_GetKeyboardState(&num_keys);
|
const Uint8* key_state = SDL_GetKeyboardState(&num_keys);
|
||||||
|
|
||||||
@ -637,7 +658,7 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_
|
|||||||
bool reload_sheets = is_reload_held && !was_reload_held;
|
bool reload_sheets = is_reload_held && !was_reload_held;
|
||||||
was_reload_held = is_reload_held;
|
was_reload_held = is_reload_held;
|
||||||
|
|
||||||
static bool menu_open = false;
|
static bool menu_open = true;
|
||||||
static bool was_toggle_menu_held = false;
|
static bool was_toggle_menu_held = false;
|
||||||
bool is_toggle_menu_held = key_state[SDL_SCANCODE_M] != 0;
|
bool is_toggle_menu_held = key_state[SDL_SCANCODE_M] != 0;
|
||||||
if (is_toggle_menu_held && !was_toggle_menu_held) {
|
if (is_toggle_menu_held && !was_toggle_menu_held) {
|
||||||
@ -645,6 +666,19 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderTexture* swap_
|
|||||||
}
|
}
|
||||||
was_toggle_menu_held = is_toggle_menu_held;
|
was_toggle_menu_held = is_toggle_menu_held;
|
||||||
|
|
||||||
|
static bool was_start_game_held = false;
|
||||||
|
bool is_start_game_held = key_state[SDL_SCANCODE_SPACE] != 0;
|
||||||
|
if (is_start_game_held && !was_start_game_held) {
|
||||||
|
Multilibultra::start_game(0);
|
||||||
|
}
|
||||||
|
was_start_game_held = is_start_game_held;
|
||||||
|
|
||||||
|
SDL_Event cur_event{};
|
||||||
|
|
||||||
|
while (try_deque_event(cur_event)) {
|
||||||
|
RmlSDL::InputEventHandler(UIContext.rml.context, cur_event);
|
||||||
|
}
|
||||||
|
|
||||||
if (menu_open) {
|
if (menu_open) {
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL_GetWindowSizeInPixels(window, &width, &height);
|
SDL_GetWindowSizeInPixels(window, &width, &height);
|
||||||
|
Loading…
Reference in New Issue
Block a user