Skip to content

Commit

Permalink
Add left click drag
Browse files Browse the repository at this point in the history
  • Loading branch information
asl97 committed Oct 27, 2017
1 parent 42c9131 commit 627aa44
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/client.cpp
Expand Up @@ -505,7 +505,7 @@ void Client::step(float dtime)
the local inventory (so the player notices the lag problem
and knows something is wrong).
*/
if(m_inventory_from_server)
if(m_inventory_from_server && !m_inhibit_inventory_revert)
{
float interval = 10.0;
float count_before = floor(m_inventory_from_server_age / interval);
Expand Down
2 changes: 2 additions & 0 deletions src/client.h
Expand Up @@ -432,6 +432,8 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
bool sendModChannelMessage(const std::string &channel, const std::string &message);
ModChannel *getModChannel(const std::string &channel);

bool m_inhibit_inventory_revert = false;

private:

// Virtual methods from con::PeerHandler
Expand Down
146 changes: 135 additions & 11 deletions src/guiFormSpecMenu.cpp
Expand Up @@ -3328,15 +3328,21 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
field while holding right mouse button
*/
if (event.EventType == EET_MOUSE_INPUT_EVENT &&
event.MouseInput.Event < 8 && // exclude DOUBLE_CLICK and TRIPLE_CLICK events
(event.MouseInput.Event != EMIE_MOUSE_MOVED ||
(event.MouseInput.Event == EMIE_MOUSE_MOVED &&
(event.MouseInput.isRightPressed() || event.MouseInput.isMiddlePressed()) &&
(event.MouseInput.isRightPressed()
|| event.MouseInput.isMiddlePressed()
|| event.MouseInput.isLeftPressed()) &&
getItemAtPos(m_pointer).i != getItemAtPos(m_old_pointer).i))) {

// Get selected item and hovered/clicked item (s)

m_old_tooltip_id = -1;
updateSelectedItem();
if (!m_left_dragging) {
updateSelectedItem();
}

ItemSpec s = getItemAtPos(m_pointer);

Inventory *inv_selected = NULL;
Expand Down Expand Up @@ -3446,6 +3452,10 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)

if (!event.MouseInput.Shift) {
// no shift: select item

// m_selected_item can be deleted by the black magic when it's empty
// As such we create our own copy of it for left drag handling
m_left_drag_item = new ItemSpec(s);
m_selected_amount = count;
m_selected_dragging = true;
m_auto_place = false;
Expand All @@ -3466,8 +3476,25 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
move_amount = 1;
else if (m_button == 2) // middle
move_amount = MYMIN(m_selected_amount, 10);
else // left
move_amount = m_selected_amount;
else { // left
ItemStack stack_to = list_s->getItem(s.i);
// TODO: support nonempty slot when dragging?
// Need a way to keep track of each slot amount
if (stack_to.empty() || identical) {
// m_selected_amount require to be modified for the leftover preview
// so we keep a copy of it for calculating the amount in each dragged to slot.
m_selected_amount_left_drag_copy = m_selected_amount;
InventoryList *list_from = inv_selected->getList(m_selected_item->listname);
m_left_drag_stack = list_from->getItem(m_selected_item->i);
m_left_dragging = true;
// m_selected_item can be deleted by the black magic when it's empty
// As such we point it to the starting drag slot which will not be empty
// and have the require item for drag leftover item preview
m_selected_item = new ItemSpec(s);
}
else
move_amount = m_selected_amount;
}

if (identical) {
if (move_amount >= m_selected_amount)
Expand Down Expand Up @@ -3506,30 +3533,73 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
}

m_selected_dragging = false;

// If the mouse was let go off once and we are in left drag mode
if (m_auto_place && m_left_dragging) {
int each = MYMIN(m_selected_amount_left_drag_copy/m_left_drag_to_stack.size(), m_left_drag_stack.getStackMax(m_client->idef()));

m_selected_amount = m_selected_amount_left_drag_copy;

for (std::set<ItemSpec*>::iterator it=m_left_drag_to_stack.begin(); it!=m_left_drag_to_stack.end(); ++it) {
ItemSpec *s = *it;

IMoveAction *a = new IMoveAction();
a->from_inv = m_left_drag_item->inventoryloc;
a->from_list = m_left_drag_item->listname;
a->from_i = m_left_drag_item->i;
a->to_inv = s->inventoryloc;
a->to_list = s->listname;
a->to_i = s->i;
a->count = each;
m_invmgr->inventoryAction(a);
m_selected_amount -= each;
}

ItemStack leftover_item_stack = m_left_drag_stack;
leftover_item_stack.count = m_selected_amount;

if (!leftover_item_stack.empty()) {
// If there are leftovers, restore it at the original slot
m_selected_item = m_left_drag_item;

Inventory *inv = m_invmgr->getInventory(m_selected_item->inventoryloc);
InventoryList *list = inv->getList(m_selected_item->listname);
list->changeItem(m_selected_item->i, leftover_item_stack);

m_selected_content_guess = ItemStack();
}

m_left_drag_to_stack.clear();
m_client->m_inhibit_inventory_revert = false;
m_left_dragging = false;
}

// Keep track of whether the mouse button be released
// One click is drag without dropping. Click + release
// + click changes to drop item when moved mode
if (m_selected_item)
m_auto_place = true;
} else if (updown == -1) {
// Mouse has been moved and rmb is down and mouse pointer just
// Mouse has been moved and a button is down and mouse pointer just
// entered a new inventory field (checked in the entry-if, this
// is the only action here that is generated by mouse movement)
if (m_selected_item != NULL && s.isValid()) {
// Move 1 item

// Ignore the left button since that is handle by the left dragging mode
if (m_selected_item != NULL && m_button != 0 && s.isValid()) {
if (m_auto_place) {
// Only move an item if the destination slot is empty
// or contains the same item type as what is going to be
// moved
assert(inv_selected && inv_s);
InventoryList *list_from = inv_selected->getList(m_selected_item->listname);
InventoryList *list_to = list_s;
assert(list_from && list_to);
ItemStack stack_from = list_from->getItem(m_selected_item->i);
ItemStack stack_to = list_to->getItem(s.i);
if (stack_to.empty() || stack_to.name == stack_from.name) {
if ((stack_to.empty() || stack_to.name == stack_from.name)) {
if (m_button == 2) // middle
move_amount = MYMIN(m_selected_amount, 10);
else // if (m_button == 1) right
else if (m_button == 1) // right
move_amount = 1;
}
}
Expand Down Expand Up @@ -3684,14 +3754,68 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
m_invmgr->inventoryAction(a);
}

// Left dragging mode handler
if (m_left_dragging) {

if (s.isValid()) {
ItemStack stack_to = list_s->getItem(s.i);

if (stack_to.empty() || identical) {

m_client->m_inhibit_inventory_revert = true;

m_selected_amount = m_selected_amount_left_drag_copy;
int each = MYMIN(m_selected_amount_left_drag_copy/(m_left_drag_to_stack.size()+1), m_left_drag_stack.getStackMax(m_client->idef()));

// Check there is enough item to split into the new slot
if (each > 0){
Inventory *inv_selected = m_invmgr->getInventory(m_left_drag_item->inventoryloc);
InventoryList *list_from = inv_selected->getList(m_left_drag_item->listname);
// Delete the selected item from the list
// It will get re-added if needed when the dragged list is replayed for the preview stuff
list_from->deleteItem(m_left_drag_item->i);
ItemSpec *i_s = new ItemSpec(s);
m_left_drag_to_stack.insert(i_s);

// Replay the dragged list, updating the slot amount
for (std::set<ItemSpec*>::iterator it=m_left_drag_to_stack.begin(); it!=m_left_drag_to_stack.end(); ++it) {
if (m_selected_amount - each >= 0){
ItemSpec *s = *it;
Inventory *inv_to = m_invmgr->getInventory(s->inventoryloc);
InventoryList *list_to = inv_to->getList(s->listname);
ItemStack stack_to = list_to->getItem(s->i);
// Reset the stack count for each slot
m_left_drag_stack.count = each;
// The slot are expected to be originally empty,
// So we just set it, there should be no leftover ether.
list_to->changeItem(s->i, m_left_drag_stack);
m_selected_amount -= each;

}
else
break;
}

// Place the leftover into our temporary m_selected_item which is used for leftover preview
Inventory *inv = m_invmgr->getInventory(m_selected_item->inventoryloc);
InventoryList *list = inv->getList(m_selected_item->listname);
ItemStack stack_from = list->getItem(m_selected_item->i);
stack_from.count += m_selected_amount;
list->changeItem(m_selected_item->i, stack_from);

}
}
}

}
// If m_selected_amount has been decreased to zero, deselect
if (m_selected_amount == 0) {
else if (m_selected_amount == 0) {
delete m_selected_item;
m_selected_item = NULL;
m_selected_amount = 0;
m_selected_dragging = false;
m_selected_content_guess = ItemStack();
}

m_old_pointer = m_pointer;
}
if (event.EventType == EET_GUI_EVENT) {
Expand Down
6 changes: 5 additions & 1 deletion src/guiFormSpecMenu.h
Expand Up @@ -21,7 +21,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,

#include <utility>
#include <stack>

#include "irrlichttypes_extrabloated.h"
#include "inventorymanager.h"
#include "modalMenu.h"
Expand Down Expand Up @@ -393,10 +392,15 @@ class GUIFormSpecMenu : public GUIModalMenu
std::vector<std::pair<FieldSpec, std::vector<std::string> > > m_dropdowns;

ItemSpec *m_selected_item = nullptr;
ItemSpec *m_left_drag_item = nullptr;
ItemStack m_left_drag_stack;
u32 m_selected_amount = 0;
bool m_selected_dragging = false;

int m_button = 0;
bool m_left_dragging = false;
u32 m_selected_amount_left_drag_copy;
std::set<ItemSpec*> m_left_drag_to_stack;

// WARNING: BLACK MAGIC
// Used to guess and keep up with some special things the server can do.
Expand Down

0 comments on commit 627aa44

Please sign in to comment.