From 12d8f0a135dd6276d16fe1c0e25f62efe792c8f0 Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 30 Nov 2024 22:24:53 +0000 Subject: [PATCH] library: rework minimap events --- src/library/doc.texi | 93 +++++++++++++++++++++++---------- src/library/gl.c | 28 +++++++--- src/library/plugin/plugin.c | 35 +++++++------ src/library/plugin/plugin.h | 26 ++++++--- src/library/plugin/plugin_api.c | 51 +++++++++++------- src/library/plugin/plugin_api.h | 3 +- 6 files changed, 156 insertions(+), 80 deletions(-) diff --git a/src/library/doc.texi b/src/library/doc.texi index a71098c..3116457 100644 --- a/src/library/doc.texi +++ b/src/library/doc.texi @@ -593,14 +593,29 @@ end) @eventobjectwarning{} -@node functions-onminimap -@section onminimap +@node functions-onminimapterrain +@section onminimapterrain -@eventhandler{minimap rendering events, @ref{objects-minimap}} +@eventhandler{minimap terrain events, @ref{objects-minimapterrain}} @example lua @verbatim -bolt.onminimap(function (event) +bolt.onminimapterrain(function (event) + -- ... +end) +@end verbatim +@end example + +@eventobjectwarning{} + +@node functions-onminimaprender2d +@section onminimaprender2d + +@eventhandler{minimap render2d events, @ref{objects-batch2d}} + +@example lua +@verbatim +bolt.onminimaprender2d(function (event) -- ... end) @end verbatim @@ -1811,8 +1826,9 @@ local m1, m2, m3, m4, @node objects-batch2d @section Batch2D Event -A Batch2D event comes from @ref{functions-onrender2d}. It occurs when -the game draws a batch of 2D icons to the screen. 2D icon renders are +A Batch2D event comes from @ref{functions-onrender2d}. or +@ref{functions-onminimaprender2d}. It occurs when the game draws a batch +of 2D icons to the screen, or to the minimap image. 2D icon renders are uploaded to the GPU in batches rather than one-at-a-time, so to look for an individual image, you'll need to iterate through each individual image in the batch, by iterating through the vertices. The number of @@ -1854,25 +1870,18 @@ separate triangles). To future-proof against possible engine updates, it's recommended to use this function instead of hard-coding the number 6 into your plugin. -@node batch2d-isminimap -@subsection isminimap - -Returns true if this render targets the minimap surface instead of the -user interface. There will usually be a maximum of one batch per frame -targeting the minimap surface. Renders that target the minimap will -overlay icons onto the static map image. - @node batch2d-targetsize @subsection targetsize Returns the width and height of the target area of this render, in pixels. -If @ref{batch2d-isminimap} is true, this will be the size of the minimap -surface - usually 256x256. Otherwise, this will be proportional to the -size of the inner area of the game window - that is, if the user has an -interface scaling other than 100%, it will be bigger or smaller than -that area, proportionally. +For a miminap render event, this will be the size of the minimap image, +usually 256x256. For a normal render2d event, this will be proportional +to the size of the inner area of the game window, given by +@ref{functions-gamewindowsize} - that is, if the user has an interface +scaling other than 100%, it will be bigger or smaller than that area, +proportionally. @node batch2d-vertexxy @subsection vertexxy @@ -2421,18 +2430,19 @@ local viewprojmatrix = event:modelviewprojmatrix(model) @end verbatim @end example -@node objects-minimap -@section Minimap Event +@node objects-minimapterrain +@section Minimap Terrain Event -A Minimap event comes from @ref{functions-onminimap}. It occurs when the -minimap gets drawn to the game view. This happens once per frame, unless -the minimap isn't visible. The event can be queried for some useful -information like the angle it's rotated to and the world position it's -centered on. +A Minimap Terrain event comes from @ref{functions-onminimapterrain}. It +occurs when the background terrain gets drawn to the minimap image, +which usually happens once per frame, unless the minimap isn't visible. +The terrain can't be inspected directly, but this event can be queried +for some useful information, like the angle the minimap is rotated to +and the world position it's centered on. @eventobjectwarning{} -@node minimap-angle +@node minimapterrain-angle @subsection angle Returns the angle at which the minimap background image is being @@ -2440,14 +2450,14 @@ rendered, in radians. The angle is 0 when upright (facing directly north), and increases counter-clockwise (note that turning the camera clockwise rotates the minimap counter-clockwise and vice versa). -@node minimap-scale +@node minimapterrain-scale @subsection scale Returns the scale at which the minimap background image is being rendered. This indicates how far in or out the minimap is zoomed. It appears to be capped between roughly 0.5 and 3.5. -@node minimap-position +@node minimapterrain-position @subsection position Returns an estimate of the X and Y position the minimap is centered on, @@ -2455,6 +2465,31 @@ in world coordinates. This is only a rough estimate and can move around a lot even while standing still. It usually doesn't vary by more than half a tile. +@node objects-renderminimap +@section Render Minimap Event + +A render minimap event comes from @ref{functions-onrenderminimap}. It +occurs when the minimap image gets drawn to the game window, which +usually happens once per frame, unless the minimap isn't visible. This +event can be used to find out the location of the minimap on the user's +screen. To get the minimap contents, see @ref{objects-minimapterrain} +and @ref{objects-minimaprender2d}. + +@eventobjectwarning{} + +@node renderminimap-xywh +@subsection xywh + +Returns the x, y, width and height of where the minimap is being drawn +on the screen, in pixel coordinates. The X and Y are relative to the +top-left pixel of the inner area of the window. + +@example lua +@verbatim +local x, y, width, height = event:xywh() +@end verbatim +@end example + @node objects-swapbuffers @section SwapBuffers event diff --git a/src/library/gl.c b/src/library/gl.c index f7f597c..ecd431d 100644 --- a/src/library/gl.c +++ b/src/library/gl.c @@ -1390,7 +1390,20 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void struct GLTexture2D* tex = c->texture_units[diffuse_map]; struct GLTexture2D* tex_target = _bolt_context_get_texture(c, draw_tex); - if (tex->is_minimap_tex_big) { + if (tex->is_minimap_tex_small && count == 6) { + const struct GLAttrBinding* binding = &attributes[c->bound_program->loc_aVertexPosition2D]; + int32_t xy0[2]; + int32_t xy2[2]; + if (!_bolt_get_attr_binding_int(c, binding, 0, 2, xy0)) return; + if (!_bolt_get_attr_binding_int(c, binding, 2, 2, xy2)) return; + const struct RenderMinimapEvent event = { + .target_x = (int16_t)xy0[0], + .target_y = (int16_t)(roundf(2.0 / projection_matrix[5]) - xy0[1]), + .target_w = (uint16_t)(xy2[0] - xy0[0]), + .target_h = (uint16_t)(xy0[1] - xy2[1]), + }; + _bolt_plugin_handle_renderminimap(&event); + } else if (tex->is_minimap_tex_big) { tex_target->is_minimap_tex_small = 1; if (count == 6) { // get XY and UV of first two vertices @@ -1447,12 +1460,12 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void const double cx = (scaled_xoffset + (small_tex_cx * angle_cos) - (small_tex_cy * angle_sin)) / dist_ratio; const double cy = (scaled_yoffset + (small_tex_cx * angle_sin) + (small_tex_cy * angle_cos)) / dist_ratio; - struct RenderMinimapEvent render; + struct MinimapTerrainEvent render; render.angle = map_angle_rads; render.scale = dist_ratio; render.x = tex->minimap_center_x + (64.0 * (cx - (double)(tex->width >> 1))); render.y = tex->minimap_center_y + (64.0 * (cy - (double)(tex->height >> 1))); - _bolt_plugin_handle_minimap(&render); + _bolt_plugin_handle_minimapterrain(&render); } } } else if (c->current_draw_framebuffer == 0) { @@ -1475,7 +1488,6 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void batch.screen_height = vertex_userdata.screen_height; batch.index_count = count; batch.vertices_per_icon = 6; - batch.is_minimap = tex_target && tex_target->is_minimap_tex_small; batch.vertex_functions.userdata = &vertex_userdata; batch.vertex_functions.xy = _bolt_gl_plugin_drawelements_vertex2d_xy; batch.vertex_functions.atlas_details = _bolt_gl_plugin_drawelements_vertex2d_atlas_details; @@ -1487,6 +1499,8 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void batch.texture_functions.compare = _bolt_gl_plugin_texture_compare; batch.texture_functions.data = _bolt_gl_plugin_texture_data; + void (*handler)(const struct RenderBatch2D*) = tex_target && tex_target->is_minimap_tex_small ? _bolt_plugin_handle_minimaprender2d : _bolt_plugin_handle_render2d; + if (tex->icons) { size_t batch_start = 0; for (size_t i = 0; i < count; i += batch.vertices_per_icon) { @@ -1505,7 +1519,7 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void batch.index_count = i - batch_start; if (batch.index_count) { vertex_userdata.indices = indices + batch_start; - _bolt_plugin_handle_render2d(&batch); + handler(&batch); } int32_t xy0[2]; int32_t xy2[2]; @@ -1524,10 +1538,10 @@ void _bolt_gl_onDrawElements(GLenum mode, GLsizei count, GLenum type, const void if (batch_start < count) { batch.index_count = count - batch_start; vertex_userdata.indices = indices + batch_start; - _bolt_plugin_handle_render2d(&batch); + handler(&batch); } } else { - _bolt_plugin_handle_render2d(&batch); + handler(&batch); } } } diff --git a/src/library/plugin/plugin.c b/src/library/plugin/plugin.c index 263c1ae..b4fdb83 100644 --- a/src/library/plugin/plugin.c +++ b/src/library/plugin/plugin.c @@ -55,18 +55,18 @@ uint64_t _bolt_plugin_get_last_mouseevent_windowid() { return last_mouseevent_wi static void _bolt_plugin_ipc_init(BoltSocketType*); static void _bolt_plugin_ipc_close(BoltSocketType); -static void _bolt_plugin_window_onreposition(struct EmbeddedWindow*, struct RepositionEvent*); -static void _bolt_plugin_window_onmousemotion(struct EmbeddedWindow*, struct MouseMotionEvent*); -static void _bolt_plugin_window_onmousebutton(struct EmbeddedWindow*, struct MouseButtonEvent*); -static void _bolt_plugin_window_onmousebuttonup(struct EmbeddedWindow*, struct MouseButtonEvent*); -static void _bolt_plugin_window_onscroll(struct EmbeddedWindow*, struct MouseScrollEvent*); -static void _bolt_plugin_window_onmouseleave(struct EmbeddedWindow*, struct MouseMotionEvent*); -static void _bolt_plugin_handle_mousemotion(struct MouseMotionEvent*); -static void _bolt_plugin_handle_mousebutton(struct MouseButtonEvent*); -static void _bolt_plugin_handle_mousebuttonup(struct MouseButtonEvent*); -static void _bolt_plugin_handle_scroll(struct MouseScrollEvent*); - -static void _bolt_plugin_handle_swapbuffers(struct SwapBuffersEvent*); +static void _bolt_plugin_window_onreposition(struct EmbeddedWindow*, const struct RepositionEvent*); +static void _bolt_plugin_window_onmousemotion(struct EmbeddedWindow*, const struct MouseMotionEvent*); +static void _bolt_plugin_window_onmousebutton(struct EmbeddedWindow*, const struct MouseButtonEvent*); +static void _bolt_plugin_window_onmousebuttonup(struct EmbeddedWindow*, const struct MouseButtonEvent*); +static void _bolt_plugin_window_onscroll(struct EmbeddedWindow*, const struct MouseScrollEvent*); +static void _bolt_plugin_window_onmouseleave(struct EmbeddedWindow*, const struct MouseMotionEvent*); +static void _bolt_plugin_handle_mousemotion(const struct MouseMotionEvent*); +static void _bolt_plugin_handle_mousebutton(const struct MouseButtonEvent*); +static void _bolt_plugin_handle_mousebuttonup(const struct MouseButtonEvent*); +static void _bolt_plugin_handle_scroll(const struct MouseScrollEvent*); + +static void _bolt_plugin_handle_swapbuffers(const struct SwapBuffersEvent*); const struct PluginManagedFunctions* _bolt_plugin_managed_functions() { return &managed_functions; @@ -126,7 +126,7 @@ uint64_t _bolt_plugin_itemicon_hash(const void* item, uint64_t seed0, uint64_t s static struct hashmap* plugins; #define DEFINE_CALLBACK(APINAME, STRUCTNAME) \ -void _bolt_plugin_handle_##APINAME(struct STRUCTNAME* e) { \ +void _bolt_plugin_handle_##APINAME(const struct STRUCTNAME* e) { \ if (!overlay_inited) return; \ size_t iter = 0; \ void* item; \ @@ -161,7 +161,7 @@ void _bolt_plugin_handle_##APINAME(struct STRUCTNAME* e) { \ #define DEFINE_CALLBACK_STATIC(APINAME, STRUCTNAME) static DEFINE_CALLBACK(APINAME, STRUCTNAME) #define DEFINE_WINDOWEVENT(APINAME, REGNAME, EVNAME) \ -void _bolt_plugin_window_on##APINAME(struct EmbeddedWindow* window, struct EVNAME* event) { \ +void _bolt_plugin_window_on##APINAME(struct EmbeddedWindow* window, const struct EVNAME* event) { \ if (window->is_deleted) return; \ lua_State* state = window->plugin; \ if (window->is_browser) { \ @@ -1125,7 +1125,9 @@ DEFINE_CALLBACK_STATIC(swapbuffers, SwapBuffersEvent) DEFINE_CALLBACK(render2d, RenderBatch2D) DEFINE_CALLBACK(render3d, Render3D) DEFINE_CALLBACK(rendericon, RenderItemIconEvent) -DEFINE_CALLBACK(minimap, RenderMinimapEvent) +DEFINE_CALLBACK(minimapterrain, MinimapTerrainEvent) +DEFINE_CALLBACK(minimaprender2d, RenderBatch2D) +DEFINE_CALLBACK(renderminimap, RenderMinimapEvent) DEFINE_CALLBACK(mousemotion, MouseMotionEvent) DEFINE_CALLBACK(mousebutton, MouseButtonEvent) DEFINE_CALLBACK(mousebuttonup, MouseButtonEvent) @@ -1219,7 +1221,8 @@ lua_settable(plugin->state, LUA_REGISTRYINDEX); SETMETA(render2d) SETMETA(render3d) SETMETA(rendericon) - SETMETA(minimap) + SETMETA(minimapterrain) + SETMETA(renderminimap) SETMETA(point) SETMETA(transform) SETMETA(buffer) diff --git a/src/library/plugin/plugin.h b/src/library/plugin/plugin.h index d6c0f4a..db2a471 100644 --- a/src/library/plugin/plugin.h +++ b/src/library/plugin/plugin.h @@ -259,7 +259,6 @@ struct RenderBatch2D { uint32_t screen_height; uint32_t index_count; uint32_t vertices_per_icon; - uint8_t is_minimap; struct Vertex2DFunctions vertex_functions; struct TextureFunctions texture_functions; }; @@ -305,13 +304,20 @@ struct RenderItemIconEvent { uint16_t target_h; }; -struct RenderMinimapEvent { +struct MinimapTerrainEvent { double angle; double scale; double x; double y; }; +struct RenderMinimapEvent { + int16_t target_x; + int16_t target_y; + uint16_t target_w; + uint16_t target_h; +}; + struct SwapBuffersEvent { #if defined(_MSC_VER) // MSVC doesn't allow empty structs @@ -391,16 +397,22 @@ void _bolt_plugin_shm_resize(struct BoltSHM* shm, size_t length, uint64_t new_id void _bolt_plugin_shm_remap(struct BoltSHM* shm, size_t length, void* handle); /// Sends a RenderBatch2D to all plugins. -void _bolt_plugin_handle_render2d(struct RenderBatch2D*); +void _bolt_plugin_handle_render2d(const struct RenderBatch2D*); /// Sends a Render3D to all plugins. -void _bolt_plugin_handle_render3d(struct Render3D*); +void _bolt_plugin_handle_render3d(const struct Render3D*); /// Sends a RenderItemIconEvent to all plugins. -void _bolt_plugin_handle_rendericon(struct RenderItemIconEvent*); +void _bolt_plugin_handle_rendericon(const struct RenderItemIconEvent*); + +/// Sends a MinimapTerrainEvent to all plugins. +void _bolt_plugin_handle_minimapterrain(const struct MinimapTerrainEvent*); + +/// Sends a RenderBatch2D for the minimap image to all plugins. +void _bolt_plugin_handle_minimaprender2d(const struct RenderBatch2D*); -/// Sends a RenderMinimap to all plugins. -void _bolt_plugin_handle_minimap(struct RenderMinimapEvent*); +/// Sends a RenderMinimapEvent to all plugins. +void _bolt_plugin_handle_renderminimap(const struct RenderMinimapEvent*); /// Gets the value from the monotonic microsecond counter, returning true on success or false on failure. /// Can only fail on Windows, and even then there are no known cases where it would fail. diff --git a/src/library/plugin/plugin_api.c b/src/library/plugin/plugin_api.c index 535b5a7..3304362 100644 --- a/src/library/plugin/plugin_api.c +++ b/src/library/plugin/plugin_api.c @@ -175,7 +175,9 @@ DEFINE_CALLBACK(swapbuffers) DEFINE_CALLBACK(render2d) DEFINE_CALLBACK(render3d) DEFINE_CALLBACK(rendericon) -DEFINE_CALLBACK(minimap) +DEFINE_CALLBACK(minimapterrain) +DEFINE_CALLBACK(minimaprender2d) +DEFINE_CALLBACK(renderminimap) DEFINE_CALLBACK(mousemotion) DEFINE_CALLBACK(mousebutton) DEFINE_CALLBACK(mousebuttonup) @@ -666,12 +668,6 @@ static int api_batch2d_verticesperimage(lua_State* state) { return 1; } -static int api_batch2d_isminimap(lua_State* state) { - const struct RenderBatch2D* batch = require_self_userdata(state, "isminimap"); - lua_pushboolean(state, batch->is_minimap); - return 1; -} - static int api_batch2d_targetsize(lua_State* state) { const struct RenderBatch2D* batch = require_self_userdata(state, "targetsize"); lua_pushinteger(state, batch->screen_width); @@ -770,25 +766,34 @@ static int api_batch2d_texturedata(lua_State* state) { return 1; } -static int api_minimap_angle(lua_State* state) { - const struct RenderMinimapEvent* render = require_self_userdata(state, "angle"); +static int api_minimapterrain_angle(lua_State* state) { + const struct MinimapTerrainEvent* render = require_self_userdata(state, "angle"); lua_pushnumber(state, render->angle); return 1; } -static int api_minimap_scale(lua_State* state) { - const struct RenderMinimapEvent* render = require_self_userdata(state, "scale"); +static int api_minimapterrain_scale(lua_State* state) { + const struct MinimapTerrainEvent* render = require_self_userdata(state, "scale"); lua_pushnumber(state, render->scale); return 1; } -static int api_minimap_position(lua_State* state) { - const struct RenderMinimapEvent* render = require_self_userdata(state, "position"); +static int api_minimapterrain_position(lua_State* state) { + const struct MinimapTerrainEvent* render = require_self_userdata(state, "position"); lua_pushnumber(state, render->x); lua_pushnumber(state, render->y); return 2; } +static int api_renderminimap_xywh(lua_State* state) { + const struct RenderMinimapEvent* render = require_self_userdata(state, "xywh"); + lua_pushinteger(state, render->target_x); + lua_pushinteger(state, render->target_y); + lua_pushinteger(state, render->target_w); + lua_pushinteger(state, render->target_h); + return 4; +} + static int api_point_transform(lua_State* state) { const struct Point3D* point = require_self_userdata(state, "transform"); const struct Transform3D* transform = require_userdata(state, 2, "transform"); @@ -1555,7 +1560,9 @@ static struct ApiFuncTemplate bolt_functions[] = { BOLTFUNC(onrender2d), BOLTFUNC(onrender3d), BOLTFUNC(onrendericon), - BOLTFUNC(onminimap), + BOLTFUNC(onminimapterrain), + BOLTFUNC(onminimaprender2d), + BOLTFUNC(onrenderminimap), BOLTFUNC(onswapbuffers), BOLTFUNC(onmousemotion), BOLTFUNC(onmousebutton), @@ -1590,7 +1597,6 @@ static struct ApiFuncTemplate bolt_functions[] = { static struct ApiFuncTemplate render2d_functions[] = { BOLTFUNC(vertexcount, batch2d), BOLTFUNC(verticesperimage, batch2d), - BOLTFUNC(isminimap, batch2d), BOLTFUNC(targetsize, batch2d), BOLTFUNC(vertexxy, batch2d), BOLTFUNC(vertexatlasdetails, batch2d), @@ -1635,10 +1641,14 @@ static struct ApiFuncTemplate rendericon_functions[] = { BOLTALIAS(modelvertexcolour, modelvertexcolor, rendericon), }; -static struct ApiFuncTemplate minimap_functions[] = { - BOLTFUNC(angle, minimap), - BOLTFUNC(scale, minimap), - BOLTFUNC(position, minimap), +static struct ApiFuncTemplate minimapterrain_functions[] = { + BOLTFUNC(angle, minimapterrain), + BOLTFUNC(scale, minimapterrain), + BOLTFUNC(position, minimapterrain), +}; + +static struct ApiFuncTemplate renderminimap_functions[] = { + BOLTFUNC(xywh, renderminimap), }; static struct ApiFuncTemplate point_functions[] = { @@ -1800,7 +1810,8 @@ void _bolt_api_push_metatable_##NAME(lua_State* state) { \ DEFPUSHMETA(render2d) DEFPUSHMETA(render3d) DEFPUSHMETA(rendericon) -DEFPUSHMETA(minimap) +DEFPUSHMETA(minimapterrain) +DEFPUSHMETA(renderminimap) DEFPUSHMETA(point) DEFPUSHMETA(transform) DEFPUSHMETAGC(buffer) diff --git a/src/library/plugin/plugin_api.h b/src/library/plugin/plugin_api.h index cc39339..2818911 100644 --- a/src/library/plugin/plugin_api.h +++ b/src/library/plugin/plugin_api.h @@ -38,7 +38,8 @@ void _bolt_api_push_bolt_table(lua_State*); void _bolt_api_push_metatable_render2d(lua_State*); void _bolt_api_push_metatable_render3d(lua_State*); void _bolt_api_push_metatable_rendericon(lua_State*); -void _bolt_api_push_metatable_minimap(lua_State*); +void _bolt_api_push_metatable_minimapterrain(lua_State*); +void _bolt_api_push_metatable_renderminimap(lua_State*); void _bolt_api_push_metatable_point(lua_State*); void _bolt_api_push_metatable_transform(lua_State*); void _bolt_api_push_metatable_buffer(lua_State*);