Manually starting dragging on a DragContainer

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Manually starting dragging on a DragContainer

Postby BigG » Wed Oct 14, 2009 16:33

Hey,

I'm writing an inventory system currently where I have the following problem:

Two inventory slots A and B containing two items (drag container containing a staticImage) 1 and 2

A contains 1
B contains 2

now I'm picking 1 and dragging it to B, which already contains 2. Now I'm dropping 1 into B.
What I want to achieve now is that 1 "replaces" 2, so that B contains 1 and 2 is being dragged automatically now.

I could think off two ways for that:
1) manually firing the dragStart on 2 by some nasty hacks in CEGUI
2) exchanging the icons contained by 1's and 2's DragContainers and somehow dismissing the Dropped event (which would require CEGUI hacks too and even more tricky code on my side)

both of them require some hacky modifications in CEGUI I guess, so I'd be really happy about any advice on this one :)

Greetings,
-BigG

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Thu Oct 15, 2009 09:14

Hi,

I'm guessing this is with the 'sticky' mode enabled, since it makes no sense otherwise?

It's something I'd not considered actually, but I think it's a useful feature to provide. Due to the internal states that needs to be adjusted to affect such a switch, I think a new function for this purpose can be added (there's no real way of doing it currently without some kind of hack, none of which are really ideal). With the new function in place, I think I would still leave it up to the user code to detect the 'drop' and subsequently call the as yet unnamed function on any existing DragContainer to pick it up (it's more flexible when left to the user to call the function, and saves us from having a thousand 'modes' for all the various options!).

I can try and get this function in for 0.7.1, since it's just a single function to add.

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Thu Oct 15, 2009 13:40

Thanks for your reply CE!
Yea, having such a function would be really cool :) I had an idea about it, how about if the CEGUI::Window::EventDragDropItemDropped event would have a specialised CEGUI::DragDropEventArgs argument that contains an additional CEGUI::DragContainer pointer to be set by the event handler, which, if set to 0, does nothing, otherwise starts a new drag event with the pointed drag container? This would require only a little amount of work and not even an additional function or anything :)

about your question whether sticky mode is enabled... well it's a tricky one. To actually drag&drop 1 to slot B, it doesn't matter whether it is enabled/being used or not. But as soon as the exchanging takes place, it has to be enabled in any case, as the user is no longer pressing any mouse button yet you need to have the container sticked to the cursor. This is because 1 has now replaced 2 in slot B (the item itself, not only the GUI part of it), so 2 is kind of 'slotless' now and MUST be put into another slot.

-BigG

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Fri Oct 16, 2009 12:07

Thanks for the suggestions and such. The issue with the event args suggestion is (of course?) that the args struct is const, so you can't set the field from a normally subscribed handler ;)

I think the function is the way we'll go, and basically it will be able to be called at any time - if the container is non-sticky, nothing will happen, otherwise the item will immediately show as attached to the mouse. I'll get this added tomorrow most likely.

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Fri Oct 16, 2009 13:10

CrazyEddie wrote:Thanks for the suggestions and such. The issue with the event args suggestion is (of course?) that the args struct is const, so you can't set the field from a normally subscribed handler ;)

duh, totally forgot about that xD well yea, I guess a function to manually start drag&drop would be the best way to go then. Thanks for helping me out on this and in advance for the patches :D

-BigG

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Sat Oct 17, 2009 10:32

This has been added in the stable v0-7 branch as of rev 2321.

There is a new CEGUI::DragContainer::pickUp function (which takes an optional boolean argument that specifies whether to automatically switch the DragContainer to sticky mode, default is false).

I've tested it for a bit in a hacked around version of our Drag&Drop demo and it all works pretty well. With regard to the sticky mode change, in my test I had it off to start with, used the force option on the new function to force it on, then manually reset it again upon the drop notification.

Exactly how you'll use the function will depend on what you're doing currently, but I think you should be able to fathom it out fairly easily ;)

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Sat Oct 17, 2009 12:37

Thanks again for your support, CE :)
Checking out the branch right now; I will post back after trying around with the new function :D

-BigG


//Edit:
OK, played around with the new function and I got to say that it works as I wanted it :D
Yet I have another question/request xD the DragContainer is always kept in a static offset to the cursor when the cursor moves. This offset is set when the dragging starts, calculated from the current DragContainer position and the current Mouse position (I think). Would it be possible to add a function like CEGUI::DragContainer::setMouseCursorOffset taking a CEGUI::UVector2 as parameter where you can specify that offset overwriting the dynamic calculation if set.The current DragContainer position would the be calculated as CursorPosition + MouseCursorOffset. That would make it possible to, for example, keep the item icon aligned to the cursor's head in my case :) Should not be a big change either :D

Thanks again
- BigG

//Edit2:
I found a small visual bug:
When calling pickUp(), the DragContainer itself stays where it is until you move the mouse, then it all works fine and it is dynamically aligned (as described above) to the mouse. But until then, it stays at its origin position, and then jumps to the cursor as soon as you move the mouse. I don't know if this is a problem in the rendering itself or in the positioning, I'll investigate on that.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Sat Oct 17, 2009 19:24

Yeah, I saw that issue too (and chose to ignore it :lol:). Should be a simple fix.

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Sat Oct 17, 2009 21:03

Hey,

