#include "gui/skin.hpp" #include "gui/engine.hpp" #include "gui/screen.hpp" #include "gui/widget.hpp" #include "gui/state_manager.hpp" #include "io/file_manager.hpp" #include #include using namespace GUIEngine; Skin::Skin(IGUISkin* fallback_skin) { m_fallback_skin = fallback_skin; m_fallback_skin->grab(); assert(fallback_skin != NULL); m_tex_button = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glassbutton.png").c_str() ); m_tex_fbutton = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glassbutton_focused.png").c_str() ); m_tex_spinner = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glassspinner.png").c_str() ); m_tex_fspinner = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glassspinner_focus.png").c_str() ); m_tex_dspinner = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glassspinner_down.png").c_str() ); m_tex_tab = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasstab.png").c_str() ); m_tex_ftab = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasstab_focus.png").c_str() ); m_tex_dtab = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasstab_down.png").c_str() ); m_tex_ficonhighlight = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glass_iconhighlight_focus.png").c_str() ); m_tex_squarefocus = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glass_square_focused.png").c_str() ); m_tex_gaugefill = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasssgauge_fill.png").c_str() ); m_tex_bubble = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/bubble.png").c_str() ); m_tex_checkbox = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasscheckbox.png").c_str() ); m_tex_fcheckbox = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasscheckbox_focus.png").c_str() ); m_tex_dcheckbox = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasscheckbox_checked.png").c_str() ); m_tex_dfcheckbox = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glasscheckbox_checked_focus.png").c_str() ); m_tex_section = GUIEngine::getDriver()->getTexture( (file_manager->getGUIDir() + "/glass_section.png").c_str() ); } Skin::~Skin() { m_fallback_skin->drop(); } /** load default values */ BoxRenderParams::BoxRenderParams() { left_border = 0; right_border = 0; top_border = 0; bottom_border = 0; preserve_h_aspect_ratios = false; hborder_out_portion = 0.5; vborder_out_portion = 1.0; areas = BODY | LEFT | RIGHT | TOP | BOTTOM; vertical_flip = false; } void Skin::drawBoxFromStretchableTexture(const core::rect< s32 > &dest, ITexture* source, const BoxRenderParams& params) { const int left_border = params.left_border; const int right_border = params.right_border; const int top_border = params.top_border; const int bottom_border = params.bottom_border; const bool preserve_h_aspect_ratios = params.preserve_h_aspect_ratios; const float hborder_out_portion = params.hborder_out_portion; const float vborder_out_portion = params.vborder_out_portion; int areas = params.areas; const bool vertical_flip = params.vertical_flip; // FIXME? - lots of things here will be re-calculated every frame, which is useless since // widgets won't move, so they'd only need to be calculated once. const int texture_w = source->getSize().Width; const int texture_h = source->getSize().Height; /* The source texture is split this way to allow for a stretchable center and borders that don't stretch : +----+--------------------+----+ | | | | +----a--------------------b----+ <-- top_border | | | | | | | | +----c--------------------d----+ <-- height - bottom-border | | | | +----+--------------------+----+ */ const int ax = left_border; const int ay = top_border; const int bx = texture_w - right_border; const int by = top_border; const int cx = left_border; const int cy = texture_h - bottom_border; const int dx = texture_w - right_border; const int dy = texture_h - bottom_border; core::rect source_area_left = core::rect(0, ay, cx, cy); core::rect source_area_center = core::rect(ax, ay, dx, dy); core::rect source_area_right = core::rect(bx, top_border, texture_w, dy); core::rect source_area_top = core::rect(ax, 0, bx, by); core::rect source_area_bottom = core::rect(cx, cy, dx, texture_h); core::rect source_area_top_left = core::rect(0, 0, ax, ay); core::rect source_area_top_right = core::rect(bx, 0, texture_w, top_border); core::rect source_area_bottom_left = core::rect(0, cy, cx, texture_h); core::rect source_area_bottom_right = core::rect(dx, dy, texture_w, texture_h); /* The dest area is split this way. Borders can go a bit beyond the given area so components inside don't go over the borders (how much it exceeds horizontally is specified in 'hborder_out_portion'. vertically is always the totality) a----b--------------------c----+ | | | | d----e--------------------f----g <-- top_border | | | | | | | | | | | | h----i--------------------j----k <-- height - bottom-border | | | | +----l--------------------m----n */ { const int dest_x = dest.UpperLeftCorner.X; const int dest_y = dest.UpperLeftCorner.Y; const int dest_x2 = dest.LowerRightCorner.X; const int dest_y2 = dest.LowerRightCorner.Y; //const float xscale = (float)(dest_x2-dest_x)/texture_w; const float yscale = (float)(dest_y2-dest_y)/texture_h; int dest_left_border, dest_right_border; // scale and keep aspect ratio if(preserve_h_aspect_ratios) { dest_left_border = (int)(left_border * (dest_y2-dest_y) / texture_h ); dest_right_border = (int)(right_border * (dest_y2-dest_y) / texture_h); } else { dest_left_border = (int)(left_border *std::min(yscale, 1.0)); dest_right_border = (int)(right_border *std::min(yscale, 1.0)); } int dest_top_border = (int)(top_border *std::min(yscale, 1.0)); int dest_bottom_border = (int)(bottom_border*std::min(yscale, 1.0)); const float hborder_in_portion = 1 - hborder_out_portion; const float vborder_in_portion = 1 - vborder_out_portion; const int ax = (int)(dest_x - dest_left_border*hborder_out_portion); const int ay = (int)(dest_y - dest_top_border*vborder_out_portion); const int bx = (int)(dest_x + dest_left_border*hborder_in_portion); const int by = ay; const int cx = (int)(dest_x2 - dest_right_border*hborder_in_portion); const int cy = ay; const int dx = ax; const int dy = (int)(dest_y + dest_top_border*vborder_in_portion); const int ex = bx; const int ey = dy; const int fx = cx; const int fy = dy; const int gx = (int)(dest_x2 + dest_right_border*hborder_out_portion); const int gy = dy; const int hx = ax; const int hy = (int)(dest_y2 - dest_bottom_border*vborder_in_portion); const int ix = bx; const int iy = hy; const int jx = cx; const int jy = hy; const int kx = gx; const int ky = hy; const int lx = bx; const int ly = (int)(dest_y2 + dest_bottom_border*vborder_out_portion); const int mx = cx; const int my = ly; const int nx = gx; const int ny = ly; core::rect dest_area_left = core::rect(dx, dy, ix, iy); core::rect dest_area_center = core::rect(ex, ey, jx, jy); core::rect dest_area_right = core::rect(fx, fy, kx, ky); core::rect dest_area_top = core::rect(bx, by, fx, fy); core::rect dest_area_bottom = core::rect(ix, iy, mx, my); core::rect dest_area_top_left = core::rect(ax, ay, ex, ey); core::rect dest_area_top_right = core::rect(cx, cy, gx, gy); core::rect dest_area_bottom_left = core::rect(hx, hy, lx, ly); core::rect dest_area_bottom_right = core::rect(jx, jy, nx, ny); if(vertical_flip) { #define FLIP_Y( X ) { const int y1 = X.UpperLeftCorner.Y - dest_y; \ const int y2 = X.LowerRightCorner.Y - dest_y; \ X.UpperLeftCorner.Y = dest_y + (dest_y2 - dest_y) - y2;\ X.LowerRightCorner.Y = dest_y + (dest_y2 - dest_y) - y1;} FLIP_Y(dest_area_left) FLIP_Y(dest_area_center) FLIP_Y(dest_area_right) FLIP_Y(dest_area_top) FLIP_Y(dest_area_bottom) FLIP_Y(dest_area_top_left) FLIP_Y(dest_area_top_right) FLIP_Y(dest_area_bottom_left) FLIP_Y(dest_area_bottom_right) #undef FLIP_Y #define FLIP_Y( X ) { const int y1 = X.UpperLeftCorner.Y; \ const int y2 = X.LowerRightCorner.Y; \ X.UpperLeftCorner.Y = y2;\ X.LowerRightCorner.Y = y1;} FLIP_Y(source_area_left) FLIP_Y(source_area_center) FLIP_Y(source_area_right) FLIP_Y(source_area_top) FLIP_Y(source_area_bottom) FLIP_Y(source_area_top_left) FLIP_Y(source_area_top_right) FLIP_Y(source_area_bottom_left) FLIP_Y(source_area_bottom_right) #undef FLIP_Y } if((areas & BoxRenderParams::LEFT) != 0) { GUIEngine::getDriver()->draw2DImage(source, dest_area_left, source_area_left, 0 /* no clipping */, 0, true /* alpha */); } if((areas & BoxRenderParams::BODY) != 0) { GUIEngine::getDriver()->draw2DImage(source, dest_area_center, source_area_center, 0 /* no clipping */, 0, true /* alpha */); } if((areas & BoxRenderParams::RIGHT) != 0) { GUIEngine::getDriver()->draw2DImage(source, dest_area_right, source_area_right, 0 /* no clipping */, 0, true /* alpha */); } if((areas & BoxRenderParams::TOP) != 0) { GUIEngine::getDriver()->draw2DImage(source, dest_area_top, source_area_top, 0 /* no clipping */, 0, true /* alpha */); } if((areas & BoxRenderParams::BOTTOM) != 0) { GUIEngine::getDriver()->draw2DImage(source, dest_area_bottom, source_area_bottom, 0 /* no clipping */, 0, true /* alpha */); } if( ((areas & BoxRenderParams::LEFT) != 0) && ((areas & BoxRenderParams::TOP) != 0) ) { GUIEngine::getDriver()->draw2DImage(source, dest_area_top_left, source_area_top_left, 0 /* no clipping */, 0, true /* alpha */); } if( ((areas & BoxRenderParams::RIGHT) != 0) && ((areas & BoxRenderParams::TOP) != 0) ) { GUIEngine::getDriver()->draw2DImage(source, dest_area_top_right, source_area_top_right, 0 /* no clipping */, 0, true /* alpha */); } if( ((areas & BoxRenderParams::LEFT) != 0) && ((areas & BoxRenderParams::BOTTOM) != 0) ) { GUIEngine::getDriver()->draw2DImage(source, dest_area_bottom_left, source_area_bottom_left, 0 /* no clipping */, 0, true /* alpha */); } if( ((areas & BoxRenderParams::RIGHT) != 0) && ((areas & BoxRenderParams::BOTTOM) != 0) ) { GUIEngine::getDriver()->draw2DImage(source, dest_area_bottom_right, source_area_bottom_right, 0 /* no clipping */, 0, true /* alpha */); } } } void Skin::drawButton(const core::rect< s32 > &rect, const bool pressed, const bool focused) { static BoxRenderParams params; // FIXME - move these numbers to a config file params.left_border = 80; params.right_border = 80; params.top_border = 0; params.bottom_border = 36; params.preserve_h_aspect_ratios = true; drawBoxFromStretchableTexture(rect, (focused ? m_tex_fbutton : m_tex_button), params); } void Skin::drawRibbon(const core::rect< s32 > &rect, const Widget* widget, const bool pressed, bool focused) { /* // only combo ribbons need a border if ( ((RibbonWidget*)widget)->getRibbonType() != RIBBON_COMBO ) return; bool draw_border = focused; // check if one of its children has focus (will happen when directly clicking on them) const int amount = widget->m_children.size(); for(int n=0; nhasFocus(widget->m_children[n].m_element)) { draw_border = true; focused = true; break; } } if(!draw_border) return; if(focused) GUIEngine::getDriver()->draw2DRectangle( SColor(255, 150, 0, 0), rect ); else GUIEngine::getDriver()->draw2DRectangle( SColor(255, 0, 150, 0), rect ); */ } void Skin::drawRibbonChild(const core::rect< s32 > &rect, const Widget* widget, const bool pressed, bool focused) { bool mark_selected = widget->isSelected(); bool always_show_selection = false; const bool parent_focused = GUIEngine::getGUIEnv()->getFocus() == widget->m_event_handler->m_element; RibbonType type = ((RibbonWidget*)widget->m_event_handler)->getRibbonType(); /* tab-bar ribbons */ if(type == RIBBON_TABS) { // ribbons containing buttons are actually tabs static BoxRenderParams params; // FIXME - specify in file, don't hardcode params.left_border = 75; params.right_border = 75; params.top_border = 0; params.bottom_border = 15; // automatically guess from position on-screen if tabs go up or down const bool vertical_flip = rect.UpperLeftCorner.Y < GUIEngine::getDriver()->getCurrentRenderTargetSize().Height/2; float portion_out = 0.2f; /* when not using plain buttons, it's probably icons, so we need more space */ if(widget->m_type != WTYPE_BUTTON) { //border_below = 40; } core::rect< s32 > rect2 = rect; params.hborder_out_portion = portion_out; params.vertical_flip = vertical_flip; if (mark_selected) { // selected tab should be slighlty bigger than others if(vertical_flip) rect2.UpperLeftCorner.Y -= 10; else rect2.LowerRightCorner.Y += 10; drawBoxFromStretchableTexture(rect2, (focused || parent_focused ? m_tex_ftab : m_tex_dtab), params); /* GUIEngine::getDriver()->draw2DLine( core::position2d< s32 >(rect2.UpperLeftCorner.X,rect2.LowerRightCorner.Y), core::position2d< s32 >(rect2.LowerRightCorner.X,rect2.LowerRightCorner.Y), SColor(255,255,0,0) ); GUIEngine::getDriver()->draw2DLine( core::position2d< s32 >(rect2.UpperLeftCorner.X,rect2.UpperLeftCorner.Y), core::position2d< s32 >(rect2.LowerRightCorner.X,rect2.UpperLeftCorner.Y), SColor(255,255,0,0) ); */ } else { drawBoxFromStretchableTexture(rect2, m_tex_tab, params); } } /* icon ribbons */ else { bool use_glow = true; if (widget->m_event_handler != NULL && widget->m_event_handler->m_properties[PROP_SQUARE] == "true") use_glow = false; if (widget->m_event_handler != NULL && widget->m_event_handler->m_event_handler != NULL && widget->m_event_handler->m_event_handler->m_properties[PROP_SQUARE] == "true") use_glow = false; /* in combo ribbons, always show selection */ RibbonWidget* w = NULL; if(widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_RIBBON) { w = dynamic_cast(widget->m_event_handler); if(w->getRibbonType() == RIBBON_COMBO) always_show_selection = true; } const bool mark_focused = focused || (parent_focused && w != NULL && w->m_focus == widget) || (mark_selected && !always_show_selection && parent_focused); if(always_show_selection && mark_selected) { core::rect< s32 > rect2 = rect; rect2.UpperLeftCorner.X -= rect.getWidth() / 5; rect2.UpperLeftCorner.Y -= rect.getHeight() / 5; rect2.LowerRightCorner.X += rect.getWidth() / 5; rect2.LowerRightCorner.Y += rect.getHeight() / 5; const int texture_w = m_tex_bubble->getSize().Width; const int texture_h = m_tex_bubble->getSize().Height; core::rect source_area = core::rect(0, 0, texture_w, texture_h); GUIEngine::getDriver()->draw2DImage(m_tex_bubble, rect2, source_area, 0 /* no clipping */, 0, true /* alpha */); } if(mark_focused) { if (use_glow) { int grow = 45; static float glow_effect = 0; const float dt = GUIEngine::getLatestDt(); glow_effect += dt*3; if (glow_effect > 6.2832f /* 2*PI */) glow_effect -= 6.2832f; grow = (int)(45 + 10*sin(glow_effect)); const int glow_center_x = rect.UpperLeftCorner.X + rect.getWidth()/2; const int glow_center_y = rect.UpperLeftCorner.Y + rect.getHeight() - 5; const int texture_w = m_tex_ficonhighlight->getSize().Width; const int texture_h = m_tex_ficonhighlight->getSize().Height; core::rect source_area = core::rect(0, 0, texture_w, texture_h); const core::rect< s32 > rect2 = core::rect< s32 >(glow_center_x - 45 - grow, glow_center_y - 25 - grow/2, glow_center_x + 45 + grow, glow_center_y + 25 + grow/2); GUIEngine::getDriver()->draw2DImage(m_tex_ficonhighlight, rect2, source_area, 0 /* no clipping */, 0, true /* alpha */); } /* if we're not using glow */ else { const bool show_focus = focused || parent_focused; if(!always_show_selection && !show_focus) return; const int texture_w = m_tex_squarefocus->getSize().Width; const int texture_h = m_tex_squarefocus->getSize().Height; core::rect source_area = core::rect(0, 0, texture_w, texture_h); static BoxRenderParams params; params.left_border = 6; params.right_border = 6; params.top_border = 6; params.bottom_border = 6; params.hborder_out_portion = 1.0; drawBoxFromStretchableTexture(rect, m_tex_squarefocus, params); } } // end if mark_focused } } void Skin::drawSpinnerBody(const core::rect< s32 > &rect, const Widget* widget, const bool pressed, bool focused) { if(!focused) { IGUIElement* focused_widget = GUIEngine::getGUIEnv()->getFocus(); if(focused_widget != NULL && widget->m_children.size()>2) { if(widget->m_children[0].id == focused_widget->getID() || widget->m_children[1].id == focused_widget->getID() || widget->m_children[2].id == focused_widget->getID()) { focused = true; } } } static BoxRenderParams params; // FIXME - move these numbers to a config file params.left_border = 110; params.right_border = 110; params.top_border = 0; params.bottom_border = 36; params.preserve_h_aspect_ratios = true; params.hborder_out_portion = 0.0f; drawBoxFromStretchableTexture(rect, (focused || pressed ? m_tex_fspinner : m_tex_spinner), params); const SpinnerWidget* w = dynamic_cast(widget); if( w->isGauge() ) { // the width of an handle is about 0.84 the height in the current skin. FIXME - don't hardcode. const int handle_size = (int)( widget->h*0.84f ); const float value = (float)(w->getValue() - w->getMin()) / (w->getMax() - w->getMin()); const core::rect< s32 > dest_area = core::rect< s32 >(widget->x + handle_size, widget->y, widget->x + handle_size + (int)((widget->w - 2*handle_size)*value), widget->y + widget->h); const int texture_w = m_tex_gaugefill->getSize().Width; const int texture_h = m_tex_gaugefill->getSize().Height; const core::rect< s32 > source_area = core::rect< s32 >(0, 0, texture_w, texture_h); GUIEngine::getDriver()->draw2DImage(m_tex_gaugefill, dest_area, source_area, 0 /* no clipping */, 0, true /* alpha */); } } void Skin::drawSpinnerChild(const core::rect< s32 > &rect, Widget* widget, const bool pressed, bool focused) { if(pressed) { Widget* spinner = widget->m_event_handler; int areas = 0; //std::cout << "drawing spinner child " << widget->m_properties[PROP_ID].c_str() << std::endl; if (widget->m_properties[PROP_ID] == "left") areas = BoxRenderParams::LEFT; else if (widget->m_properties[PROP_ID] == "right") areas = BoxRenderParams::RIGHT; else return; core::rect< s32 > rect2 = core::rect< s32 >( spinner->x, spinner->y, spinner->x + spinner->w, spinner->y + spinner->h ); static BoxRenderParams params; // FIXME - move these numbers to a config file params.left_border = 110; params.right_border = 110; params.top_border = 0; params.bottom_border = 36; params.preserve_h_aspect_ratios = true; params.hborder_out_portion = 0.0f; params.areas = areas; drawBoxFromStretchableTexture(rect2, m_tex_dspinner, params); } } void Skin::drawCheckBox(const core::rect< s32 > &rect, Widget* widget, bool focused) { CheckBoxWidget* w = dynamic_cast(widget); const int texture_w = m_tex_checkbox->getSize().Width; const int texture_h = m_tex_checkbox->getSize().Height; const core::rect< s32 > source_area = core::rect< s32 >(0, 0, texture_w, texture_h); if(w->getState() == true) { GUIEngine::getDriver()->draw2DImage( focused ? m_tex_dfcheckbox : m_tex_dcheckbox, rect, source_area, 0 /* no clipping */, 0, true /* alpha */); } else { GUIEngine::getDriver()->draw2DImage( focused ? m_tex_fcheckbox : m_tex_checkbox, rect, source_area, 0 /* no clipping */, 0, true /* alpha */); } } void Skin::drawList(const core::rect< s32 > &rect, Widget* widget, bool focused) { static BoxRenderParams params; params.left_border = 15; params.right_border = 15; params.top_border = 15; params.bottom_border = 15; params.hborder_out_portion = 1.0; params.vborder_out_portion = 1.0f; drawBoxFromStretchableTexture( rect, m_tex_section, params ); } void Skin::drawListSelection(const core::rect< s32 > &rect, Widget* widget, bool focused) { // focused render params static BoxRenderParams focusparams; focusparams.left_border = 0; focusparams.right_border = 0; focusparams.top_border = 0; focusparams.bottom_border = 0; focusparams.hborder_out_portion = 0.0f; focusparams.vborder_out_portion = 0.0f; // non-focused render params static BoxRenderParams params; params.left_border = 80; params.right_border = 80; params.top_border = 0; params.bottom_border = 36; params.preserve_h_aspect_ratios = true; params.areas = BoxRenderParams::BODY; params.hborder_out_portion = 1.0f; params.vborder_out_portion = 1.0f; // adjust render area core::rect< s32 > rect2 = rect; rect2.UpperLeftCorner.X -= 10; rect2.LowerRightCorner.X += 10; if(focused) drawBoxFromStretchableTexture( rect2, m_tex_gaugefill, focusparams ); else drawBoxFromStretchableTexture( rect2, m_tex_button, params ); } /** recusrive function to render all sections (recursion allows to easily travesre the tree of children and sub-children) */ void Skin::renderSections(ptr_vector* within_vector) { if(within_vector == NULL) within_vector = &getCurrentScreen()->m_widgets; const unsigned short widgets_amount = within_vector->size(); for(int n=0; n rect = core::rect( widget.x, widget.y, widget.x + widget.w, widget.y + widget.h ); //getDriver()->draw2DImage(g_skin->m_tex_section, rect, source_area, // 0 /* no clipping */, 0, true /* alpha */); static BoxRenderParams params; params.left_border = 15; params.right_border = 15; params.top_border = 15; params.bottom_border = 15; params.hborder_out_portion = 1.0; params.vborder_out_portion = 0.2f; drawBoxFromStretchableTexture( rect, m_tex_section, params ); /* void drawBoxFromStretchableTexture(const core::rect< s32 > &dest, ITexture* source, const int left_border, const int right_border, const int top_border, const int bottom_border, const bool preserve_h_aspect_ratios=false, const float hborder_out_portion = 0.5, int areas = BODY | LEFT | RIGHT | TOP | BOTTOM, const bool vertical_flip=false); */ } else { renderSections( &widget.m_children ); } } } // next } #if 0 #pragma mark - #pragma mark irrlicht skin functions #endif void Skin::draw2DRectangle (IGUIElement *element, const video::SColor &color, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { if(StateManager::isGameState()) return; // ignore in game mode //const bool focused = GUIEngine::getGUIEnv()->hasFocus(element); const int id = element->getID(); Widget* widget = GUIEngine::getCurrentScreen()->getWidget(id); if(widget == NULL) return; const bool focused = GUIEngine::getGUIEnv()->hasFocus(element); const WidgetType type = widget->m_type; if(type == WTYPE_LIST) { // list selection background drawListSelection(rect, widget, focused); } } void Skin::process3DPane(IGUIElement *element, const core::rect< s32 > &rect, const bool pressed) { const bool focused = GUIEngine::getGUIEnv()->hasFocus(element); const int id = element->getID(); Widget* widget = GUIEngine::getCurrentScreen()->getWidget(id); if(widget == NULL) return; const WidgetType type = widget->m_type; // buttons are used for other uses than plain clickable buttons because irrLicht // does not have widgets for everything we need. so at render time, we just check // which type this button represents and render accordingly if(widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_RIBBON) { drawRibbonChild(rect, widget, pressed /* pressed */, focused /* focused */); } else if(widget->m_event_handler != NULL && widget->m_event_handler->m_type == WTYPE_SPINNER) { drawSpinnerChild(rect, widget, pressed /* pressed */, focused /* focused */); } else if(type == WTYPE_ICON_BUTTON) { if(!focused) return; /* don't draw any border in this case */ else drawButton(rect, pressed /* pressed */, true /* focused */); } else if(type == WTYPE_BUTTON) { drawButton(rect, pressed, focused); } else if(type == WTYPE_RIBBON) { drawRibbon(rect, widget, pressed, focused); } else if(type == WTYPE_SPINNER) { drawSpinnerBody(rect, widget, pressed, focused); } else if(type == WTYPE_CHECKBOX) { drawCheckBox(rect, widget, focused); } } void Skin::draw3DButtonPanePressed (IGUIElement *element, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { process3DPane(element, rect, true /* pressed */ ); } void Skin::draw3DButtonPaneStandard (IGUIElement *element, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { process3DPane(element, rect, false /* pressed */ ); } void Skin::draw3DSunkenPane (IGUIElement *element, video::SColor bgcolor, bool flat, bool fillBackGround, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { const int id = element->getID(); Widget* widget = GUIEngine::getCurrentScreen()->getWidget(id); if(widget == NULL) return; const WidgetType type = widget->m_type; const bool focused = GUIEngine::getGUIEnv()->getFocus() == element; if(type == WTYPE_LIST) { drawList(rect, widget, focused); } //if(focused) // GUIEngine::getDriver()->draw2DRectangle( SColor(255, 150, 0, 0), rect ); //else // GUIEngine::getDriver()->draw2DRectangle( SColor(255, 0, 150, 0), rect ); } core::rect< s32 > Skin::draw3DWindowBackground (IGUIElement *element, bool drawTitleBar, video::SColor titleBarColor, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { // fade out background GUIEngine::getDriver()->draw2DRectangle( SColor(150, 255, 255, 255), core::rect< s32 >(position2d< s32 >(0,0) , GUIEngine::getDriver()->getCurrentRenderTargetSize()) ); static BoxRenderParams params; params.left_border = 15; params.right_border = 15; params.top_border = 15; params.bottom_border = 15; params.hborder_out_portion = 1.0; params.vborder_out_portion = 0.2f; // draw frame (since it's transluscent, draw many times to get opacity) drawBoxFromStretchableTexture(rect, m_tex_section, params); drawBoxFromStretchableTexture(rect, m_tex_section, params); return rect; } void Skin::draw3DMenuPane (IGUIElement *element, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { //printf("draw menu pane\n"); } void Skin::draw3DTabBody (IGUIElement *element, bool border, bool background, const core::rect< s32 > &rect, const core::rect< s32 > *clip, s32 tabHeight, gui::EGUI_ALIGNMENT alignment) { //printf("draw tab body\n"); } void Skin::draw3DTabButton (IGUIElement *element, bool active, const core::rect< s32 > &rect, const core::rect< s32 > *clip, gui::EGUI_ALIGNMENT alignment) { //printf("draw tab button\n"); } void Skin::draw3DToolBar (IGUIElement *element, const core::rect< s32 > &rect, const core::rect< s32 > *clip) { } void Skin::drawIcon (IGUIElement *element, EGUI_DEFAULT_ICON icon, const core::position2di position, u32 starttime, u32 currenttime, bool loop, const core::rect< s32 > *clip) { /* m_fallback_skin->drawIcon(element, icon, position, starttime, currenttime, loop, clip); */ } video::SColor Skin::getColor (EGUI_DEFAULT_COLOR color) const { /* EGDC_3D_DARK_SHADOW Dark shadow for three-dimensional display elements. EGDC_3D_SHADOW Shadow color for three-dimensional display elements (for edges facing away from the light source). EGDC_3D_FACE Face color for three-dimensional display elements and for dialog box backgrounds. EGDC_3D_HIGH_LIGHT Highlight color for three-dimensional display elements (for edges facing the light source.). EGDC_3D_LIGHT Light color for three-dimensional display elements (for edges facing the light source.). EGDC_ACTIVE_BORDER Active window border. EGDC_ACTIVE_CAPTION Active window title bar text. EGDC_APP_WORKSPACE Background color of multiple document interface (MDI) applications. EGDC_BUTTON_TEXT Text on a button. EGDC_GRAY_TEXT Grayed (disabled) text. EGDC_HIGH_LIGHT Item(s) selected in a control. EGDC_HIGH_LIGHT_TEXT Text of item(s) selected in a control. EGDC_INACTIVE_BORDER Inactive window border. EGDC_INACTIVE_CAPTION Inactive window caption. EGDC_TOOLTIP Tool tip text color. EGDC_TOOLTIP_BACKGROUND Tool tip background color. EGDC_SCROLLBAR Scrollbar gray area. EGDC_WINDOW Window background. EGDC_WINDOW_SYMBOL Window symbols like on close buttons, scroll bars and check boxes. EGDC_ICON Icons in a list or tree. EGDC_ICON_HIGH_LIGHT Selected icons in a list or tree. */ // TODO : make configurable switch(color) { case EGDC_BUTTON_TEXT: return SColor(255, 0, 0, 0); break; case EGDC_GRAY_TEXT: return SColor(255, 80, 80, 80); break; case EGDC_HIGH_LIGHT: case EGDC_ICON_HIGH_LIGHT: case EGDC_HIGH_LIGHT_TEXT: return SColor(255, 0, 0, 0); //return SColor(255, 0, 150, 0); default: return SColor(255, 255, 255, 255); } } const wchar_t* Skin::getDefaultText (EGUI_DEFAULT_TEXT text) const { return L"SuperTuxKart"; } IGUIFont* Skin::getFont (EGUI_DEFAULT_FONT which) const { return GUIEngine::getFont(); } u32 Skin::getIcon (EGUI_DEFAULT_ICON icon) const { //return m_fallback_skin->getIcon(icon); // return m_fallback_skin->getIcon(irr::gui::EGUI_DEFAULT_ICON); return 0; } s32 Skin::getSize (EGUI_DEFAULT_SIZE size) const { return m_fallback_skin->getSize(size); } IGUISpriteBank* Skin::getSpriteBank () const { return m_fallback_skin->getSpriteBank(); } //EGUI_SKIN_TYPE getType () const void Skin::setColor (EGUI_DEFAULT_COLOR which, video::SColor newColor) { m_fallback_skin->setColor(which, newColor); } void Skin::setDefaultText (EGUI_DEFAULT_TEXT which, const wchar_t *newText) { m_fallback_skin->setDefaultText(which, newText); } void Skin::setFont (IGUIFont *font, EGUI_DEFAULT_FONT which) { m_fallback_skin->setFont(font, which); } void Skin::setIcon (EGUI_DEFAULT_ICON icon, u32 index) { m_fallback_skin->setIcon(icon, index); } void Skin::setSize (EGUI_DEFAULT_SIZE which, s32 size) { m_fallback_skin->setSize(which, size); //printf("setting size\n"); } void Skin::setSpriteBank (IGUISpriteBank *bank) { //printf("setting sprite bank\n"); m_fallback_skin->setSpriteBank(bank); //this->m_bank = bank; }