2011-12-24 03:51:58 -07:00
|
|
|
/*
|
|
|
|
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>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
|
2011-12-31 04:48:42 -07:00
|
|
|
#include "Core.h"
|
|
|
|
#include "BitArray.h"
|
2011-12-24 03:51:58 -07:00
|
|
|
|
2011-12-24 06:27:35 -07:00
|
|
|
// Stop some MS stupidity
|
|
|
|
#ifdef interface
|
|
|
|
#undef interface
|
|
|
|
#endif
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
namespace DFHack
|
|
|
|
{
|
|
|
|
class virtual_class {};
|
|
|
|
|
2011-12-24 06:17:01 -07:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
typedef void *virtual_ptr;
|
|
|
|
#else
|
|
|
|
typedef virtual_class *virtual_ptr;
|
|
|
|
#endif
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
class DFHACK_EXPORT virtual_identity {
|
|
|
|
static virtual_identity *list;
|
|
|
|
static std::map<void*, virtual_identity*> known;
|
|
|
|
|
|
|
|
virtual_identity *prev, *next;
|
|
|
|
const char *dfhack_name;
|
|
|
|
const char *original_name;
|
|
|
|
virtual_identity *parent;
|
|
|
|
std::vector<virtual_identity*> children;
|
|
|
|
|
|
|
|
void *vtable_ptr;
|
|
|
|
bool has_children;
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent);
|
|
|
|
|
2011-12-24 06:17:01 -07:00
|
|
|
static void *get_vtable(virtual_ptr instance_ptr) { return *(void**)instance_ptr; }
|
2011-12-24 03:51:58 -07:00
|
|
|
|
|
|
|
public:
|
|
|
|
const char *getName() { return dfhack_name; }
|
|
|
|
const char *getOriginalName() { return original_name ? original_name : dfhack_name; }
|
|
|
|
|
|
|
|
virtual_identity *getParent() { return parent; }
|
|
|
|
const std::vector<virtual_identity*> &getChildren() { return children; }
|
|
|
|
|
2011-12-29 05:30:55 -07:00
|
|
|
public:
|
2011-12-24 06:17:01 -07:00
|
|
|
static virtual_identity *get(virtual_ptr instance_ptr);
|
2011-12-29 05:30:55 -07:00
|
|
|
|
|
|
|
bool is_subclass(virtual_identity *subtype);
|
2011-12-24 06:17:01 -07:00
|
|
|
bool is_instance(virtual_ptr instance_ptr) {
|
2011-12-24 03:51:58 -07:00
|
|
|
if (!instance_ptr) return false;
|
|
|
|
if (vtable_ptr) {
|
|
|
|
void *vtable = get_vtable(instance_ptr);
|
|
|
|
if (vtable == vtable_ptr) return true;
|
|
|
|
if (!has_children) return false;
|
|
|
|
}
|
2011-12-29 05:30:55 -07:00
|
|
|
return is_subclass(get(instance_ptr));
|
2011-12-24 03:51:58 -07:00
|
|
|
}
|
|
|
|
|
2011-12-24 06:17:01 -07:00
|
|
|
bool is_direct_instance(virtual_ptr instance_ptr) {
|
2011-12-24 03:51:58 -07:00
|
|
|
if (!instance_ptr) return false;
|
|
|
|
return vtable_ptr ? (vtable_ptr == get_vtable(instance_ptr))
|
2011-12-29 05:30:55 -07:00
|
|
|
: (this == get(instance_ptr));
|
2011-12-24 03:51:58 -07:00
|
|
|
}
|
|
|
|
|
2011-12-29 05:30:55 -07:00
|
|
|
public:
|
|
|
|
bool can_instantiate() { return (vtable_ptr != NULL); }
|
|
|
|
virtual_ptr instantiate() { return can_instantiate() ? do_instantiate() : NULL; }
|
|
|
|
static virtual_ptr clone(virtual_ptr obj);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual virtual_ptr do_instantiate() = 0;
|
|
|
|
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) = 0;
|
|
|
|
public:
|
|
|
|
static void Init(Core *core);
|
|
|
|
|
|
|
|
// Strictly for use in virtual class constructors
|
|
|
|
void adjust_vtable(virtual_ptr obj, virtual_identity *main);
|
2011-12-24 03:51:58 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
2011-12-24 06:17:01 -07:00
|
|
|
inline T *virtual_cast(virtual_ptr ptr) {
|
2011-12-24 03:51:58 -07:00
|
|
|
return T::_identity.is_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-02 07:46:24 -07:00
|
|
|
#define VIRTUAL_CAST_VAR(var,type,input) type *var = virtual_cast<type>(input)
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
template<class T>
|
2011-12-24 06:17:01 -07:00
|
|
|
inline T *strict_virtual_cast(virtual_ptr ptr) {
|
2011-12-24 03:51:58 -07:00
|
|
|
return T::_identity.is_direct_instance(ptr) ? static_cast<T*>(ptr) : NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-02 07:46:24 -07:00
|
|
|
#define STRICT_VIRTUAL_CAST_VAR(var,type,input) type *var = strict_virtual_cast<type>(input)
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
void InitDataDefGlobals(Core *core);
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
T *ifnull(T *a, T *b) { return a ? a : b; }
|
2012-01-03 08:25:55 -07:00
|
|
|
|
2012-01-09 05:20:17 -07:00
|
|
|
// Enums
|
2012-01-03 08:25:55 -07:00
|
|
|
template<class T, T start, bool (*isvalid)(T)>
|
|
|
|
inline T next_enum_item_(T v) {
|
|
|
|
v = T(int(v) + 1);
|
|
|
|
return isvalid(v) ? v : start;
|
|
|
|
}
|
2012-01-03 11:56:05 -07:00
|
|
|
|
2012-01-06 11:08:09 -07:00
|
|
|
template<class T>
|
|
|
|
struct enum_list_attr {
|
|
|
|
int size;
|
|
|
|
const T *items;
|
|
|
|
};
|
2012-01-03 11:56:05 -07:00
|
|
|
|
2012-01-09 05:20:17 -07:00
|
|
|
// Bitfields
|
|
|
|
struct bitfield_item_info {
|
|
|
|
const char *name;
|
|
|
|
int size;
|
|
|
|
};
|
|
|
|
|
2012-01-03 11:56:05 -07:00
|
|
|
DFHACK_EXPORT std::string bitfieldToString(const void *p, int size, const bitfield_item_info *items);
|
2012-01-08 09:02:12 -07:00
|
|
|
DFHACK_EXPORT int findBitfieldField(const std::string &name, int size, const bitfield_item_info *items);
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline int findBitfieldField(const T &val, const std::string &name) {
|
|
|
|
return findBitfieldField(name, sizeof(val.whole), val.get_items());
|
|
|
|
}
|
2012-01-03 11:56:05 -07:00
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline std::string bitfieldToString(const T &val) {
|
|
|
|
return bitfieldToString(&val.whole, sizeof(val.whole), val.get_items());
|
|
|
|
}
|
2011-12-24 03:51:58 -07:00
|
|
|
}
|
|
|
|
|
2012-01-09 05:20:17 -07:00
|
|
|
template<class T>
|
|
|
|
int linear_index(const DFHack::enum_list_attr<T> &lst, T val) {
|
|
|
|
for (int i = 0; i < lst.size; i++)
|
|
|
|
if (lst.items[i] == val)
|
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline int linear_index(const DFHack::enum_list_attr<const char*> &lst, const std::string &val) {
|
|
|
|
for (int i = 0; i < lst.size; i++)
|
|
|
|
if (lst.items[i] == val)
|
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
namespace df
|
|
|
|
{
|
2011-12-29 05:30:55 -07:00
|
|
|
using DFHack::virtual_ptr;
|
|
|
|
using DFHack::virtual_identity;
|
2011-12-24 03:51:58 -07:00
|
|
|
using DFHack::virtual_class;
|
2012-01-03 11:56:05 -07:00
|
|
|
using DFHack::bitfield_item_info;
|
2012-01-06 11:08:09 -07:00
|
|
|
using DFHack::enum_list_attr;
|
2011-12-24 03:51:58 -07:00
|
|
|
using DFHack::BitArray;
|
|
|
|
|
|
|
|
template<class T>
|
2011-12-29 05:30:55 -07:00
|
|
|
class class_virtual_identity : public virtual_identity {
|
2011-12-24 03:51:58 -07:00
|
|
|
public:
|
|
|
|
class_virtual_identity(const char *dfhack_name, const char *original_name, virtual_identity *parent)
|
|
|
|
: virtual_identity(dfhack_name, original_name, parent) {};
|
2011-12-29 05:30:55 -07:00
|
|
|
|
|
|
|
T *instantiate() { return static_cast<T*>(virtual_identity::instantiate()); }
|
|
|
|
T *clone(T* obj) { return static_cast<T*>(virtual_identity::clone(obj)); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual virtual_ptr do_instantiate() { return new T(); }
|
|
|
|
virtual void do_copy(virtual_ptr tgt, virtual_ptr src) { *static_cast<T*>(tgt) = *static_cast<T*>(src); }
|
2011-12-24 03:51:58 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
template<class EnumType, class IntType = int32_t>
|
|
|
|
struct enum_field {
|
|
|
|
IntType value;
|
|
|
|
|
|
|
|
enum_field() {}
|
|
|
|
enum_field(EnumType ev) : value(IntType(ev)) {}
|
|
|
|
template<class T>
|
|
|
|
enum_field(enum_field<EnumType,T> ev) : value(IntType(ev.value)) {}
|
|
|
|
|
|
|
|
operator EnumType () { return EnumType(value); }
|
|
|
|
enum_field<EnumType,IntType> &operator=(EnumType ev) {
|
|
|
|
value = IntType(ev); return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-01-07 08:21:07 -07:00
|
|
|
template<class EnumType, class IntType1, class IntType2>
|
|
|
|
inline bool operator== (enum_field<EnumType,IntType1> a, enum_field<EnumType,IntType2> b)
|
|
|
|
{
|
|
|
|
return EnumType(a) == EnumType(b);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class EnumType, class IntType1, class IntType2>
|
|
|
|
inline bool operator!= (enum_field<EnumType,IntType1> a, enum_field<EnumType,IntType2> b)
|
|
|
|
{
|
|
|
|
return EnumType(a) != EnumType(b);
|
|
|
|
}
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
namespace enums {}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ENUM_ATTR(enum,attr,val) (df::enums::enum::get_##attr(val))
|
|
|
|
#define ENUM_ATTR_STR(enum,attr,val) DFHack::ifnull(ENUM_ATTR(enum,attr,val),"?")
|
|
|
|
#define ENUM_KEY_STR(enum,val) ENUM_ATTR_STR(enum,key,val)
|
|
|
|
#define ENUM_FIRST_ITEM(enum) (df::enums::enum::_first_item_of_##enum)
|
|
|
|
#define ENUM_LAST_ITEM(enum) (df::enums::enum::_last_item_of_##enum)
|
|
|
|
|
2012-01-03 08:25:55 -07:00
|
|
|
#define ENUM_NEXT_ITEM(enum,val) \
|
|
|
|
(DFHack::next_enum_item_<df::enum,ENUM_FIRST_ITEM(enum),df::enums::enum::is_valid>(val))
|
|
|
|
#define FOR_ENUM_ITEMS(enum,iter) \
|
|
|
|
for(df::enum iter = ENUM_FIRST_ITEM(enum); iter < ENUM_LAST_ITEM(enum); iter = df::enum(1+int(iter)))
|
|
|
|
|
2011-12-24 03:51:58 -07:00
|
|
|
namespace df {
|
|
|
|
#define DF_KNOWN_GLOBALS \
|
2011-12-29 05:30:55 -07:00
|
|
|
GLOBAL(cursor,cursor) \
|
|
|
|
GLOBAL(selection_rect,selection_rect) \
|
2011-12-24 03:51:58 -07:00
|
|
|
GLOBAL(world,world) \
|
|
|
|
GLOBAL(ui,ui) \
|
|
|
|
GLOBAL(gview,interface) \
|
|
|
|
GLOBAL(init,init) \
|
2012-01-01 12:05:45 -07:00
|
|
|
GLOBAL(d_init,d_init) \
|
2012-01-04 08:39:38 -07:00
|
|
|
SIMPLE_GLOBAL(job_next_id,int) \
|
2012-01-01 12:05:45 -07:00
|
|
|
SIMPLE_GLOBAL(ui_look_cursor,int) \
|
|
|
|
SIMPLE_GLOBAL(ui_workshop_job_cursor,int) \
|
2012-01-14 08:31:43 -07:00
|
|
|
SIMPLE_GLOBAL(ui_building_item_cursor,int) \
|
2012-01-02 04:18:23 -07:00
|
|
|
SIMPLE_GLOBAL(ui_workshop_in_add,bool) \
|
2012-01-14 08:31:43 -07:00
|
|
|
SIMPLE_GLOBAL(ui_selected_unit,int) \
|
|
|
|
SIMPLE_GLOBAL(cur_year,int) \
|
|
|
|
SIMPLE_GLOBAL(cur_year_tick,int) \
|
2012-01-01 12:05:45 -07:00
|
|
|
GLOBAL(ui_sidebar_menus,ui_sidebar_menus) \
|
|
|
|
GLOBAL(ui_build_selector,ui_build_selector) \
|
2012-01-14 08:31:43 -07:00
|
|
|
GLOBAL(ui_look_list,ui_look_list) \
|
|
|
|
GLOBAL(ui_unit_view_mode, ui_unit_view_mode)
|
|
|
|
|
2012-01-01 12:05:45 -07:00
|
|
|
|
|
|
|
#define SIMPLE_GLOBAL(name,tname) \
|
2011-12-24 03:51:58 -07:00
|
|
|
namespace global { extern DFHACK_EXPORT tname *name; }
|
2012-01-01 12:05:45 -07:00
|
|
|
#define GLOBAL(name,tname) \
|
|
|
|
struct tname; SIMPLE_GLOBAL(name,tname)
|
2011-12-24 03:51:58 -07:00
|
|
|
DF_KNOWN_GLOBALS
|
|
|
|
#undef GLOBAL
|
2012-01-01 12:05:45 -07:00
|
|
|
#undef SIMPLE_GLOBAL
|
2011-12-24 03:51:58 -07:00
|
|
|
}
|