Mercurial > projects > mde
view mde/input/config.d @ 7:b544c3a7c9ca
Some changes to exceptions and a few more debug commands.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Wed, 16 Jan 2008 12:48:07 +0000 |
parents | 9a990644948c |
children | f63f4f41a2dc |
line wrap: on
line source
/// This module contains a class for holding configs and handles saving, loading and editing. module mde.input.config; debug import mde.text.format; import mde.input.exception; import mde.mergetag.read; import mde.text.parse; import tango.util.log.Log : Log, Logger; import tango.util.collection.TreeBag : TreeBag; Logger logger; static this() { logger = Log.getLogger ("mde.input.config"); } /** Class to hold the configuration for the input system. Thus loading and switching between * multiple configurations should be easy. * * Class extends DataSection so that it can be loaded by mergetag easily. */ class Config : DataSection { alias uint[] outQueue; // This is the type for the out queue config data. /** Button event type bit-codes * * These bitcodes are OR'd to the identifier code for the input device, to indicate which type * of input they are for. E.g. when a key event is recieved with code x, look up * $(_B _B.SDLKEY) | x in button. Keyboard events are SDL-specific since the codes may differ for other * libraries. * * For joystick hat events, a motion should be converted into up and down events on separate * U,L,D,R positions and up and down events sent to the appropriate outputs. */ enum B : uint { KEY = 0x8000_0000u, /// 0x8000_0000u SDLKEY = 0x8800_0000u, /// 0x8800_0000u MOUSE = 0x4000_0000u, /// 0x4000_0000u JOYBUTTON = 0x2000_0000u, /// 0x2000_0000u JOYHAT = 0x1000_0000u, /// 0x1000_0000u JOYHAT_U = 0x1800_0000u, /// 0x1800_0000u JOYHAT_D = 0x1400_0000u, /// 0x1400_0000u JOYHAT_L = 0x1200_0000u, /// 0x1200_0000u JOYHAT_R = 0x1100_0000u, /// 0x1100_0000u } /** Axis event type bit-codes * * Well, SDL only supports one type of axis now, but this could be extended in the future. */ enum A : uint { JOYAXIS = 0x8000_0000u, /// 0x8000_0000u } /** Mouse & Joystick ball event type bit-codes * * Currently, mouse input only comes from the window manager: the code is exactly M.WMMOUSE. */ enum M : uint { MOUSE = 0x8000_0000u, /// 0x8000_0000u WMMOUSE = 0x8800_0000u, /// 0x8800_0000u JOYBALL = 0x4000_0000u, /// 0x4000_0000u } /** Output queues: the core of the input configuration. * * button, axis and mouse each have their own index specifications. This is split into two parts: * the first byte specifies the type of input (given by the above enums), and the last three * bytes define where the input comes from. * * For B.SDLKEY, the last three bytes are for the SDL keysym. * For B.MOUSE, B.JOY*, A.JOY* & M.JOY*, the last three bytes are split into two sets of 12 * bits (with masks 0x00FF_F000 and 0x0000_0FFF), the higher of which specifies the device * (which mouse or joystick), and the lower of which specifies the button/axis/ball. * * The code for mouse motion is currently only M.WMMOUSE. If/when multiple mice are supported * new codes will be defined. */ outQueue[uint] button; outQueue[uint] axis; /// ditto outQueue[uint] mouse; /// ditto debug uint dnbc; // debug num button configs char[] name; /// Name for user to save this under. uint[] inheritants; /// Other profiles to inherit. // FIXME: using uint IDs really isn't nice... static Config[uint] configs; /// All configs loaded by load(). private static TreeBag!(char[]) loadedFiles; // all filenames load tried to read //BEGIN File loading/saving code static this () { loadedFiles = new TreeBag!(char[]); } // Load all configs from a file. static void load (char[] filename) { if (loadedFiles.contains (filename)) return; // forget it; already done that loadedFiles.add (filename); Reader file; try { file = new Reader(filename, null, true); // open and read header // TODO: also load user-config file file.dataSecCreator = function DataSection (ID) { return new Config; }; enum : ID { CONFIGS } ID[] configs; // active config sections (may not exist) uint[]* configs_p = CONFIGS in file.dataset.header._uintA; if (configs_p) file.read(cast(ID[]) *configs_p); // restrict to this set IF a restriction was given else file.read(); // otherwise read all } catch (MTException) { logger.error ("Unable to load configs from: " ~ filename); throw new ConfigLoadException; } // FIXME: don't override configs if not empty configs = cast (Config[uint]) file.dataset.sec; // NOTE: this is in some ways dangerous (assuming all DataSections are Configs), but they should be. debug { char tmp[128] = void; logger.info (logger.format (tmp, "Loaded {} config sections.", configs.length)); foreach (id, cfg; configs) { logger.trace ("Section "~format!(uint)(id)~": " ~ format!(uint[][uint])(cfg.button) ~ " (" ~ format!(uint)(cfg.dnbc) ~ ")"); } } } private enum QUEUE : ID { BUTTON, AXIS, MOUSE } private this() {} // Private since this class should only be created from here. void addTag (char[] tp, ID id, char[] dt) { if (tp == "uint[][uint]") { if (id == QUEUE.BUTTON) { button = cast(outQueue[uint]) parse!(uint[][uint]) (dt); debug logger.trace ("Added button config: " ~ format!(uint[][uint])(button)); debug ++dnbc; } else if (id == QUEUE.AXIS) axis = cast(outQueue[uint]) parse!(uint[][uint]) (dt); else if (id == QUEUE.MOUSE) mouse = cast(outQueue[uint]) parse!(uint[][uint]) (dt); else { char[80] tmp; logger.info (logger.format(tmp, "Unexpected tag encountered with ID {}", id)); } } // FIXME: add support for name and inheritants. else throw new MTUnknownTypeException ("Input Config: only uint[][uint] type supported"); } void writeAll (ItemDelg) { // FIXME } debug void debugFunc () { logger.trace ("After parse: " ~ format!(uint[][uint])(button) ~ " (" ~ format!(uint)(dnbc) ~ ")"); } //END File loading/saving code }