Add Renderer module - safer way to install custom renderers

develop
lethosor 2015-08-28 16:21:11 -04:00
parent 757c05db86
commit 8de710f1c1
5 changed files with 255 additions and 0 deletions

@ -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

@ -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);
}
}}

@ -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();
};

@ -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)

@ -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 <PluginCommand> &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);
}