Hotkey UI for linux.

develop
Petr Mrázek 2011-07-09 11:33:58 +02:00
parent 65d7278f53
commit d894ef0ffa
16 changed files with 380 additions and 123 deletions

@ -803,8 +803,8 @@
<Group name="GUI" description="Offsets used by the GUI module.">
<Address name="pause_state" description="a flag that determines if the game is paused."/>
<Address name="current_cursor_creature" description="A vector? of creatures currently under the cursor."/>
<Address name="interface" description="Pointer to the global interfacest object (gview symbol on Linux)."/>
<Address name="current_menu_state" description="A numeric value that describes the state of the current GUI element (switching between menus will change this)."/>
<Address name="view_screen" description="Pointer to the current view screen object (GUI screen)."/>
<Address name="hotkeys" description="Address where the array of hotkeys starts." />
</Group>
<Group name="Maps" description="Offsets used by the Maps module.">
@ -1127,8 +1127,6 @@
<Group name="GUI">
<Address name="pause_state" value="0x146e45f" />
<Address name="current_cursor_creature" value="0xae82cc" valid="false" />
<Address name="current_menu_state" value="0x017f6f38" />
<Address name="view_screen" value="0xae82cc" valid="false" />
<Address name="hotkeys" value="0x01476ecc" />
</Group>
<Group name="Maps">
@ -1307,7 +1305,6 @@
constructions 0xffffffff
creatures 0x0166eccc
current_cursor_creature 0x00ae82cc
current_menu_state 0x017f6f38
cursor_xyz 0x0166ecd4
effects_vector 0x017f6da0
hotkey_start 0x01476ecc
@ -1323,7 +1320,6 @@
settlement_current 0xffffffff
settlements 0x016af4a4
translation_vector 0x016b0010
view_screen 0xffffffff
window_dims 0x017f5abc
window_x 0x00e32798
window_y 0x00e60838
@ -3019,6 +3015,8 @@
WORLD: 0x93f77a0
<Group name="GUI">
<Address name="hotkeys" value="0x93f740c" />
<Address name="interface" value="0x8C3E900" />
<Address name="current_menu_state" value="0x93F756C" />
</Group>
<Group name="Creatures">
Maybe, possibly.

