mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-21 20:54:43 -04:00
Merge remote-tracking branch 'refs/remotes/origin/main' into unhackify-widescreen
# Conflicts: # src/m_Do/m_Do_main.cpp
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include "f_op/f_op_camera_mng.h"
|
||||
#include "m_Do/m_Do_graphic.h"
|
||||
|
||||
namespace {
|
||||
enum class Op : uint8_t {
|
||||
@@ -63,11 +64,9 @@ bool g_enabled = false;
|
||||
bool g_recording = false;
|
||||
bool g_interpolating = false;
|
||||
bool g_sync_presentation = false;
|
||||
uint32_t g_presentation_counter = 0;
|
||||
|
||||
float g_step = 0.0f;
|
||||
uint32_t g_pending_presentation_ui_ticks = 0;
|
||||
uint32_t g_current_presentation_ui_ticks = 0;
|
||||
bool g_ui_tick_pending = false;
|
||||
|
||||
Recording g_current_recording;
|
||||
Recording g_previous_recording;
|
||||
@@ -84,6 +83,7 @@ struct CameraSnapshot {
|
||||
f32 aspect{};
|
||||
f32 near_{};
|
||||
f32 far_{};
|
||||
bool wideZoom{};
|
||||
bool valid{};
|
||||
};
|
||||
|
||||
@@ -347,6 +347,9 @@ void begin_record() {
|
||||
return;
|
||||
} else {
|
||||
copy_view_to_snap(&s_cam_prev, cam->view);
|
||||
#if WIDESCREEN_SUPPORT
|
||||
s_cam_prev.wideZoom = s_cam_curr.valid ? s_cam_curr.wideZoom : false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,11 +369,6 @@ void interpolate(float step) {
|
||||
interpolate_branch(old_root, g_current_recording.root, g_step);
|
||||
}
|
||||
|
||||
void notify_presentation_frame() {
|
||||
ensure_initialized();
|
||||
++g_presentation_counter;
|
||||
}
|
||||
|
||||
void request_presentation_sync() {
|
||||
ensure_initialized();
|
||||
if (!g_enabled) {
|
||||
@@ -391,33 +389,14 @@ float get_interpolation_step() {
|
||||
return presentation_sync_active() ? 1.0f : g_step;
|
||||
}
|
||||
|
||||
void notify_sim_tick_complete() {
|
||||
void set_ui_tick_pending(bool value) {
|
||||
if (g_ui_tick_pending == value) { return; }
|
||||
g_ui_tick_pending = value;
|
||||
}
|
||||
|
||||
bool get_ui_tick_pending() {
|
||||
ensure_initialized();
|
||||
g_pending_presentation_ui_ticks++;
|
||||
}
|
||||
|
||||
uint32_t begin_presentation_ui_pass() {
|
||||
ensure_initialized();
|
||||
g_current_presentation_ui_ticks = g_pending_presentation_ui_ticks;
|
||||
g_pending_presentation_ui_ticks = 0;
|
||||
return g_current_presentation_ui_ticks;
|
||||
}
|
||||
|
||||
uint32_t get_presentation_ui_advance_ticks() {
|
||||
if (!s_initialized) {
|
||||
return 0;
|
||||
}
|
||||
if (!g_enabled) {
|
||||
return 1;
|
||||
}
|
||||
return g_current_presentation_ui_ticks;
|
||||
}
|
||||
|
||||
void end_presentation_ui_pass() {
|
||||
if (!s_initialized) {
|
||||
return;
|
||||
}
|
||||
g_current_presentation_ui_ticks = 0;
|
||||
return g_enabled ? g_ui_tick_pending : true;
|
||||
}
|
||||
|
||||
void open_child(const void* key, int32_t id) {
|
||||
@@ -502,6 +481,9 @@ void record_camera(::camera_process_class* cam, int camera_id) {
|
||||
return;
|
||||
}
|
||||
copy_view_to_snap(&s_cam_curr, cam->view);
|
||||
#if WIDESCREEN_SUPPORT
|
||||
s_cam_curr.wideZoom = mDoGph_gInf_c::isWideZoom();
|
||||
#endif
|
||||
}
|
||||
|
||||
void begin_presentation_camera() {
|
||||
@@ -545,6 +527,13 @@ void begin_presentation_camera() {
|
||||
view->near_ = s_cam_prev.near_ + (s_cam_curr.near_ - s_cam_prev.near_) * step;
|
||||
view->far_ = s_cam_prev.far_ + (s_cam_curr.far_ - s_cam_prev.far_) * step;
|
||||
|
||||
// FRAME INTERP TODO: It might be better if I rewired the game to not clear this flag until the next sim frame, but I don't care enough to right now
|
||||
#if WIDESCREEN_SUPPORT
|
||||
if (mDoGph_gInf_c::isWide() && !mDoGph_gInf_c::isWideZoom() && step >= 0.5f ? s_cam_curr.wideZoom : s_cam_prev.wideZoom) {
|
||||
mDoGph_gInf_c::onWideZoom();
|
||||
}
|
||||
#endif
|
||||
|
||||
// FRAME INTERP TODO: Largely copied from d_camera's camera_draw function from this point, got any better ideas?
|
||||
C_MTXPerspective(view->projMtx, view->fovy, view->aspect, view->near_, view->far_);
|
||||
mDoMtx_lookAt(view->viewMtx, &view->lookat.eye, &view->lookat.center, &view->lookat.up, view->bank);
|
||||
@@ -601,6 +590,10 @@ void begin_presentation_camera() {
|
||||
|
||||
mDoLib_clipper::setup(view->fovy, view->aspect, view->near_, far_);
|
||||
|
||||
#if WIDESCREEN_SUPPORT
|
||||
mDoGph_gInf_c::offWideZoom();
|
||||
#endif
|
||||
|
||||
s_presentation_depth = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "dusk/game_clock.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace dusk {
|
||||
namespace game_clock {
|
||||
|
||||
using clock = std::chrono::steady_clock;
|
||||
|
||||
bool s_initialized = false;
|
||||
clock::time_point s_previous_sample{};
|
||||
float s_sim_accumulator = 0.0f;
|
||||
|
||||
std::unordered_map<uintptr_t, clock::time_point> s_interval_last_sample;
|
||||
|
||||
void ensure_initialized() {
|
||||
if (s_initialized) {
|
||||
return;
|
||||
}
|
||||
s_previous_sample = clock::now();
|
||||
s_sim_accumulator = sim_pace();
|
||||
s_initialized = true;
|
||||
}
|
||||
|
||||
void reset_accumulator() {
|
||||
ensure_initialized();
|
||||
s_sim_accumulator = 0.0f;
|
||||
}
|
||||
|
||||
MainLoopPacer advance_main_loop() {
|
||||
ensure_initialized();
|
||||
|
||||
const clock::time_point now = clock::now();
|
||||
const float presentation_dt = std::chrono::duration<float>(now - s_previous_sample).count();
|
||||
s_previous_sample = now;
|
||||
|
||||
s_sim_accumulator += presentation_dt;
|
||||
|
||||
MainLoopPacer out{};
|
||||
out.presentation_dt_seconds = presentation_dt;
|
||||
|
||||
const bool should_interpolate = dusk::getSettings().game.enableFrameInterpolation && !dusk::getTransientSettings().skipFrameRateLimit;
|
||||
out.is_interpolating = should_interpolate;
|
||||
out.sim_pace = sim_pace();
|
||||
|
||||
if (!should_interpolate) {
|
||||
s_sim_accumulator = 0.0f;
|
||||
out.do_sim_tick = true;
|
||||
out.interpolation_step = 0.0f;
|
||||
return out;
|
||||
} else {
|
||||
out.do_sim_tick = s_sim_accumulator >= sim_pace();
|
||||
out.interpolation_step = out.do_sim_tick ? 0.0f : s_sim_accumulator / sim_pace();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
float consume_interval(const void* consumer) {
|
||||
ensure_initialized();
|
||||
const uintptr_t key = reinterpret_cast<uintptr_t>(consumer);
|
||||
const clock::time_point now = clock::now();
|
||||
|
||||
float dt = ui_initial_dt();
|
||||
const auto it = s_interval_last_sample.find(key);
|
||||
if (it != s_interval_last_sample.end()) {
|
||||
dt = std::chrono::duration<float>(now - it->second).count();
|
||||
dt = std::min(dt, ui_maximum_dt());
|
||||
}
|
||||
s_interval_last_sample[key] = now;
|
||||
return dt;
|
||||
}
|
||||
|
||||
} // namespace game_clock
|
||||
} // namespace dusk
|
||||
+3
-3
@@ -35,7 +35,7 @@ bool s_sensor_keep_alive = false;
|
||||
bool get_sensor_keep_alive() { return s_sensor_keep_alive; }
|
||||
void set_sensor_keep_alive(bool value) { s_sensor_keep_alive = value; }
|
||||
|
||||
bool queryGyroAimItemContext() {
|
||||
bool queryGyroAimContext() {
|
||||
if (!static_cast<bool>(dusk::getSettings().game.enableGyroAim)) {
|
||||
return false;
|
||||
}
|
||||
@@ -45,11 +45,11 @@ bool queryGyroAimItemContext() {
|
||||
return false;
|
||||
}
|
||||
|
||||
return link->checkGyroAimItemContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
|
||||
return link->checkGyroAimContext() && dComIfGp_checkCameraAttentionStatus(link->field_0x317c, 0x10);
|
||||
}
|
||||
|
||||
void read(float dt) {
|
||||
if (!s_sensor_keep_alive && !(dusk::getSettings().game.enableGyroAim && queryGyroAimItemContext())) {
|
||||
if (!s_sensor_keep_alive && !queryGyroAimContext()) {
|
||||
if (s_sensor_enabled) {
|
||||
PADSetSensorEnabled(PAD_CHAN0, PAD_SENSOR_GYRO, FALSE);
|
||||
s_sensor_enabled = false;
|
||||
|
||||
@@ -368,10 +368,16 @@ namespace dusk {
|
||||
m_menuTools.ShowStateShare();
|
||||
DuskDebugPad(); // temporary, remove later
|
||||
|
||||
// Only show cursor when menu or any windows are open
|
||||
if (showMenu || ImGui::GetIO().MetricsRenderWindows > 0) {
|
||||
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange;
|
||||
// Imgui will re-show cursor.
|
||||
// Hide mouse cursor if the F1 menu is not open and the cursor is idle for 3 seconds.
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (showMenu) {
|
||||
mouseHideTimer = 0.0f;
|
||||
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; // Imgui will re-show cursor.
|
||||
} else if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) {
|
||||
mouseHideTimer = 0.0f;
|
||||
ImGui::GetIO().ConfigFlags &= ~ImGuiConfigFlags_NoMouseCursorChange; // Imgui will re-show cursor.
|
||||
} else if (mouseHideTimer <= 3.0f) {
|
||||
mouseHideTimer += ImGui::GetIO().DeltaTime;
|
||||
} else {
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange;
|
||||
SDL_HideCursor();
|
||||
|
||||
@@ -38,6 +38,8 @@ private:
|
||||
remain(duration) {}
|
||||
};
|
||||
|
||||
float mouseHideTimer = 0.0f;
|
||||
|
||||
bool m_isHidden = true;
|
||||
bool m_isLaunchInitialized = false;
|
||||
bool m_touchTapActive = false;
|
||||
|
||||
@@ -65,6 +65,11 @@ namespace dusk {
|
||||
ImGui::SetTooltip("Skip the delay when writing to the Memory Card.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Hold B for Instant Text", getSettings().game.instantText);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Make text scroll immediately by holding B.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("No Climbing Miss Animation", getSettings().game.noMissClimbing);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Prevents Link from playing a struggle animation\n"
|
||||
@@ -144,8 +149,10 @@ namespace dusk {
|
||||
|
||||
config::ImGuiCheckbox("Gyro Aim", getSettings().game.enableGyroAim);
|
||||
if (ImGui::IsItemHovered()) {
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers while aiming the\n"
|
||||
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s), Ball and Chain, and Dominion Rod.");
|
||||
ImGui::SetTooltip("Enables the gyroscope on supported controllers\n"
|
||||
"while in look mode (C-Up) and while aiming the\n"
|
||||
"Slingshot, Gale Boomerang, Hero's Bow, Clawshot(s),\n"
|
||||
"Ball and Chain, and Dominion Rod.");
|
||||
}
|
||||
|
||||
config::ImGuiCheckbox("Gyro Rollgoal", getSettings().game.enableGyroRollgoal);
|
||||
|
||||
@@ -35,6 +35,7 @@ UserSettings g_userSettings = {
|
||||
.noMissClimbing {"game.noMissClimbing", false},
|
||||
.fastTears {"game.fastTears", false},
|
||||
.instantSaves {"game.instantSaves", false},
|
||||
.instantText {"game.instantText", false},
|
||||
.sunsSong {"game.sunsSong", false},
|
||||
|
||||
// Preferences
|
||||
@@ -121,6 +122,7 @@ void registerSettings() {
|
||||
Register(g_userSettings.game.fastClimbing);
|
||||
Register(g_userSettings.game.fastTears);
|
||||
Register(g_userSettings.game.instantSaves);
|
||||
Register(g_userSettings.game.instantText);
|
||||
Register(g_userSettings.game.sunsSong);
|
||||
Register(g_userSettings.game.enableMirrorMode);
|
||||
Register(g_userSettings.game.invertCameraXAxis);
|
||||
|
||||
Reference in New Issue
Block a user