Changeset 195
- Timestamp:
- 07/18/10 00:14:00 (2 years ago)
- Files:
-
- trunk/src/demo2/main.d (modified) (1 diff)
- trunk/src/yage/gui/surface.d (modified) (5 diffs)
- trunk/src/yage/gui/textblock.d (modified) (9 diffs)
- trunk/src/yage/system/input.d (modified) (7 diffs)
- trunk/src/yage/system/window.d (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/demo2/main.d
r193 r195 92 92 return false; 93 93 }; 94 info.editable = view.editable = true; 94 95 //info.style.transform = Matrix().scale(Vec3f(.5, .5, .5)); 95 96 trunk/src/yage/gui/surface.d
r193 r195 48 48 49 49 /** 50 * Triggered when a key is pressed down and repeats at the key repeat rate.50 * Triggered when a key is pressed down and repeats at Input's key repeat rates. 51 51 * Unlike onKeyDown and onKeyUp, key is the unicode value of the key press, instead of the sdl key code. */ 52 52 bool delegate(Surface self, dchar key, int modifier) onKeyPress; … … 371 371 372 372 textBlock.update(text, cs, width, height); 373 Image textImage = textBlock.render(cs, true ); // TODO: Change true to Probe.NextPow2373 Image textImage = textBlock.render(cs, true, editable && focusSurface==this ? &textCursor : null); // TODO: Change true to Probe.NextPow2 374 374 assert(textImage !is null); 375 375 … … 438 438 /** 439 439 * Trigger a keyDown event and call the onKeyDown callback function if set. 440 * If the onKeyDown function is not set, call the parent's keyDown function. */ 440 * If the onKeyDown function is not set, call the parent's keyDown function. 441 * Params: 442 * key = SDL's key code of the pressed key. 443 * mod = Modifier key held down while key was pressed.*/ 441 444 void keyDown(int key, int mod=ModifierKey.NONE) 442 445 { bool propagate = true; … … 449 452 /** 450 453 * Trigger a keyUp event and call the onKeyUp callback function if set. 451 * If the onKeyUp function is not set, call the parent's keyUp function.*/ 454 * If the onKeyUp function is not set, call the parent's keyUp function. 455 * Params: 456 * key = SDL's key code of the pressed key. 457 * mod = Modifier key held down while key was pressed.*/ 452 458 void keyUp(int key, int mod=ModifierKey.NONE) 453 459 { bool propagate = true; … … 459 465 460 466 /** 461 * Trigger a keyUp event and call the onKeyUp callback function if set. 462 * If the onKeyUp function is not set, call the parent's keyUp function.*/ 467 * Trigger a keyPress event and call the onKeyPress callback function if set. 468 * If the onKeyPress function is not set, call the parent's keyPress function. 469 * Params: 470 * key = SDL's key code of the pressed key. 471 * mod = Modifier key held down while key was pressed. 472 * unicode = unicode value of pressed key. */ 463 473 void keyPress(int key, int mod=ModifierKey.NONE, dchar unicode=0) 464 474 { bool propagate = true; trunk/src/yage/gui/textblock.d
r193 r195 25 25 import yage.core.format; 26 26 import yage.core.math.math; 27 import yage.core.math.vector; 27 28 import yage.core.memory; 28 29 import yage.core.object2; … … 61 62 private ArrayBuilder!(InlineStyle) styles; // Styles pointed to by the letters 62 63 63 /** 64 * Get a line number and the position in that line from a position relative to the start of the TextBlock 65 * Params: 66 * position = Character position from the beginning of the TextBlock 67 * After the function executes, this will be the position on the line returned. 68 * Returns: The line number. If position is after the last line, then the number of the last line +1 is returned.*/ 69 int positionToLine(inout int position) 70 { foreach (i, line; lines.data) 71 { if (position < line.letters.length) 72 return i; 73 position -= line.letters.length; 74 } 75 return lines.length; 76 } 77 78 /** 79 * Get cursor position from the beginning of the TextBlock based on a line number and the position in that line. 80 * Params: 81 * line = 82 * position = Position from the beginning of the line. 83 * Returns: */ 84 int lineToPosition(int line, int position) 85 { int m = min(line, lines.length); 86 for (int i=0; i<m; i++) 87 position += lines[i].letters.length; 88 return position; 64 65 66 /// Functions for converting between line/letter/cursor space and x/y position. 67 struct { 68 69 /// 70 Vec2i cursorToXy(int position) 71 { Vec2i result; 72 int line = cursorToLine(position); 73 for (int i=0; i<line; i++) 74 result.y += lines[i].height; 75 line = min(line, lines.length-1); 76 Log.trace(position); 77 int last = min(lines[line].letters.length, position); 78 for (int i=0; i<last; i++) 79 result.x += lines[line].letters[i].advanceX; 80 return result; 81 } 82 83 int xyToCursor(Vec2i xy) 84 { 85 int line; 86 for (; line<lines.length && 0 <= xy.y; line++) 87 xy.y -= lines[line].height; 88 89 int position; 90 for (; position<lines[line].letters.length && 0 < xy.x; position++) 91 xy.x -= lines[line].letters[position].advanceX; 92 93 return lineToCursor(line, position); 94 } 95 96 97 /** 98 * Get a line number and the position in that line from a position relative to the start of the TextBlock 99 * Params: 100 * position = Character position from the beginning of the TextBlock 101 * After the function executes, this will be the position on the line returned. 102 * Returns: The line number. If position is after the last line, then the number of the last line +1 is returned.*/ 103 int cursorToLine(inout int position) 104 { foreach (i, line; lines.data) 105 { if (position < line.letters.length) 106 return i; 107 position -= line.letters.length; 108 } 109 return lines.length; 110 } 111 112 /** 113 * Get cursor position from the beginning of the TextBlock based on a line number and the position in that line. 114 * Params: 115 * line = 116 * position = Position from the beginning of the line. 117 * Returns: */ 118 int lineToCursor(int line, int position) 119 { int m = min(line, lines.length); 120 for (int i=0; i<m; i++) 121 position += lines[i].letters.length; 122 return position; 123 } 124 /* 125 // Get the x position in pixels of a character on a line. TODO: Also y. 126 int positionToX(int line, int position) 127 { assert (line < lines.length); 128 int x; 129 int last = min(lines[line].letters.length, position); 130 for (int i=0; i<last; i++) 131 x+= lines[line].letters[i].advanceX; 132 return x; 133 } 134 135 // Get the nearest character position on a line from an x poxition in pixels 136 int xToPosition(int line, int x) 137 { 138 for (int i=0; i<lines[line].letters.length; i++) 139 { x-= lines[line].letters[i].advanceX; 140 if (x<0) // TODO: More accurate rounding 141 return i; 142 } 143 } 144 */ 89 145 } 90 146 … … 102 158 assert(cursor.position <= letters.length); 103 159 104 // Get the x position in pixels of a character on a line.105 int positionToX(int line, int position)106 { assert (line < lines.length);107 int x;108 int last = min(lines[line].letters.length, position);109 for (int i=0; i<last; i++)110 x+= lines[line].letters[i].advanceX;111 return x;112 }113 114 // Get the nearest character position on a line from an x poxition in pixels115 int xToPosition(int line, int x)116 { int position;117 for (int i=0; i<lines[line].letters.length; i++)118 { x-= lines[line].letters[i].advanceX;119 if (x<0) // TODO: More accurate rounding120 return i;121 }122 }123 124 160 // Position cursor 125 161 int position = cursor.position; 126 int currentLine = positionToLine(position);162 int currentLine = cursorToLine(position); 127 163 switch(key) 128 164 { … … 132 168 case SDLK_UP: 133 169 if (currentLine > 0) 134 { int x = positionToX(currentLine, position);135 currentLine--;136 cursor.position = lineTo Position(currentLine, xToPosition(currentLine, x));170 { Vec2i xy = cursorToXy(cursor.position).x; 171 xy.y -= lines[currentLine].height; 172 cursor.position = lineToCursor(currentLine, xyToCursor(xy)); 137 173 } 138 174 break; 139 175 case SDLK_DOWN: 140 176 if (currentLine < lines.length-1) 141 { int x = positionToX(currentLine, position);142 currentLine++;143 cursor.position = lineTo Position(currentLine, xToPosition(currentLine, x));177 { Vec2i xy = cursorToXy(cursor.position).x; 178 xy.y += lines[currentLine].height; 179 cursor.position = lineToCursor(currentLine, xyToCursor(xy)); 144 180 } 145 181 break; 146 182 case SDLK_HOME: 147 positionToLine(position); // position is now relativeto the beginning of the line.183 //cursorToLine(position); // position is now relativeto the beginning of the line. 148 184 cursor.position -= position; 149 185 break; 150 186 case SDLK_END: 151 positionToLine(position);187 //cursorToLine(position); 152 188 cursor.position += (lines[currentLine].letters.length - position); 153 189 break; … … 161 197 } 162 198 break; 163 case SDLK_DELETE: break;199 case SDLK_DELETE: 164 200 if (cursor.position < letters.length) // doesn't work 165 201 letters.splice(cursor.position, 1); 202 break; 166 203 // New letters 167 204 default: … … 183 220 } 184 221 break; 185 // ctrl+a, z, x, c, v222 // TODO: selection, ctrl+a, z, x, c, v 186 223 } 187 224 … … 200 237 * Characters with a italic/oblique font-style are rendered skewed. 201 238 * For ideal rendering, instead use a font-family that has a bold or italic style. 202 * Params: 203 * text = String of utf-8 encoded html text to render. 204 * The following html tags are supported:<br> 205 * a, b, br, del, i, span, sub, sup, u <br> 206 * The following css is supported via inline style attributes: <br> 207 * color, font-family, font-size[%|px], font-style[normal|italic|oblique], font-weight[normal|bold], 208 * letter-spacing[%|px], line-height[%|px], 209 * text-align[left|center|right] text-decoration[none|underline|overline|line-through] 239 * Params: 210 240 * style = A style with fontSize and lineHeight in terms of pixels 211 * width = Available width for rendering text212 * height = Available height for rendering text.241 * pow2 = Render an image with dimensions that are a power of 2 (useful for older graphics cards) 242 * cursor = Render this text cursor if not null. 213 243 * Returns: An RGBA image of width pixels wide and is shorter or equal to height. 214 244 * Note that the same buffer is used for each return, so one call to this function will overwrite a previous result.*/ 215 Image render(Style style, bool pow2=false )245 Image render(Style style, bool pow2=false, TextCursor* cursor=null) 216 246 { 217 247 Image result; … … 270 300 271 301 302 if (cursor) 303 { 304 Vec2i xy = cursorToXy(cursor.position+1); 305 for (int h=max(0, xy.y); h<min(line.height+xy.y, height); h++) 306 for (int w=max(0, xy.x); w<min(xy.x+2, width); w++) 307 result[w, h] = style.color.ub; 308 309 } 310 272 311 x+= letter.advanceX; // + istyle.letterSpacing; 273 312 y+= letter.advanceY; … … 335 374 * This is unlike input(), which modifies the text based on a single keystroke. 336 375 * Params: 337 * text = 338 * style = Root style of the text. Inline styles override this. 339 * width = 340 * height = 376 * text = String of utf-8 encoded html text to render. 377 * The following html tags are supported:<br> 378 * a, b, br, del, i, span, sub, sup, u <br> 379 * The following css is supported via inline style attributes: <br> 380 * color, font-family, font-size[%|px], font-style[normal|italic|oblique], font-weight[normal|bold], 381 * letter-spacing[%|px], line-height[%|px], 382 * text-align[left|center|right] text-decoration[none|underline|overline|line-through] 383 * style = A style with fontSize and lineHeight in terms of pixels 384 * width = Available width for rendering text 385 * height = Available height for rendering text. 341 386 * Returns: True if the text will need to be re-rendered, false otherwise. 342 387 * TODO: Should this be a constructor to maintain RAII? */ trunk/src/yage/system/input.d
r175 r195 8 8 9 9 public import derelict.sdl.sdl; 10 10 import tango.stdc.time; 11 11 import yage.core.math.vector; 12 12 import yage.system.log; … … 23 23 class Input 24 24 { 25 public static int KEY_DELAY = 500; /// milliseconds before repeating a call to keyPress after holding a key down. 26 public static int KEY_REPEAT = 30; /// milliseconds before subsequent calls to keyPress after KEY_DELAY occurs. 27 25 28 protected static Vec2i mouse; // The current pixel location of the mouse cursor; (0, 0) is top left. 26 29 protected static Surface currentSurface; // Surface that the mouse is currently over 27 30 31 protected static SDL_keysym lastKeyDown; // Used for manual key-repeat. 32 protected static uint lastKeyDownTime; 33 28 34 /** 29 35 * Process input, handle window resize and close events, and send the remaining events to surface, … … 31 37 static void processAndSendTo(Surface surface) 32 38 { 33 // Disable key repeating, we'll handle that manually.34 //SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL); // why doesn't this work? Need to try again since I have the latest version of SDL35 39 36 40 SDL_EnableUNICODE(1); 41 auto focus = getFocusSurface(surface); 37 42 38 43 SDL_Event event; … … 43 48 // Keyboard 44 49 case SDL_KEYDOWN: 45 46 auto focus = getFocusSurface(surface);47 50 if(focus) // keysym.sym gets all keys on the keyboard, including separate keys for numpad, keysym.unicde should be reserved for text. 48 51 { focus.keyDown(event.key.keysym.sym, event.key.keysym.mod); 52 53 // Kepress will be called with the key repeat settings. 49 54 focus.keyPress(event.key.keysym.sym, event.key.keysym.mod, event.key.keysym.unicode); 50 //focus.keyDown(event.key.keysym.unicode, event.key.keysym.mod);51 //focus.text ~= toUTF8([cast(dchar)(event.key.keysym.sym)]);55 lastKeyDown = event.key.keysym; 56 lastKeyDownTime = clock()*1000 / CLOCKS_PER_SEC; 52 57 } 53 58 break; 54 case SDL_KEYUP: 55 56 auto focus = getFocusSurface(surface); 59 case SDL_KEYUP: 57 60 if(focus) 58 61 focus.keyUp(event.key.keysym.sym, event.key.keysym.mod); 59 62 //focus.keyUp(event.key.keysym.unicode, event.key.keysym.mod); 60 63 lastKeyDownTime = uint.max; 61 64 break; 62 65 // Mouse … … 92 95 currentSurface = over; //The new current surface 93 96 } 94 97 95 98 break; 96 99 … … 108 111 break; 109 112 } 110 } 113 } 114 115 // Key repeat 116 if (focus) 117 { 118 uint now = clock()*1000/CLOCKS_PER_SEC; 119 if (now - KEY_DELAY > lastKeyDownTime) 120 { focus.keyPress(lastKeyDown.sym, lastKeyDown.mod, lastKeyDown.unicode); 121 lastKeyDownTime += KEY_REPEAT; 122 } 123 } 111 124 } 112 125 … … 120 133 121 134 /** 122 * Get the surface that currently has focus .*/135 * Get the surface that currently has focus, or the given surface if no surface has focus */ 123 136 private static Surface getFocusSurface(Surface surface) { 124 137 if(Surface.getFocusSurface()) trunk/src/yage/system/window.d
r190 r195 152 152 // These have to be set after window creation. 153 153 SDL_EnableUNICODE(1); 154 SDL_EnableKeyRepeat(1, 100); 154 //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); 155 SDL_EnableKeyRepeat(0, 0); // disable, we handle it ourselves 155 156 156 157 // Attempt to load multitexturing
