Changeset 76

Show
Ignore:
Timestamp:
07/13/08 22:30:26 (5 months ago)
Author:
JoeCoder
Message:

This build is broken, please ignore.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/yage/core/array.d

    r73 r76  
    6969 
    7070 
    71 /// Return the element with the maximum value of an array. 
     71/// Return the element with the minimum or maximum value of an array. 
    7272T amax(T)(T[] array, ) 
    7373{   T m = array[0]; 
     
    7777    return m; 
    7878} 
    79 ///  
     79/// ditto 
    8080T amax(T, K)(T[] array, K delegate(T elem) getKey) 
    8181{   T m = array[0]; 
     
    8686    return m; 
    8787} 
    88 T amax(T, K)(T[T] array, K delegate(T elem) getKey) 
    89 {   T m; 
    90     K mk; 
    91     foreach (T a; array) 
    92     {   m = a; 
    93         mk = getKey(a); 
    94         break;       
    95     } 
    96     foreach (T a; array) 
    97     {   if (getKey(a)>mk) 
    98             m=a;     
    99     } 
    100     return m; 
    101 
    102  
    103 /// Return the minimum value of an array. 
     88/// ditto 
    10489T amin(T)(T[] array) 
    10590{   T m = array[0]; 
     
    10994    return m; 
    11095} 
     96/// ditto 
     97T amin(T, K)(T[] array, K delegate(T elem) getKey) 
     98{   T m = array[0]; 
     99    K mk = getKey(array[0]); 
     100    foreach (T a; array) 
     101        if (getKey(a)<mk) 
     102            m=a;     
     103    return m; 
     104} 
     105 
    111106 
    112107/** 
  • trunk/yage/core/color.d

    r68 r76  
    1919 * so Color(0x6633ff00).hex == "00FF3366" 
    2020 * All Colors default to transparent black. 
    21  * TODO: Convert to using four floats for better arithmetic 
     21 * TODO: Convert to using four floats for better arithmetic? 
    2222 *  
    2323 * Example: 
     
    3131struct Color 
    3232{ 
    33     private static real frac = 1.0f/255; 
     33    private const real frac = 1.0f/255; 
    3434     
    3535    union 
     
    136136            case "yellow":  return Color(0xFF00FFFF); 
    137137            default: break; 
    138         }        
    139      
     138        } 
     139         
     140        // Allow hex colors to start with hash. 
     141        if (string[0] == '#') 
     142            string = string[1..length]; 
     143             
    140144        // Append alpha to 6-digit hex string. 
    141145        if (string.length == 6) 
    142             string ~= "FF";         
    143          
    144         // Convert string one char at a a time. 
     146            string ~= "FF"; // creates garbage! 
     147         
     148        // Convert string one char at a time. 
    145149        Color result; 
    146150        int digit; 
     
    210214    unittest 
    211215    {   assert(Color.sizeof == 4); 
    212          
     216            
    213217        // Test initializers 
    214218        assert(Color([0, 102, 51, 255]).hex == "006633FF"); 
  • trunk/yage/core/tree.d

    r73 r76  
    2020class Tree(T) 
    2121{    
    22     T parent; 
    23     T[] children; 
    24     int index=-1; 
    25      
    26     /// Ensure that child is removed from its parent. 
    27 //  ~this() 
    28 //  {   remove();        
    29 //  } 
     22    protected T parent;         // reference to parent 
     23    protected T[] children;     // array of this element's children. 
     24    protected int index=-1;     // index of this element in its parent's array, -1 if no parent. 
    3025     
    3126    /** 
     
    6661    } 
    6762     
    68     /// Is elem a child of this element? 
     63    /** 
     64     * Is elem a child of this element? 
     65     * This function will also return false if elem is null. */  
    6966    bool isChild(T elem) 
    70     {   if (elem.index < 0 || elem.index >= children.length) 
     67    {   if (!elem || elem.index < 0 || elem.index >= children.length) 
    7168            return false; 
    7269        return cast(bool)(children[elem.index] == elem); 
  • trunk/yage/core/vector.d

    r67 r76  
    4141    } 
    4242 
    43     invariant 
    44     {   foreach (T t; v) 
    45             assert(t != float.nan); 
    46     } 
    47  
    4843    /// Create a zero vector 
    4944    static VST opCall() 
     
    7267        VST res; 
    7368        res.v[0..S] = s[0..S]; 
    74         return res; 
    75     } 
    76  
    77     /// 
    78     VST add(VST s) 
    79     {   VST res; 
    80         for (int i=0; i<v.length; i++) 
    81             res.v[i] = v[i]+s.v[i]; 
    8269        return res; 
    8370    } 
     
    10895    } 
    10996 
     97    /// Is this Vector inside a box/cube/etc. defined by topLeft and bottomRight 
     98    bool inside(VST topLeft, VST bottomRight, bool inclusive=true) 
     99    {   if (inclusive) 
     100        {   for (int i=0; i<v.length; i++) 
     101                if (v[i] <= topLeft[i] || v[i] >= bottomRight[i]) 
     102                    return false; 
     103        } else 
     104        {   for (int i=0; i<v.length; i++) 
     105                if (v[i] < topLeft[i] || v[i] > bottomRight[i]) 
     106                    return false; 
     107        }                    
     108        return true; 
     109    } 
     110     
    110111    /// Return the _length of the vector (the magnitude). 
    111112    float length() 
     
    121122    } 
    122123 
     124 
     125    /// Allow for linnear additions and subtractions among Vectors of the same size and type. 
     126    VST opAdd(VST s) 
     127    {   VST res; 
     128        for (int i=0; i<v.length; i++) 
     129            res.v[i] = v[i]+s.v[i]; 
     130        return res; 
     131    } 
     132    /// Ditto 
     133    void opAddAssign(VST s) 
     134    {   for (int i=0; i<v.length; i++) 
     135            v[i] += s.v[i]; 
     136    }    
     137    /// Ditto 
     138    VST opSub(VST s) 
     139    {   VST res; 
     140        for (int i=0; i<v.length; i++) 
     141            res.v[i] = v[i]-s.v[i]; 
     142        return res; 
     143    } 
     144    /// Ditto 
     145    void opSubAssign(VST s) 
     146    {   for (int i=0; i<v.length; i++) 
     147            v[i] -= s.v[i]; 
     148    } 
     149     
     150    /// Allow casting to float where appropriate 
     151    static if (is(T : float))   // if T can be implicitly cast to float 
     152    {   Vec!(S, float) opCast() 
     153        {   Vec!(S, float) result; 
     154            for (int i=0; i<v.length; i++) 
     155                result.v[i] = v[i]; 
     156            return result; 
     157    }   } 
     158     
    123159    /// Get the element at i 
    124     float opIndex(ubyte i) 
     160    float opIndex(size_t i) 
    125161    {   return v[i]; 
    126162    } 
    127163 
    128164    /// Assign value to the element at i 
    129     float opIndexAssign(T value, ubyte i) 
     165    float opIndexAssign(T value, size_t i) 
    130166    {   return v[i] = value; 
    131167    } 
     
    200236        {   float x, y, z; 
    201237    }   } 
    202  
    203     invariant 
    204     {   foreach (float t; v) 
    205             assert(t != float.nan); 
    206     } 
    207238 
    208239    /** Test some of the more common and more complex functions. */ 
  • trunk/yage/gui/style.d

    r67 r76  
    44module yage.gui.style; 
    55 
     6import std.regexp; 
     7import std.string; 
     8import std.stdio; 
     9import std.conv; 
    610import yage.core.color; 
    711import yage.core.vector; 
     12import yage.resource.resource; 
    813import yage.resource.material; 
     14import yage.resource.texture; 
    915 
    1016/** 
    1117 * Specifies the style of a Surface. 
    12  * Inspired by the CSS specification (http://www.w3schools.com/css/css_reference.asp)
    13  * Defined here to keep things well separated.  
    14  * Styles that have a top, right, bottom, left (like margin, border) are stored in arrays of length 4.*/ 
     18 * Inspired by the <a href="http://www.w3schools.com/css/css_reference.asp">CSS specification</a>
     19 *  
     20 * This struct is not fully documented. */ 
    1521struct Style 
    16 
    17     enum Unit {PX, PERCENT}; 
    18  
    19     Material backgroundMaterial; 
    20     Color   backgroundColor; 
    21     float[4] backgroundCoordinates;  // Texture coordinates for top, right, bottom, left edges 
    22  
    23     float[4] borderWidth; 
    24     Unit[4]  borderWidthUnits; 
    25     Color[4] borderColor; 
    26     Material decoration;        // Overrides radius and color if set 
    27     byte[5]  decorationRepeat;  // top, right, bottom, left, center 
    28  
    29     Material cursor; 
    30     bool visible = false;; 
    31     byte position; 
    32  
    33     //Font  fontFamily; 
    34     float fontSize; 
    35     byte  fontSizeUnits; 
    36     float fontWeight; 
    37  
    38     float[4] padding; 
    39     Unit[4] paddingUnits; 
    40  
    41     float[4] dimension;         // top, right, bottom, left 
    42     byte[4] dimensionUnits; 
    43     float height; 
    44     Unit  heightUnits; 
    45     float width; 
    46     Unit  widthUnits; 
    47     int   zIndex; 
    48  
    49     Color color; 
    50     byte  textAlign; 
    51     byte  textDecoration; 
    52     float lineHeight; 
    53     byte  lineHeightUnits; 
    54  
    55     /** 
    56      * Set properties from a string of text, css style. 
    57      * Example: 
    58      * style.set("border: 2px solid black; font-family: arial.ttf; color: white"); 
    59     void set(char[] style); */ 
     22{    
     23    // Types 
     24    alias ubyte Unit;    
     25     
     26    enum {  
     27        /** 
     28         * Enumeration values used to set units for measurements, such as width, padding, etc. */ 
     29        PX,          
     30        PERCENT,    /// ditto 
     31 
     32        /** 
     33         * Enumeration values used to set backgroundRepeat 
     34         * See: http://livedocs.adobe.com/flash/9.0/UsingFlash/help.html?content=WSd60f23110762d6b883b18f10cb1fe1af6-7db8.html*/ 
     35        NONE,        
     36        STRETCH,    /// ditto 
     37        NINESLICE,  /// ditto 
     38        /*, REPEAT, REPEATX, REPEATY*/  
     39 
     40        HIDDEN=false, 
     41        VISIBLE=true         
     42    } 
     43    // Associative arrays used for translation 
     44    static int[char[]] translate; 
     45    static this() 
     46    {   translate["none"] = NONE; 
     47        translate["stretch"] = STRETCH; 
     48        translate["nineslice"] = NINESLICE; 
     49    } 
     50 
     51    struct Edge(int S, T) 
     52    {   static assert (S==2 || S==4); 
     53        static if (S==2) 
     54        {   union 
     55            {   struct { T x, y; }; 
     56                T[S] values; 
     57        }   } 
     58        else 
     59        {   union 
     60            {   struct { T top, right, bottom, left; }; 
     61                T[S] values; 
     62        }   } 
     63    } 
     64     
     65     
     66     
     67    // Fields 
     68     
     69    // Background 
     70    GPUTexture backgroundMaterial;  
     71    Color backgroundColor; 
     72    byte backgroundRepeat = STRETCH; 
     73    union { 
     74        struct { 
     75            float backgroundPositionX=0; 
     76            float backgroundPositionY=0; 
     77        } 
     78        Edge!(2, float) backgroundPosition; 
     79    } 
     80    union { 
     81        struct { 
     82            Unit backgroundPositionXUnit=Style.PX; 
     83            Unit backgroundPositionYUnit=Style.PX; 
     84        } 
     85        Edge!(2, Unit) backgroundPositionUnits; 
     86    } 
     87     
     88    // Border 
     89    union {  
     90        struct {  
     91            float borderWidthTop=0; 
     92            float borderWidthRight=0; 
     93            float borderWidthBottom=0; 
     94            float borderWidthLeft=0;  
     95        }  
     96        Edge!(4, float) borderWidth;  
     97    } 
     98    union {  
     99        struct {  
     100            Unit borderWidthTopUnit; 
     101            Unit borderWidthRightUnit; 
     102            Unit borderWidthBottomUnit; 
     103            Unit borderWidthLeftUnit;    
     104        } 
     105        Edge!(4, Unit) borderWidthUnits; 
     106    } 
     107    union { 
     108        struct { 
     109            Color borderColorTop; 
     110            Color borderColorRight; 
     111            Color borderColorBottom; 
     112            Color borderColorLeft; 
     113        } 
     114        Edge!(4, Color) borderColor; 
     115    } 
     116         
     117 
     118    // Cursor 
     119    Material cursor; 
     120    float cursorSize; // in pixels 
     121         
     122    // Dimension 
     123    union {  
     124        struct {  
     125            float top=float.nan;        /// Distance of an edge from its parent, use float.nan to leave unset. 
     126            float right=float.nan;      /// ditto 
     127            float bottom=float.nan;     /// ditto 
     128            float left=float.nan;       /// ditto 
     129        }  
     130        Edge!(4, float) dimension;  /// Store all four dimension properties in one struct (top, left, bottom, right). 
     131    } 
     132    union {  
     133        struct {  
     134            Unit topUnit=Style.PX; 
     135            Unit rightUnit=Style.PX; 
     136            Unit bottomUnit=Style.PX; 
     137            Unit leftUnit=Style.PX;  
     138        } 
     139        Edge!(4, Unit) dimensionUnits; 
     140    } 
     141    union { 
     142        struct { 
     143            float width=float.nan; 
     144            float height=float.nan; 
     145        } 
     146        Edge!(2, float) size; 
     147    } 
     148    union { 
     149        struct { 
     150            Unit widthUnit=Style.PX; 
     151            Unit heightUnit=Style.PX; 
     152        } 
     153        Edge!(2, Unit) sizeUnits; 
     154    } 
     155    // Font 
     156    //Font  fontFamily; 
     157    //float fontSize; 
     158    //byte fontSizeUnit; 
     159    //float fontWeight; 
     160    //Color color; 
     161         
     162    // Padding 
     163    //float paddingTop, paddingRight, paddingBottom, paddingLeft; 
     164    //Unit paddingTopUnit, paddingRightUnit, paddingBottomUnit, paddingLeftUnit; 
     165 
     166    // Text 
     167    //byte  textAlign; 
     168    //byte  textDecoration; 
     169    //float lineHeight; 
     170    //byte  lineHeightUnits; 
     171 
     172    // Other 
     173    union { 
     174        bool visible = true; /// Set whether the element is visible. visibility is an alias of visible for CSS compatibility. 
     175        bool visibility; 
     176    } 
     177    int zIndex; 
     178     
     179 
     180    /** 
     181     * Set properties from a string of text, css style. 
     182     * TODO: Fix this function so it cleans up its garbage. 
     183     * Example: 
     184     * style.set("border: 2px solid black; font-family: arial.ttf; color: white");*/ 
     185    void set(char[] style) 
     186    {    
     187        /* 
     188         * Populate values and units from string. 
     189         * Not sure if returning values through arguments w/o inout is future-proof. */  
     190        void toEdge(char[] string, float[] edge, Unit[] edge_units) 
     191        in { assert(edge_units.length >= edge.length); } 
     192        body 
     193        {   char[][] values = std.regexp.split(string, "\\s+"); 
     194             
     195            // Restore to defaults 
     196            edge[0..length] = float.nan; 
     197            edge_units[0..length] = Style.PX; 
     198             
     199            // Loop through and set what we can parse. 
     200            for (int i=0; i<values.length && i<edge.length; i++) 
     201            {   char[] num = std.regexp.sub(values[i], "[^0-9]+", "", "g"); 
     202                if (num.length) // val=="auto" leaves the value as float.nan 
     203                    edge[i] = toFloat(num); 
     204                else if (values[i] != "auto") // entire string is already toLower'd 
     205                    throw new Exception("Could not parse CSS value: '" ~ values[i] ~"`"); // garbage! 
     206                if (std.string.rfind(values[i], "%") != -1) 
     207                    edge_units[i] = Style.PERCENT; 
     208                //delete num; // This causes problems, but std.regexp.sub should've made a copy, right? 
     209            } 
     210            // If only specified 2 values and edge has 4 values.         
     211            if (values.length==2 && edge.length >=4) 
     212            {   edge[2] = edge[0]; 
     213                edge[3] = edge[1]; 
     214                edge_units[2] = edge_units[0]; 
     215                edge_units[3] = edge_units[1]; 
     216            } 
     217        } 
     218         
     219        /* 
     220         * Remove the url('...') from a css path, if it's present. 
     221         * Returns: A slice of the original url to avoid creating garbage.*/  
     222        char[] removeUrl(char[] url) 
     223        {   if (url[0..5] == "url('" || url[0..5] == "url(\"") 
     224                return url[5..length-2]; 
     225            if (url[0..4] == "url(" || url[0..4] == "url(") 
     226                return url[4..length-1]; 
     227            return url; 
     228        } 
     229     
     230 
     231        // Parse and apply the style 
     232        style = tolower(style); // creates garbage if changed 
     233        char[][] expressions =  std.regexp.split(style, ";\\s*"); 
     234        foreach (exp; expressions) 
     235        {   char[][] tokens = std.regexp.split(exp, ":[ ]*"); 
     236            char[] property = replace(tokens[0], "-", ""); // creates garbage. 
     237            if (!property.length) 
     238                continue; 
     239             
     240            // TODO: account for parse errors. 
     241             
     242            switch (property) 
     243            {   /// TODO: Lots more properties 
     244                case "backgroundcolor":     backgroundColor = Color(tokens[1]); break; 
     245                case "backgroundrepeat":    backgroundRepeat = translate[tokens[1]]; break; 
     246                case "backgroundmaterial":  backgroundMaterial = Resource.texture(removeUrl(tokens[1])).texture; break; 
     247                 
     248             
     249                case "backgroundpositionx":toEdge(tokens[1], backgroundPosition.values[0..1], backgroundPositionUnits.values[0..1]); break; 
     250                case "backgroundpositiony":toEdge(tokens[1], backgroundPosition.values[1..2], backgroundPositionUnits.values[1..2]); break; 
     251                case "backgroundposition": toEdge(tokens[1], backgroundPosition.values, backgroundPositionUnits.values); break; 
     252             
     253                case "top":         toEdge(tokens[1], dimension.values[0..1], dimensionUnits.values[0..1]); break; 
     254                case "right":       toEdge(tokens[1], dimension.values[1..2], dimensionUnits.values[1..2]); break; 
     255                case "bottom":      toEdge(tokens[1], dimension.values[2..3], dimensionUnits.values[2..3]); break; 
     256                case "left":        toEdge(tokens[1], dimension.values[3..4], dimensionUnits.values[3..4]); break; 
     257                case "dimension":   toEdge(tokens[1], dimension.values, dimensionUnits.values); break; 
     258                case "width":       toEdge(tokens[1], size.values[0..1], sizeUnits.values[0..1]); break; 
     259                case "height":      toEdge(tokens[1], size.values[1..2], sizeUnits.values[1..2]); break; 
     260                case "size":        toEdge(tokens[1], size.values, sizeUnits.values); break;     
     261                 
     262                case "zIndex":      zIndex = toInt(tokens[1]); break; 
     263                case "visible": 
     264                case "visibility":  visible = (tokens[1] == "true" || tokens[1] == "visible"); break; 
     265                 
     266                default: 
     267                    writefln("Unsupported CSS Property: '", tokens[0], "'."); // garbage! 
     268            } 
     269             
     270            delete property; 
     271        } 
     272        //delete style; // can't do because tolower style only someties returns a copy. 
     273         
     274         
     275    } 
    60276} 
  • trunk/yage/gui/surface.d

    r73 r76  
    11/** 
    22 * Copyright:  (c) 2005-2007 Eric Poggel 
    3  * Authors:    Joe Pusderis (deformative0@gmail.com) 
    4  * License:    <a href="lgpl.txt">LGPL</a>  
     3 * Authors:    Joe Pusderis (deformative0@gmail.com), Eric Poggel 
     4 * License:    <a href="lgpl.txt">LGPL</a>  
    55 */ 
    66 
     
    88 
    99import std.stdio; 
     10import std.math; 
    1011import derelict.opengl.gl; 
    1112import derelict.sdl.sdl; 
     13import derelict.opengl.glext; 
     14import derelict.opengl.glu; 
    1215import yage.core.all; 
    1316import yage.system.device; 
     
    1619import yage.resource.texture; 
    1720import yage.gui.style; 
    18  
    19  
    20 //move to constants 
    21 enum{ 
    22     traditional, //default 
    23     stretched, 
    24     tiled 
    25 
    26  
    27 float third = 1.0/3.0; 
     21import yage.system.rendertarget; 
     22 
     23 
     24const float third = 1.0/3.0; 
    2825 
    2926/**  
     
    3633{ 
    3734    static final Style defaultStyle; 
    38     Style style; 
    39      
    40     //Change from GPUTexture to Texture or Material 
    41     protected GPUTexture texture; 
    42      
    43     //Surface parent; 
    44     //Surface[] children; 
    45     //Not sure if I should have a reference to Parent or not, but for now, I will. 
    46      
    47      
    48     Vec2f topLeft;//rid self of these 
    49     Vec2f bottomRight; 
    50      
    51     //these are calculated, not for calculating 
    52     Vec2i position1; 
    53     Vec2i position2; 
    54     Vec2i size; 
    55      
    56     //these are for calculating 
    57     protected Vec2i locationAdd; 
    58      
    59     //used for the texture 
    60     Vec2f portion; 
    61      
    62     bool visible; 
    63     bool mouseIn; 
    64      
    65     byte fill = traditional; 
    66      
    67     //Not sure how to impelement gluUnProject 
    68      
    69     //Perhaps add some of these for global events. 
    70     void delegate(typeof(this) self) onBlur; 
    71      
    72     //dunno how 
    73     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onClick; 
    74  
    75     //dunno how 
    76     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onDblclick; 
    77  
     35    Style style;     
     36     
     37    // internal values 
     38    Vec2f topLeft;      // pixel distance of the topleft corner from parent's top left 
     39    Vec2f bottomRight;  // pixel distance of the bottom right corner from parent's top left 
     40    Vec2f offset;       // pixel distance of top left from the window's top left at 0, 0 
     41     
     42    bool mouseIn; // is this used? 
     43     
     44    protected Style old_style; // Used for comparison to see if dirty. 
     45    protected Surface old_parent; 
     46     
     47    protected float[72] vertices = 0; // Used for rendering 
     48    protected float[72] tex_coords = 0; 
     49 
     50    /// Callback functions 
     51    void delegate(typeof(this) self) onBlur; // Unfinished 
    7852    void delegate(typeof(this) self) onFocus; //Done -- See Raise, no fall through 
    79  
    80     void delegate(typeof(this) self, byte key) onKeydown; 
    81     void keydown(byte key){ 
    82         if(onKeydown)onKeydown(this, key); 
    83         else if(parent !is null) parent.keydown(key); 
    84     } 
    85      
    86     void delegate(typeof(this) self, byte key, byte modifiers) onKeypress; //Why is this here when we have down? 
    87      
    88     void delegate(typeof(this) self, byte key) onKeyup; 
    89     void keyup(byte key){ 
    90         if(onKeyup)onKeyup(this, key); 
    91         else if(parent !is null) parent.keyup(key); 
    92     } 
    93  
    94     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMousedown; //Done 
    95     void mousedown(byte buttons, Vec2i coordinates){  
    96         if(onMousedown)onMousedown(this, buttons, coordinates); 
    97         else if(parent !is null) parent.mousedown(buttons, coordinates); 
    98     } 
    99  
    100     void delegate(typeof(this) self, byte buttons, Vec2i rel) onMousemove; //Done 
    101     void mousemove(byte buttons, Vec2i rel){ 
    102         if(onMousemove)onMousemove(this, buttons, rel); 
    103         else if(parent !is null) parent.mousemove(buttons, rel); 
    104     } 
    105  
    106     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseleave; 
    107     void mouseleave(Surface next, byte buttons, Vec2i coordinates){ 
    108         if(mouseIn == true){ 
    109             if(isChild(next)) 
    110                 return; 
    111             else{ 
    112                 mouseIn = false; 
    113                 if(onMouseleave) 
    114                     onMouseleave(this, buttons, coordinates); 
    115              
    116                 if(next !is parent && parent !is null) 
    117                     parent.mouseleave(next, buttons, coordinates); 
    118             } 
    119         } 
    120     } 
    121      
    122     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseenter; 
    123     void mouseenter(byte buttons, Vec2i coordinates){ 
    124         if(mouseIn == false){ 
    125             if(parent !is null) parent.mouseenter(buttons, coordinates); 
    126              
    127             mouseIn = true; 
    128             if(onMouseenter) onMouseenter(this, buttons, coordinates); 
    129         } 
    130     } 
    131      
    132     void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseup; //Done 
    133     void mouseup(byte buttons, Vec2i coordinates){  
    134         if(onMouseup)onMouseup(this, buttons, coordinates); 
    135         else if(parent !is null) parent.mouseup(buttons, coordinates); 
    136     } 
    137  
    138     void delegate(typeof(this) self) onResize; //Done -- See recalculate, no fall through 
    139      
    140      
    141     this(Surface p){ 
     53    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onClick; // unfinished 
     54    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onDblCick; // unfinished 
     55    void delegate(typeof(this) self, byte key) onKeyDown; 
     56    void delegate(typeof(this) self, byte key) onKeyUp; 
     57    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseDown; 
     58    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseUp; 
     59    void delegate(typeof(this) self, byte buttons, Vec2i amount) onMouseMove; 
     60    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseOver; 
     61    void delegate(typeof(this) self, byte buttons, Vec2i coordinates) onMouseOut; 
     62    void delegate(typeof(this) self, Vec2f amount) onResize; 
     63 
     64    /// Constructor 
     65    this(Surface p=null){ 
    14266        parent = p; 
    143         if(parent is null){ 
    144             Device.children ~= this; 
    145             this.recalculate(); 
    146         } 
    147         else{ 
    148             parent.children ~= this; 
    149             this.recalculate(); 
    150         } 
    151     } 
    152      
    153     void setTexture(GPUTexture tex){ 
    154         texture = tex; 
    155         recalculateTexture(); 
    156     } 
    157      
    158     void recalculate(Vec2i parent1, Vec2i parent2, Vec2i parentSize, bool doSubs = true){ //not done 
    159          
    160         position1.x = cast(int)(topLeft.x * cast(float)parentSize.x) + parent1.x + locationAdd.x; 
    161         position1.y = cast(int)(topLeft.y * cast(float)parentSize.y) + parent1.y + locationAdd.y; 
    162          
    163         position2.x = parent2.x - cast(int)((1.0 - bottomRight.x) * cast(float)parentSize.x) + locationAdd.x; 
    164         position2.y = parent2.y - cast(int)((1.0 - bottomRight.y) * cast(float)parentSize.y) + locationAdd.y; 
    165          
    166         size.x = position2.x - position1.x; 
    167         size.y = position2.y - position1.y; 
    168          
    169         if(onResize)onResize(this); 
    170          
    171         if(doSubs) 
    172             recalculateSubs(); 
    173     } 
    174      
    175     private void recalculateSubs(){ 
    176         foreach(sub; this.children) 
    177             sub.recalculate(position1, position2, size); 
    178     } 
    179      
    180     void recalculate(bool doSubs = true){ 
    181         if(parent is null){ 
    182             recalculate(Vec2i(0,0), Device.size, Device.size, doSubs); 
    183         } 
     67        if(!(parent is null)) 
     68            parent.addChild(this); 
     69        calculate(); 
     70    } 
     71     
     72    // Set style dimensions from pixels. 
     73    protected void top(float v)    { style.top    = style.topUnit   ==Style.PERCENT ? 100*v/parentHeight() : v; } 
     74    protected void bottom(float v) { style.bottom = style.bottomUnit==Style.PERCENT ? 100*v/parentHeight() : v; } 
     75    protected void height(float v) { style.height = style.heightUnit==Style.PERCENT ? 100*v/parentHeight() : v; } 
     76    protected void left(float v)   { style.left   = style.leftUnit  ==Style.PERCENT ? 100*v/parentWidth() : v; } 
     77    protected void right(float v)  { style.right  = style.rightUnit ==Style.PERCENT ? 100*v/parentWidth() : v; } 
     78    protected void width(float v)  { style.width  = style.widthUnit ==Style.PERCENT ? 100*v/parentWidth() : v; } 
     79     
     80    /** 
     81     * Get the calculated values of this Surface's dimensions in pixel values from the top left corner. */ 
     82    float top()   { return topLeft.y; } 
     83    float right() { return bottomRight.x; } /// ditto 
     84    float bottom(){ return bottomRight.y; } /// ditto 
     85    float left()  { return topLeft.x; } /// ditto 
     86    float width() { return bottomRight.x - topLeft.x; } /// ditto 
     87    float height(){ return bottomRight.y - topLeft.y; } /// ditto 
     88     
     89    /// Get dimensions of this Surface's parent in pixels 
     90    float parentWidth() { return parent ? parent.width()  : Device.getWidth(); } 
     91    float parentHeight(){ return parent ? parent.height() : Device.getHeight(); }   /// Ditto 
     92     
     93 
     94 
     95    /** 
     96     * Recalculate all properties of this Surface based on its style.*/ 
     97    void calculate() 
     98    {            
     99        // Calculate real values from percents 
     100        float parent_width = parentWidth(); 
     101        float parent_height= parentHeight(); 
     102         
     103        float top   = style.topUnit    == Style.PERCENT ? style.top   * parent_height*.01f : style.top; 
     104        float right = style.rightUnit  == Style.PERCENT ? style.right * parent_width *.01f : style.right; 
     105        float bottom= style.bottomUnit == Style.PERCENT ? style.bottom* parent_height*.01f : style.bottom; 
     106        float left  = style.leftUnit   == Style.PERCENT ? style.left  * parent_width *.01f : style.left; 
     107        float width = style.widthUnit  == Style.PERCENT ? style.width * parent_width *.01f : style.width; 
     108        float height= style.heightUnit == Style.PERCENT ? style.height* parent_height*.01f : style.height; 
     109 
     110        Vec2f resized_by = Vec2f(this.width(), this.height()); 
     111        Vec2f offset_by = offset; 
     112         
     113        // Ensure top and left are set if bottom and right are not. 
     114        if (isnan(left) && isnan(right)) 
     115            left = 0.0f; 
     116        if (isnan(top) && isnan(bottom)) 
     117            top = 0.0f; 
     118 
     119        // If left side is anchored 
     120        if (!isnan(left)) 
     121        {   topLeft.x = left; 
     122            if (!isnan(width)) // if width 
     123                bottomRight.x = left + width; 
     124            else if (isnan(right)) // if not width and not right 
     125            {} // TODO: Figure out what default size should be.  size to contents? 
     126        } 
     127         
     128        // If right side is anchored 
     129        if (!isnan(right)) 
     130        {   bottomRight.x = parent_width - right; 
     131            if (isnan(left)) // if not left 
     132            {   if (!isnan(width)) // if width 
     133                    topLeft.x = parent_width - right - width; 
     134                else 
     135                {} // TODO: Figure out what default size should be.  size to contents? 
     136        }   } 
     137         
     138        // If top side is anchored 
     139        if (!isnan(top)) 
     140        {   topLeft.y = top; 
     141            if (!isnan(height)) // if Height 
     142                bottomRight.y =top + height; 
     143            else if (isnan(bottom)) // if not Height and not bottom 
     144            {} // TODO: Figure out what default size should be.  size to contents? 
     145        } 
     146        // If bottom side is anchored 
     147        if (!isnan(bottom)) 
     148        {   bottomRight.y = parent_height - bottom; 
     149            if (isnan(top)) // if not top 
     150            {   if (!isnan(height)) // if Height 
     151                    topLeft.y = parent_height - bottom - height; 
     152                else 
     153                {} // TODO: Figure out what default size should be.  size to contents? 
     154        }   } 
     155         
     156        // Calculate offset 
     157        if (parent) 
     158            offset = parent.offset + topLeft; 
    184159        else 
    185             recalculate(parent.position1, parent.position2, parent.size, doSubs); 
    186     } 
    187      
    188     void startDrag(){ 
    189         lock(); 
    190     } 
    191      
    192     void drag(Vec2i add){ 
    193         locationAdd.x += add.x; 
    194         locationAdd.y += add.y; 
    195          
    196          
    197         recalculate(false); 
    198          
    199          
    200         //All of the below is for not going out of boundry 
    201         if(parent is null){ 
    202             recalculateSubs(); 
    203             return; 
    204         } 
    205          
    206         if(position1.x < parent.position1.x){ 
    207             position1.x = parent.position1.x; 
    208             position2.x = position1.x + size.x; 
    209         } 
    210         else if(position2.x > parent.position2.x){ 
    211             position2.x = parent.position2.x; 
    212             position1.x = position2.x - size.x; 
    213         } 
    214          
    215         if(position1.y < parent.position1.y){ 
    216             position1.y = parent.position1.y; 
    217             position2.y = position1.y + size.y; 
    218         } 
    219         else if(position2.y > parent.position2.y){ 
    220             position2.y = parent.position2.y; 
    221             position1.y = position2.y - size.y; 
    222         } 
    223          
    224         recalculateSubs(); 
    225     } 
    226      
    227     void endDrag(){ 
    228         recalculate(false); 
    229         if(parent is null) goto after; 
    230          
    231          
    232         if(position1.x < parent.position1.x) 
    233             locationAdd.x += parent.position1.x - position1.x; 
    234         else if(position2.x > parent.position2.x) 
    235             locationAdd.x -= position2.x - parent.position2.x; 
    236          
    237          
    238         if(position1.y < parent.position1.y) 
    239             locationAdd.y += parent.position1.y - position1.y; 
    240         else if(position2.y > parent.position2.y) 
    241             locationAdd.y -= position2.y - parent.position2.y; 
    242          
    243         recalculate(false); 
    244         after: 
    245         unlock(); 
    246     } 
    247      
    248     //I would like textures to automatically do this so that it doesn't need to happen for every single surface on every single frame 
    249     void recalculateTexture(){  //Dunno if this will be needed when we change to materials 
    250         portion.x = texture.requested_width/cast(float)texture.getWidth(); 
    251         portion.y = texture.requested_height/cast(float)texture.getHeight(); 
    252     } 
    253      
    254     void render(){ 
     160            offset = topLeft; 
     161         
     162        // See if anything has changed. 
     163        resized_by = Vec2f(this.width(), this.height()) - resized_by; 
     164        offset_by = offset - offset_by;      
     165        float resized_length2 = resized_by.length2(); 
     166        if (resized_length2 > 0 || offset_by.length2() > 0) 
     167        {    
     168            // Calculate vertices 
     169            Vec2f portion; 
     170             
     171            // Portion of the Texture to use for drawing 
     172            // This won't be necessary when we support rectangular textures. 
     173            if (style.backgroundMaterial) 
     174            {   portion.x = style.backgroundMaterial.requested_width/cast(float)style.backgroundMaterial.getWidth(); 
     175                portion.y = style.backgroundMaterial.requested_height/cast(float)style.backgroundMaterial.getHeight(); 
     176            } else 
     177            {   portion.x = 1; 
     178                portion.y = 1; 
     179            } 
     180             
     181            switch(style.backgroundRepeat) 
     182            { 
     183                case Style.STRETCH: 
     184                    float w = this.width(); 
     185                    float h = this.height();