void LinkEvent::ReplaceLinkByLinkedEvents(gd::Project & project, EventsList & eventList, unsigned int indexOfTheEventInThisList) { //Finding what to link to. const EventsList * eventsToInclude = NULL; gd::ExternalEvents * linkedExternalEvents = NULL; if ( project.HasExternalEventsNamed(GetTarget()) ) { linkedExternalEvents = &project.GetExternalEvents(GetTarget()); eventsToInclude = &project.GetExternalEvents(GetTarget()).GetEvents(); } else if ( project.HasLayoutNamed(GetTarget()) ) eventsToInclude = &project.GetLayout(GetTarget()).GetEvents(); if ( eventsToInclude != NULL ) { unsigned int firstEvent = IncludeAllEvents() ? 0 : GetIncludeStart(); unsigned int lastEvent = IncludeAllEvents() ? eventsToInclude->size() - 1 : GetIncludeEnd(); //Check bounds if ( firstEvent >= eventsToInclude->size() ) { std::cout << "Unable to get events from a link ( Invalid start )" << std::endl; linkWasInvalid = true; return; } if ( lastEvent >= eventsToInclude->size() ) { std::cout << "Unable to get events from a link ( Invalid end )" << std::endl; linkWasInvalid = true; return; } if ( firstEvent > lastEvent ) { std::cout << "Unable to get events from a link ( End is before start )" << std::endl; linkWasInvalid = true; return; } //Insert an empty event to replace the link event ( we'll delete the link event at the end ) //( If we just erase the link event without adding a blank event to replace it, //the first event inserted by the link will not be preprocessed ( and it can be annoying if it require preprocessing, such as another link event ). ) gd::EmptyEvent emptyEvent; eventList.InsertEvent(emptyEvent, indexOfTheEventInThisList); eventList.InsertEvents(*eventsToInclude, firstEvent, lastEvent, indexOfTheEventInThisList+1); //Delete the link event ( which is now at the end of the list of events we've just inserted ) eventList.RemoveEvent(indexOfTheEventInThisList + 1 + static_cast<unsigned>(lastEvent-firstEvent)+1); } else { std::cout << "Unable to get events from a link." << std::endl; linkWasInvalid = true; //Delete the link event eventList.RemoveEvent(indexOfTheEventInThisList); return; } linkWasInvalid = false; }
gd::String EventsCodeGenerator::GenerateExternalEventsCompleteCode(gd::Project & project, gd::ExternalEvents & events, bool compilationForRuntime) { DependenciesAnalyzer analyzer(project, events); gd::String associatedSceneName = analyzer.ExternalEventsCanBeCompiledForAScene(); if ( associatedSceneName.empty() || !project.HasLayoutNamed(associatedSceneName) ) { std::cout << "ERROR: Cannot generate code for an external event: No unique associated scene." << std::endl; return ""; } gd::Layout & associatedScene = project.GetLayout(project.GetLayoutPosition(associatedSceneName)); gd::String output; //Prepare the global context ( Used to get needed header files ) gd::EventsCodeGenerationContext context; EventsCodeGenerator codeGenerator(project, associatedScene); codeGenerator.PreprocessEventList(events.GetEvents()); codeGenerator.SetGenerateCodeForRuntime(compilationForRuntime); //Generate whole events code gd::String wholeEventsCode = codeGenerator.GenerateEventsListCode(events.GetEvents(), context); //Generate default code around events: //Includes output += "#include <vector>\n#include <map>\n#include <string>\n#include <algorithm>\n#include <SFML/System/Clock.hpp>\n#include <SFML/System/Vector2.hpp>\n#include <SFML/Graphics/Color.hpp>\n#include \"GDCpp/RuntimeContext.h\"\n#include \"GDCpp/RuntimeObject.h\"\n"; for ( set<gd::String>::iterator include = codeGenerator.GetIncludeFiles().begin() ; include != codeGenerator.GetIncludeFiles().end(); ++include ) output += "#include \""+*include+"\"\n"; //Extra declarations needed by events for ( set<gd::String>::iterator declaration = codeGenerator.GetCustomGlobalDeclaration().begin() ; declaration != codeGenerator.GetCustomGlobalDeclaration().end(); ++declaration ) output += *declaration+"\n"; output += codeGenerator.GetCustomCodeOutsideMain()+ "\n" "void "+EventsCodeNameMangler::Get()->GetExternalEventsFunctionMangledName(events.GetName())+"(RuntimeContext * runtimeContext)\n" "{\n" +codeGenerator.GetCustomCodeInMain() +wholeEventsCode+ "return;\n" "}\n"; return output; }
void EventsChangesNotifier::GetScenesAndExternalEventsLinkedTo( const gd::EventsList& events, gd::Project& project, std::vector<gd::Layout*>& layouts, std::vector<gd::ExternalEvents*>& externalEvents) { for (std::size_t i = 0; i < events.size(); ++i) { try { const gd::LinkEvent& linkEvent = dynamic_cast<const gd::LinkEvent&>(events[i]); // We've got a link event, search now linked scene/external events if (project.HasExternalEventsNamed(linkEvent.GetTarget())) { gd::ExternalEvents& linkedExternalEvents = project.GetExternalEvents(linkEvent.GetTarget()); // Protect against circular references if (find(externalEvents.begin(), externalEvents.end(), &linkedExternalEvents) == externalEvents.end()) { externalEvents.push_back(&linkedExternalEvents); GetScenesAndExternalEventsLinkedTo(linkedExternalEvents.GetEvents(), project, layouts, externalEvents); } } else if (project.HasLayoutNamed(linkEvent.GetTarget())) { gd::Layout& linkedLayout = project.GetLayout(linkEvent.GetTarget()); // Protect against circular references if (find(layouts.begin(), layouts.end(), &linkedLayout) == layouts.end()) { layouts.push_back(&linkedLayout); GetScenesAndExternalEventsLinkedTo( linkedLayout.GetEvents(), project, layouts, externalEvents); } } } catch (...) { } if (events[i].CanHaveSubEvents()) GetScenesAndExternalEventsLinkedTo( events[i].GetSubEvents(), project, layouts, externalEvents); } }