Skip to content

Commit 8f9688b

Browse files
committed
Code cleanup and implement review suggestions
1 parent bfd9bc4 commit 8f9688b

File tree

3 files changed

+46
-37
lines changed

3 files changed

+46
-37
lines changed

library/include/modules/DFSDL.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ namespace DFHack
8383
DFHACK_EXPORT bool getClipboardTextCp437Multiline(std::vector<std::string> * lines);
8484
DFHACK_EXPORT bool setClipboardTextCp437Multiline(std::string text);
8585

86-
// Queue a cb to be run on the render thread, with optional userdata
87-
DFHACK_EXPORT void runOnRenderThread(std::function<void(void*)> cb, void* userdata);
86+
// Queue a cb to be run on the render thread
87+
DFHACK_EXPORT void runOnRenderThread(std::function<void()> cb);
8888
DFHACK_EXPORT void runRenderThreadCallbacks();
8989
}

library/modules/DFSDL.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,11 @@ DFHACK_EXPORT bool DFHack::setClipboardTextCp437Multiline(string text) {
290290
// Queue to run callbacks on the render thread.
291291
// Semantics loosely based on SDL3's SDL_RunOnMainThread
292292
static std::recursive_mutex render_cb_lock;
293-
static std::vector<std::pair<std::function<void(void*)>, void*>> render_cb_queue;
293+
static std::vector<std::function<void()>> render_cb_queue;
294294

295-
DFHACK_EXPORT void DFHack::runOnRenderThread(std::function<void (void *)> cb, void *userdata) {
295+
DFHACK_EXPORT void DFHack::runOnRenderThread(std::function<void()> cb) {
296296
std::lock_guard<std::recursive_mutex> l(render_cb_lock);
297-
render_cb_queue.push_back({std::move(cb), userdata});
297+
render_cb_queue.push_back(std::move(cb));
298298
}
299299

300300
DFHACK_EXPORT void DFHack::runRenderThreadCallbacks() {
@@ -304,7 +304,7 @@ DFHACK_EXPORT void DFHack::runRenderThreadCallbacks() {
304304
std::swap(local_queue, render_cb_queue);
305305
}
306306
for (auto& cb : local_queue) {
307-
std::get<0>(cb)(std::get<1>(cb));
307+
cb();
308308
}
309309
local_queue.clear();
310310
}

plugins/edgescroll.cpp

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
#include "ColorText.h"
2-
#include "PluginManager.h"
32
#include "MemAccess.h"
3+
#include "PluginManager.h"
44

5-
#include "df/world_generatorst.h"
65
#include "modules/Gui.h"
76
#include "modules/DFSDL.h"
87

@@ -16,6 +15,7 @@
1615
#include "df/viewscreen_new_regionst.h"
1716
#include "df/world.h"
1817
#include "df/world_data.h"
18+
#include "df/world_generatorst.h"
1919

2020
#include <cstdint>
2121
#include <optional>
@@ -53,33 +53,37 @@ DFhackCExport command_result plugin_shutdown([[maybe_unused]] color_ostream &out
5353
return CR_OK;
5454
}
5555

56-
static std::atomic_bool request_queued = false;
56+
static std::atomic_bool callback_queued = false;
5757

5858
struct scroll_state {
5959
int8_t xdiff;
6060
int8_t ydiff;
6161
};
6262

63-
static const scroll_state state_default(0, 0);
63+
static scroll_state state;
64+
static scroll_state queued;
6465

65-
static scroll_state state = state_default;
66-
static scroll_state queued = state_default;
67-
68-
static void render_thread_cb([[maybe_unused]] void* _) {
69-
queued = state_default;
66+
static void render_thread_cb() {
67+
queued = {0};
7068
// Ignore the mouse if outside the window
7169
if (!enabler->mouse_focus) {
72-
request_queued.store(false);
70+
callback_queued.store(false);
7371
return;
7472
}
7573

76-
// Determine window border location in window coordinates
74+
// Calculate the render rect in window coordinates
7775
auto* renderer = virtual_cast<df::renderer_2d>(enabler->renderer);
78-
int origin_x, origin_y = 0;
76+
int origin_x, origin_y;
7977
int end_x, end_y;
80-
DFSDL::DFSDL_RenderLogicalToWindow((SDL_Renderer*)renderer->sdl_renderer, renderer->origin_x, renderer->origin_y, &origin_x, &origin_y);
81-
DFSDL::DFSDL_RenderLogicalToWindow((SDL_Renderer*)renderer->sdl_renderer, renderer->cur_w - renderer->origin_x, renderer->cur_h - renderer->origin_y, &end_x, &end_y);
82-
78+
DFSDL::DFSDL_RenderLogicalToWindow(
79+
(SDL_Renderer*)renderer->sdl_renderer, (float)renderer->origin_x,
80+
(float)renderer->origin_y, &origin_x, &origin_y);
81+
DFSDL::DFSDL_RenderLogicalToWindow(
82+
(SDL_Renderer*)renderer->sdl_renderer,
83+
(float)renderer->cur_w - (float)renderer->origin_x,
84+
(float)(renderer->cur_h - renderer->origin_y), &end_x, &end_y);
85+
86+
// Get the mouse location in window coordinates
8387
int mx, my;
8488
DFSDL::DFSDL_GetMouseState(&mx, &my);
8589

@@ -94,26 +98,28 @@ static void render_thread_cb([[maybe_unused]] void* _) {
9498
queued.ydiff++;
9599
}
96100

97-
request_queued.store(false);
101+
callback_queued.store(false);
98102
}
99103

100104
static bool update_mouse_pos() {
101-
if (request_queued.load())
102-
return false; // No new inputs, and a request for more is already placed
105+
if (callback_queued.load())
106+
return false; // Queued callback not complete, check back later
103107

108+
// Queued callback complete, save the results and enqueue again
104109
state = queued;
105-
queued = state_default;
106-
DFHack::runOnRenderThread(render_thread_cb, nullptr);
107-
request_queued.store(true);
110+
queued = {0};
111+
DFHack::runOnRenderThread(render_thread_cb);
112+
callback_queued.store(true);
108113
return true;
109114
}
110115

111-
// Scrolling behavior
116+
// Apply scroll whilst maintaining boundaries
112117
template<typename T>
113118
static void apply_scroll(T* out, T diff, T min, T max) {
114119
*out = std::min(std::max(*out + diff, min), max);
115120
}
116121

122+
// Scroll main fortress/adventure world views
117123
static void scroll_dwarfmode(int xdiff, int ydiff) {
118124
using df::global::window_x;
119125
using df::global::window_y;
@@ -137,7 +143,7 @@ static void scroll_dwarfmode(int xdiff, int ydiff) {
137143
}
138144

139145
template<typename T>
140-
static void scroll_world(T* screen, int xdiff, int ydiff) {
146+
static void scroll_world_internal(T* screen, int xdiff, int ydiff) {
141147
if constexpr(std::is_same_v<T, df::viewscreen_choose_start_sitest>) {
142148
if (screen->zoomed_in) {
143149
int max_x = (world->world_data->world_width * 16)-1;
@@ -169,6 +175,9 @@ using world_map = std::variant<df::viewscreen_choose_start_sitest*, df::viewscre
169175
static std::optional<world_map> get_map() {
170176
df::viewscreen* screen = Gui::getCurViewscreen(true);
171177
screen = Gui::getDFViewscreen(true, screen); // Get the first non-dfhack viewscreen
178+
if(!screen)
179+
return {};
180+
172181
if (auto start_site = virtual_cast<df::viewscreen_choose_start_sitest>(screen))
173182
return start_site;
174183
if (auto world_map = virtual_cast<df::viewscreen_worldst>(screen))
@@ -183,9 +192,9 @@ static std::optional<world_map> get_map() {
183192

184193
static void scroll_world(world_map screen, int xdiff, int ydiff) {
185194
const auto visitor = overloads {
186-
[xdiff, ydiff](df::viewscreen_choose_start_sitest* s) {scroll_world(s, xdiff, ydiff);},
187-
[xdiff, ydiff](df::viewscreen_worldst* s) {scroll_world(s, xdiff, ydiff);},
188-
[xdiff, ydiff](df::viewscreen_new_regionst* s) {scroll_world(s, xdiff, ydiff);},
195+
[xdiff, ydiff](df::viewscreen_choose_start_sitest* s) {scroll_world_internal(s, xdiff, ydiff);},
196+
[xdiff, ydiff](df::viewscreen_worldst* s) {scroll_world_internal(s, xdiff, ydiff);},
197+
[xdiff, ydiff](df::viewscreen_new_regionst* s) {scroll_world_internal(s, xdiff, ydiff);},
189198
};
190199
std::visit(visitor, screen);
191200
}
@@ -198,18 +207,18 @@ DFhackCExport command_result plugin_onupdate(color_ostream &out) {
198207
if (now < last_action + cooldown_ms)
199208
return CR_OK;
200209

201-
// Update mouse_x/y to values from the render thread
210+
// Update mouse_x/y from values read in render thread callback
202211
if (!update_mouse_pos())
203-
return CR_OK;
212+
return CR_OK; // No new input to process
213+
214+
if (state.xdiff == 0 && state.ydiff == 0)
215+
return CR_OK; // No work to do
204216

205217
// Ensure either a map viewscreen or the main viewport are visible
206218
auto worldmap = get_map();
207219
if (!worldmap.has_value() && (!gps->main_viewport || !gps->main_viewport->flag.bits.active))
208220
return CR_OK;
209221

210-
if (state.xdiff == 0 && state.ydiff == 0)
211-
return CR_OK; // No work to do
212-
213222
// Dispatch scrolling to active scrollables
214223
if (worldmap.has_value())
215224
scroll_world(worldmap.value(), state.xdiff, state.ydiff);

0 commit comments

Comments
 (0)