/** GDevelop - Timed Event Extension Copyright (c) 2011-2016 Florian Rival (Florian.Rival@gmail.com) This project is released under the MIT License. */ #include "GDCpp/Extensions/ExtensionBase.h" #include "TimedEvent.h" #include "TimedEventsManager.h" #include "GDCpp/Runtime/CommonTools.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerator.h" #include "GDCore/Events/CodeGeneration/ExpressionsCodeGeneration.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h" #include "GDCore/Events/Tools/EventsCodeNameMangler.h" #include "GDCpp/Runtime/RuntimeScene.h" #include "GDCore/Events/CodeGeneration/EventsCodeGenerationContext.h" /** * \brief This class declares information about the extension. */ class Extension : public ExtensionBase { public: /** * Constructor of an extension declares everything the extension contains: objects, actions, conditions and expressions. */ Extension() { SetExtensionInformation("TimedEvent", _("Timed events"), _("These events can launch their conditions and actions only after an amount of time passes."), "Florian Rival", "Open source (MIT License)"); #if defined(GD_IDE_ONLY) AddEvent("TimedEvent", _("Timed event"), _("This event launches its conditions and actions only after an amount of time passes."), "", "CppPlatform/Extensions/timedevent16.png", std::make_shared()) .SetCodeGenerator([](gd::BaseEvent & event_, gd::EventsCodeGenerator & codeGenerator, gd::EventsCodeGenerationContext & context) { TimedEvent & event = dynamic_cast(event_); codeGenerator.AddIncludeFile("TimedEvent/TimedEventTools.h"); //Notify parent timed event that they have a child for (std::size_t i = 0;icodeGenerationChildren.push_back(&event); //And register this event as potential parent TimedEvent::codeGenerationCurrentParents.push_back(&event); event.codeGenerationChildren.clear(); //Prepare code for computing timeout gd::String timeOutCode; gd::CallbacksForGeneratingExpressionCode callbacks(timeOutCode, codeGenerator, context); gd::ExpressionParser parser(event.GetTimeoutExpression()); if (!parser.ParseMathExpression(codeGenerator.GetPlatform(), codeGenerator.GetProject(), codeGenerator.GetLayout(), callbacks) || timeOutCode.empty()) timeOutCode = "0"; //Prepare name gd::String codeName = !event.GetName().empty() ? "GDNamedTimedEvent_"+codeGenerator.ConvertToString(event.GetName()) : "GDTimedEvent_"+gd::String::From(&event); gd::String outputCode; outputCode += "if ( static_cast(GDpriv::TimedEvents::UpdateAndGetTimeOf(*runtimeContext->scene, \""+codeName+"\"))/1000000.0 > "+timeOutCode+")"; outputCode += "{"; outputCode += codeGenerator.GenerateConditionsListCode(event.GetConditions(), context); gd::String ifPredicat; for (std::size_t i = 0;iscene, \""+codeName+"\");\n"; return gd::String(""); }); AddAction("ResetTimedEventAndSubs", _("Reset a timed event and sub events"), _("Reset a timed event, as well as all of its sub events."), _("Reset the timed event called _PARAM1_, as well as all of its sub events"), _("Timed events"), "CppPlatform/Extensions/timedevent24.png", "CppPlatform/Extensions/timedevent16.png") .AddParameter("", _("Name")) .codeExtraInformation.SetCustomCodeGenerator([](gd::Instruction & instruction, gd::EventsCodeGenerator & codeGenerator, gd::EventsCodeGenerationContext & context) { codeGenerator.AddIncludeFile("TimedEvent/TimedEventTools.h"); for (std::size_t i = 0;iGetName() == instruction.GetParameter(0).GetPlainString()) { TimedEvent & timedEvent = *TimedEvent::codeGenerationCurrentParents[i]; gd::String code; { gd::String codeName = !timedEvent.GetName().empty() ? "GDNamedTimedEvent_"+codeGenerator.ConvertToString(timedEvent.GetName()) : "GDTimedEvent_"+gd::String::From(&timedEvent); code += "GDpriv::TimedEvents::Reset(*runtimeContext->scene, \""+codeName+"\");\n"; } for (std::size_t j = 0;jGetName().empty() ? "GDNamedTimedEvent_"+codeGenerator.ConvertToString(timedEvent.codeGenerationChildren[j]->GetName()) : "GDTimedEvent_"+gd::String::From(timedEvent.codeGenerationChildren[j]); code += "GDpriv::TimedEvents::Reset(*runtimeContext->scene, \""+codeName+"\");\n"; } return code; } } return gd::String(""); }) .SetIncludeFile("TimedEvent/TimedEventTools.h"); #endif GD_COMPLETE_EXTENSION_COMPILATION_INFORMATION(); }; #if defined(GD_IDE_ONLY) bool HasDebuggingProperties() const { return true; }; void GetPropertyForDebugger(RuntimeScene & scene, std::size_t propertyNb, gd::String & name, gd::String & value) const { std::size_t i = 0; std::map < gd::String, ManualTimer >::const_iterator end = TimedEventsManager::managers[&scene].timedEvents.end(); for (std::map < gd::String, ManualTimer >::iterator iter = TimedEventsManager::managers[&scene].timedEvents.begin();iter != end;++iter) { if ( propertyNb == i ) { name = iter->first; //Unmangle name if ( name.find("GDNamedTimedEvent_") == 0 && name.length() > 18 ) name = name.substr(18, name.length()); else name = _("No name"); value = gd::String::From(static_cast(iter->second.GetTime())/1000000.0)+"s"; return; } ++i; } } bool ChangeProperty(RuntimeScene & scene, std::size_t propertyNb, gd::String newValue) { std::size_t i = 0; std::map < gd::String, ManualTimer >::const_iterator end = TimedEventsManager::managers[&scene].timedEvents.end(); for (std::map < gd::String, ManualTimer >::iterator iter = TimedEventsManager::managers[&scene].timedEvents.begin();iter != end;++iter) { if ( propertyNb == i ) { iter->second.SetTime(newValue.To()*1000000.0); return true; } ++i; } return false; } std::size_t GetNumberOfProperties(RuntimeScene & scene) const { return TimedEventsManager::managers[&scene].timedEvents.size(); } #endif void SceneLoaded(RuntimeScene & scene) { TimedEventsManager::managers[&scene].timedEvents.clear(); } }; /** * Used by GDevelop to create the extension class * -- Do not need to be modified. -- */ extern "C" ExtensionBase * GD_EXTENSION_API CreateGDExtension() { return new Extension; }