// Copyright (C) 2002-2009 Nikolaus Gebhardt // This file is part of the "Irrlicht Engine". // For conditions of distribution and use, see copyright notice in irrlicht.h #include "CGUIColorSelectDialog.h" #ifdef _IRR_COMPILE_WITH_GUI_ #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIButton.h" #include "IGUIStaticText.h" #include "IGUIFont.h" #include "IGUISpriteBank.h" #include "IFileList.h" #include "os.h" #include "SoftwareDriver2_helper.h" #include "CImage.h" namespace irr { namespace gui { const s32 CSD_WIDTH = 350; const s32 CSD_HEIGHT = 300; struct sTemplate { const wchar_t *pre; const wchar_t *init; const wchar_t *pos; int x, y; int range_down ,range_up; }; static const sTemplate Template [] = { { L"A:", L"0", 0,20,165, 0, 255 }, { L"R:", L"0", 0,20,205, 0, 255 }, { L"G:", L"0", 0,20,230, 0, 255 }, { L"B:", L"0", 0,20,255, 0, 255 }, { L"H:", L"0", L"°",180,205, 0, 360 }, { L"S:", L"0", L"%",180,230, 0, 100 }, { L"L:", L"0", L"%",180,255, 0, 100 }, }; //! constructor CGUIColorSelectDialog::CGUIColorSelectDialog(const wchar_t* title, IGUIEnvironment* environment, IGUIElement* parent, s32 id) : IGUIColorSelectDialog(environment, parent, id, core::rect((parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2, (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2, (parent->getAbsolutePosition().getWidth()-CSD_WIDTH)/2+CSD_WIDTH, (parent->getAbsolutePosition().getHeight()-CSD_HEIGHT)/2+CSD_HEIGHT)), Dragging(false) { #ifdef _DEBUG IGUIElement::setDebugName("CGUIColorSelectDialog"); #endif Text = title; IGUISkin* skin = Environment->getSkin(); const s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH); const s32 posx = RelativeRect.getWidth() - buttonw - 4; CloseButton = Environment->addButton(core::rect(posx, 3, posx + buttonw, 3 + buttonw), this, -1, L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close"); if (skin && skin->getSpriteBank()) { CloseButton->setSpriteBank(skin->getSpriteBank()); CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL)); CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), skin->getColor(EGDC_WINDOW_SYMBOL)); } CloseButton->setSubElement(true); CloseButton->setTabStop(false); CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CloseButton->grab(); OKButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 30, RelativeRect.getWidth()-10, 50), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_OK) : L"OK"); OKButton->setSubElement(true); OKButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); OKButton->grab(); CancelButton = Environment->addButton( core::rect(RelativeRect.getWidth()-80, 55, RelativeRect.getWidth()-10, 75), this, -1, skin ? skin->getDefaultText(EGDT_MSG_BOX_CANCEL) : L"Cancel"); CancelButton->setSubElement(true); CancelButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT); CancelButton->grab(); video::IVideoDriver* driver = Environment->getVideoDriver(); ColorRing.Texture = driver->getTexture ( "#colorring" ); if ( 0 == ColorRing.Texture ) { buildColorRing(core::dimension2d(128, 128), 1, Environment->getSkin()->getColor(EGDC_3D_SHADOW).color); } core::rect r(20,20, 0,0); ColorRing.Control = Environment->addImage(ColorRing.Texture, r.UpperLeftCorner, true, this); ColorRing.Control->setSubElement(true); ColorRing.Control->grab(); for ( u32 i = 0; i != sizeof (Template) / sizeof ( sTemplate ); ++i ) { if ( Template[i].pre ) { r.UpperLeftCorner.X = Template[i].x; r.UpperLeftCorner.Y = Template[i].y; r.LowerRightCorner.X = r.UpperLeftCorner.X + 15; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; IGUIElement *t = Environment->addStaticText(Template[i].pre, r, false, false, this); t->setSubElement(true); } if ( Template[i].pos ) { r.UpperLeftCorner.X = Template[i].x + 52; r.UpperLeftCorner.Y = Template[i].y; r.LowerRightCorner.X = r.UpperLeftCorner.X + 15; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; IGUIElement *t = Environment->addStaticText( Template[i].pos, r, false, false, this); t->setSubElement(true); } SBatteryItem item; r.UpperLeftCorner.X = Template[i].x + 15; r.UpperLeftCorner.Y = Template[i].y; r.LowerRightCorner.X = r.UpperLeftCorner.X + 35; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 20; item.Edit = Environment->addEditBox( Template[i].init, r, true, this); item.Edit->setSubElement(true); item.Edit->grab(); r.UpperLeftCorner.X = Template[i].x + 70; r.UpperLeftCorner.Y = Template[i].y + 4; r.LowerRightCorner.X = r.UpperLeftCorner.X + 60; r.LowerRightCorner.Y = r.UpperLeftCorner.Y + 12; item.Scrollbar = Environment->addScrollBar(true, r, this); item.Scrollbar->grab (); item.Scrollbar->setSubElement(true); item.Scrollbar->setMax ( Template[i].range_up - Template[i].range_down ); item.Scrollbar->setSmallStep ( 1 ); Battery.push_back ( item ); } bringToFront(CancelButton); bringToFront(OKButton); } //! destructor CGUIColorSelectDialog::~CGUIColorSelectDialog() { if (CloseButton) CloseButton->drop(); if (OKButton) OKButton->drop(); if (CancelButton) CancelButton->drop(); for ( u32 i = 0; i != Battery.size ();++i ) { Battery[i].Edit->drop(); Battery[i].Scrollbar->drop(); } if (ColorRing.Control) ColorRing.Control->drop(); } //! renders a antialiased, colored ring void CGUIColorSelectDialog::buildColorRing( const core::dimension2d & dim, s32 supersample, const u32 borderColor ) { const core::dimension2d d(dim.Width * supersample, dim.Height * supersample); video::CImage *RawTexture = new video::CImage(video::ECF_A8R8G8B8, d); RawTexture->fill ( 0x00808080 ); u8 * data= (u8*) RawTexture->lock(); const u32 pitch = RawTexture->getPitch(); const s32 radiusOut = ( d.Width / 2 ) - 4; const s32 fullR2 = radiusOut * radiusOut; video::SColor rgb(0xFF000000); video::SColorHSL hsl; hsl.Luminance = 0.5f; hsl.Saturation = 1.f; core::position2d p; u32 *dst; for ( p.Y = -radiusOut; p.Y <= radiusOut; p.Y += 1 ) { s32 y2 = p.Y * p.Y; dst = (u32*) ( (u8* ) data + ( ( 4 + p.Y + radiusOut ) * pitch ) + (4 << 2 ) ); for ( p.X = -radiusOut; p.X <= radiusOut; p.X += 1, dst += 1 ) { s32 r2 = y2 + ( p.X * p.X ); // test point in circle s32 testa = r2 - fullR2; if ( testa < 0 ) { // dotproduct u ( x,y ) * v ( 1, 0 ) = cosinus(a) const f32 r = sqrtf((f32) r2); // normalize, dotproduct = xnorm const f32 xn = -p.X * core::reciprocal(r); hsl.Hue = acosf(xn); if ( p.Y > 0 ) hsl.Hue = (2.f * core::PI ) - hsl.Hue; hsl.Hue -= core::PI / 2.f; const f32 rTest = r / radiusOut; /* if ( rTest < 0.25f ) { hsl.Luminance = rTest / 0.25f; hsl.Saturation = 0.f; hsl.toRGB ( rgb ); *dst = rgb.color; } else if ( rTest < 0.4f ) { hsl.Saturation = ( rTest - 0.25f ) / 0.15f; hsl.Luminance = 1.f - ( hsl.Saturation / 2.4f ); hsl.Luminance = 0.5f; hsl.toRGB ( rgb ); // *dst = rgb.color; } else if ( rTest < 0.75f ) { hsl.Luminance = 0.5f; hsl.Saturation = 1.f; hsl.toRGB ( rgb ); *dst = rgb.color; } else if ( rTest < 0.98f ) { hsl.Luminance = 0.5f - ( ( rTest - 0.75f ) / 0.75f ); hsl.Saturation = 1.f; hsl.toRGB ( rgb ); *dst = rgb.color; } */ if ( rTest >= 0.5f ) { hsl.Luminance = 0.5f; hsl.Saturation = 1.f; hsl.toRGB(rgb); *dst = rgb.color; } if ( rTest >= 0.5f && rTest <= 0.55f ) { u32 alpha = (s32) ( (rTest - 0.5f ) * ( 255.f / 0.05f ) ); *dst = (*dst & 0x00ffffff) | (alpha << 24); } if ( rTest >= 0.95f ) { u32 alpha = (s32) ( (rTest - 0.95f ) * ( 255.f / 0.05f ) ); alpha = 255 - alpha; *dst = (*dst & 0x00ffffff) | (alpha << 24); } } } } RawTexture->unlock (); if ( supersample > 1 ) { video::CImage * filter = new video::CImage(video::ECF_A8R8G8B8, dim ); RawTexture->copyToScalingBoxFilter(filter); RawTexture->drop(); RawTexture = filter; } video::IVideoDriver* driver = Environment->getVideoDriver(); bool generateMipLevels = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, false); ColorRing.Texture = driver->addTexture ( L"#colorring", RawTexture); RawTexture->drop(); driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, generateMipLevels); } //! called if an event happened. bool CGUIColorSelectDialog::OnEvent(const SEvent& event) { if (IsEnabled) { switch(event.EventType) { case EET_GUI_EVENT: switch(event.GUIEvent.EventType) { case EGET_SCROLL_BAR_CHANGED: { for ( u32 i = 0; i!= Battery.size (); ++i ) { if ( event.GUIEvent.Caller == Battery[i].Scrollbar ) { const s32 value = Template[i].range_down + Battery[i].Scrollbar->getPos(); Battery[i].Edit->setText(core::stringw(value).c_str()); } } return true; } case EGET_ELEMENT_FOCUS_LOST: Dragging = false; break; case EGET_BUTTON_CLICKED: if (event.GUIEvent.Caller == CloseButton || event.GUIEvent.Caller == CancelButton) { sendCancelEvent(); remove(); return true; } else if (event.GUIEvent.Caller == OKButton) { sendSelectedEvent(); remove(); return true; } break; case EGET_LISTBOX_CHANGED: case EGET_LISTBOX_SELECTED_AGAIN: default: break; } break; case EET_MOUSE_INPUT_EVENT: switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; Dragging = true; Environment->setFocus(this); return true; case EMIE_LMOUSE_LEFT_UP: Dragging = false; Environment->removeFocus(this); return true; case EMIE_MOUSE_MOVED: if (Dragging) { // gui window should not be dragged outside its parent if (Parent) if (event.MouseInput.X < Parent->getAbsolutePosition().UpperLeftCorner.X +1 || event.MouseInput.Y < Parent->getAbsolutePosition().UpperLeftCorner.Y +1 || event.MouseInput.X > Parent->getAbsolutePosition().LowerRightCorner.X -1 || event.MouseInput.Y > Parent->getAbsolutePosition().LowerRightCorner.Y -1) return true; move(core::position2d(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y)); DragStart.X = event.MouseInput.X; DragStart.Y = event.MouseInput.Y; return true; } default: break; } default: break; } } return IGUIElement::OnEvent(event); } //! draws the element and its children void CGUIColorSelectDialog::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), AbsoluteRect, &AbsoluteClippingRect); if (Text.size()) { rect.UpperLeftCorner.X += 2; rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(EGDF_WINDOW); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &AbsoluteClippingRect); } IGUIFont* font = Environment->getBuiltInFont(); if (font) font->draw(L"+", core::rect(20,20,50,50), video::SColor(), false, false, &AbsoluteClippingRect); IGUIElement::draw(); } //! sends the event that the file has been selected. void CGUIColorSelectDialog::sendSelectedEvent() { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_FILE_SELECTED; Parent->OnEvent(event); } //! sends the event that the file choose process has been canceld void CGUIColorSelectDialog::sendCancelEvent() { SEvent event; event.EventType = EET_GUI_EVENT; event.GUIEvent.Caller = this; event.GUIEvent.Element = 0; event.GUIEvent.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED; Parent->OnEvent(event); } } // end namespace gui } // end namespace irr #endif // _IRR_COMPILE_WITH_GUI_