void FLiveEditorManager::RegisterEventListener( UObject *Target, FName EventName ) { if ( !Target ) return; UFunction *Function = Target->FindFunction( EventName ); if ( Function == NULL ) return; ULiveEditorBlueprint *Blueprint = Cast<ULiveEditorBlueprint>(Target); check( Blueprint != NULL ); FString BlueprintName = Blueprint->GetName(); int32 chopIndex = BlueprintName.Find( TEXT("_C"), ESearchCase::CaseSensitive, ESearchDir::FromEnd ); if ( chopIndex != INDEX_NONE ) { BlueprintName = BlueprintName.LeftChop( BlueprintName.Len() - chopIndex ); } const FLiveEditBinding* Binding = LiveEditorUserData->GetBinding( BlueprintName, EventName.ToString() ); if ( Binding != NULL ) { ILiveEditListener *Listener = new ILiveEditListener(EventName, *Binding, Target); int ID = LISTENER_ID(Listener->Binding.Channel,Listener->Binding.ControlID); //needs to remain int (instead of int32) since numbers are derived from TPL that uses int EventListeners.Add(ID,Listener); } else { FString Message = FString::Printf( TEXT("A LiveEditor Event (%s) is not bound and will not work. Please Re-bind this LiveEditorBlueprint in the LiveEditor Control Panel"), *EventName.ToString() ); FPlatformMisc::MessageBoxExt( EAppMsgType::Ok, *Message, *NSLOCTEXT("MessageDialog", "DefaultDebugMessageTitle", "ShowDebugMessagef").ToString() ); } }
class ULiveEditorBlueprint *FLiveEditorManager::FindActiveBlueprint( const FString &Name ) { FString CheckName = Name.Left( Name.Find( TEXT("."), ESearchCase::IgnoreCase, ESearchDir::FromEnd ) ); for ( TArray< FActiveBlueprintRecord >::TIterator It(ActiveBlueprints); It; It++ ) { ULiveEditorBlueprint *BP = (*It).Blueprint.Get(); if ( !BP ) continue; FString CheckPathName = BP->GetArchetype()->GetPathName(); CheckPathName = CheckPathName.Left( CheckPathName.Find( TEXT("."), ESearchCase::IgnoreCase, ESearchDir::FromEnd ) ); UE_LOG( LiveEditorManagerLog, Log, TEXT("%s | %s"), *CheckPathName, *CheckName ); if ( CheckPathName == CheckName ) return BP; } return NULL; }
FString GetSafeBlueprintName( const ULiveEditorBlueprint &Instance ) { FString BlueprintName = Instance.GetName(); int32 chopIndex = BlueprintName.Find( TEXT("_C"), ESearchCase::CaseSensitive, ESearchDir::FromEnd ); if ( chopIndex != INDEX_NONE ) { BlueprintName = BlueprintName.LeftChop( BlueprintName.Len() - chopIndex ); } return BlueprintName; }
bool FLiveEditorManager::DeActivate( const FString &Name ) { RealWorld = GWorld; check( LiveEditorWorld != NULL ); GWorld = LiveEditorWorld; bool bSuccess = false; ULiveEditorBlueprint *BP = FindActiveBlueprint(Name); if ( BP != NULL ) { UnregisterAllListeners(BP); BP->OnShutdown(); //BP->MarkPendingKill(); TODO how do we delete this without crashing? int32 i = 0; while( i < ActiveBlueprints.Num() ) { if ( ActiveBlueprints[i].Blueprint.Get() == BP ) { ActiveBlueprints.RemoveAtSwap(i); continue; } else { ++i; } } bSuccess = true; } GWorld = RealWorld; RealWorld = NULL; return bSuccess; }
void FLiveEditorManager::Tick(float DeltaTime) { //avoid multiple tick DOOM ( FTickableGameObject's get ticked once per UWorld that is active and Ticking ) float CurTime = GWorld->GetRealTimeSeconds(); if ( LastUpdateTime == CurTime ) { return; } LastUpdateTime = CurTime; if ( LiveEditorWorld == NULL ) { CreateLiveEditorWorld(); } RealWorld = GWorld; check( LiveEditorWorld != NULL ); GWorld = LiveEditorWorld; if ( ActiveBlueprints.Num() > 0 ) LiveEditorWorld->Tick( ELevelTick::LEVELTICK_All, DeltaTime ); // //update our ActiveBlueprints // int32 i = 0; while ( i < ActiveBlueprints.Num() ) { FActiveBlueprintRecord record = ActiveBlueprints[i]; ULiveEditorBlueprint *Instance = record.Blueprint.Get(); if ( Instance == NULL ) { ActiveBlueprints.RemoveAtSwap(i); //clean out the dead entry Activate( record.Name ); //try to ressurect the Blueprint (user has likely just recompiled it) continue; } Instance->Tick( DeltaTime ); ++i; } // // handle the actual MIDI messages // for( TMap< PmDeviceID, FLiveEditorDeviceInstance >::TIterator It(InputConnections); It; ++It ) { PmDeviceID DeviceID = (*It).Key; FLiveEditorDeviceInstance &DeviceInstance = (*It).Value; int NumRead = Pm_Read( DeviceInstance.Connection.MIDIStream, MIDIBuffer, DEFAULT_BUFFER_SIZE ); //needs to remain int (instead of int32) since numbers are derived from TPL that uses int if ( NumRead < 0 ) { continue; //error occurred, portmidi should handle this silently behind the scenes } else if ( NumRead > 0 ) { DeviceInstance.Data.LastInputTime = GWorld->GetTimeSeconds(); } //dispatch for ( int32 BufferIndex = 0; BufferIndex < NumRead; BufferIndex++ ) { PmMessage Msg = MIDIBuffer[BufferIndex].message; int Status = Pm_MessageStatus(Msg); //needs to remain int (instead of int32) since numbers are derived from TPL that uses int int Data1 = Pm_MessageData1(Msg); //needs to remain int (instead of int32) since numbers are derived from TPL that uses int int Data2 = Pm_MessageData2(Msg); //needs to remain int (instead of int32) since numbers are derived from TPL that uses int if ( ActiveWizard != NULL ) { ActiveWizard->ProcessMIDI( Status, Data1, Data2, DeviceID, DeviceInstance.Data ); } else { switch ( DeviceInstance.Data.ConfigState ) { case FLiveEditorDeviceData::UNCONFIGURED: break; case FLiveEditorDeviceData::CONFIGURED: Dispatch( Status, Data1, Data2, DeviceInstance.Data ); break; default: break; } } } } PieObjectCache.EvaluatePendingCreations(); GWorld = RealWorld; RealWorld = NULL; }