@ -20,6 +20,7 @@ SET(PROJECT_HDRS
include/DFHack.h
include/dfhack/Error.h
include/dfhack/Export.h
include/dfhack/Virtual.h
include/dfhack/MiscUtils.h
include/dfhack/Module.h
include/dfhack/Pragma.h
@ -53,6 +54,7 @@ PluginManager.cpp
VersionInfo.cpp
VersionInfoFactory.cpp
TileTypes.cpp
Virtual.cpp
depends/md5/md5.cpp
depends/md5/md5wrapper.cpp

@ -38,14 +38,14 @@ using namespace std;
#include "dfhack/Process.h"
#include "dfhack/Core.h"
#include "dfhack/Console.h"
#include "dfhack/Module.h"
#include "dfhack/VersionInfoFactory.h"
#include "dfhack/PluginManager.h"
#include "ModuleFactory.h"
#include "dfhack/modules/Gui.h"
#include "dfhack/modules/Vegetation.h"
#include "dfhack/modules/Maps.h"
#include "dfhack/modules/World.h"
#include "dfhack/SDL_fakes/events.h"
#include <stdio.h>
#include <iomanip>
using namespace DFHack;
@ -63,11 +63,41 @@ struct IODATA
PluginManager * plug_mgr;
};
// A thread function... for handling hotkeys. This is needed because
// all the plugin commands are expected to be run from foreign threads.
// Running them from one of the main DF threads will result in deadlock!
int fHKthread(void * iodata)
{
Core * core = ((IODATA*) iodata)->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
if(plug_mgr == 0 || core == 0)
{
cerr << "Hotkey thread has croaked." << endl;
return 0;
}
while(1)
{
std::string stuff = core->getHotkeyCmd(); // waits on mutex!
if(!stuff.empty())
{
vector <string> crap;
plug_mgr->InvokeCommand(stuff, crap);
}
}
}
// A thread function... for the interactive console.
static bool flip0 = false;
int fIOthread(void * iodata)
{
if(!flip0)
{
std::cerr << "Console from Thread " << SDL_ThreadID() << std::endl;
flip0 = true;
}
Core * core = ((IODATA*) iodata)->core;
PluginManager * plug_mgr = ((IODATA*) iodata)->plug_mgr;
if(plug_mgr == 0)
if(plug_mgr == 0 || core == 0)
{
dfout << "Something horrible happened to the plugin manager in Core's constructor..." << std::endl;
return 0;
@ -140,8 +170,34 @@ int fIOthread(void * iodata)
Core::Core()
{
// init the console. This must be always the first step!
con = new Console();
con = 0;
plug_mgr = 0;
vif = 0;
p = 0;
errorstate = false;
vinfo = 0;
started = false;
memset(&(s_mods), 0, sizeof(s_mods));
// create mutex for syncing with interactive tasks
AccessMutex = 0;
// set up hotkey capture
memset(hotkey_states,0,sizeof(hotkey_states));
hotkey_set = false;
HotkeyMutex = 0;
HotkeyCond = 0;
};
static bool flip1 = 0;
bool Core::Init()
{
// init the console. This must be always the first step!
con = new Console();
if(!flip1)
{
std::cerr << "Construct from Thread " << SDL_ThreadID() << std::endl;
flip1 = true;
}
// find out what we are...
vif = new DFHack::VersionInfoFactory("Memory.xml");
p = new DFHack::Process(vif);
@ -151,36 +207,71 @@ Core::Core()
errorstate = true;
delete p;
p = NULL;
return;
return false;
}
vinfo = p->getDescriptor();
// init module storage
allModules.clear();
memset(&(s_mods), 0, sizeof(s_mods));
// create mutex for syncing with interactive tasks
AccessMutex = SDL_CreateMutex();
if(!AccessMutex)
{
dfout << "Mutex creation failed." << std::endl;
errorstate = true;
return;
return false;
}
// all OK
errorstate = false;
// lock mutex
SDL_mutexP(AccessMutex);
// create plugin manager
plug_mgr = new PluginManager(this);
if(!plug_mgr)
{
dfout << "Failed to create the Plugin Manager." << std::endl;
errorstate = true;
return false;
}
// look for all plugins,
// create IO thread
IODATA *temp = new IODATA;
temp->core = this;
temp->plug_mgr = plug_mgr;
DFThread * IO = SDL_CreateThread(fIOthread, (void *) temp);
delete temp;
// and let DF do its thing.
};
SDL::Thread * IO = SDL_CreateThread(fIOthread, (void *) temp);
// set up hotkey capture
HotkeyMutex = SDL_CreateMutex();
HotkeyCond = SDL_CreateCond();
SDL::Thread * HK = SDL_CreateThread(fHKthread, (void *) temp);
started = true;
return true;
}
/// sets the current hotkey command
bool Core::setHotkeyCmd( std::string cmd )
{
// access command
SDL_mutexP(HotkeyMutex);
{
hotkey_set = true;
hotkey_cmd = cmd;
SDL_CondSignal(HotkeyCond);
}
SDL_mutexV(HotkeyMutex);
return true;
}
/// removes the hotkey command and gives it to the caller thread
std::string Core::getHotkeyCmd( void )
{
string returner;
SDL_mutexP(HotkeyMutex);
while ( ! hotkey_set )
{
SDL_CondWait(HotkeyCond, HotkeyMutex);
}
hotkey_set = false;
returner = hotkey_cmd;
hotkey_cmd.clear();
SDL_mutexV(HotkeyMutex);
return returner;
}
void Core::Suspend()
{
@ -198,10 +289,18 @@ void Core::Resume()
SDL_mutexV(AccessMutex);
}
// should always be from simulation thread!
static bool flip2 = false;
int Core::Update()
{
if(!started) Init();
if(errorstate)
return -1;
if(!flip2)
{
std::cerr << "Update from Thread " << SDL_ThreadID() << std::endl;
flip2 = true;
}
// notify all the plugins that a game tick is finished
plug_mgr->OnUpdate();
SDL_mutexV(AccessMutex);
@ -228,20 +327,58 @@ int Core::Shutdown ( void )
memset(&(s_mods), 0, sizeof(s_mods));
dfout << std::endl;
// kill the console object
delete con;
if(con)
delete con;
con = 0;
return -1;
}
void Core::SDL_Event(FakeSDL::Event* event)
static bool flip3 = 0;
int Core::SDL_Event(SDL::Event* ev, int orig_return)
{
if(!event)
return;
if(event->type == FakeSDL::ET_KEYDOWN)
// do NOT process events before we are ready.
if(!started) return orig_return;
if(!flip3)
{
std::cerr << "Event from Thread " << SDL_ThreadID() << std::endl;
flip3 = true;
}
if(!ev)
return orig_return;
if(ev && ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP)
{
FakeSDL::KeyboardEvent * kev = (FakeSDL::KeyboardEvent *) event;
cerr << "Key " << kev->ksym.sym << std::endl;
SDL::KeyboardEvent * ke = (SDL::KeyboardEvent *)ev;
bool shift = ke->ksym.mod & SDL::KMOD_SHIFT;
// consuming F1 .. F8
int idx = ke->ksym.sym - SDL::K_F1;
if(idx < 0 || idx > 7)
return orig_return;
idx += 8*shift;
// now we have the real index...
if(ke->state == SDL::BTN_PRESSED && !hotkey_states[idx])
{
hotkey_states[idx] = 1;
Gui * g = getGui();
if(g->hotkeys && g->interface && g->menu_state)
{
t_viewscreen * ws = g->GetCurrentScreen();
if(ws->getClassName() == "viewscreen_dwarfmodest" && *g->menu_state == 0x23)
return orig_return;
else
{
std::cerr << "Hotkey " << idx << " triggered. Thread " << SDL_ThreadID() << std::endl;
t_hotkey & hotkey = (*g->hotkeys)[idx];
setHotkeyCmd(hotkey.name);
}
}
}
else if(ke->state == SDL::BTN_RELEASED)
{
hotkey_states[idx] = 0;
}
}
return orig_return;
// do stuff with the events...
}
/*******************************************************************************

@ -85,7 +85,7 @@ DFhackCExport int SDL_NumJoysticks(void)
//static void (*_SDL_GL_SwapBuffers)(void) = 0;
static void (*_SDL_Quit)(void) = 0;
static int (*_SDL_Init)(uint32_t flags) = 0;
static DFThread * (*_SDL_CreateThread)(int (*fn)(void *), void *data) = 0;
static SDL::Thread * (*_SDL_CreateThread)(int (*fn)(void *), void *data) = 0;
//static int (*_SDL_Flip)(void * some_ptr) = 0;
/*
// hook - called every tick in OpenGL mode of DF
@ -119,26 +119,26 @@ DFhackCExport int SDL_Flip(void * some_ptr)
}
*/
static DFMutex * (*_SDL_CreateMutex)(void) = 0;
DFhackCExport DFMutex * SDL_CreateMutex(void)
static SDL::Mutex * (*_SDL_CreateMutex)(void) = 0;
DFhackCExport SDL::Mutex * SDL_CreateMutex(void)
{
return _SDL_CreateMutex();
}
static int (*_SDL_mutexP)(DFMutex * mutex) = 0;
DFhackCExport int SDL_mutexP(DFMutex * mutex)
static int (*_SDL_mutexP)(SDL::Mutex * mutex) = 0;
DFhackCExport int SDL_mutexP(SDL::Mutex * mutex)
{
return _SDL_mutexP(mutex);
}
static int (*_SDL_mutexV)(DFMutex * mutex) = 0;
DFhackCExport int SDL_mutexV(DFMutex * mutex)
static int (*_SDL_mutexV)(SDL::Mutex * mutex) = 0;
DFhackCExport int SDL_mutexV(SDL::Mutex * mutex)
{
return _SDL_mutexV(mutex);
}
static void (*_SDL_DestroyMutex)(DFMutex * mutex) = 0;
DFhackCExport void SDL_DestroyMutex(DFMutex * mutex)
static void (*_SDL_DestroyMutex)(SDL::Mutex * mutex) = 0;
DFhackCExport void SDL_DestroyMutex(SDL::Mutex * mutex)
{
_SDL_DestroyMutex(mutex);
}
@ -155,41 +155,77 @@ DFhackCExport void SDL_Quit(void)
}
// called by DF to check input events
static int (*_SDL_PollEvent)(FakeSDL::Event* event) = 0;
DFhackCExport int SDL_PollEvent(FakeSDL::Event* event)
static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
DFhackCExport int SDL_PollEvent(SDL::Event* event)
{
int ret = _SDL_PollEvent(event);
int orig_return = _SDL_PollEvent(event);
// only send events to Core after we get first SDL_NumJoysticks call
// DF event loop is possibly polling for SDL events before things get inited properly
// SDL handles it. We don't, because we use some other parts of SDL too.
if(inited && event != 0)
{
DFHack::Core & c = DFHack::Core::getInstance();
c.SDL_Event(event);
return c.SDL_Event(event, orig_return);
}
return ret;
return orig_return;
}
static uint32_t (*_SDL_ThreadID)(void) = 0;
DFhackCExport uint32_t SDL_ThreadID()
{
return _SDL_ThreadID();
}
static SDL::Cond * (*_SDL_CreateCond)(void) = 0;
DFhackCExport SDL::Cond *SDL_CreateCond(void)
{
return _SDL_CreateCond();
}
static void (*_SDL_DestroyCond)(SDL::Cond *) = 0;
DFhackCExport void SDL_DestroyCond(SDL::Cond *cond)
{
_SDL_DestroyCond(cond);
}
static int (*_SDL_CondSignal)(SDL::Cond *) = 0;
DFhackCExport int SDL_CondSignal(SDL::Cond *cond)
{
return _SDL_CondSignal(cond);
}
static int (*_SDL_CondWait)(SDL::Cond *, SDL::Mutex *) = 0;
DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut)
{
return _SDL_CondWait(cond, mut);
}
// hook - called at program start, initialize some stuffs we'll use later
DFhackCExport int SDL_Init(uint32_t flags)
{
freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
// horrible casts not supported by the C or C++ standards. Only POSIX. Damn you, POSIX.
// find real functions
//_SDL_GL_SwapBuffers = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_GL_SwapBuffers");
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
//_SDL_Flip = (int (*)( void * )) dlsym(RTLD_NEXT, "SDL_Flip");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");
_SDL_CreateThread = (DFThread* (*)(int (*fn)(void *), void *data))dlsym(RTLD_NEXT, "SDL_CreateThread");
_SDL_CreateMutex = (DFMutex*(*)())dlsym(RTLD_NEXT,"SDL_CreateMutex");
_SDL_DestroyMutex = (void (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_DestroyMutex");
_SDL_mutexP = (int (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_mutexP");
_SDL_mutexV = (int (*)(DFMutex*))dlsym(RTLD_NEXT,"SDL_mutexV");
_SDL_PollEvent = (int (*)(FakeSDL::Event*))dlsym(RTLD_NEXT,"SDL_PollEvent");
_SDL_CreateThread = (SDL::Thread* (*)(int (*fn)(void *), void *data))dlsym(RTLD_NEXT, "SDL_CreateThread");
_SDL_CreateMutex = (SDL::Mutex*(*)())dlsym(RTLD_NEXT,"SDL_CreateMutex");
_SDL_DestroyMutex = (void (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_DestroyMutex");
_SDL_mutexP = (int (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_mutexP");
_SDL_mutexV = (int (*)(SDL::Mutex*))dlsym(RTLD_NEXT,"SDL_mutexV");
_SDL_PollEvent = (int (*)(SDL::Event*))dlsym(RTLD_NEXT,"SDL_PollEvent");
_SDL_ThreadID = (uint32_t (*)())dlsym(RTLD_NEXT,"SDL_ThreadID");
_SDL_CreateCond = (SDL::Cond * (*)())dlsym(RTLD_NEXT,"SDL_CreateCond");
_SDL_DestroyCond = (void(*)(SDL::Cond *))dlsym(RTLD_NEXT,"SDL_DestroyCond");
_SDL_CondSignal = (int (*)(SDL::Cond *))dlsym(RTLD_NEXT,"SDL_CondSignal");
_SDL_CondWait = (int (*)(SDL::Cond *, SDL::Mutex *))dlsym(RTLD_NEXT,"SDL_CondWait");
// check if we got them
if(_SDL_Init && _SDL_Quit && _SDL_CreateThread && _SDL_CreateMutex && _SDL_DestroyMutex && _SDL_mutexP && _SDL_mutexV)
if(_SDL_Init && _SDL_Quit && _SDL_CreateThread
&& _SDL_CreateMutex && _SDL_DestroyMutex && _SDL_mutexP
&& _SDL_mutexV && _SDL_PollEvent && _SDL_ThreadID
&& _SDL_CondSignal && _SDL_CondWait && _SDL_CreateCond && _SDL_DestroyCond)
{
fprintf(stderr,"dfhack: hooking successful\n");
}

@ -170,7 +170,7 @@ PluginManager::~PluginManager()
all_plugins.clear();
}
Plugin *PluginManager::getPluginByName (const std::string & name)
const Plugin *PluginManager::getPluginByName (const std::string & name)
{
for(int i = 0; i < all_plugins.size(); i++)
{

@ -53,6 +53,9 @@ namespace DFHack
class Console;
class PluginManager;
class Core;
class Hotkey;
// anon type, pretty much
struct DFLibrary;
DFLibrary * OpenPlugin (const char * filename);
void * LookupPlugin (DFLibrary * plugin ,const char * function);
@ -65,7 +68,7 @@ namespace DFHack
{
friend int ::SDL_NumJoysticks(void);
friend void ::SDL_Quit(void);
friend int ::SDL_PollEvent(FakeSDL::Event *);
friend int ::SDL_PollEvent(SDL::Event *);
public:
/// Get the single Core instance or make one.
static Core& getInstance()
@ -103,20 +106,25 @@ namespace DFHack
Buildings * getBuildings();
/// get the constructions module
Constructions * getConstructions();
/// sets the current hotkey command
bool setHotkeyCmd( std::string cmd );
/// removes the hotkey command and gives it to the caller thread
std::string getHotkeyCmd( void );
DFHack::Process * p;
DFHack::VersionInfo * vinfo;
DFHack::Console * con;
private:
Core();
bool Init();
int Update (void);
int Shutdown (void);
void SDL_Event(FakeSDL::Event* event);
int SDL_Event(SDL::Event* event, int orig_return);
Core(Core const&); // Don't Implement
void operator=(Core const&); // Don't implement
bool errorstate;
// mutex for access to DF
DFMutex * AccessMutex;
SDL::Mutex * AccessMutex;
// FIXME: shouldn't be kept around like this
DFHack::VersionInfoFactory * vif;
// Module storage
@ -136,5 +144,13 @@ namespace DFHack
} s_mods;
std::vector <Module *> allModules;
DFHack::PluginManager * plug_mgr;
// hotkey-related stuff
int hotkey_states[16];
std::string hotkey_cmd;
bool hotkey_set;
SDL::Mutex * HotkeyMutex;
SDL::Cond * HotkeyCond;
// Very important!
bool started;
};
}

@ -32,29 +32,37 @@ distribution.
#include "dfhack/Export.h"
#include <string>
#include <stdint.h>
#include "dfhack/SDL_fakes/events.h"
#include "dfhack/SDL_fakes/keyboard.h"
#include "dfhack/SDL_fakes/keysym.h"
// function and variable pointer... we don't try to understand what SDL does here
typedef void * fPtr;
typedef void * vPtr;
struct DFMutex;
struct DFThread;
struct DFLibrary;
namespace SDL
{
union Event;
struct Thread;
struct Mutex;
struct Cond;
}
// mutex and thread functions. We can call these.
DFhackCExport DFMutex * SDL_CreateMutex(void);
DFhackCExport int SDL_mutexP(DFMutex *);
DFhackCExport int SDL_mutexV(DFMutex *);
DFhackCExport void SDL_DestroyMutex(DFMutex *);
DFhackCExport DFThread *SDL_CreateThread(int (*fn)(void *), void *data);
// mutex stuff
DFhackCExport SDL::Mutex * SDL_CreateMutex(void);
DFhackCExport int SDL_mutexP(SDL::Mutex *);
DFhackCExport int SDL_mutexV(SDL::Mutex *);
DFhackCExport void SDL_DestroyMutex(SDL::Mutex *);
// thread stuff
DFhackCExport SDL::Thread *SDL_CreateThread(int (*fn)(void *), void *data);
DFhackCExport uint32_t SDL_ThreadID();
// condition variables
DFhackCExport SDL::Cond *SDL_CreateCond(void);
DFhackCExport void SDL_DestroyCond(SDL::Cond *cond);
DFhackCExport int SDL_CondSignal(SDL::Cond *cond);
DFhackCExport int SDL_CondWait(SDL::Cond *cond, SDL::Mutex * mut);
// these functions are here because they call into DFHack::Core and therefore need to
// be declared as friend functions/known
DFhackCExport int SDL_NumJoysticks(void);
DFhackCExport void SDL_Quit(void);
DFhackCExport int SDL_PollEvent(FakeSDL::Event* event);
DFhackCExport int SDL_PollEvent(SDL::Event* event);
/*
// not yet.
DFhackCExport int SDL_Init(uint32_t flags);

@ -92,13 +92,15 @@ namespace DFHack
};
class DFHACK_EXPORT PluginManager
{
public:
// PRIVATE METHODS
friend class Core;
PluginManager(Core * core);
~PluginManager();
Plugin *getPluginByName (const std::string & name);
command_result InvokeCommand( std::string & command, std::vector <std::string> & parameters);
void OnUpdate( void );
//FIXME: how do we deal with errors inside DF? Unhandled exceptions are deadly.
// PUBLIC METHODS
public:
const Plugin *getPluginByName (const std::string & name);
command_result InvokeCommand( std::string & command, std::vector <std::string> & parameters );
const Plugin* operator[] (std::size_t index)
{
if(index >= all_plugins.size())
@ -109,6 +111,7 @@ namespace DFHack
{
return all_plugins.size();
}
// DATA
private:
std::map <std::string, const PluginCommand *> commands;
std::vector <Plugin *> all_plugins;

@ -20,10 +20,13 @@
slouken@libsdl.org
*/
// Fake - only structs. Shamelessly pilfered from the SDL library.
// Needed for processing its event types without polluting our namespaces with C garbage
#pragma once
#include "keyboard.h"
namespace FakeSDL
namespace SDL
{
enum ButtonState
{

@ -27,7 +27,7 @@
#include "keysym.h"
#include <stdint.h>
namespace FakeSDL
namespace SDL
{
/** Keysym structure
*

@ -20,9 +20,12 @@
slouken@libsdl.org
*/
// Fake - only structs. Shamelessly pilfered from the SDL library.
// Needed for processing its event types without polluting our namespaces with C garbage
#pragma once
namespace FakeSDL
namespace SDL
{
/** What we really want is a mapping of every raw key on the keyboard.
* To support international keyboards, we use the range 0xA1 - 0xFF

@ -0,0 +1,35 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2011 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#pragma once
#include <string>
namespace DFHack
{
/// very generic representation of a virtual class... just the pointer to the vtable.
struct t_virtual
{
void * vptr;
std::string getClassName();
};
}

@ -28,6 +28,8 @@ distribution.
#include "dfhack/Export.h"
#include "dfhack/Module.h"
#include "dfhack/Virtual.h"
#include <string>
/**
* \defgroup grp_gui query DF's GUI state
@ -40,13 +42,27 @@ namespace DFHack
/**
* \ingroup grp_gui
*/
struct t_viewscreen
struct t_viewscreen : public t_virtual
{
int32_t type;
//There is more info in these objects, but I don't know what it is yet
t_viewscreen * child;
t_viewscreen * parent;
char unk1; // varies
char unk2; // state?
};
/**
* \ingroup grp_gui
*/
struct t_interface
{
int fps;
t_viewscreen view;
unsigned int flags; // ?
// more crud this way ...
};
#define NUM_HOTKEYS 16
/**
* The hotkey structure
* \ingroup grp_gui
*/
struct t_hotkey
@ -57,8 +73,10 @@ namespace DFHack
int32_t y;
int32_t z;
};
typedef t_hotkey hotkey_array[16];
typedef t_hotkey hotkey_array[NUM_HOTKEYS];
/**
* One tile of the screen. Possibly outdated.
* \ingroup grp_gui
*/
struct t_screen
@ -70,6 +88,7 @@ namespace DFHack
uint8_t gtile;
uint8_t grayscale;
};
/**
* The Gui module
* \ingroup grp_modules
@ -91,6 +110,16 @@ namespace DFHack
bool getCursorCoords (int32_t &x, int32_t &y, int32_t &z);
bool setCursorCoords (const int32_t x, const int32_t y, const int32_t z);
/*
* Gui screens
*/
/// handle to the interface object
t_interface * interface;
/// Get the current top-level view-screen
t_viewscreen * GetCurrentScreen();
/// The DF menu state (designation menu ect)
uint32_t * menu_state;
/*
* Hotkeys (DF's zoom locations)
*/
@ -105,11 +134,6 @@ namespace DFHack
* Screen tiles
*/
bool getScreenTiles(int32_t width, int32_t height, t_screen screen[]);
/// read the DF menu view state (stock screen, unit screen, other screens
bool ReadViewScreen(t_viewscreen &);
/// read the DF menu state (designation menu ect)
uint32_t ReadMenuState();
private:
struct Private;

@ -34,6 +34,7 @@ distribution.
#include "dfhack/Module.h"
#include "dfhack/modules/Vegetation.h"
#include <vector>
#include "dfhack/Virtual.h"
/**
* \defgroup grp_maps Maps module and its types
@ -145,10 +146,6 @@ namespace DFHack
uint32_t origin;
};
struct t_virtual
{
void * vptr;
};
/**
* mineral vein object - bitmap with a material type
* \ingroup grp_maps

@ -48,14 +48,9 @@ struct Gui::Private
{
Private()
{
Started = ViewScreeInited = MenuStateInited = false;
Started = false;
StartedScreen = false;
}
bool ViewScreeInited;
uint32_t view_screen_offset;
bool MenuStateInited;
uint32_t current_menu_state_offset;
bool Started;
uint32_t window_x_offset;
@ -77,6 +72,8 @@ Gui::Gui()
d->owner = c.p;
VersionInfo * mem = c.vinfo;
OffsetGroup * OG_Gui = mem->getGroup("GUI");
// Setting up hotkeys
try
{
hotkeys = (hotkey_array *) OG_Gui->getAddress("hotkeys");
@ -85,18 +82,27 @@ Gui::Gui()
{
hotkeys = 0;
};
// Setting up menu state
try
{
d->current_menu_state_offset = OG_Gui->getAddress("current_menu_state");
d->MenuStateInited = true;
menu_state = (uint32_t *) OG_Gui->getAddress("current_menu_state");
}
catch(exception &){};
catch(Error::All &)
{
menu_state = 0;
};
// Setting up the view screen stuff
try
{
d->view_screen_offset = OG_Gui->getAddress ("view_screen");
d->ViewScreeInited = true;
interface = (t_interface *) OG_Gui->getAddress ("interface");
}
catch(exception &){};
catch(exception &)
{
interface = 0;
};
OffsetGroup * OG_Position;
try
{
@ -132,30 +138,19 @@ bool Gui::Finish()
return true;
}
uint32_t Gui::ReadMenuState()
{
if(d->MenuStateInited)
return(d->owner->readDWord(d->current_menu_state_offset));
return false;
}
// FIXME: variable screenAddr set but not used [-Wunused-but-set-variable]
bool Gui::ReadViewScreen (t_viewscreen &screen)
t_viewscreen * Gui::GetCurrentScreen()
{
if (!d->ViewScreeInited) return false;
Process * p = d->owner;
uint32_t last = p->readDWord (d->view_screen_offset);
uint32_t screenAddr = p->readDWord (last);
uint32_t nextScreenPtr = p->readDWord (last + 4);
while (nextScreenPtr != 0)
if(!interface)
return 0;
t_viewscreen * ws = &interface->view;
while(ws)
{
last = nextScreenPtr;
screenAddr = p->readDWord (nextScreenPtr);
nextScreenPtr = p->readDWord (nextScreenPtr + 4);
if(ws->child)
ws = ws->child;
else
return ws;
}
Core & c = Core::getInstance();
return c.vinfo->resolveObjectToClassID (last, screen.type);
return 0;
}
bool Gui::getViewCoords (int32_t &x, int32_t &y, int32_t &z)

@ -97,7 +97,7 @@ DFhackCExport command_result plugin_shutdown ( Core * c )
DFhackCExport command_result reveal(DFHack::Core * c, std::vector<std::string> & params)
{
bool no_hell = false;
if(params[0] == "safe")
if(params.size() && params[0] == "safe")
{
no_hell = true;
}
@ -177,7 +177,7 @@ DFhackCExport command_result reveal(DFHack::Core * c, std::vector<std::string> &
c->Resume();
dfout << "Map revealed." << std::endl;
if(!no_hell)
dfout << "Unpausing can unleash the forces of hell, so it has been temporarily disabled!" << std::endl;
dfout << "Unpausing can unleash the forces of hell, so it has been temporarily disabled." << std::endl;
dfout << "Run 'unreveal' to revert to previous state." << std::endl;
return CR_OK;
}