Still couldn't figure out the reason for that bug but I modified the DragContainer class a bit to realise my request about having the DragContainer sticked to the mouse at a fixed offset instead of taking the offset it has when dragging starts. As I do not know how to submit the changes to you, I'll try to do so in this post :D. Feel free to do whatever you want to do with this code :)

CEGUIDragContainer.h
In data, add two protected members:

Code: Select all

      //! true to always position at a fixed offset to the mouse cursor instead of taking the offset
      //  from when dragging started
      bool d_hasFixedMouseOffset;
      //! the fixed mouse offset
      UVector2 d_fixedMouseOffset;


and get/set functions for these:

Code: Select all

      /*!
      \brief
         Set the fixed mouse offset moving mode data
      \param has_offset
         - true to use a fixed offset, false to dynamically calculate it when dragging starts

      \param fixed_offset
         - UVector2 containing the fixed offset relative to the cursor's position
      */
      void setFixedMouseOffset(const bool has_offset, const UVector2& fixed_offset);

      /*!
      \brief
         Retrieve the fixed mouse offset moving mode data
      \param has_offset
         see setFixedMouseOffset
      \param fixed_offset
         see setFixedMouseOffset
      */
      void getFixedMouseOffset(bool& has_offset,UVector2& fixed_offset);


CEGUIDragContainer.cpp
code of the get/set functions:

Code: Select all

void DragContainer::setFixedMouseOffset(const bool has_offset, const UVector2& fixed_offset)
{
   d_hasFixedMouseOffset = has_offset;
   d_fixedMouseOffset = fixed_offset;
}

//----------------------------------------------------------------------------//
void DragContainer::getFixedMouseOffset(bool& has_offset, UVector2& fixed_offset)
{
   has_offset = d_hasFixedMouseOffset;
   fixed_offset = d_fixedMouseOffset;
}


and a small change in void DragContainer::doDragging(const Point& local_mouse) - replace

Code: Select all

offset -= d_dragPoint;

with

Code: Select all

offset -= (d_hasFixedMouseOffset) ? d_fixedMouseOffset : d_dragPoint;


and that's it :D usage is like:

Code: Select all

this->m_IconDragContainer->setFixedMouseOffset(true,CEGUI::UVector2(cegui_absdim(0),cegui_absdim(0)));

which will, for example, position the DragContainer always at the cursor's head :)

Maybe it's worth adding this configuration as property settable in the .layout files too (can DragContainers even be created in .layout files? :shock:)

I must say, I'm still being impressed by the flexibility of this engine :D

Greetings,
-BigG

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Sun Oct 18, 2009 06:54

I missed the first edit yesterday, which is why I did not respond to it :roll:

It turns out the minor glitch is due to not re/setting the drag point when manually picking up the item. While it's possible to set that in the pickUP function ot the cursor offset used elsewhere, this could lead to issues if, for example, some user code decides to 'pick up' an item when the mouse is nowhere near the item being picked up (the item would then be floating in mid-air far from the mouse cursor). So my solution to this part of the issue will be to instead set the drag point to the centre of the DargContainer.

Following on from the above, your suggestion is then even more valuable since it allows the user to effectively customise the above positioning. I may implemented it as two functions or one function with just the offset, firstly because it makes property processing easier and secondly for consistency reasons with the rest of the API (largely the public getters all return the got value as opposed to setting output variables, so while your code as presented is perfectly reasonable, where possible (and I know we fail at times!) it's preferred to keep a consistent approach).

As you may infer from the above mention of properties, yes it's possible to have a DargContainer in a layout, indeed we take this approach in the drag and drop demo layout ;)

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Sun Oct 18, 2009 10:24

Wow, didn't think about that cause for the bug :D well, about the way to implement the get/set functions, I came across one problem when only having one get/set function for only the offset: there is no way to determine whether the user actually _wants_ the fixed offset on or off. So you'd either need two functions like DragContainer::setFixedCursorOffset and DragContainer::setNoFixedCursorOffset or, similar my approach, two get/set pairs for both variables.

Anyway, I'm happy to see my work helps to improve CEGUI :)

-BigG

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Sun Oct 18, 2009 12:57

You are of course correct - although I would have spotted this deliberate mistake before implementing it (honest! ;)). I'll attempt to finish this up later this afternoon.

CE.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Manually starting dragging on a DragContainer

Postby CrazyEddie » Sun Oct 18, 2009 16:56

I have added:

functions:
void DragContainer::setFixedDragOffset(const UVector2& offset);
const UVector2& DragContainer::getFixedDragOffset() const;

void DragContainer::setUsingFixedDragOffset(bool enable);
bool DragContainer::isUsingFixedDragOffset() const;

Properties:
FixedDragOffset
UsingFixedDragOffset

I also fixed that issue with the initial position glitch, and also a small bug (not checking whether dragging is even enabled).

CE.

BigG
Not too shy to talk
Not too shy to talk
Posts: 22
Joined: Tue Oct 13, 2009 14:25

Re: Manually starting dragging on a DragContainer

Postby BigG » Mon Oct 19, 2009 12:39

Thumbs up, CE :)
Checking out newest revision now and if I find anything, I'll post back^^

-BigG

//Edit:
It's all working flawlessly as far as I tested it :D thanks again for your help, CE!


Return to “Help”

Who is online

Users browsing this forum: No registered users and 20 guests