8
Classes, Forms, Controls, Graphics, ExtCtrls, OpenGLContext,
9
GL, LCLType, fpImage, SysUtils;
22
OpenGLControl1: TOpenGLControl;
24
procedure FormCreate(Sender: TObject);
25
procedure FormKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
26
procedure FormKeyPress(Sender: TObject; var Key: char);
27
procedure OpenGLControl1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
28
procedure OpenGLControl1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
29
procedure OpenGLControl1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
30
procedure OpenGLControl1Paint(Sender: TObject);
31
procedure Timer1Timer(Sender: TObject);
33
{ private declarations }
35
{ public declarations }
53
procedure SetMousePos(X, Y: integer);
72
procedure UIStateType.Init;
88
procedure UIStateType.SetMousePos(X, Y: integer);
96
function GLColor(color: GLuint): TGLColor;
98
Result.red := (color shr 16) and $0000ff;
99
Result.green := (color shr 8) and $0000ff;
100
Result.blue := (color shr 0) and $0000ff;
101
//Result.alpha := (color shr 0) and $000000ff;
105
//Draw the string. Characters are fixed width, so this is also
107
procedure drawstring(str: string; x, y: double);
109
glTextOut(x, y + 14, 0, 14, 14, 1, 0, str);
112
//Simplified interface to OpenGL's fillrect call
113
procedure drawrect(x, y, w, h: integer; AColor: TGLColor);
115
glColor3ub(AColor.red, AColor.green, AColor.blue);
116
glRectf(x, y, x + w, y + h);
119
//Check whether current mouse position is within a rectangle
120
function regionhit(x, y, w, h: integer): integer;
122
if (uistate.mousex < x) or
123
(uistate.mousey < y) or
124
(uistate.mousex >= x + w) or
125
(uistate.mousey >= y + h) then
131
//Simple button IMGUI widget
132
function button(id: integer; x: integer; y: integer): integer;
134
//Check whether the button should be hot
135
if regionhit(x, y, 64, 48) = 1 then
137
uistate.hotitem := id;
138
if (uistate.activeitem = 0) and (uistate.mousedown = 1) then
139
uistate.activeitem := id;
142
//If no widget has keyboard focus, take it
143
if uistate.kbditem = 0 then
144
uistate.kbditem := id;
146
//If we have keyboard focus, show it
147
if uistate.kbditem = id then
148
drawrect(x - 6, y - 6, 84, 68, GLColor($ff0000));
150
drawrect(x + 8, y + 8, 64, 48, GLColor($000000));
153
if uistate.hotitem = id then
155
if uistate.activeitem = id then
156
//Button is both 'hot' and 'active'
157
drawrect(x + 2, y + 2, 64, 48, GLColor($ffffff))
159
//Button is merely 'hot'
160
drawrect(x, y, 64, 48, GLColor($ffffff));
163
//button is not hot, but it may be active
164
drawrect(x, y, 64, 48, GLColor($aaaaaa));
166
//If we have keyboard focus, we'll need to process the keys
167
if uistate.kbditem = id then
169
case uistate.keyentered of
172
//If tab is pressed, lose keyboard focus.
173
//Next widget will grab the focus.
174
uistate.kbditem := 0;
176
//If shift was also pressed, we want to move focus
177
//to the previous widget instead.
178
if ssShift in uistate.keymod then
179
uistate.kbditem := uistate.lastwidget;
181
//Also clear the key so that next widget
183
uistate.keyentered := 0;
187
//Had keyboard focus, received return,
188
//so we'll act as if we were clicked.
194
uistate.lastwidget := id;
196
//If button is hot and active, but mouse button is not
197
//down, the user must have clicked the button.
198
if (uistate.mousedown = 0) and
199
(uistate.hotitem = id) and
200
(uistate.activeitem = id) then
203
//Otherwise, no clicky.
207
//Simple scroll bar IMGUI widget
208
function slider(id: integer; x: integer; y: integer; max: integer; var Value: integer): integer;
214
//Calculate mouse cursor's relative y offset
215
ypos := ((256 - 16) * Value) div max;
218
if regionhit(x + 8, y + 8, 16, 255) = 1 then
220
uistate.hotitem := id;
221
if (uistate.activeitem = 0) and (uistate.mousedown = 1) then
222
uistate.activeitem := id;
225
//If no widget has keyboard focus, take it
226
if uistate.kbditem = 0 then
227
uistate.kbditem := id;
229
//If we have keyboard focus, show it
230
if uistate.kbditem = id then
231
drawrect(x - 4, y - 4, 40, 280, GLColor($ff0000));
233
drawrect(x, y, 32, 256 + 16, GLColor($777777));
235
//Render the scrollbar
236
if (uistate.activeitem = id) or (uistate.hotitem = id) then
237
drawrect(x + 8, y + 8 + ypos, 16, 16, GLColor($ffffff))
239
drawrect(x + 8, y + 8 + ypos, 16, 16, GLColor($aaaaaa));
241
//If we have keyboard focus, we'll need to process the keys
242
if uistate.kbditem = id then
244
case uistate.keyentered of
247
//If tab is pressed, lose keyboard focus.
248
//Next widget will grab the focus.
249
uistate.kbditem := 0;
251
//If shift was also pressed, we want to move focus
252
//to the previous widget instead.
253
if ssShift in uistate.keymod then
254
uistate.kbditem := uistate.lastwidget;
256
//Also clear the key so that next widget
258
uistate.keyentered := 0;
262
//Slide slider up (if not at zero)
273
//Slide slider down (if not at max)
284
uistate.lastwidget := id;
286
//Update widget value
287
if uistate.activeitem = id then
289
mousepos := uistate.mousey - (y + 8);
294
if mousepos > 255 then
297
v := (mousepos * max) div 255;
311
function GetTickCount: DWord;
313
Result := DWord(Trunc(Now * 24 * 60 * 60 * 1000));
316
function textfield(id: integer; x: integer; y: integer; var buffer: string): integer;
321
len := Length(buffer);
325
if regionhit(x - 4, y - 4, 30 * 14 + 8, 24 + 8) = 1 then
327
uistate.hotitem := id;
329
if (uistate.activeitem = 0) and (uistate.mousedown = 1) then
330
uistate.activeitem := id;
333
//If no widget has keyboard focus, take it
334
if uistate.kbditem = 0 then
335
uistate.kbditem := id;
337
//If we have keyboard focus, show it
338
if uistate.kbditem = id then
339
drawrect(x - 6, y - 6, 30 * 14 + 12, 24 + 12, GLColor($ff0000));
341
//Render the text field
342
if (uistate.activeitem = id) or (uistate.hotitem = id) then
343
drawrect(x - 4, y - 4, 30 * 14 + 8, 24 + 8, GLColor($aaaaaa))
345
drawrect(x - 4, y - 4, 30 * 14 + 8, 24 + 8, GLColor($777777));
347
glColor3ub($00, $00, $00);
348
drawstring(buffer, x, y);
350
//Render cursor if we have keyboard focus
351
if (uistate.kbditem = id) and (((GetTickCount shr 8) and 1) = 1) then
352
drawstring('_', x + len * 14, y);
354
//If we have keyboard focus, we'll need to process the keys
355
if uistate.kbditem = id then
357
case uistate.keyentered of
360
//If tab is pressed, lose keyboard focus.
361
//Next widget will grab the focus.
362
uistate.kbditem := 0;
364
//If shift was also pressed, we want to move focus
365
//to the previous widget instead.
366
if ssShift in uistate.keymod then
367
uistate.kbditem := uistate.lastwidget;
369
uistate.keyentered := 0;
373
//Also clear the key so that next widget
377
Delete(buffer, len, 1);
384
if (uistate.keychar >= 32) and (uistate.keychar < 127) and (len < 30) then
386
buffer := buffer + Chr(uistate.keyentered);
392
//If button is hot and active, but mouse button is not
393
//down, the user must have clicked the widget; give it
395
if (uistate.mousedown = 0) and (uistate.hotitem = id) and (uistate.activeitem = id) then
396
uistate.kbditem := id;
398
uistate.lastwidget := id;
403
procedure imgui_prepare;
405
uistate.hotitem := 0;
409
procedure imgui_finish;
411
if uistate.mousedown = 0 then
412
uistate.activeitem := 0
414
if uistate.activeitem = 0 then
415
uistate.activeitem := -1;
417
//If no widget grabbed tab, clear focus
418
if uistate.keyentered = VK_TAB then
419
uistate.kbditem := 0;
421
//Clear the entered key
422
uistate.keyentered := 0;
423
uistate.keychar := 0;
426
function GEN_ID: integer;
435
slidervalue: integer;
439
button(GEN_ID, 50, 50);
441
button(GEN_ID, 150, 50);
443
if button(GEN_ID, 50, 150) = 1 then
444
bgcolor := Round(Random * $ffffff);
446
if button(GEN_ID, 150, 150) = 1 then
449
textfield(GEN_ID, 50, 250, sometext);
451
slidervalue := bgcolor and $ff;
452
if slider(GEN_ID, 500, 40, 255, slidervalue) = 1 then
453
bgcolor := (bgcolor and $ffff00) or slidervalue;
455
slidervalue := ((bgcolor shr 10) and $3f);
456
if slider(GEN_ID, 550, 40, 63, slidervalue) = 1 then
457
bgcolor := (bgcolor and $ff00ff) or (slidervalue shl 10);
459
slidervalue := ((bgcolor shr 20) and $f);
460
if slider(GEN_ID, 600, 40, 15, slidervalue) = 1 then
461
bgcolor := (bgcolor and $00ffff) or (slidervalue shl 20);
468
procedure TForm1.OpenGLControl1Paint(Sender: TObject);
470
//setup 2D projection
471
glMatrixMode(GL_PROJECTION);
473
glOrtho(0, OpenGLControl1.Width, OpenGLControl1.Height, 0, 0, 1);
474
glMatrixMode(GL_MODELVIEW);
477
drawrect(0, 0, 640, 480, GLColor(bgcolor));
481
glColor3ub($ff, $00, $00);
482
glTextOut(10, 20, 0, 10, 10, 1, 0, Format('%f FPS', [1000 / OpenGLControl1.FrameDiffTimeInMSecs]));
484
OpenGLControl1.SwapBuffers;
487
procedure TForm1.Timer1Timer(Sender: TObject);
489
OpenGLControl1.Paint;
492
procedure TForm1.OpenGLControl1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: integer);
494
uistate.SetMousePos(X, Y);
497
procedure TForm1.OpenGLControl1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
499
uistate.mousedown := 1;
502
procedure TForm1.FormKeyDown(Sender: TObject; var Key: word; Shift: TShiftState);
504
uistate.keymod := Shift;
505
uistate.keyentered := Key;
508
procedure TForm1.FormKeyPress(Sender: TObject; var Key: char);
510
//if escape is pressed, quit the application
511
if Ord(Key) = VK_ESCAPE then
514
uistate.keyentered := Ord(Key);
516
//if key is ASCII, accept it as character input
517
if (uistate.keyentered and $FF80) = 0 then
518
uistate.keychar := uistate.keyentered and $7f;
521
procedure TForm1.FormCreate(Sender: TObject);
524
sometext := 'Some text';
527
procedure TForm1.OpenGLControl1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer);
529
uistate.mousedown := 0;