Skip to content

Commit e51be42

Browse files
authored
Merge pull request #5670 from NicksWorld/feat/edgescroll
Add new plugin edgescroll to automate panning of game/region maps
2 parents 7f6f80c + cd825e0 commit e51be42

File tree

9 files changed

+306
-0
lines changed

9 files changed

+306
-0
lines changed

docs/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ Template for new versions:
5555
# Future
5656

5757
## New Tools
58+
- ``edgescroll``: Introduced plugin to pan the view automatically when the mouse reaches the screen border.
5859

5960
## New Features
6061

docs/plugins/edgescroll.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
edgescroll
2+
==========
3+
4+
.. dfhack-tool::
5+
:summary: Scroll the game world and region maps when the mouse reaches the window border.
6+
:tags: interface
7+
8+
Usage
9+
-----
10+
11+
::
12+
13+
enable edgescroll

library/Core.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2063,6 +2063,10 @@ bool Core::DFH_SDL_Event(SDL_Event* ev) {
20632063
return ret;
20642064
}
20652065

2066+
void Core::DFH_SDL_Loop() {
2067+
DFHack::runRenderThreadCallbacks();
2068+
}
2069+
20662070
bool Core::doSdlInputEvent(SDL_Event* ev)
20672071
{
20682072
// this should only ever be called from the render thread

library/Hooks.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ DFhackCExport void dfhooks_sdl_loop() {
6868
if (disabled)
6969
return;
7070
// TODO: wire this up to the new SDL-based console once it is merged
71+
DFHack::Core::getInstance().DFH_SDL_Loop();
7172
}
7273

7374
// called from the main thread for each utf-8 char read from the ncurses input

library/include/Core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ namespace DFHack
152152
friend void ::dfhooks_update();
153153
friend void ::dfhooks_prerender();
154154
friend bool ::dfhooks_sdl_event(SDL_Event* event);
155+
friend void ::dfhooks_sdl_loop();
155156
friend bool ::dfhooks_ncurses_key(int key);
156157
public:
157158
/// Get the single Core instance or make one.
@@ -263,6 +264,7 @@ namespace DFHack
263264
int Update (void);
264265
int Shutdown (void);
265266
bool DFH_SDL_Event(SDL_Event* event);
267+
void DFH_SDL_Loop();
266268
bool ncurses_wgetch(int in, int & out);
267269
bool DFH_ncurses_key(int key);
268270

library/include/modules/DFSDL.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
#include "Export.h"
44
#include "ColorText.h"
55

6+
#include <cstdint>
7+
#include <functional>
68
#include <vector>
79

810
struct SDL_Surface;
911
struct SDL_Rect;
12+
struct SDL_Renderer;
1013
struct SDL_PixelFormat;
1114
struct SDL_Window;
1215
union SDL_Event;
@@ -55,6 +58,10 @@ namespace DFHack::DFSDL
5558
DFHACK_EXPORT SDL_Surface* DFSDL_CreateRGBSurfaceWithFormat(uint32_t flags, int width, int height, int depth, uint32_t format);
5659
DFHACK_EXPORT int DFSDL_ShowSimpleMessageBox(uint32_t flags, const char* title, const char* message, SDL_Window* window);
5760

61+
DFHACK_EXPORT uint32_t DFSDL_GetMouseState(int* x, int* y);
62+
DFHACK_EXPORT void DFSDL_RenderWindowToLogical(SDL_Renderer* renderer, int windowX, int windowY, float* logicalX, float* logicalY);
63+
DFHACK_EXPORT void DFSDL_RenderLogicalToWindow(SDL_Renderer* renderer, float logicalX, float logicalY, int* windowX, int* windowY);
64+
5865
// submitted and returned text is UTF-8
5966
// see wrapper functions below for cp-437 variants
6067
DFHACK_EXPORT char* DFSDL_GetClipboardText();
@@ -76,4 +83,7 @@ namespace DFHack
7683
DFHACK_EXPORT bool getClipboardTextCp437Multiline(std::vector<std::string> * lines);
7784
DFHACK_EXPORT bool setClipboardTextCp437Multiline(std::string text);
7885

86+
// Queue a cb to be run on the render thread
87+
DFHACK_EXPORT void runOnRenderThread(std::function<void()> cb);
88+
DFHACK_EXPORT void runRenderThreadCallbacks();
7989
}

library/modules/DFSDL.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include <SDL_stdinc.h>
1010

