📄 config.h
字号:
// config.h -- by Thatcher Ulrich <tu@tulrich.com> 22 July 2001// This source code has been donated to the Public Domain. Do// whatever you want with it.// Configuration glue. C++ interface to Lua scripting library, plus utilities.#ifndef CONFIG_H#define CONFIG_H// @@ this probably doesn't belong in "base"... move it somewhere and// finish later...#if 0extern "C" {#include <lua.h>}namespace config { void open(); void close(); // void clear(); // // Globals to help interface w/ Lua. User code usually won't be // interested in these. // extern lua_State* L; // Lua state. Passed as a param to most lua_ calls. extern int g_cfloat_tag; // TODO: no need to expose this, so hide it (need to hide cfloat::lua_push()).};class cfloat// A class that holds a floating point value. Accessible from Lua via// a global variable. Has the time efficiency of an ordinary C++// float when accessed from C++, so it's OK to use these in inner// loops.{public: cfloat( float val ) // Constructs; does not assign to a Lua global variable. { m_value = val; } cfloat( const char* name, float val ) // Constructs, and assigns to the Lua global variable whose name is given. { m_value = val; lua_push(); lua_setglobal( config::L, name ); } void lua_push() { // Identify us to Lua as a cfloat. config::open(); // make sure Lua is set up. lua_pushuserdata( config::L, this ); lua_settag( config::L, config::g_cfloat_tag ); } ~cfloat() { // do nothing? // set our global var to nil ??? To a Lua number equal to our value??? } operator float() // Return our value. { return m_value; } void operator=( float f ) // Set our value to f. { m_value = f; } // +=, -=, *=, /= etc // config::open() will hook in some handlers so Lua can have access to our value.//private: float m_value;};#define declare_cfloat( name, value ) cfloat name( #name, ( value ) )// Do we even need a C++ cfloat class? E.g. just use a pointer to// an ordinary float:// #define declare_cfloat(name, value) \x// extern float name = value; config::export_float(#name, &f);//// Probably still need a class constructor tho, to do that export automatically.// usage, very much like a C++ global float://// extern cfloat max_pixel_error;// declare_cfloat( max_pixel_error, 5.0f ); would this work?: cfloat name( #name ) = value;// declare_cfloat( max_pixel_error );//// // Use it like an ordinary float.// max_pixel_error = 10.f;// printf( "%f\n", max_pixel_error );//// // But, it can be accessed from Lua at nominal cost...//// config.lua:// max_pixel_error = 5.0f;//// Lua scripts, debugger or console can find and manipulate.class cvalue {// Hook to anonymous, dynamically typed Lua value. Holds a Lua// reference to its value for proper gc.//// Can use this for handy evaluation of Lua snippets, by passing some// Lua code to the constructor.public: cvalue( const cvalue& c ); cvalue( const char* lua_constructor ); ~cvalue(); static cvalue lua_stacktop_reference(); // factory; creates a reference to the Lua stack top, and pops.private: cvalue(); // Used only in cvalue::lua_stacktop_reference()public: void operator=( const char* str ); void operator=( float num ); void operator=( const cvalue& cval ); // other basic stuff, such as arithmetic ops, and string concatenation... operator float() const; // tonumber operator const char*() const; // tostring // Lua tables can be indexed by both strings and numbers. void set( const char* index, cvalue val ); void set( float index, cvalue val ); void set( cvalue index, cvalue val ); void set( const char* index, float f ); void set( float index, float f ); void set( const char* index, const char* str ); void set( float index, const char* str ); cvalue get( const char* index ); cvalue get( float index ); // const char* type(); void lua_push() const; // push our value onto the Lua stack.private: int m_lua_ref;};// cvalue cv("return point(10, 10)");// cv.set("x", 20);// printf("y = %f\n", (float) cv.get("y"));class cvar {// Hook to Lua variable. cvars are dynamically typed and have to do// hash lookups & type coercion to access from the C++ side. Some// gc issues with conversion to C strings.public: cvar( const char* name ); cvar( const char* name, const cvalue& val ); cvar( const char* name, const char* str ); cvar( const char* name, float val ); ~cvar();// const char* get_name() const; // is this useful, maybe for debugging? Build up the name, etc. Could maybe return a cvalue() and use Lua string-handling & gc. operator float() const; operator const char*() const; void operator=( float f ); void operator=( const char* s ); void operator=( cfloat c ); // cvalue access operator cvalue() const; void operator=( const cvalue& c ); // TODO: vec3 access // TODO: orientation access // TODO: actor, component access // cvar assignment void operator=( cvar c );private: void init(const char* name); void push_table_and_key() const; int m_lua_key_count; int* m_lua_key_reference; // Array of lua key references, for quicker lookup.};#define declare_cvar( name, value ) cvar name( #name, value )// e.g.//// declare_cvar( "varname", "string" );// float f = cvar( "varname" );// e.g.//// declare_cvar( snowflakes, 5.0f );// declare_cvar( snowflake_image, "snowflake.jpg" );//// snowflakes++;// snowflakes = 10;// for ( i = 0; i < snowflakes; i++ ) { // hash lookup here// make_snowflake( snowflake_image ); // hash lookup here// }//// how to do "varname = val" from c? config::set(var, float/string/cvalue); cset(var, val) == shorthand?//declare_cvalue("varname", "'string'");//declare_cstring(varname, "string"); // Will C preprocessor quote the embedded quotes???//declare_cfloat(varname, 10.f);// e.g.//// namespace playerprefs {// cvar jumpheight("playerprefs.jumpheight");// cvar runspeed("playerprefs.runspeed");// };//// The problem with this idiom is that it involves a lot of// error-prone duplicate typing of names. Really it would be nice to// have some C++ level construct to do constructors that look more// like Lua. Maybe some wacky macros do the trick:#if 0#define PREFS(tablename) \ namespace tablename { const char* _tablename = #tablename;#define PREF(varname) \ cvar varname(_tablename, #varname)#define END_PREFS }PREFS(playerprefs) PREF(jumpheight); PREF(runspeed);END_PREFS#endif // 0// Access the cvars using namespace syntax. So,// float vspeed = compute_vspeed(playerprefs::jumpheight, gravity);// Can't do nested stuff like://// PREFS(actorprefs.player.movement)// etc...;// The best-looking and least-error-prone way would be to use some// kind of preprocessor that scans C++ and replaces Lua prefs// declarations. But that's somewhat radical. It might look like// this://// PREFS actorprefs::player::movement {// cfloat runspeed = 10;// cvar jumpheight = 27;// cproperty ....;// };//// which would emit C++ code://// namespace actorprefs { namespace player { namespace movement {// cvar runspeed("runspeed", 10);// cvar jumpheight("jumpheight", 27);// } } }//// And then access via://// float vspeed = compute_vspeed(actorprefs::player::movement, gravity);//// could even use "using" declarations...#endif // 0#endif // CONFIG_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -