(C++) icon/slot drag/drop rpg style gui

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.

Postby doqkhanh » Sat Jun 21, 2008 9:17 am

B@z wrote:HTTP1.1 STATUS 403 Remote Access to this object forbidden

Direct Access Forbidden
This file cannot be directly accessed from a remote site, but must be linked through the Brinkster Member's site.

:roll: New link for you B@z, but in my game, the application crash when I try to drag and drop.
doqkhanh
 
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan

Postby pera » Sat Jul 05, 2008 5:08 am

This code works only from main function... if you have icon touch crash, that is because slotArray went out of scope, like the man said few years ago. Make slotArray global, or do some intelligent modification.
pera
 
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia

Postby doqkhanh » Sat Jul 05, 2008 5:39 am

pera wrote:This code works only from main function... if you have icon touch crash, that is because slotArray went out of scope, like the man said few years ago. Make slotArray global, or do some intelligent modification.


You are right. But, this code have 2 logic error when processing event.
doqkhanh
 
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan

Postby pera » Sat Jul 05, 2008 9:23 am

Yes, that is correct.
When code was moved to Irrlicht 1.4, only compiler errors were fixed.
In order to make it work, you have to use 1.4 OnEvent functions for GUIWindow, and CIcon. I There were some changes in event handling, so you have to do it like that for it to work properly.
I made those changes and succeded to make code work fine, I can post changes later, but during code exploration I relized this GUI component was pretty awkwardly coded. There is two new classes CSlotWindow and that BringUpButton wich don't do anything different then regular component (CSlotWindow creates slotArray and returns it but its not even member component of CSlotWindow, and BringUpButton shows/hides window wich any regular button can do - no need for special class I think).
my favorite is
Dragged = true*Movable;
Anyhow, I think This inventory should be one GUI class that can be added to window like any other button or list or text. It should have addItem and couple of more functions and thats about it. If I make something like that usable, I'll post it.
pera
 
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia

Postby pera » Mon Jul 07, 2008 8:37 pm

This are my modifications to Window class in order to make it work in Irrlicht 1.4:

Code: Select all
#include "CGUISlotWindow.h"
#include "CGUIBringUpSlotWindowButton.h"
#include "CGUIIconSlot.h"

namespace irr
{
namespace gui
{


//! constructor
CGUISlotWindow::CGUISlotWindow(IrrlichtDevice* device, IGUIElement* parent, s32 id, core::rect<s32> rectangle)
: IGUIWindow(device->getGUIEnvironment(), parent, id, rectangle), Dragging(false), Device(device)
{
   #ifdef _DEBUG
   setDebugName("CGUISlotWindow");
   #endif

   IGUISkin* skin = 0;
   if (Environment)
      skin = Environment->getSkin();

   IGUISpriteBank* sprites = 0;
   video::SColor color(255,255,255,255);

   s32 buttonw = 15;
   if (skin)
   {
      buttonw = skin->getSize(EGDS_WINDOW_BUTTON_WIDTH);
      sprites = skin->getSpriteBank();
      color = skin->getColor(EGDC_WINDOW_SYMBOL);
   }
   s32 posx = RelativeRect.getWidth() - buttonw - 4;

   CloseButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
      L"", skin ? skin->getDefaultText(EGDT_WINDOW_CLOSE) : L"Close" );
   CloseButton->setSubElement(true);
   CloseButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   if (sprites)
   {
      CloseButton->setSpriteBank(sprites);
      CloseButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_CLOSE), color);
      CloseButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_CLOSE), color);
   }
   posx -= buttonw + 2;

   RestoreButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
      L"", skin ? skin->getDefaultText(EGDT_WINDOW_RESTORE) : L"Restore" );
   RestoreButton->setVisible(false);
   RestoreButton->setSubElement(true);
   RestoreButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   if (sprites)
   {
      RestoreButton->setSpriteBank(sprites);
      RestoreButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_RESTORE), color);
      RestoreButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_RESTORE), color);
   }
   posx -= buttonw + 2;

   MinButton = Environment->addButton(core::rect<s32>(posx, 3, posx + buttonw, 3 + buttonw), this, -1,
      L"", skin ? skin->getDefaultText(EGDT_WINDOW_MINIMIZE) : L"Minimize" );
   MinButton->setVisible(false);
   MinButton->setSubElement(true);
   MinButton->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_UPPERLEFT);
   if (sprites)
   {
      MinButton->setSpriteBank(sprites);
      MinButton->setSprite(EGBS_BUTTON_UP, skin->getIcon(EGDI_WINDOW_MINIMIZE), color);
      MinButton->setSprite(EGBS_BUTTON_DOWN, skin->getIcon(EGDI_WINDOW_MINIMIZE), color);
   }

   MinButton->grab();
   RestoreButton->grab();
   CloseButton->grab();
}



//! destructor
CGUISlotWindow::~CGUISlotWindow()
{
   if (MinButton)
      MinButton->drop();

   if (RestoreButton)
      RestoreButton->drop();

   if (CloseButton)
      CloseButton->drop();
}



//! called if an event happened.
bool CGUISlotWindow::OnEvent(const SEvent& event)
{
   switch(event.EventType)
   {
   case EET_GUI_EVENT:
      if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
      {
         Dragging = false;
      }
      else
      if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
      {
         if (event.GUIEvent.Caller == this && Parent)
         {
            Parent->bringToFront(this);
         }
      }
      else
      if (event.GUIEvent.EventType == EGET_BUTTON_CLICKED)
      {
         if (event.GUIEvent.Caller == CloseButton)
         {
            if (Parent)
            {
               // send close event to parent
               SEvent e;
               e.EventType = EET_GUI_EVENT;
               e.GUIEvent.Caller = this;
               e.GUIEvent.Element = 0;
               e.GUIEvent.EventType = EGET_ELEMENT_CLOSED;

               // if the event was not absorbed
               if (!Parent->OnEvent(e))
               {
                  remove();
               }
               return true;

            }
            else
            {
               remove();
               return true;
            }
         }
      }
      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;
         if (!Environment->hasFocus(this))
         {
            Environment->setFocus(this);
            if (Parent)
               Parent->bringToFront(this);
         }
         return true;
      case EMIE_LMOUSE_LEFT_UP:
         Dragging = false;
         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<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
            DragStart.X = event.MouseInput.X;
            DragStart.Y = event.MouseInput.Y;
            return true;
         }
         break;
      default:
         break;
      }
   default:
      break;
   }

   return IGUIElement::OnEvent(event);
}

//! Updates the absolute position.
void CGUISlotWindow::updateAbsolutePosition()
{
   IGUIElement::updateAbsolutePosition();
}



//! draws the element and its children
void CGUISlotWindow::draw()
{
   if (!IsVisible)
      return;

   IGUISkin* skin = Environment->getSkin();

   core::rect<s32> rect = AbsoluteRect;
   core::rect<s32> *cl = &AbsoluteClippingRect;

   // draw body fast
   rect = skin->draw3DWindowBackground(this, true, skin->getColor(EGDC_ACTIVE_BORDER),
      AbsoluteRect, &AbsoluteClippingRect);

   if (Text.size())
   {
      rect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X);
      rect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y);
      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, cl);
   }

   IGUIElement::draw();
}



//! Returns pointer to the close button
IGUIButton* CGUISlotWindow::getCloseButton() const
{
   return CloseButton;
}



//! Returns pointer to the minimize button
IGUIButton* CGUISlotWindow::getMinimizeButton() const
{
   return MinButton;
}



//! Returns pointer to the maximize button
IGUIButton* CGUISlotWindow::getMaximizeButton() const
{
   return RestoreButton;
}

//! adds a bring-up button
CGUIBringUpSlotWindowButton* CGUISlotWindow::createBringUpButton(core::rect<s32> rectangle, IGUIElement* parent,
                                                              s32 id, const wchar_t* text,
                                                              const wchar_t* tooltip)
{
    if(!parent)
        parent = Environment->getRootGUIElement();

    CGUIBringUpSlotWindowButton* button = new CGUIBringUpSlotWindowButton(Device, parent, id, rectangle, this);

    if(text)
        button->setText(text);

    if(tooltip)
        button->setToolTipText(tooltip);

    return button;
}

//! adds a slot array to the window
core::array<IGUIElement*> CGUISlotWindow::addSlotArray(core::rect<s32> slotRect, video::ITexture* texture,
                                                        IGUIElement* parent, s32 id ,
                                                        core::position2d<s32> relPos,
                                                        core::dimension2d<s32> arrayDim,
                                                        core::dimension2d<s32> spacing)
{
    if(!parent)
        parent = this;

    //create the array
    core::array<IGUIElement*> slotArray;
    for(s32 x = 0; x < arrayDim.Width; x++)
    {
        for(s32 y = 0; y < arrayDim.Height; y++)
        {
            CGUIIconSlot* slot = new CGUIIconSlot(Environment, parent, id, slotRect);
            slot->setImage(texture);
            slot->setRelativePosition(core::rect<s32>(relPos.X + x*(spacing.Width + slotRect.LowerRightCorner.X),
                                                      relPos.Y + y*(spacing.Height + slotRect.LowerRightCorner.Y),
                                                      slotRect.LowerRightCorner.X + (relPos.X + x*(spacing.Width + slotRect.LowerRightCorner.X)),
                                                      slotRect.LowerRightCorner.Y +(relPos.Y + y*(spacing.Height + slotRect.LowerRightCorner.Y))));
            slotArray.push_back(slot);
            slot->drop();
        }
    }

    return slotArray;
}

}//end namespace gui
}//end namespace irr




These are modifications to CIcon class:

Code: Select all

#include "CGUIIcon.h"
#include "CGUIIconSlot.h"

namespace irr
{
namespace gui
{

//! Constructor
CGUIIcon::CGUIIcon(gui::IGUIEnvironment* environment, gui::IGUIElement* parent, s32 id, core::rect<s32> rectangle)
    : IGUIElement(gui::EGUIET_ELEMENT , environment, parent, id, rectangle), Texture(0),
    Moveable(true), CanBeOutsideSlot(false), Slot(0), Dragging(false) {
   
      UsableSlots.clear();
   }

//! Destructor
CGUIIcon::~CGUIIcon()
{
    if(Texture)
        Texture->drop();
}


//! Sets an image which should be displayed as the icon
void CGUIIcon::setImage(video::ITexture *img)
{
    if(Texture)
        Texture->drop();

    Texture = img;

    if(Texture)
        Texture->grab();
}

//! draws the element and its children
void CGUIIcon::draw()
{
    if (!IsVisible)
        return;

    irr::video::IVideoDriver* driver = Environment->getVideoDriver();

    if (Texture)
    {
        driver->draw2DImage(Texture, AbsoluteRect.UpperLeftCorner,
            core::rect<s32>(core::position2d<s32>(0,0), Texture->getOriginalSize()));

        IGUIElement::draw();
    }
}

//! called if an event happened.
bool CGUIIcon::OnEvent(const SEvent& event)
{
   switch(event.EventType)
   {
   case EET_GUI_EVENT:
      if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST)
      {
         Dragging = false;
      }
      else
      if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUSED)
      {
         if (event.GUIEvent.Caller == this && Parent)
         {
            Parent->bringToFront(this);
         }
      }
      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 = Moveable;
         if (!Environment->hasFocus(this))
         {
            Environment->setFocus(this);
            if (Parent)
            {
               Parent->bringToFront(this);

                    //if the icon is in a slot (if the parent isn't the gui root element)
                    if(!(Parent == Environment->getRootGUIElement()))
                    {
                        //make the icon a child of the root element (removing it from the slot)
                        Environment->getRootGUIElement()->addChild(this);
                        //the current position
                        core::rect<s32> currPos = getAbsolutePosition();
                        //move the icon the the right position (ready for dragging)
                        move(core::position2d<s32>(event.MouseInput.X - (event.MouseInput.X-currPos.UpperLeftCorner.X),
                                                    event.MouseInput.Y - (event.MouseInput.Y-currPos.UpperLeftCorner.Y)));
                    }
            }
         }
         return true;
      case EMIE_LMOUSE_LEFT_UP:
         {
            Dragging = false;
            bool movedToSlot = false;
            //is the icon droped in a useable slot's rect
            u32 size = UsableSlots.size();
            IGUIElement *slot = 0;
            for(u32 i = 0; i < size; i++)
            {
               //get the slot
               slot = UsableSlots[i];

               if(slot)
               {
                  //get the slot rect
                  core::rect<s32> slotRect = slot->getAbsolutePosition();

                  //if the position the icon is dropped in, is inside the rect
                  if(slotRect.isPointInside(DragStart))
                  {
                     //move the icon to the slot
                     moveToSlot(slot);
                     movedToSlot = true;
                  }
               }
            }
            //if the icon is dropped outside a slot, and it's not supposed to
            if(!movedToSlot && !CanBeOutsideSlot)
            {
               if(Slot)
               {
                  //move it back to where it came from
                  moveToSlot(Slot);
               }
            }
         }
         return true;
      case EMIE_MOUSE_MOVED:
         if (Dragging)
         {
            move(core::position2d<s32>(event.MouseInput.X - DragStart.X, event.MouseInput.Y - DragStart.Y));
            DragStart.X = event.MouseInput.X;
            DragStart.Y = event.MouseInput.Y;
            return true;
         }
         break;
      default:
         break;
      }
   default:
      break;
   }

   return IGUIElement::OnEvent(event);

}//end function OnEvent

