Files
GDevelop/Core/GDCore/IDE/EventsEditorSelection.cpp
T
Florian Rival 8844642ae0 Updated copyrights.
Added doxygen files.
Cleaned some files.
2014-06-26 00:20:36 +02:00

367 lines
12 KiB
C++

/*
* Game Develop Core
* Copyright 2008-2014 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the GNU Lesser General Public License.
*/
#if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI)
#include "GDCore/IDE/EventsEditorSelection.h"
#include "GDCore/IDE/EventsEditorItemsAreas.h"
#include "GDCore/Events/Event.h"
#include "GDCore/Events/EventsList.h"
#include <iostream>
#include <map>
#include <list>
namespace gd {
void EventsEditorSelection::ClearSelection(bool refresh)
{
eventsSelected.clear();
instructionsSelected.clear();
if ( refresh ) eventsEditorCallback.Refresh();
}
void EventsEditorSelection::AddEvent(const gd::EventItem & eventSelection)
{
if ( eventSelection.event == boost::shared_ptr<gd::BaseEvent>() || eventSelection.eventsList == NULL )
{
std::cout << "WARNING, attempted to add a bad event to selection";
return;
}
if ( !EventSelected(eventSelection))
{
eventsSelected.insert(eventSelection);
eventsEditorCallback.Refresh();
}
}
/**
* True if an event is selected
*/
bool EventsEditorSelection::EventSelected(const gd::EventItem & event)
{
return eventsSelected.find(event) != eventsSelected.end();
}
void EventsEditorSelection::AddInstruction(const gd::InstructionItem & instr)
{
if ( instr.instruction == NULL || instr.instructionList == NULL )
{
std::cout << "WARNING, attempted to add a bad instruction to selection";
return;
}
if ( !InstructionSelected(instr))
{
instructionsSelected.insert(instr);
eventsEditorCallback.Refresh();
}
}
/**
* Return a vector with all selected events
*/
std::vector < EventItem > EventsEditorSelection::GetAllSelectedEvents()
{
std::vector < EventItem > results;
for (boost::unordered_set< EventItem >::iterator it = eventsSelected.begin();it!=eventsSelected.end();++it)
results.push_back(*it);
return results;
}
std::vector < EventItem > EventsEditorSelection::GetAllSelectedEventsWithoutSubEvents()
{
std::vector < EventItem > results;
for (boost::unordered_set< EventItem >::iterator it = eventsSelected.begin();it!=eventsSelected.end();++it)
{
bool isAlreadyIncludedAsSubEvent = false;
for (boost::unordered_set< EventItem >::iterator it2 = eventsSelected.begin();it2!=eventsSelected.end();++it2)
{
if ((*it).event != (*it2).event &&
(*it2).event != boost::shared_ptr<gd::BaseEvent>() &&
(*it2).event->CanHaveSubEvents() )
{
if ( (*it2).event->GetSubEvents().Contains(*(*it).event) )
isAlreadyIncludedAsSubEvent = true;
}
}
if (!isAlreadyIncludedAsSubEvent)
results.push_back(*it);
}
return results;
}
/**
* Return a vector with all selected instructions
*/
std::vector < gd::InstructionItem > EventsEditorSelection::GetAllSelectedInstructions()
{
std::vector < gd::InstructionItem > results;
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
results.push_back(*it);
return results;
}
bool EventsEditorSelection::HasSelectedActions()
{
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
if ( !it->isCondition ) return true;
return false;
}
bool EventsEditorSelection::HasSelectedConditions()
{
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
if ( it->isCondition ) return true;
return false;
}
bool EventsEditorSelection::InstructionSelected(const gd::InstructionItem & instr)
{
return instructionsSelected.find(instr) != instructionsSelected.end();
}
void EventsEditorSelection::SetHighlighted(const gd::EventItem & eventSelection)
{
eventHighlighted = eventSelection;
}
void EventsEditorSelection::SetHighlighted(const gd::InstructionItem & instructionSelection)
{
instructionHighlighted = instructionSelection;
}
void EventsEditorSelection::SetHighlighted(const InstructionListItem & item)
{
instructionListHighlighted = item;
}
void EventsEditorSelection::SetHighlighted(const ParameterItem & parameterItem)
{
parameterHighlighted = parameterItem;
}
void EventsEditorSelection::BeginDragEvent()
{
dragging = true;
}
bool EventsEditorSelection::IsDraggingEvent()
{
return dragging;
}
bool EventsEditorSelection::EndDragEvent(bool deleteDraggedEvent, bool dropAfterHighlightedElement)
{
if (!dragging) return false;
dragging = false;
if ( eventHighlighted.eventsList == NULL ) return false;
//Be sure we do not try to drag inside an event selected
for (boost::unordered_set< EventItem >::iterator it = eventsSelected.begin();it!=eventsSelected.end();++it)
{
if ( (*it).event == boost::shared_ptr<gd::BaseEvent>() )
{
std::cout << "WARNING: Bad event in selection";
continue;
}
if ( (*it).event == eventHighlighted.event || ((*it).event->CanHaveSubEvents() && (*it).event->GetSubEvents().Contains(*eventHighlighted.event)) )
{
return false;
}
}
//Insert copy of dragged events
size_t positionInList = !dropAfterHighlightedElement ? eventHighlighted.positionInList : eventHighlighted.positionInList+1;
for (boost::unordered_set< EventItem >::iterator it = eventsSelected.begin();it!=eventsSelected.end();++it)
{
if ( (*it).event != boost::shared_ptr<gd::BaseEvent>() )
eventHighlighted.eventsList->InsertEvent(*(*it).event, positionInList);
}
//Remove them from their initial position
if ( deleteDraggedEvent )
{
for (boost::unordered_set< EventItem >::iterator it = eventsSelected.begin();it!=eventsSelected.end();++it)
{
if ( (*it).event != boost::shared_ptr<gd::BaseEvent>() && (*it).eventsList != NULL)
(*it).eventsList->RemoveEvent(*(*it).event);
}
}
ClearSelection();
return true;
}
void EventsEditorSelection::BeginDragInstruction()
{
draggingInstruction = true;
}
bool EventsEditorSelection::IsDraggingInstruction()
{
return draggingInstruction;
}
std::vector<gd::Instruction> * EventsEditorSelection::EndDragInstruction(bool deleteDraggedInstruction, bool dropAfterHighlightedElement)
{
if (!draggingInstruction) return NULL;
draggingInstruction = false;
//Find where to drag
std::vector<gd::Instruction> * list = NULL;
size_t positionInList = std::string::npos;
if ( instructionHighlighted.instructionList != NULL )
{
list = instructionHighlighted.instructionList;
positionInList = instructionHighlighted.positionInList;
if ( instructionHighlighted.event != NULL ) instructionHighlighted.event->eventHeightNeedUpdate = true;
else std::cout << "WARNING : Instruction hightlighted event is not valid! " << std::endl;
if ( dropAfterHighlightedElement ) positionInList++;
}
else if ( instructionListHighlighted.instructionList != NULL )
{
list = instructionListHighlighted.instructionList;
if ( instructionListHighlighted.event != NULL ) instructionListHighlighted.event->eventHeightNeedUpdate = true;
else std::cout << "WARNING : Instruction list hightlighted event is not valid! " << std::endl;
}
else return NULL;
//Be sure we do not try to drag inside an instruction selected
if (instructionHighlighted.instruction != NULL)
{
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
{
if ( (*it).instruction == NULL )
{
std::cout << "WARNING: Bad instr in selection";
continue;
}
if ( (*it).instruction == instructionHighlighted.instruction || (FindInInstructionsAndSubInstructions((*it).instruction->GetSubInstructions(), instructionHighlighted.instruction)) )
{
return NULL;
}
if (FindInInstructionsAndSubInstructions(instructionHighlighted.instruction->GetSubInstructions(), (*it).instruction) )
{
return NULL;
}
}
}
//Copy dragged instructions
std::vector<gd::Instruction> draggedInstructions;
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
{
if ( (*it).instruction != NULL )
draggedInstructions.push_back(*(*it).instruction);
}
//Insert dragged instructions into their new list.
for (unsigned int i = 0;i<draggedInstructions.size();++i)
{
if ( positionInList < list->size() )
list->insert(list->begin()+positionInList, draggedInstructions[i]);
else
list->push_back(draggedInstructions[i]);
}
if ( deleteDraggedInstruction )
{
//Update selection as some selected instruction can have become invalid
boost::unordered_set< gd::InstructionItem > newInstructionsSelected;
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
{
if ((*it).instructionList == instructionHighlighted.instructionList && (*it).positionInList > instructionHighlighted.positionInList)
{
gd::InstructionItem newItem = (*it);
newItem.instruction = NULL;
newItem.positionInList += draggedInstructions.size();
newInstructionsSelected.insert(newItem);
}
else newInstructionsSelected.insert(*it);
}
instructionsSelected = newInstructionsSelected;
//Remove dragged instructions
DeleteAllInstructionSelected();
}
ClearSelection();
std::cout << "RETURNING THIS LIST" << std::endl;
for (std::vector<gd::Instruction>::iterator i = list->begin(); i != list->end(); ++i)
{
std::cout << i->GetType() << std::endl;
}
return list;
}
void EventsEditorSelection::InstructionHighlightedOnBottomPart(bool isOnbottomHandSide)
{
isOnbottomHandSideOfInstruction = isOnbottomHandSide;
}
void EventsEditorSelection::EventHighlightedOnBottomPart(bool isOnbottomHandSide)
{
isOnbottomHandSideOfEvent = isOnbottomHandSide;
}
void EventsEditorSelection::DeleteAllInstructionSelected()
{
//1) Construct a map with their list and their index in the list
std::map< std::vector<gd::Instruction>*, std::list<unsigned int> > mapOfDeletionsRequest;
for (boost::unordered_set< gd::InstructionItem >::iterator it = instructionsSelected.begin();it!=instructionsSelected.end();++it)
{
if ( (*it).event != NULL ) (*it).event->eventHeightNeedUpdate = true;
if ( (*it).instructionList != NULL)
mapOfDeletionsRequest[(*it).instructionList].push_back((*it).positionInList);
}
//2) For each list, erase each index
for (std::map<std::vector<gd::Instruction>*,std::list<unsigned int> >::iterator it = mapOfDeletionsRequest.begin();it!=mapOfDeletionsRequest.end();++it)
{
std::list<unsigned int> & listOfIndexesToDelete = it->second;
listOfIndexesToDelete.sort();
listOfIndexesToDelete.reverse(); //We have erase from end to start to prevent index changing
for (std::list<unsigned int>::iterator index = listOfIndexesToDelete.begin();index!=listOfIndexesToDelete.end();++index)
it->first->erase(it->first->begin()+*index);
}
}
EventsEditorSelection::EventsEditorSelection(gd::EventsEditorRefreshCallbacks & eventsEditorCallback_) :
dragging(false),
draggingInstruction(false),
eventsEditorCallback(eventsEditorCallback_)
{
}
bool EventsEditorSelection::FindInInstructionsAndSubInstructions(std::vector<gd::Instruction> & list, const gd::Instruction * instrToSearch)
{
for (unsigned int i = 0;i<list.size();++i)
{
if ( &list[i] == instrToSearch) return true;
if ( FindInInstructionsAndSubInstructions(list[i].GetSubInstructions(), instrToSearch) )
return true;
}
return false;
}
}
#endif