Changeset 76
- Timestamp:
- 07/13/08 22:30:26 (5 months ago)
- Files:
-
- trunk/src/yage/node (deleted)
- trunk/yage (copied) (copied from trunk/src/yage)
- trunk/yage/all.d (copied) (copied from trunk/src/yage/all.d)
- trunk/yage/core/array.d (copied) (copied from trunk/src/yage/core/array.d) (4 diffs)
- trunk/yage/core/color.d (modified) (4 diffs)
- trunk/yage/core/tree.d (copied) (copied from trunk/src/yage/core/tree.d) (2 diffs)
- trunk/yage/core/vector.d (modified) (5 diffs)
- trunk/yage/gui/style.d (modified) (1 diff)
- trunk/yage/gui/surface.d (copied) (copied from trunk/src/yage/gui/surface.d) (9 diffs)
- trunk/yage/resource/all.d (modified) (1 diff)
- trunk/yage/resource/exception.d (added)
- trunk/yage/resource/font.d (added)
- trunk/yage/resource/image.d (modified) (5 diffs)
- trunk/yage/resource/layer.d (copied) (copied from trunk/src/yage/resource/layer.d)
- trunk/yage/resource/material.d (modified) (1 diff)
- trunk/yage/resource/model.d (copied) (copied from trunk/src/yage/resource/model.d)
- trunk/yage/resource/ms3dloader.d (modified) (1 diff)
- trunk/yage/resource/resource.d (modified) (7 diffs)
- trunk/yage/resource/sound.d (modified) (1 diff)
- trunk/yage/resource/texture.d (modified) (9 diffs)
- trunk/yage/scene (copied) (copied from trunk/src/yage/scene)
- trunk/yage/scene/camera.d (modified) (4 diffs)
- trunk/yage/scene/terrain.d (modified) (1 diff)
- trunk/yage/system/all.d (modified) (1 diff)
- trunk/yage/system/constant.d (modified) (1 diff)
- trunk/yage/system/device.d (copied) (copied from trunk/src/yage/system/device.d) (12 diffs)
- trunk/yage/system/input.d (modified) (8 diffs)
- trunk/yage/system/log.d (modified) (3 diffs)
- trunk/yage/system/render.d (copied) (copied from trunk/src/yage/system/render.d) (1 diff)
- trunk/yage/system/rendertarget.d (added)
- trunk/yage/util/flyer.d (copied) (copied from trunk/src/yage/util/flyer.d) (1 diff)
- trunk/yage/util/misc.d (copied) (copied from trunk/src/yage/util/misc.d)
- trunk/yage/util/spring.d (copied) (copied from trunk/src/yage/util/spring.d)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/yage/core/array.d
r73 r76 69 69 70 70 71 /// Return the element with the m aximum value of an array.71 /// Return the element with the minimum or maximum value of an array. 72 72 T amax(T)(T[] array, ) 73 73 { T m = array[0]; … … 77 77 return m; 78 78 } 79 /// 79 /// ditto 80 80 T amax(T, K)(T[] array, K delegate(T elem) getKey) 81 81 { T m = array[0]; … … 86 86 return m; 87 87 } 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 104 89 T amin(T)(T[] array) 105 90 { T m = array[0]; … … 109 94 return m; 110 95 } 96 /// ditto 97 T 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 111 106 112 107 /** trunk/yage/core/color.d
r68 r76 19 19 * so Color(0x6633ff00).hex == "00FF3366" 20 20 * 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? 22 22 * 23 23 * Example: … … 31 31 struct Color 32 32 { 33 private staticreal frac = 1.0f/255;33 private const real frac = 1.0f/255; 34 34 35 35 union … … 136 136 case "yellow": return Color(0xFF00FFFF); 137 137 default: break; 138 } 139 138 } 139 140 // Allow hex colors to start with hash. 141 if (string[0] == '#') 142 string = string[1..length]; 143 140 144 // Append alpha to 6-digit hex string. 141 145 if (string.length == 6) 142 string ~= "FF"; 143 144 // Convert string one char at a atime.146 string ~= "FF"; // creates garbage! 147 148 // Convert string one char at a time. 145 149 Color result; 146 150 int digit; … … 210 214 unittest 211 215 { assert(Color.sizeof == 4); 212 216 213 217 // Test initializers 214 218 assert(Color([0, 102, 51, 255]).hex == "006633FF"); trunk/yage/core/tree.d
r73 r76 20 20 class Tree(T) 21 21 { 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. 30 25 31 26 /** … … 66 61 } 67 62 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. */ 69 66 bool isChild(T elem) 70 { if ( elem.index < 0 || elem.index >= children.length)67 { if (!elem || elem.index < 0 || elem.index >= children.length) 71 68 return false; 72 69 return cast(bool)(children[elem.index] == elem); trunk/yage/core/vector.d
r67 r76 41 41 } 42 42 43 invariant44 { foreach (T t; v)45 assert(t != float.nan);46 }47 48 43 /// Create a zero vector 49 44 static VST opCall() … … 72 67 VST res; 73 68 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];82 69 return res; 83 70 } … … 108 95 } 109 96 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 110 111 /// Return the _length of the vector (the magnitude). 111 112 float length() … … 121 122 } 122 123 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 123 159 /// Get the element at i 124 float opIndex( ubytei)160 float opIndex(size_t i) 125 161 { return v[i]; 126 162 } 127 163 128 164 /// Assign value to the element at i 129 float opIndexAssign(T value, ubytei)165 float opIndexAssign(T value, size_t i) 130 166 { return v[i] = value; 131 167 } … … 200 236 { float x, y, z; 201 237 } } 202 203 invariant204 { foreach (float t; v)205 assert(t != float.nan);206 }207 238 208 239 /** Test some of the more common and more complex functions. */ trunk/yage/gui/style.d
r67 r76 4 4 module yage.gui.style; 5 5 6 import std.regexp; 7 import std.string; 8 import std.stdio; 9 import std.conv; 6 10 import yage.core.color; 7 11 import yage.core.vector; 12 import yage.resource.resource; 8 13 import yage.resource.material; 14 import yage.resource.texture; 9 15 10 16 /** 11 17 * 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. */ 15 21 struct 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 } 60 276 } trunk/yage/gui/surface.d
r73 r76 1 1 /** 2 2 * 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> 5 5 */ 6 6 … … 8 8 9 9 import std.stdio; 10 import std.math; 10 11 import derelict.opengl.gl; 11 12 import derelict.sdl.sdl; 13 import derelict.opengl.glext; 14 import derelict.opengl.glu; 12 15 import yage.core.all; 13 16 import yage.system.device; … … 16 19 import yage.resource.texture; 17 20 import 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; 21 import yage.system.rendertarget; 22 23 24 const float third = 1.0/3.0; 28 25 29 26 /** … … 36 33 { 37 34 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 78 52 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){ 142 66 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; 184 159 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();
