// Copyright (C) 2002-2007 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" #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(); core::rect rec; s32 buttonw = environment->getSkin()->getSize(EGDS_WINDOW_BUTTON_WIDTH); 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->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(); core::rect r; 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); } r.UpperLeftCorner.X = 20; r.UpperLeftCorner.Y = 20; 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 ) { video::CImage *RawTexture; core::dimension2d d; d.Width = dim.Width * supersample; d.Height = dim.Height * supersample; RawTexture = new video::CImage ( irr::video::ECF_A8R8G8B8, d ); RawTexture->fill ( 0x00808080 ); u8 * data= (u8*) RawTexture->lock(); const u32 pitch = RawTexture->getPitch (); s32 radiusOut = ( d.Width / 2 ) - 4; const s32 fullR2 = radiusOut * radiusOut; video::SColorHSL hsl; video::SColor rgb; rgb.color = 0xFF000000; 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) f32 r = (f32) sqrt ( (f32) r2 ); // normalize, dotproduct = xnorm f32 t = (f32) 1.0 / r; f32 xn = -p.X * t; hsl.Hue = (f32) acos ( xn ); if ( p.Y > 0 ) hsl.Hue = (2.f * core::PI ) - hsl.Hue; hsl.Hue -= core::PI / 2.f; f32 rTest = r / radiusOut; /* if ( rTest < 0.25f ) { hsl.Luminance = rTest / 0.25f; hsl.Saturation = 0.f; hsl.settoRGB ( 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.settoRGB ( rgb ); // *dst = rgb.color; } else if ( rTest < 0.75f ) { hsl.Luminance = 0.5f; hsl.Saturation = 1.f; hsl.settoRGB ( rgb ); *dst = rgb.color; } else if ( rTest < 0.98f ) { hsl.Luminance = 0.5f - ( ( rTest - 0.75f ) / 0.75f ); hsl.Saturation = 1.f; hsl.settoRGB ( rgb ); *dst = rgb.color; } */ if ( rTest >= 0.5f ) { hsl.Luminance = 0.5f; hsl.Saturation = 1.f; hsl.settoRGB ( 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(irr::video::ECF_A8R8G8B8, dim ); RawTexture->copyToScalingBoxFilter ( filter, 0 ); 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 ( "#colorring", RawTexture ); RawTexture->drop (); driver->setTextureCreationFlag( video::ETCF_CREATE_MIP_MAPS, generateMipLevels); } //! called if an event happened. bool CGUIColorSelectDialog::OnEvent(SEvent event) { 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 ) { s32 pos = Battery[i].Scrollbar->getPos (); s32 value = Template[i].range_down + ( pos ); core::stringw s ( value ); Battery[i].Edit->setText ( s.c_str() ); } } return true; } break; 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: { } break; case EGET_LISTBOX_SELECTED_AGAIN: { } 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; } break; } } return Parent ? Parent->OnEvent(event) : false; } //! draws the element and its children void CGUIColorSelectDialog::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); core::rect rect = AbsoluteRect; rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER), rect, &AbsoluteClippingRect); if (Text.size()) { rect.UpperLeftCorner.X += 2; rect.LowerRightCorner.X -= skin->getSize(EGDS_WINDOW_BUTTON_WIDTH) + 5; IGUIFont* font = skin->getFont(); if (font) font->draw(Text.c_str(), rect, skin->getColor(EGDC_ACTIVE_CAPTION), false, true, &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.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.EventType = EGET_FILE_CHOOSE_DIALOG_CANCELLED; Parent->OnEvent(event); } } // end namespace gui } // end namespace irr