diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index fc0b91e0f..3cd415780 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -127,6 +127,7 @@ include/modules/MapCache.h include/modules/Materials.h include/modules/Notes.h include/modules/Random.h +include/modules/Renderer.h include/modules/Screen.h include/modules/Translation.h include/modules/Vermin.h @@ -152,6 +153,7 @@ modules/Maps.cpp modules/Materials.cpp modules/Notes.cpp modules/Random.cpp +modules/Renderer.cpp modules/Screen.cpp modules/Translation.cpp modules/Vermin.cpp diff --git a/library/include/modules/Renderer.h b/library/include/modules/Renderer.h new file mode 100644 index 000000000..11abd7c1d --- /dev/null +++ b/library/include/modules/Renderer.h @@ -0,0 +1,38 @@ +#include "Export.h" +#include "df/enabler.h" +#include "df/graphic.h" +#include "df/renderer.h" +#pragma once + +namespace DFHack { namespace Renderer { + struct DFHACK_EXPORT renderer_wrap : public df::renderer { + void set_to_null(); + void copy_from_parent(); + void copy_to_parent(); + renderer_wrap *parent; + renderer_wrap *child; + + virtual void update_tile(int32_t x, int32_t y); + virtual void update_all(); + virtual void render(); + virtual void set_fullscreen(); + virtual void zoom(df::zoom_commands z); + virtual void resize(int32_t w, int32_t h); + virtual void grid_resize(int32_t w, int32_t h); + virtual ~renderer_wrap() { + // All necessary cleanup should be handled by RemoveRenderer() + }; + virtual bool get_mouse_coords(int32_t *x, int32_t *y); + virtual bool uses_opengl(); + }; + // Returns the renderer instance given on success, or deletes it and returns NULL on failure + // Usage: renderer_foo *r = AddRenderer(new renderer_foo) + DFHACK_EXPORT renderer_wrap *AddRenderer(renderer_wrap*, bool refresh_screen = false); + // Removes and deletes the given renderer instance + DFHACK_EXPORT void RemoveRenderer(renderer_wrap*); + DFHACK_EXPORT bool RendererExists(renderer_wrap*); + inline renderer_wrap *GetRenderer() + { + return (renderer_wrap*)(df::global::enabler ? df::global::enabler->renderer : NULL); + } +}} diff --git a/library/modules/Renderer.cpp b/library/modules/Renderer.cpp new file mode 100644 index 000000000..474dc3656 --- /dev/null +++ b/library/modules/Renderer.cpp @@ -0,0 +1,156 @@ +#include "DataDefs.h" +#include "MiscUtils.h" +#include "modules/Renderer.h" + +using namespace DFHack; +using df::global::enabler; +using df::global::gps; +using DFHack::Renderer::renderer_wrap; + +static renderer_wrap *original_renderer = NULL; + +bool init() +{ + if (!original_renderer) + original_renderer = Renderer::GetRenderer(); + return original_renderer; +} + +renderer_wrap *Renderer::AddRenderer (renderer_wrap *r, bool refresh_screen) +{ + if (!init()) + { + delete r; + return NULL; + } + renderer_wrap *cur = GetRenderer(); + r->parent = cur; + r->child = NULL; + r->copy_from_parent(); + if (cur != original_renderer) + { + cur->child = original_renderer; + } + r->copy_from_parent(); + enabler->renderer = r; + if (refresh_screen && gps) + gps->force_full_display_count++; + return r; +} + +void Renderer::RemoveRenderer (renderer_wrap *r) +{ + if (r) + { + if (original_renderer) + { + r->parent->child = r->child; + if (r->child) + { + r->child->parent = r->parent; + } + enabler->renderer = r->parent; + } + delete r; + } +} + +bool Renderer::RendererExists (renderer_wrap *r) +{ + renderer_wrap *cur = GetRenderer(); + while (cur && cur != r && cur != original_renderer) + cur = cur->parent; + return cur == r; +} + +void Renderer::renderer_wrap::set_to_null() { + screen = NULL; + screentexpos = NULL; + screentexpos_addcolor = NULL; + screentexpos_grayscale = NULL; + screentexpos_cf = NULL; + screentexpos_cbr = NULL; + screen_old = NULL; + screentexpos_old = NULL; + screentexpos_addcolor_old = NULL; + screentexpos_grayscale_old = NULL; + screentexpos_cf_old = NULL; + screentexpos_cbr_old = NULL; +} + +void Renderer::renderer_wrap::copy_from_parent() { + screen = parent->screen; + screentexpos = parent->screentexpos; + screentexpos_addcolor = parent->screentexpos_addcolor; + screentexpos_grayscale = parent->screentexpos_grayscale; + screentexpos_cf = parent->screentexpos_cf; + screentexpos_cbr = parent->screentexpos_cbr; + screen_old = parent->screen_old; + screentexpos_old = parent->screentexpos_old; + screentexpos_addcolor_old = parent->screentexpos_addcolor_old; + screentexpos_grayscale_old = parent->screentexpos_grayscale_old; + screentexpos_cf_old = parent->screentexpos_cf_old; + screentexpos_cbr_old = parent->screentexpos_cbr_old; +} + +void Renderer::renderer_wrap::copy_to_parent() { + parent->screen = screen; + parent->screentexpos = screentexpos; + parent->screentexpos_addcolor = screentexpos_addcolor; + parent->screentexpos_grayscale = screentexpos_grayscale; + parent->screentexpos_cf = screentexpos_cf; + parent->screentexpos_cbr = screentexpos_cbr; + parent->screen_old = screen_old; + parent->screentexpos_old = screentexpos_old; + parent->screentexpos_addcolor_old = screentexpos_addcolor_old; + parent->screentexpos_grayscale_old = screentexpos_grayscale_old; + parent->screentexpos_cf_old = screentexpos_cf_old; + parent->screentexpos_cbr_old = screentexpos_cbr_old; +} + +void Renderer::renderer_wrap::update_tile(int32_t x, int32_t y) { + copy_to_parent(); + parent->update_tile(x,y); +}; + +void Renderer::renderer_wrap::update_all() { + copy_to_parent(); + parent->update_all(); +}; + +void Renderer::renderer_wrap::render() { + copy_to_parent(); + parent->render(); +}; + +void Renderer::renderer_wrap::set_fullscreen() { + copy_to_parent(); + parent->set_fullscreen(); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::zoom(df::zoom_commands z) { + copy_to_parent(); + parent->zoom(z); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::resize(int32_t w, int32_t h) { + copy_to_parent(); + parent->resize(w,h); + copy_from_parent(); +}; + +void Renderer::renderer_wrap::grid_resize(int32_t w, int32_t h) { + copy_to_parent(); + parent->grid_resize(w,h); + copy_from_parent(); +}; + +bool Renderer::renderer_wrap::get_mouse_coords(int32_t* x, int32_t* y) { + return parent->get_mouse_coords(x,y); +}; + +bool Renderer::renderer_wrap::uses_opengl() { + return parent->uses_opengl(); +}; diff --git a/plugins/devel/CMakeLists.txt b/plugins/devel/CMakeLists.txt index 74c198645..79bf55ff6 100644 --- a/plugins/devel/CMakeLists.txt +++ b/plugins/devel/CMakeLists.txt @@ -14,6 +14,7 @@ DFHACK_PLUGIN(memview memview.cpp) DFHACK_PLUGIN(nestboxes nestboxes.cpp) DFHACK_PLUGIN(notes notes.cpp) DFHACK_PLUGIN(onceExample onceExample.cpp) +DFHACK_PLUGIN(renderer-msg renderer-msg.cpp) DFHACK_PLUGIN(rprobe rprobe.cpp) DFHACK_PLUGIN(stepBetween stepBetween.cpp) DFHACK_PLUGIN(stockcheck stockcheck.cpp) diff --git a/plugins/devel/renderer-msg.cpp b/plugins/devel/renderer-msg.cpp new file mode 100644 index 000000000..a2143d137 --- /dev/null +++ b/plugins/devel/renderer-msg.cpp @@ -0,0 +1,58 @@ +#include "Console.h" +#include "Core.h" +#include "DataDefs.h" +#include "Export.h" +#include "PluginManager.h" +#include "modules/Screen.h" +#include "modules/Renderer.h" + +#include "df/enabler.h" +#include "df/renderer.h" + +//#include "df/world.h" + +using namespace DFHack; + +DFHACK_PLUGIN("renderer-msg"); +DFHACK_PLUGIN_IS_ENABLED(is_enabled); +REQUIRE_GLOBAL(enabler); +REQUIRE_GLOBAL(gps); + +struct scdata { + uint8_t ch, fg, bg, bold; +}; + +struct renderer_msg : public Renderer::renderer_wrap { + virtual void update_tile (int32_t x, int32_t y) { + static std::string str = std::string("DFHack: ") + plugin_name + " active"; + Screen::paintString(Screen::Pen(' ', 9, 0), 0, gps->dimy - 1, str); + for (size_t i = 0; i < gps->dimx; ++i) + ((scdata*)screen)[i * gps->dimy + gps->dimy - 1].bg = 2; + renderer_wrap::update_tile(x, y); + }; +}; + +DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) +{ + return CR_OK; +} + +static Renderer::renderer_wrap *w = NULL; +DFhackCExport command_result plugin_enable (color_ostream &out, bool enable) +{ + if (is_enabled == enable) + return CR_OK; + CoreSuspender s; + is_enabled = enable; + if (enable) + w = Renderer::AddRenderer(new renderer_msg, true); + else + Renderer::RemoveRenderer(w); + return CR_OK; +} + +DFhackCExport command_result plugin_shutdown (color_ostream &out) +{ + plugin_enable(out, false); + return plugin_enable(out, false); +}