//! Sets whether the icon can be moved
void CGUIIcon::setMoveable(bool state)
{
    Moveable = state;
}

//! Sets whether the icon can be dropped outside a slot
void CGUIIcon::setCanBeOutsideSlot(bool state)
{
    CanBeOutsideSlot = state;
}

//! Adds a single slot to the usable slots
void CGUIIcon::addUsableSlot(IGUIElement* slot)
{
    UsableSlots.push_back(slot);
}

//! Adds the slots in the array to the usable slots
void CGUIIcon::addUsableSlotArray(const core::array<IGUIElement*>& slotArray)
{
    s32 arraySize = slotArray.size();
    for(s32 i = 0; i < arraySize; i++)
    {
        UsableSlots.push_back(slotArray[i]);
    }

}

//! Moves the icon to the passed slot
void CGUIIcon::moveToSlot(IGUIElement* slot)
{
    //check if the slot is usable
    bool usable = false;
    u32 size = UsableSlots.size();
    for(u32 i = 0; i < size; i++)
    {
        if(UsableSlots[i] == slot)
            usable = true;
    }

    //if the slot is not usable - make it usable
    if(!usable)
        UsableSlots.push_back(slot);

    //if the slot is in use (if the slot has a children)
    if(slot->getChildren().getSize())
    {
        /* get the icon from the slot. Gets the last child of the child list,
        asuming that this is the only child the slot has,
        and that this child is an CGUIIcon */
        CGUIIcon* icon = (CGUIIcon*)(*slot->getChildren().getLast());
        //move the icon to where the currently moving icon came from
        //if(Slot)
        //{
        //    icon->moveToSlot(Slot);
        //}
    }

    //add the currently moving icon to the slot
    slot->addChild(this);

    //save the slot
    Slot = slot;

    //set the relative position
    setRelativePosition(core::rect<s32>(core::position2d<s32>(0,0), Texture->getOriginalSize()));
}

//! Gets the slot the icon is in
IGUIElement* CGUIIcon::getSlot()
{
    return Slot;
}

}//end namespace gui
}//end namespace irr



And use addUsableSlotArray instead of setUsableSlotArray to avoid global variable error...
pera
 
Posts: 460
Joined: Wed May 14, 2008 1:05 pm
Location: Novi Sad, Serbia

Postby doqkhanh » Tue Jul 08, 2008 12:49 am

doqkhanh
 
Posts: 158
Joined: Sat Mar 01, 2008 3:14 am
Location: Tokyo, Japan

Postby full_newbie » Thu Jul 15, 2010 1:18 pm

Please help! I am getting errors:
Code: Select all
CGUISlotWindow.cpp:233: error: cannot allocate an object of type `irr::gui::CGUIBringUpSlotWindowButton'
CGUISlotWindow.cpp:233: error:   because the following virtual functions are abstract:
IGUIButton.h:128: error:  virtual void irr::gui::IGUIButton::setScaleImage(bool)
IGUIButton.h:131: error:  virtual bool irr::gui::IGUIButton::isScalingImage() const

What happens?
Sorry, my english is very bad. | I use minGW+CodeBlocks+Irrlicht 1.7.1(1.6,1.5)
full_newbie
 
Posts: 27
Joined: Mon Apr 05, 2010 7:33 am

Previous

Return to Code Snippets

Who is online

Users browsing this forum: No registered users and 0 guests