11+
#include <vector>
12+
1113
#ifdef WIN32
1214
# include <regex>
1315
#endif
@@ -61,6 +63,9 @@ SDL_Surface* (*g_SDL_CreateRGBSurfaceWithFormat)(uint32_t flags, int width, int
6163
int (*g_SDL_ShowSimpleMessageBox)(uint32_t flags, const char *title, const char *message, SDL_Window *window) = nullptr;
6264
char* (*g_SDL_GetPrefPath)(const char* org, const char* app) = nullptr;
6365
char* (*g_SDL_GetBasePath)() = nullptr;
66+
uint32_t (*g_SDL_GetMouseState)(int* x, int* y) = nullptr;
67+
void (*g_SDL_RenderWindowToLogical)(SDL_Renderer* renderer, int windowX, int windowY, float* logicalX, float* logicalY);
68+
void (*g_SDL_RenderLogicalToWindow)(SDL_Renderer* renderer, float logicalX, float logicalY, int* windowX, int* windowY);
6469

6570
bool DFSDL::init(color_ostream &out) {
6671
for (auto &lib_str : SDL_LIBS) {
@@ -106,6 +111,9 @@ bool DFSDL::init(color_ostream &out) {
106111
bind(g_sdl_handle, SDL_ShowSimpleMessageBox);
107112
bind(g_sdl_handle, SDL_GetPrefPath);
108113
bind(g_sdl_handle, SDL_GetBasePath);
114+
bind(g_sdl_handle, SDL_GetMouseState);
115+
bind(g_sdl_handle, SDL_RenderWindowToLogical);
116+
bind(g_sdl_handle, SDL_RenderLogicalToWindow);
109117
#undef bind
110118

111119
DEBUG(dfsdl,out).print("sdl successfully loaded\n");
@@ -190,6 +198,18 @@ char* DFSDL::DFSDL_GetBasePath()
190198
return g_SDL_GetBasePath();
191199
}
192200

201+
uint32_t DFSDL::DFSDL_GetMouseState(int* x, int* y) {
202+
return g_SDL_GetMouseState(x, y);
203+
}
204+
205+
void DFSDL::DFSDL_RenderWindowToLogical(SDL_Renderer *renderer, int windowX, int windowY, float *logicalX, float *logicalY) {
206+
g_SDL_RenderWindowToLogical(renderer, windowX, windowY, logicalX, logicalY);
207+
}
208+
209+
void DFSDL::DFSDL_RenderLogicalToWindow(SDL_Renderer *renderer, float logicalX, float logicalY, int *windowX, int *windowY) {
210+
g_SDL_RenderLogicalToWindow(renderer, logicalX, logicalY, windowX, windowY);
211+
}
212+
193213
int DFSDL::DFSDL_ShowSimpleMessageBox(uint32_t flags, const char *title, const char *message, SDL_Window *window) {
194214
if (!g_SDL_ShowSimpleMessageBox)
195215
return -1;
@@ -266,3 +286,25 @@ DFHACK_EXPORT bool DFHack::setClipboardTextCp437Multiline(string text) {
266286
}
267287
return 0 == DFHack::DFSDL::DFSDL_SetClipboardText(str.str().c_str());
268288
}
289+
290+
// Queue to run callbacks on the render thread.
291+
// Semantics loosely based on SDL3's SDL_RunOnMainThread
292+
static std::recursive_mutex render_cb_lock;
293+
static std::vector<std::function<void()>> render_cb_queue;
294+
295+
DFHACK_EXPORT void DFHack::runOnRenderThread(std::function<void()> cb) {
296+
std::lock_guard<std::recursive_mutex> l(render_cb_lock);
297+
render_cb_queue.push_back(std::move(cb));
298+
}
299+
300+
DFHACK_EXPORT void DFHack::runRenderThreadCallbacks() {
301+
static decltype(render_cb_queue) local_queue;
302+
{
303+
std::lock_guard<std::recursive_mutex> l(render_cb_lock);
304+
std::swap(local_queue, render_cb_queue);
305+
}
306+
for (auto& cb : local_queue) {
307+
cb();
308+
}
309+
local_queue.clear();
310+
}

plugins/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ if(BUILD_SUPPORTED)
7575
dfhack_plugin(dwarfvet dwarfvet.cpp LINK_LIBRARIES lua)
7676
#dfhack_plugin(dwarfmonitor dwarfmonitor.cpp LINK_LIBRARIES lua)
7777
#add_subdirectory(embark-assistant)
78+
dfhack_plugin(edgescroll edgescroll.cpp)
7879
dfhack_plugin(eventful eventful.cpp LINK_LIBRARIES lua)
7980
dfhack_plugin(fastdwarf fastdwarf.cpp)
8081
dfhack_plugin(filltraffic filltraffic.cpp)

0 commit comments

Comments
 (0)