1 // Copyright (C) 2002-2012 Nikolaus Gebhardt
\r
2 // Copyright (C) 2019 Irrlick
\r
4 // This file is part of the "Irrlicht Engine".
\r
5 // For conditions of distribution and use, see copyright notice in irrlicht.h
\r
8 #ifdef _IRR_COMPILE_WITH_GUI_
\r
10 #include "IGUIFont.h"
\r
11 #include "IGUISpriteBank.h"
\r
12 #include "IGUIElement.h"
\r
13 #include "IVideoDriver.h"
\r
14 #include "IAttributes.h"
\r
21 GUISkin::GUISkin(EGUI_SKIN_TYPE type, video::IVideoDriver* driver)
\r
22 : SpriteBank(0), Driver(driver), Type(type)
\r
25 setDebugName("GUISkin");
\r
28 if ((Type == EGST_WINDOWS_CLASSIC) || (Type == EGST_WINDOWS_METALLIC))
\r
30 Colors[EGDC_3D_DARK_SHADOW] = video::SColor(101,50,50,50);
\r
31 Colors[EGDC_3D_SHADOW] = video::SColor(101,130,130,130);
\r
32 Colors[EGDC_3D_FACE] = video::SColor(101,210,210,210);
\r
33 Colors[EGDC_3D_HIGH_LIGHT] = video::SColor(101,255,255,255);
\r
34 Colors[EGDC_3D_LIGHT] = video::SColor(101,210,210,210);
\r
35 Colors[EGDC_ACTIVE_BORDER] = video::SColor(101,16,14,115);
\r
36 Colors[EGDC_ACTIVE_CAPTION] = video::SColor(255,255,255,255);
\r
37 Colors[EGDC_APP_WORKSPACE] = video::SColor(101,100,100,100);
\r
38 Colors[EGDC_BUTTON_TEXT] = video::SColor(240,10,10,10);
\r
39 Colors[EGDC_GRAY_TEXT] = video::SColor(240,130,130,130);
\r
40 Colors[EGDC_HIGH_LIGHT] = video::SColor(101,8,36,107);
\r
41 Colors[EGDC_HIGH_LIGHT_TEXT] = video::SColor(240,255,255,255);
\r
42 Colors[EGDC_INACTIVE_BORDER] = video::SColor(101,165,165,165);
\r
43 Colors[EGDC_INACTIVE_CAPTION] = video::SColor(255,30,30,30);
\r
44 Colors[EGDC_TOOLTIP] = video::SColor(200,0,0,0);
\r
45 Colors[EGDC_TOOLTIP_BACKGROUND] = video::SColor(200,255,255,225);
\r
46 Colors[EGDC_SCROLLBAR] = video::SColor(101,230,230,230);
\r
47 Colors[EGDC_WINDOW] = video::SColor(101,255,255,255);
\r
48 Colors[EGDC_WINDOW_SYMBOL] = video::SColor(200,10,10,10);
\r
49 Colors[EGDC_ICON] = video::SColor(200,255,255,255);
\r
50 Colors[EGDC_ICON_HIGH_LIGHT] = video::SColor(200,8,36,107);
\r
51 Colors[EGDC_GRAY_WINDOW_SYMBOL] = video::SColor(240,100,100,100);
\r
52 Colors[EGDC_EDITABLE] = video::SColor(255,255,255,255);
\r
53 Colors[EGDC_GRAY_EDITABLE] = video::SColor(255,120,120,120);
\r
54 Colors[EGDC_FOCUSED_EDITABLE] = video::SColor(255,240,240,255);
\r
57 Sizes[EGDS_SCROLLBAR_SIZE] = 14;
\r
58 Sizes[EGDS_MENU_HEIGHT] = 30;
\r
59 Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15;
\r
60 Sizes[EGDS_CHECK_BOX_WIDTH] = 18;
\r
61 Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500;
\r
62 Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200;
\r
63 Sizes[EGDS_BUTTON_WIDTH] = 80;
\r
64 Sizes[EGDS_BUTTON_HEIGHT] = 30;
\r
66 Sizes[EGDS_TEXT_DISTANCE_X] = 2;
\r
67 Sizes[EGDS_TEXT_DISTANCE_Y] = 0;
\r
69 Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 2;
\r
70 Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 0;
\r
75 Colors[EGDC_3D_DARK_SHADOW] = 0x60767982;
\r
76 //Colors[EGDC_3D_FACE] = 0xc0c9ccd4; // tab background
\r
77 Colors[EGDC_3D_FACE] = 0xc0cbd2d9; // tab background
\r
78 Colors[EGDC_3D_SHADOW] = 0x50e4e8f1; // tab background, and left-top highlight
\r
79 Colors[EGDC_3D_HIGH_LIGHT] = 0x40c7ccdc;
\r
80 Colors[EGDC_3D_LIGHT] = 0x802e313a;
\r
81 Colors[EGDC_ACTIVE_BORDER] = 0x80404040; // window title
\r
82 Colors[EGDC_ACTIVE_CAPTION] = 0xffd0d0d0;
\r
83 Colors[EGDC_APP_WORKSPACE] = 0xc0646464; // unused
\r
84 Colors[EGDC_BUTTON_TEXT] = 0xd0161616;
\r
85 Colors[EGDC_GRAY_TEXT] = 0x3c141414;
\r
86 Colors[EGDC_HIGH_LIGHT] = 0x6c606060;
\r
87 Colors[EGDC_HIGH_LIGHT_TEXT] = 0xd0e0e0e0;
\r
88 Colors[EGDC_INACTIVE_BORDER] = 0xf0a5a5a5;
\r
89 Colors[EGDC_INACTIVE_CAPTION] = 0xffd2d2d2;
\r
90 Colors[EGDC_TOOLTIP] = 0xf00f2033;
\r
91 Colors[EGDC_TOOLTIP_BACKGROUND] = 0xc0cbd2d9;
\r
92 Colors[EGDC_SCROLLBAR] = 0xf0e0e0e0;
\r
93 Colors[EGDC_WINDOW] = 0xf0f0f0f0;
\r
94 Colors[EGDC_WINDOW_SYMBOL] = 0xd0161616;
\r
95 Colors[EGDC_ICON] = 0xd0161616;
\r
96 Colors[EGDC_ICON_HIGH_LIGHT] = 0xd0606060;
\r
97 Colors[EGDC_GRAY_WINDOW_SYMBOL] = 0x3c101010;
\r
98 Colors[EGDC_EDITABLE] = 0xf0ffffff;
\r
99 Colors[EGDC_GRAY_EDITABLE] = 0xf0cccccc;
\r
100 Colors[EGDC_FOCUSED_EDITABLE] = 0xf0fffff0;
\r
102 Sizes[EGDS_SCROLLBAR_SIZE] = 14;
\r
103 Sizes[EGDS_MENU_HEIGHT] = 48;
\r
104 Sizes[EGDS_WINDOW_BUTTON_WIDTH] = 15;
\r
105 Sizes[EGDS_CHECK_BOX_WIDTH] = 18;
\r
106 Sizes[EGDS_MESSAGE_BOX_WIDTH] = 500;
\r
107 Sizes[EGDS_MESSAGE_BOX_HEIGHT] = 200;
\r
108 Sizes[EGDS_BUTTON_WIDTH] = 80;
\r
109 Sizes[EGDS_BUTTON_HEIGHT] = 30;
\r
111 Sizes[EGDS_TEXT_DISTANCE_X] = 3;
\r
112 Sizes[EGDS_TEXT_DISTANCE_Y] = 2;
\r
114 Sizes[EGDS_TITLEBARTEXT_DISTANCE_X] = 3;
\r
115 Sizes[EGDS_TITLEBARTEXT_DISTANCE_Y] = 2;
\r
118 Sizes[EGDS_MESSAGE_BOX_GAP_SPACE] = 15;
\r
119 Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_WIDTH] = 0;
\r
120 Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_WIDTH] = 500;
\r
121 Sizes[EGDS_MESSAGE_BOX_MIN_TEXT_HEIGHT] = 0;
\r
122 Sizes[EGDS_MESSAGE_BOX_MAX_TEXT_HEIGHT] = 99999;
\r
124 Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X] = 1;
\r
125 Sizes[EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y] = 1;
\r
126 Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_X] = 0;
\r
127 Sizes[EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y] = 2;
\r
129 Texts[EGDT_MSG_BOX_OK] = L"OK";
\r
130 Texts[EGDT_MSG_BOX_CANCEL] = L"Cancel";
\r
131 Texts[EGDT_MSG_BOX_YES] = L"Yes";
\r
132 Texts[EGDT_MSG_BOX_NO] = L"No";
\r
133 Texts[EGDT_WINDOW_CLOSE] = L"Close";
\r
134 Texts[EGDT_WINDOW_RESTORE] = L"Restore";
\r
135 Texts[EGDT_WINDOW_MINIMIZE] = L"Minimize";
\r
136 Texts[EGDT_WINDOW_MAXIMIZE] = L"Maximize";
\r
138 Icons[EGDI_WINDOW_MAXIMIZE] = 225;
\r
139 Icons[EGDI_WINDOW_RESTORE] = 226;
\r
140 Icons[EGDI_WINDOW_CLOSE] = 227;
\r
141 Icons[EGDI_WINDOW_MINIMIZE] = 228;
\r
142 Icons[EGDI_CURSOR_UP] = 229;
\r
143 Icons[EGDI_CURSOR_DOWN] = 230;
\r
144 Icons[EGDI_CURSOR_LEFT] = 231;
\r
145 Icons[EGDI_CURSOR_RIGHT] = 232;
\r
146 Icons[EGDI_MENU_MORE] = 232;
\r
147 Icons[EGDI_CHECK_BOX_CHECKED] = 233;
\r
148 Icons[EGDI_DROP_DOWN] = 234;
\r
149 Icons[EGDI_SMALL_CURSOR_UP] = 235;
\r
150 Icons[EGDI_SMALL_CURSOR_DOWN] = 236;
\r
151 Icons[EGDI_RADIO_BUTTON_CHECKED] = 237;
\r
152 Icons[EGDI_MORE_LEFT] = 238;
\r
153 Icons[EGDI_MORE_RIGHT] = 239;
\r
154 Icons[EGDI_MORE_UP] = 240;
\r
155 Icons[EGDI_MORE_DOWN] = 241;
\r
156 Icons[EGDI_WINDOW_RESIZE] = 242;
\r
157 Icons[EGDI_EXPAND] = 243;
\r
158 Icons[EGDI_COLLAPSE] = 244;
\r
160 Icons[EGDI_FILE] = 245;
\r
161 Icons[EGDI_DIRECTORY] = 246;
\r
163 for (u32 i=0; i<EGDF_COUNT; ++i)
\r
166 UseGradient = (Type == EGST_WINDOWS_METALLIC) || (Type == EGST_BURNING_SKIN) ;
\r
171 GUISkin::~GUISkin()
\r
173 for (u32 i=0; i<EGDF_COUNT; ++i)
\r
180 SpriteBank->drop();
\r
184 //! returns default color
\r
185 video::SColor GUISkin::getColor(EGUI_DEFAULT_COLOR color) const
\r
187 if ((u32)color < EGDC_COUNT)
\r
188 return Colors[color];
\r
190 return video::SColor();
\r
194 //! sets a default color
\r
195 void GUISkin::setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor)
\r
197 if ((u32)which < EGDC_COUNT)
\r
198 Colors[which] = newColor;
\r
202 //! returns size for the given size type
\r
203 s32 GUISkin::getSize(EGUI_DEFAULT_SIZE size) const
\r
205 if ((u32)size < EGDS_COUNT)
\r
206 return Sizes[size];
\r
212 //! sets a default size
\r
213 void GUISkin::setSize(EGUI_DEFAULT_SIZE which, s32 size)
\r
215 if ((u32)which < EGDS_COUNT)
\r
216 Sizes[which] = size;
\r
220 //! returns the default font
\r
221 IGUIFont* GUISkin::getFont(EGUI_DEFAULT_FONT which) const
\r
223 if (((u32)which < EGDF_COUNT) && Fonts[which])
\r
224 return Fonts[which];
\r
226 return Fonts[EGDF_DEFAULT];
\r
230 //! sets a default font
\r
231 void GUISkin::setFont(IGUIFont* font, EGUI_DEFAULT_FONT which)
\r
233 if ((u32)which >= EGDF_COUNT)
\r
240 Fonts[which]->drop();
\r
242 Fonts[which] = font;
\r
247 //! gets the sprite bank stored
\r
248 IGUISpriteBank* GUISkin::getSpriteBank() const
\r
254 //! set a new sprite bank or remove one by passing 0
\r
255 void GUISkin::setSpriteBank(IGUISpriteBank* bank)
\r
261 SpriteBank->drop();
\r
267 //! Returns a default icon
\r
268 u32 GUISkin::getIcon(EGUI_DEFAULT_ICON icon) const
\r
270 if ((u32)icon < EGDI_COUNT)
\r
271 return Icons[icon];
\r
277 //! Sets a default icon
\r
278 void GUISkin::setIcon(EGUI_DEFAULT_ICON icon, u32 index)
\r
280 if ((u32)icon < EGDI_COUNT)
\r
281 Icons[icon] = index;
\r
285 //! Returns a default text. For example for Message box button captions:
\r
286 //! "OK", "Cancel", "Yes", "No" and so on.
\r
287 const wchar_t* GUISkin::getDefaultText(EGUI_DEFAULT_TEXT text) const
\r
289 if ((u32)text < EGDT_COUNT)
\r
290 return Texts[text].c_str();
\r
292 return Texts[0].c_str();
\r
296 //! Sets a default text. For example for Message box button captions:
\r
297 //! "OK", "Cancel", "Yes", "No" and so on.
\r
298 void GUISkin::setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText)
\r
300 if ((u32)which < EGDT_COUNT)
\r
301 Texts[which] = newText;
\r
305 //! draws a standard 3d button pane
\r
306 /** Used for drawing for example buttons in normal state.
\r
307 It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
\r
308 EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\r
309 \param rect: Defining area where to draw.
\r
310 \param clip: Clip area.
\r
311 \param element: Pointer to the element which wishes to draw this. This parameter
\r
312 is usually not used by ISkin, but can be used for example by more complex
\r
313 implementations to find out how to draw the part exactly. */
\r
315 void GUISkin::drawColored3DButtonPaneStandard(IGUIElement* element,
\r
316 const core::rect<s32>& r,
\r
317 const core::rect<s32>* clip,
\r
318 const video::SColor* colors)
\r
326 core::rect<s32> rect = r;
\r
328 if ( Type == EGST_BURNING_SKIN )
\r
330 rect.UpperLeftCorner.X -= 1;
\r
331 rect.UpperLeftCorner.Y -= 1;
\r
332 rect.LowerRightCorner.X += 1;
\r
333 rect.LowerRightCorner.Y += 1;
\r
334 draw3DSunkenPane(element,
\r
335 colors[ EGDC_WINDOW ].getInterpolated( 0xFFFFFFFF, 0.9f )
\r
336 ,false, true, rect, clip);
\r
340 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
342 rect.LowerRightCorner.X -= 1;
\r
343 rect.LowerRightCorner.Y -= 1;
\r
344 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
346 rect.UpperLeftCorner.X += 1;
\r
347 rect.UpperLeftCorner.Y += 1;
\r
348 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
350 rect.LowerRightCorner.X -= 1;
\r
351 rect.LowerRightCorner.Y -= 1;
\r
355 Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
\r
359 const video::SColor c1 = colors[EGDC_3D_FACE];
\r
360 const video::SColor c2 = c1.getInterpolated(colors[EGDC_3D_DARK_SHADOW], 0.4f);
\r
361 Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
\r
367 //! draws a pressed 3d button pane
\r
368 /** Used for drawing for example buttons in pressed state.
\r
369 It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
\r
370 EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\r
371 \param rect: Defining area where to draw.
\r
372 \param clip: Clip area.
\r
373 \param element: Pointer to the element which wishes to draw this. This parameter
\r
374 is usually not used by ISkin, but can be used for example by more complex
\r
375 implementations to find out how to draw the part exactly. */
\r
377 void GUISkin::drawColored3DButtonPanePressed(IGUIElement* element,
\r
378 const core::rect<s32>& r,
\r
379 const core::rect<s32>* clip,
\r
380 const video::SColor* colors)
\r
388 core::rect<s32> rect = r;
\r
389 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
391 rect.LowerRightCorner.X -= 1;
\r
392 rect.LowerRightCorner.Y -= 1;
\r
393 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
395 rect.UpperLeftCorner.X += 1;
\r
396 rect.UpperLeftCorner.Y += 1;
\r
397 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
399 rect.UpperLeftCorner.X += 1;
\r
400 rect.UpperLeftCorner.Y += 1;
\r
404 Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
\r
408 const video::SColor c1 = colors[EGDC_3D_FACE];
\r
409 const video::SColor c2 = c1.getInterpolated(colors[EGDC_3D_DARK_SHADOW], 0.4f);
\r
410 Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
\r
416 //! draws a sunken 3d pane
\r
417 /** Used for drawing the background of edit, combo or check boxes.
\r
418 \param element: Pointer to the element which wishes to draw this. This parameter
\r
419 is usually not used by ISkin, but can be used for example by more complex
\r
420 implementations to find out how to draw the part exactly.
\r
421 \param bgcolor: Background color.
\r
422 \param flat: Specifies if the sunken pane should be flat or displayed as sunken
\r
423 deep into the ground.
\r
424 \param rect: Defining area where to draw.
\r
425 \param clip: Clip area. */
\r
427 void GUISkin::drawColored3DSunkenPane(IGUIElement* element, video::SColor bgcolor,
\r
428 bool flat, bool fillBackGround,
\r
429 const core::rect<s32>& r,
\r
430 const core::rect<s32>* clip,
\r
431 const video::SColor* colors)
\r
439 core::rect<s32> rect = r;
\r
441 if (fillBackGround)
\r
442 Driver->draw2DRectangle(bgcolor, rect, clip);
\r
446 // draw flat sunken pane
\r
448 rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
\r
449 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // top
\r
451 ++rect.UpperLeftCorner.Y;
\r
452 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
453 rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
\r
454 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // left
\r
457 ++rect.UpperLeftCorner.Y;
\r
458 rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
\r
459 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // right
\r
462 ++rect.UpperLeftCorner.X;
\r
463 rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
\r
464 --rect.LowerRightCorner.X;
\r
465 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // bottom
\r
469 // draw deep sunken pane
\r
470 rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
\r
471 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // top
\r
472 ++rect.UpperLeftCorner.X;
\r
473 ++rect.UpperLeftCorner.Y;
\r
474 --rect.LowerRightCorner.X;
\r
475 ++rect.LowerRightCorner.Y;
\r
476 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
478 rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
\r
479 rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y+1;
\r
480 rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
\r
481 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
482 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip); // left
\r
483 ++rect.UpperLeftCorner.X;
\r
484 ++rect.UpperLeftCorner.Y;
\r
485 ++rect.LowerRightCorner.X;
\r
486 --rect.LowerRightCorner.Y;
\r
487 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
490 rect.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
\r
491 ++rect.UpperLeftCorner.Y;
\r
492 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // right
\r
493 --rect.UpperLeftCorner.X;
\r
494 ++rect.UpperLeftCorner.Y;
\r
495 --rect.LowerRightCorner.X;
\r
496 --rect.LowerRightCorner.Y;
\r
497 Driver->draw2DRectangle(colors[EGDC_3D_LIGHT], rect, clip);
\r
500 ++rect.UpperLeftCorner.X;
\r
501 rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
\r
502 --rect.LowerRightCorner.X;
\r
503 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip); // bottom
\r
504 ++rect.UpperLeftCorner.X;
\r
505 --rect.UpperLeftCorner.Y;
\r
506 --rect.LowerRightCorner.X;
\r
507 --rect.LowerRightCorner.Y;
\r
508 Driver->draw2DRectangle(colors[EGDC_3D_LIGHT], rect, clip);
\r
513 //! draws a window background
\r
514 // return where to draw title bar text.
\r
516 core::rect<s32> GUISkin::drawColored3DWindowBackground(IGUIElement* element,
\r
517 bool drawTitleBar, video::SColor titleBarColor,
\r
518 const core::rect<s32>& r,
\r
519 const core::rect<s32>* clip,
\r
520 core::rect<s32>* checkClientArea,
\r
521 const video::SColor* colors)
\r
525 if ( checkClientArea )
\r
527 *checkClientArea = r;
\r
535 core::rect<s32> rect = r;
\r
538 rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
\r
539 if ( !checkClientArea )
\r
541 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
545 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
546 rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
\r
547 if ( !checkClientArea )
\r
549 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
552 // right border dark outer line
\r
553 rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1;
\r
554 rect.LowerRightCorner.X = r.LowerRightCorner.X;
\r
555 rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y;
\r
556 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
557 if ( !checkClientArea )
\r
559 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
562 // right border bright innner line
\r
563 rect.UpperLeftCorner.X -= 1;
\r
564 rect.LowerRightCorner.X -= 1;
\r
565 rect.UpperLeftCorner.Y += 1;
\r
566 rect.LowerRightCorner.Y -= 1;
\r
567 if ( !checkClientArea )
\r
569 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
572 // bottom border dark outer line
\r
573 rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
\r
574 rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
\r
575 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
576 rect.LowerRightCorner.X = r.LowerRightCorner.X;
\r
577 if ( !checkClientArea )
\r
579 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
582 // bottom border bright inner line
\r
583 rect.UpperLeftCorner.X += 1;
\r
584 rect.LowerRightCorner.X -= 1;
\r
585 rect.UpperLeftCorner.Y -= 1;
\r
586 rect.LowerRightCorner.Y -= 1;
\r
587 if ( !checkClientArea )
\r
589 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
592 // client area for background
\r
594 rect.UpperLeftCorner.X +=1;
\r
595 rect.UpperLeftCorner.Y +=1;
\r
596 rect.LowerRightCorner.X -= 2;
\r
597 rect.LowerRightCorner.Y -= 2;
\r
598 if (checkClientArea)
\r
600 *checkClientArea = rect;
\r
603 if ( !checkClientArea )
\r
607 Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
\r
609 else if ( Type == EGST_BURNING_SKIN )
\r
611 const video::SColor c1 = colors[EGDC_WINDOW].getInterpolated ( 0xFFFFFFFF, 0.9f );
\r
612 const video::SColor c2 = colors[EGDC_WINDOW].getInterpolated ( 0xFFFFFFFF, 0.8f );
\r
614 Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
\r
618 const video::SColor c2 = colors[EGDC_3D_SHADOW];
\r
619 const video::SColor c1 = colors[EGDC_3D_FACE];
\r
620 Driver->draw2DRectangle(rect, c1, c1, c1, c2, clip);
\r
626 rect.UpperLeftCorner.X += 2;
\r
627 rect.UpperLeftCorner.Y += 2;
\r
628 rect.LowerRightCorner.X -= 2;
\r
629 rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + getSize(EGDS_WINDOW_BUTTON_WIDTH) + 2;
\r
633 if (checkClientArea)
\r
635 (*checkClientArea).UpperLeftCorner.Y = rect.LowerRightCorner.Y;
\r
640 //if (!UseGradient)
\r
641 // Driver->draw2DRectangle(titleBarColor, rect, clip);
\r
643 if ( Type == EGST_BURNING_SKIN )
\r
645 const video::SColor c = titleBarColor.getInterpolated( video::SColor(titleBarColor.getAlpha(),255,255,255), 0.8f);
\r
646 Driver->draw2DRectangle(rect, titleBarColor, titleBarColor, c, c, clip);
\r
650 const video::SColor c = titleBarColor.getInterpolated(video::SColor(titleBarColor.getAlpha(),0,0,0), 0.2f);
\r
651 Driver->draw2DRectangle(rect, titleBarColor, c, titleBarColor, c, clip);
\r
661 //! draws a standard 3d menu pane
\r
662 /** Used for drawing for menus and context menus.
\r
663 It uses the colors EGDC_3D_DARK_SHADOW, EGDC_3D_HIGH_LIGHT, EGDC_3D_SHADOW and
\r
664 EGDC_3D_FACE for this. See EGUI_DEFAULT_COLOR for details.
\r
665 \param element: Pointer to the element which wishes to draw this. This parameter
\r
666 is usually not used by ISkin, but can be used for example by more complex
\r
667 implementations to find out how to draw the part exactly.
\r
668 \param rect: Defining area where to draw.
\r
669 \param clip: Clip area. */
\r
671 void GUISkin::drawColored3DMenuPane(IGUIElement* element,
\r
672 const core::rect<s32>& r, const core::rect<s32>* clip,
\r
673 const video::SColor* colors)
\r
681 core::rect<s32> rect = r;
\r
683 if ( Type == EGST_BURNING_SKIN )
\r
685 rect.UpperLeftCorner.Y -= 3;
\r
686 draw3DButtonPaneStandard(element, rect, clip);
\r
690 // in this skin, this is exactly what non pressed buttons look like,
\r
691 // so we could simply call
\r
692 // draw3DButtonPaneStandard(element, rect, clip);
\r
694 // but if the skin is transparent, this doesn't look that nice. So
\r
695 // We draw it a little bit better, with some more draw2DRectangle calls,
\r
696 // but there aren't that much menus visible anyway.
\r
698 rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 1;
\r
699 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
701 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
702 rect.LowerRightCorner.X = rect.UpperLeftCorner.X + 1;
\r
703 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], rect, clip);
\r
705 rect.UpperLeftCorner.X = r.LowerRightCorner.X - 1;
\r
706 rect.LowerRightCorner.X = r.LowerRightCorner.X;
\r
707 rect.UpperLeftCorner.Y = r.UpperLeftCorner.Y;
\r
708 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
709 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
711 rect.UpperLeftCorner.X -= 1;
\r
712 rect.LowerRightCorner.X -= 1;
\r
713 rect.UpperLeftCorner.Y += 1;
\r
714 rect.LowerRightCorner.Y -= 1;
\r
715 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
717 rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
\r
718 rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
\r
719 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
720 rect.LowerRightCorner.X = r.LowerRightCorner.X;
\r
721 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], rect, clip);
\r
723 rect.UpperLeftCorner.X += 1;
\r
724 rect.LowerRightCorner.X -= 1;
\r
725 rect.UpperLeftCorner.Y -= 1;
\r
726 rect.LowerRightCorner.Y -= 1;
\r
727 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
730 rect.UpperLeftCorner.X +=1;
\r
731 rect.UpperLeftCorner.Y +=1;
\r
732 rect.LowerRightCorner.X -= 2;
\r
733 rect.LowerRightCorner.Y -= 2;
\r
736 Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
\r
739 const video::SColor c1 = colors[EGDC_3D_FACE];
\r
740 const video::SColor c2 = colors[EGDC_3D_SHADOW];
\r
741 Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
\r
747 //! draws a standard 3d tool bar
\r
748 /** Used for drawing for toolbars and menus.
\r
749 \param element: Pointer to the element which wishes to draw this. This parameter
\r
750 is usually not used by ISkin, but can be used for example by more complex
\r
751 implementations to find out how to draw the part exactly.
\r
752 \param rect: Defining area where to draw.
\r
753 \param clip: Clip area. */
\r
755 void GUISkin::drawColored3DToolBar(IGUIElement* element,
\r
756 const core::rect<s32>& r,
\r
757 const core::rect<s32>* clip,
\r
758 const video::SColor* colors)
\r
766 core::rect<s32> rect = r;
\r
768 rect.UpperLeftCorner.X = r.UpperLeftCorner.X;
\r
769 rect.UpperLeftCorner.Y = r.LowerRightCorner.Y - 1;
\r
770 rect.LowerRightCorner.Y = r.LowerRightCorner.Y;
\r
771 rect.LowerRightCorner.X = r.LowerRightCorner.X;
\r
772 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], rect, clip);
\r
775 rect.LowerRightCorner.Y -= 1;
\r
779 Driver->draw2DRectangle(colors[EGDC_3D_FACE], rect, clip);
\r
782 if ( Type == EGST_BURNING_SKIN )
\r
784 const video::SColor c1 = 0xF0000000 | colors[EGDC_3D_FACE].color;
\r
785 const video::SColor c2 = 0xF0000000 | colors[EGDC_3D_SHADOW].color;
\r
787 rect.LowerRightCorner.Y += 1;
\r
788 Driver->draw2DRectangle(rect, c1, c2, c1, c2, clip);
\r
792 const video::SColor c1 = colors[EGDC_3D_FACE];
\r
793 const video::SColor c2 = colors[EGDC_3D_SHADOW];
\r
794 Driver->draw2DRectangle(rect, c1, c1, c2, c2, clip);
\r
799 //! draws a tab button
\r
800 /** Used for drawing for tab buttons on top of tabs.
\r
801 \param element: Pointer to the element which wishes to draw this. This parameter
\r
802 is usually not used by ISkin, but can be used for example by more complex
\r
803 implementations to find out how to draw the part exactly.
\r
804 \param active: Specifies if the tab is currently active.
\r
805 \param rect: Defining area where to draw.
\r
806 \param clip: Clip area. */
\r
808 void GUISkin::drawColored3DTabButton(IGUIElement* element, bool active,
\r
809 const core::rect<s32>& frameRect, const core::rect<s32>* clip, EGUI_ALIGNMENT alignment,
\r
810 const video::SColor* colors)
\r
818 core::rect<s32> tr = frameRect;
\r
820 if ( alignment == EGUIA_UPPERLEFT )
\r
822 tr.LowerRightCorner.X -= 2;
\r
823 tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1;
\r
824 tr.UpperLeftCorner.X += 1;
\r
825 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
827 // draw left highlight
\r
829 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
830 tr.UpperLeftCorner.Y += 1;
\r
831 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
833 // draw grey background
\r
835 tr.UpperLeftCorner.X += 1;
\r
836 tr.UpperLeftCorner.Y += 1;
\r
837 tr.LowerRightCorner.X -= 2;
\r
838 Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
\r
840 // draw right middle gray shadow
\r
841 tr.LowerRightCorner.X += 1;
\r
842 tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1;
\r
843 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
\r
845 tr.LowerRightCorner.X += 1;
\r
846 tr.UpperLeftCorner.X += 1;
\r
847 tr.UpperLeftCorner.Y += 1;
\r
848 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], tr, clip);
\r
852 tr.LowerRightCorner.X -= 2;
\r
853 tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
\r
854 tr.UpperLeftCorner.X += 1;
\r
855 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
857 // draw left highlight
\r
859 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
860 tr.LowerRightCorner.Y -= 1;
\r
861 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
863 // draw grey background
\r
865 tr.UpperLeftCorner.X += 1;
\r
866 tr.UpperLeftCorner.Y -= 1;
\r
867 tr.LowerRightCorner.X -= 2;
\r
868 tr.LowerRightCorner.Y -= 1;
\r
869 Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
\r
871 // draw right middle gray shadow
\r
872 tr.LowerRightCorner.X += 1;
\r
873 tr.UpperLeftCorner.X = tr.LowerRightCorner.X - 1;
\r
874 //tr.LowerRightCorner.Y -= 1;
\r
875 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
\r
877 tr.LowerRightCorner.X += 1;
\r
878 tr.UpperLeftCorner.X += 1;
\r
879 tr.LowerRightCorner.Y -= 1;
\r
880 Driver->draw2DRectangle(colors[EGDC_3D_DARK_SHADOW], tr, clip);
\r
886 //! draws a tab control body
\r
887 /** \param element: Pointer to the element which wishes to draw this. This parameter
\r
888 is usually not used by ISkin, but can be used for example by more complex
\r
889 implementations to find out how to draw the part exactly.
\r
890 \param border: Specifies if the border should be drawn.
\r
891 \param background: Specifies if the background should be drawn.
\r
892 \param rect: Defining area where to draw.
\r
893 \param clip: Clip area. */
\r
895 void GUISkin::drawColored3DTabBody(IGUIElement* element, bool border, bool background,
\r
896 const core::rect<s32>& rect, const core::rect<s32>* clip, s32 tabHeight, EGUI_ALIGNMENT alignment,
\r
897 const video::SColor* colors)
\r
905 core::rect<s32> tr = rect;
\r
907 if ( tabHeight == -1 )
\r
908 tabHeight = getSize(gui::EGDS_BUTTON_HEIGHT);
\r
913 if ( alignment == EGUIA_UPPERLEFT )
\r
915 // draw left hightlight
\r
916 tr.UpperLeftCorner.Y += tabHeight + 2;
\r
917 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
918 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
920 // draw right shadow
\r
921 tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
\r
922 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
923 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
\r
925 // draw lower shadow
\r
927 tr.UpperLeftCorner.Y = tr.LowerRightCorner.Y - 1;
\r
928 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
\r
932 // draw left hightlight
\r
933 tr.LowerRightCorner.Y -= tabHeight + 2;
\r
934 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
935 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
937 // draw right shadow
\r
938 tr.UpperLeftCorner.X = rect.LowerRightCorner.X - 1;
\r
939 tr.LowerRightCorner.X = tr.UpperLeftCorner.X + 1;
\r
940 Driver->draw2DRectangle(colors[EGDC_3D_SHADOW], tr, clip);
\r
942 // draw lower shadow
\r
944 tr.LowerRightCorner.Y = tr.UpperLeftCorner.Y + 1;
\r
945 Driver->draw2DRectangle(colors[EGDC_3D_HIGH_LIGHT], tr, clip);
\r
951 if ( alignment == EGUIA_UPPERLEFT )
\r
954 tr.UpperLeftCorner.Y += tabHeight + 2;
\r
955 tr.LowerRightCorner.X -= 1;
\r
956 tr.UpperLeftCorner.X += 1;
\r
957 tr.LowerRightCorner.Y -= 1;
\r
962 tr.UpperLeftCorner.X += 1;
\r
963 tr.UpperLeftCorner.Y -= 1;
\r
964 tr.LowerRightCorner.X -= 1;
\r
965 tr.LowerRightCorner.Y -= tabHeight + 2;
\r
966 //tr.UpperLeftCorner.X += 1;
\r
970 Driver->draw2DRectangle(colors[EGDC_3D_FACE], tr, clip);
\r
973 video::SColor c1 = colors[EGDC_3D_FACE];
\r
974 video::SColor c2 = colors[EGDC_3D_SHADOW];
\r
975 Driver->draw2DRectangle(tr, c1, c1, c2, c2, clip);
\r
982 //! draws an icon, usually from the skin's sprite bank
\r
983 /** \param parent: Pointer to the element which wishes to draw this icon.
\r
984 This parameter is usually not used by IGUISkin, but can be used for example
\r
985 by more complex implementations to find out how to draw the part exactly.
\r
986 \param icon: Specifies the icon to be drawn.
\r
987 \param position: The position to draw the icon
\r
988 \param starttime: The time at the start of the animation
\r
989 \param currenttime: The present time, used to calculate the frame number
\r
990 \param loop: Whether the animation should loop or not
\r
991 \param clip: Clip area. */
\r
993 void GUISkin::drawColoredIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
\r
994 const core::position2di position,
\r
995 u32 starttime, u32 currenttime,
\r
996 bool loop, const core::rect<s32>* clip,
\r
997 const video::SColor* colors)
\r
1005 bool gray = element && !element->isEnabled();
\r
1006 SpriteBank->draw2DSprite(Icons[icon], position, clip,
\r
1007 colors[gray? EGDC_GRAY_WINDOW_SYMBOL : EGDC_WINDOW_SYMBOL], starttime, currenttime, loop, true);
\r
1012 EGUI_SKIN_TYPE GUISkin::getType() const
\r
1018 //! draws a 2d rectangle.
\r
1019 void GUISkin::draw2DRectangle(IGUIElement* element,
\r
1020 const video::SColor &color, const core::rect<s32>& pos,
\r
1021 const core::rect<s32>* clip)
\r
1023 Driver->draw2DRectangle(color, pos, clip);
\r
1027 //! Writes attributes of the object.
\r
1028 //! Implement this to expose the attributes of your scene node animator for
\r
1029 //! scripting languages, editors, debuggers or xml serialization purposes.
\r
1030 void GUISkin::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
\r
1033 for (i=0; i<EGDC_COUNT; ++i)
\r
1034 out->addColor(GUISkinColorNames[i], Colors[i]);
\r
1036 for (i=0; i<EGDS_COUNT; ++i)
\r
1037 out->addInt(GUISkinSizeNames[i], Sizes[i]);
\r
1039 for (i=0; i<EGDT_COUNT; ++i)
\r
1040 out->addString(GUISkinTextNames[i], Texts[i].c_str());
\r
1042 for (i=0; i<EGDI_COUNT; ++i)
\r
1043 out->addInt(GUISkinIconNames[i], Icons[i]);
\r
1047 //! Reads attributes of the object.
\r
1048 //! Implement this to set the attributes of your scene node animator for
\r
1049 //! scripting languages, editors, debuggers or xml deserialization purposes.
\r
1050 void GUISkin::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
\r
1052 // TODO: This is not nice code for downward compatibility, whenever new values are added and users
\r
1053 // load an old skin the corresponding values will be set to 0.
\r
1055 for (i=0; i<EGDC_COUNT; ++i)
\r
1056 Colors[i] = in->getAttributeAsColor(GUISkinColorNames[i]);
\r
1058 for (i=0; i<EGDS_COUNT; ++i)
\r
1059 Sizes[i] = in->getAttributeAsInt(GUISkinSizeNames[i]);
\r
1061 for (i=0; i<EGDT_COUNT; ++i)
\r
1062 Texts[i] = in->getAttributeAsStringW(GUISkinTextNames[i]);
\r
1064 for (i=0; i<EGDI_COUNT; ++i)
\r
1065 Icons[i] = in->getAttributeAsInt(GUISkinIconNames[i]);
\r
1069 //! gets the colors
\r
1071 void GUISkin::getColors(video::SColor* colors)
\r
1074 for (i=0; i<EGDC_COUNT; ++i)
\r
1075 colors[i] = Colors[i];
\r
1079 } // end namespace gui
\r
1080 } // end namespace irr
\r
1083 #endif // _IRR_COMPILE_WITH_GUI_
\r