void SPropertyEditorAsset::Construct( const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor ) { PropertyEditor = InPropertyEditor; PropertyHandle = InArgs._PropertyHandle; OnSetObject = InArgs._OnSetObject; OnShouldFilterAsset = InArgs._OnShouldFilterAsset; UProperty* Property = nullptr; if(PropertyEditor.IsValid()) { Property = PropertyEditor->GetPropertyNode()->GetProperty(); bAllowClear = !(Property->PropertyFlags & CPF_NoClear); ObjectClass = GetObjectPropertyClass(Property); bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); } else { bAllowClear = InArgs._AllowClear; ObjectPath = InArgs._ObjectPath; ObjectClass = InArgs._Class; bIsActor = ObjectClass->IsChildOf( AActor::StaticClass() ); if (PropertyHandle.IsValid() && PropertyHandle->IsValidHandle()) { Property = PropertyHandle->GetProperty(); } else { CustomClassFilters.Add(ObjectClass); } } // Account for the allowed classes specified in the property metadata if (Property) { FString ClassFilterString; if (UArrayProperty* ArrayParent = Cast<UArrayProperty>(Property->GetOuter())) { ClassFilterString = ArrayParent->GetMetaData("AllowedClasses"); } else { ClassFilterString = Property->GetMetaData("AllowedClasses"); } if (ClassFilterString.IsEmpty()) { CustomClassFilters.Add(ObjectClass); } else { TArray<FString> CustomClassFilterNames; ClassFilterString.ParseIntoArray(CustomClassFilterNames, TEXT(","), true); for (auto It = CustomClassFilterNames.CreateIterator(); It; ++It) { FString& ClassName = *It; // User can potentially list class names with leading or trailing whitespace ClassName.Trim(); ClassName.TrimTrailing(); UClass* Class = FindObject<UClass>(ANY_PACKAGE, *ClassName); if (!Class) { Class = LoadObject<UClass>(nullptr, *ClassName); } if (Class) { // If the class is an interface, expand it to be all classes in memory that implement the class. if (Class->HasAnyClassFlags(CLASS_Interface)) { for (TObjectIterator<UClass> ClassIt; ClassIt; ++ClassIt) { UClass* const ClassWithInterface = (*ClassIt); if (ClassWithInterface->ImplementsInterface(Class)) { CustomClassFilters.Add(ClassWithInterface); } } } else { CustomClassFilters.Add(Class); } } } } } if (InArgs._NewAssetFactories.IsSet()) { NewAssetFactories = InArgs._NewAssetFactories.GetValue(); } else if (CustomClassFilters.Num() > 1 || !CustomClassFilters.Contains(UObject::StaticClass())) { NewAssetFactories = PropertyCustomizationHelpers::GetNewAssetFactoriesForClasses(CustomClassFilters); } TSharedPtr<SHorizontalBox> ValueContentBox = NULL; ChildSlot [ SNew( SAssetDropTarget ) .OnIsAssetAcceptableForDrop( this, &SPropertyEditorAsset::OnAssetDraggedOver ) .OnAssetDropped( this, &SPropertyEditorAsset::OnAssetDropped ) [ SAssignNew( ValueContentBox, SHorizontalBox ) ] ]; TAttribute<bool> IsEnabledAttribute(this, &SPropertyEditorAsset::CanEdit); TAttribute<FText> TooltipAttribute(this, &SPropertyEditorAsset::OnGetToolTip); if (Property && Property->HasAllPropertyFlags(CPF_DisableEditOnTemplate)) { // There are some cases where editing an Actor Property is not allowed, such as when it is contained within a struct or a CDO TArray<UObject*> ObjectList; PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList); // If there is no objects, that means we must have a struct asset managing this property if (ObjectList.Num() == 0) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplate", "Editing this value in structure's defaults is not allowed")); } else { // Go through all the found objects and see if any are a CDO, we can't set an actor in a CDO default. for (UObject* Obj : ObjectList) { if (Obj->HasAllFlags(RF_ClassDefaultObject)) { IsEnabledAttribute.Set(false); TooltipAttribute.Set(LOCTEXT("VariableHasDisableEditOnTemplateTooltip", "Editing this value in a Class Default Object is not allowed")); break; } } } } bool bOldEnableAttribute = IsEnabledAttribute.Get(); if (bOldEnableAttribute && !InArgs._EnableContentPicker) { IsEnabledAttribute.Set(false); } AssetComboButton = SNew(SComboButton) .ToolTipText(TooltipAttribute) .ButtonStyle( FEditorStyle::Get(), "PropertyEditor.AssetComboStyle" ) .ForegroundColor(FEditorStyle::GetColor("PropertyEditor.AssetName.ColorAndOpacity")) .OnGetMenuContent( this, &SPropertyEditorAsset::OnGetMenuContent ) .OnMenuOpenChanged( this, &SPropertyEditorAsset::OnMenuOpenChanged ) .IsEnabled( IsEnabledAttribute ) .ContentPadding(2.0f) .ButtonContent() [ // Show the name of the asset or actor SNew(STextBlock) .TextStyle( FEditorStyle::Get(), "PropertyEditor.AssetClass" ) .Font( FEditorStyle::GetFontStyle( PropertyEditorConstants::PropertyFontStyle ) ) .Text(this,&SPropertyEditorAsset::OnGetAssetName) ]; if (bOldEnableAttribute && !InArgs._EnableContentPicker) { IsEnabledAttribute.Set(true); } TSharedRef<SHorizontalBox> ButtonBox = SNew( SHorizontalBox ); TSharedPtr<SVerticalBox> CustomContentBox; if( ShouldDisplayThumbnail(InArgs) ) { FObjectOrAssetData Value; GetValue( Value ); AssetThumbnail = MakeShareable( new FAssetThumbnail( Value.AssetData, InArgs._ThumbnailSize.X, InArgs._ThumbnailSize.Y, InArgs._ThumbnailPool ) ); ValueContentBox->AddSlot() .Padding( 0.0f, 0.0f, 2.0f, 0.0f ) .AutoWidth() [ SAssignNew( ThumbnailBorder, SBorder ) .Padding( 5.0f ) .BorderImage( this, &SPropertyEditorAsset::GetThumbnailBorder ) .OnMouseDoubleClick( this, &SPropertyEditorAsset::OnAssetThumbnailDoubleClick ) [ SNew( SBox ) .ToolTipText(TooltipAttribute) .WidthOverride( InArgs._ThumbnailSize.X ) .HeightOverride( InArgs._ThumbnailSize.Y ) [ AssetThumbnail->MakeThumbnailWidget() ] ] ]; ValueContentBox->AddSlot() [ SNew( SBox ) .VAlign( VAlign_Center ) [ SAssignNew( CustomContentBox, SVerticalBox ) + SVerticalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SVerticalBox::Slot() .AutoHeight() .Padding( 0.0f, 2.0f, 4.0f, 2.0f ) [ ButtonBox ] ] ]; } else { ValueContentBox->AddSlot() [ SAssignNew( CustomContentBox, SVerticalBox ) +SVerticalBox::Slot() .VAlign( VAlign_Center ) [ SNew( SHorizontalBox ) + SHorizontalBox::Slot() [ AssetComboButton.ToSharedRef() ] + SHorizontalBox::Slot() .AutoWidth() .Padding( 4.f, 0.f ) [ ButtonBox ] ] ]; } if( InArgs._CustomContentSlot.Widget != SNullWidget::NullWidget ) { CustomContentBox->AddSlot() .VAlign( VAlign_Center ) .Padding( FMargin( 0.0f, 2.0f ) ) [ InArgs._CustomContentSlot.Widget ]; } if( !bIsActor && InArgs._DisplayUseSelected ) { ButtonBox->AddSlot() .VAlign(VAlign_Center) .AutoWidth() .Padding( 2.0f, 0.0f ) [ PropertyCustomizationHelpers::MakeUseSelectedButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnUse ), FText(), IsEnabledAttribute ) ]; } if( InArgs._DisplayBrowse ) { ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ PropertyCustomizationHelpers::MakeBrowseButton( FSimpleDelegate::CreateSP( this, &SPropertyEditorAsset::OnBrowse ), TAttribute<FText>( this, &SPropertyEditorAsset::GetOnBrowseToolTip ) ) ]; } if( bIsActor ) { TSharedRef<SWidget> ActorPicker = PropertyCustomizationHelpers::MakeInteractiveActorPicker( FOnGetAllowedClasses::CreateSP(this, &SPropertyEditorAsset::OnGetAllowedClasses), FOnShouldFilterActor(), FOnActorSelected::CreateSP( this, &SPropertyEditorAsset::OnActorSelected ) ); ActorPicker->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 2.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ActorPicker ]; } if(InArgs._ResetToDefaultSlot.Widget != SNullWidget::NullWidget ) { TSharedRef<SWidget> ResetToDefaultWidget = InArgs._ResetToDefaultSlot.Widget; ResetToDefaultWidget->SetEnabled( IsEnabledAttribute ); ButtonBox->AddSlot() .Padding( 4.0f, 0.0f ) .AutoWidth() .VAlign(VAlign_Center) [ ResetToDefaultWidget ]; } }
void FPropertyTable::PasteTextAtCell( const FString& Text, const TSharedRef< IPropertyTableCell >& Cell ) { if ( !SelectedCells.Contains( Cell ) ) { return; } int32 CurrentRowIdx = 0; int32 CurrentColumnIdx = 0; TSharedPtr< IPropertyTableCell > FirstCellInRow = Cell; TSharedPtr< IPropertyTableCell > TargetCell = Cell; // Parse into row strings TArray<FString> RowStrings; Text.ParseIntoArray(RowStrings, TEXT("\n"), true); // Parse row strings into individual cell strings TArray<FString> CellStrings; RowStrings[CurrentRowIdx++].ParseIntoArray(CellStrings, TEXT("\t"), false); // Get the maximum paste operations before displaying the slow task int32 NumPasteOperationsBeforeWarning = GetDefault<UEditorPerProjectUserSettings>()->PropertyMatrix_NumberOfPasteOperationsBeforeWarning; const bool bShowCancelButton = false; const bool bShowProgressDialog = SelectedCells.Num() > NumPasteOperationsBeforeWarning; GWarn->BeginSlowTask(LOCTEXT("UpdatingPropertiesSlowTaskLabel", "Updating properties..."), bShowProgressDialog, bShowCancelButton); if ( RowStrings.Num() == 1 && CellStrings.Num() == 1 ) { int32 CurrentCellIndex = 0; for( auto CellIter = SelectedCells.CreateIterator(); CellIter; ++CellIter ) { SetCellValue( *CellIter, CellStrings[0] ); if ( bShowProgressDialog ) { GWarn->UpdateProgress(CurrentCellIndex, SelectedCells.Num()); CurrentCellIndex++; } } } else if ( StartingCellSelectionRange.IsValid() && EndingCellSelectionRange.IsValid() ) { // Paste values into cells while ( TargetCell.IsValid() && SelectedCells.Contains( TargetCell.ToSharedRef() ) && CurrentColumnIdx < CellStrings.Num() ) { SetCellValue( TargetCell.ToSharedRef(), CellStrings[CurrentColumnIdx++] ); // Move to next column TargetCell = GetNextCellInRow(TargetCell.ToSharedRef()); if ( ( !TargetCell.IsValid() || !SelectedCells.Contains( TargetCell.ToSharedRef() ) || CurrentColumnIdx == CellStrings.Num() ) && CurrentRowIdx < RowStrings.Num() ) { // Move to next row TargetCell = GetNextCellInColumn(FirstCellInRow.ToSharedRef()); if ( TargetCell.IsValid() && SelectedCells.Contains( TargetCell.ToSharedRef() ) ) { // Prepare data to operate on next row CurrentColumnIdx = 0; FirstCellInRow = TargetCell; RowStrings[CurrentRowIdx++].ParseIntoArray(CellStrings, TEXT("\t"), false); if ( bShowProgressDialog ) { GWarn->UpdateProgress(CurrentRowIdx, RowStrings.Num()); } } } } } GWarn->EndSlowTask(); }
bool UGatherTextFromSourceCommandlet::FMacroDescriptor::ParseArgsFromMacro(const FString& Text, TArray<FString>& Args, FSourceFileParseContext& Context) const { // Attempt to parse something of the format // NAME(param0, param1, param2, etc) bool Success = false; FString RemainingText = Text.RightChop(GetToken().Len()).Trim(); int32 OpenBracketIdx = RemainingText.Find(TEXT("(")); if (0 > OpenBracketIdx) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Missing bracket '(' in %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); //Dont assume this is an error. It's more likely trying to parse something it shouldn't be. return false; } else { Args.Empty(); bool bInDblQuotes = false; bool bInSglQuotes = false; int32 BracketStack = 1; bool bEscapeNextChar = false; const TCHAR* ArgStart = *RemainingText + OpenBracketIdx + 1; const TCHAR* Cursor = ArgStart; for (; 0 < BracketStack && '\0' != *Cursor; ++Cursor) { if (bEscapeNextChar) { bEscapeNextChar = false; } else if ((bInDblQuotes || bInSglQuotes) && !bEscapeNextChar && '\\' == *Cursor) { bEscapeNextChar = true; } else if (bInDblQuotes) { if ('\"' == *Cursor) { bInDblQuotes = false; } } else if (bInSglQuotes) { if ('\'' == *Cursor) { bInSglQuotes = false; } } else if ('\"' == *Cursor) { bInDblQuotes = true; } else if ('\'' == *Cursor) { bInSglQuotes = true; } else if ('(' == *Cursor) { ++BracketStack; } else if (')' == *Cursor) { --BracketStack; if (0 > BracketStack) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Unexpected bracket ')' in %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); return false; } } else if (1 == BracketStack && ',' == *Cursor) { // create argument from ArgStart to Cursor and set Start next char Args.Add(FString(Cursor - ArgStart, ArgStart)); ArgStart = Cursor + 1; } } if (0 == BracketStack) { Args.Add(FString(Cursor - ArgStart - 1, ArgStart)); } else { Args.Add(FString(ArgStart)); } Success = 0 < Args.Num() ? true : false; } return Success; }
bool FXmlFile::LoadFile(const FString& InFile, EConstructMethod::Type ConstructMethod) { // Remove any file stuff if it already exists Clear(); // So far no error (Early so it can be overwritten below by errors) ErrorMessage = NSLOCTEXT("XmlParser", "LoadSuccess", "XmlFile was loaded successfully").ToString(); TArray<FString> Input; if(ConstructMethod == EConstructMethod::ConstructFromFile) { // Create file reader TUniquePtr<FArchive> FileReader(IFileManager::Get().CreateFileReader(*InFile)); if(!FileReader) { ErrorMessage = NSLOCTEXT("XmlParser", "FileLoadFail", "Failed to load the file").ToString(); ErrorMessage += TEXT("\""); ErrorMessage += InFile; ErrorMessage += TEXT("\""); return false; } // Create buffer for file input uint32 BufferSize = FileReader->TotalSize(); void* Buffer = FMemory::Malloc(BufferSize); FileReader->Serialize(Buffer, BufferSize); // Parse file buffer into an array of lines if (!FindCharSizeAndSplitLines(Input, Buffer, BufferSize)) { ErrorMessage = NSLOCTEXT("XmlParser", "InvalidFormatFail", "Failed to parse the file (Unsupported character encoding)").ToString(); ErrorMessage += TEXT("\""); ErrorMessage += InFile; ErrorMessage += TEXT("\""); return false; } // Release resources FMemory::Free(Buffer); } else { // Parse input buffer into an array of lines SplitLines(Input, *InFile, *InFile + InFile.Len()); } // Pre-process the input PreProcessInput(Input); // Tokenize the input TArray<FString> Tokens = Tokenize(Input); // Parse the input & create the nodes CreateNodes(Tokens); // All done with creation, set up necessary information if(bFileLoaded == true) { if(ConstructMethod == EConstructMethod::ConstructFromFile) { LoadedFile = InFile; } } else { LoadedFile = TEXT(""); RootNode = nullptr; } // Now check the status flag of the creation. It may have actually failed, but given us a // partially created representation if(bCreationFailed) { Clear(); } return bFileLoaded; }
/** * A utility function to help separate a package name and asset name out * from a full asset object path. * * @param AssetObjPathIn The asset object path you want split. * @param PackagePathOut The first half of the in string (the package portion). * @param AssetNameOut The second half of the in string (the asset name portion). */ static void SplitPackagePathAndAssetName(FString const& AssetObjPathIn, FString& PackagePathOut, FString& AssetNameOut) { AssetObjPathIn.Split(TEXT("."), &PackagePathOut, &AssetNameOut); }
DWORD CDirEnumerator::GetNextFile(NFind::CFileInfo &fi, bool &filled, FString &resPath) { filled = false; resPath.Empty(); for (;;) { if (Enumerators.IsEmpty()) { if (Index >= FilePaths.Size()) return S_OK; const FString &path = FilePaths[Index++]; int pos = path.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos >= 0) resPath.SetFrom(path, pos + 1); #ifdef _WIN32 if (BasePrefix.IsEmpty() && path.Len() == 2 && path[1] == ':') { // we use "c:" item as directory item fi.Clear(); fi.Name = path; fi.SetAsDir(); fi.Size = 0; } else #endif if (!fi.Find(BasePrefix + path)) { DWORD error = GetNormalizedError(); resPath = path; return error; } break; } bool found; if (Enumerators.Back().Next(fi, found)) { if (found) { resPath = Prefixes.Back(); break; } } else { DWORD error = GetNormalizedError(); resPath = Prefixes.Back(); Enumerators.DeleteBack(); Prefixes.DeleteBack(); return error; } Enumerators.DeleteBack(); Prefixes.DeleteBack(); } resPath += fi.Name; if (EnterToDirs && fi.IsDir()) { FString s = resPath; s += FCHAR_PATH_SEPARATOR; Prefixes.Add(s); s += FCHAR_ANY_MASK; Enumerators.Add(NFind::CEnumerator(BasePrefix + s)); } filled = true; return S_OK; }
bool FDesktopPlatformBase::EnumerateProjectsKnownByEngine(const FString &Identifier, bool bIncludeNativeProjects, TArray<FString> &OutProjectFileNames) { // Get the engine root directory FString RootDir; if (!GetEngineRootDirFromIdentifier(Identifier, RootDir)) { return false; } FString GameAgnosticConfigDir = GetEngineSavedConfigDirectory(Identifier); if (GameAgnosticConfigDir.Len() == 0) { return false; } // Find all the created project directories. Start with the default project creation path. TArray<FString> SearchDirectories; SearchDirectories.AddUnique(GetDefaultProjectCreationPath()); // Load the config file FConfigFile GameAgnosticConfig; FConfigCacheIni::LoadExternalIniFile(GameAgnosticConfig, TEXT("EditorSettings"), NULL, *GameAgnosticConfigDir, false); // Find the editor game-agnostic settings FConfigSection* Section = GameAgnosticConfig.Find(TEXT("/Script/UnrealEd.EditorSettings")); if (Section == NULL) { FConfigCacheIni::LoadExternalIniFile(GameAgnosticConfig, TEXT("EditorGameAgnostic"), NULL, *GameAgnosticConfigDir, false); Section = GameAgnosticConfig.Find(TEXT("/Script/UnrealEd.EditorGameAgnosticSettings")); } if(Section != NULL) { // Add in every path that the user has ever created a project file. This is to catch new projects showing up in the user's project folders TArray<FString> AdditionalDirectories; Section->MultiFind(TEXT("CreatedProjectPaths"), AdditionalDirectories); for(int Idx = 0; Idx < AdditionalDirectories.Num(); Idx++) { FPaths::NormalizeDirectoryName(AdditionalDirectories[Idx]); SearchDirectories.AddUnique(AdditionalDirectories[Idx]); } // Also add in all the recently opened projects TArray<FString> RecentlyOpenedFiles; Section->MultiFind(TEXT("RecentlyOpenedProjectFiles"), RecentlyOpenedFiles); for(int Idx = 0; Idx < RecentlyOpenedFiles.Num(); Idx++) { FPaths::NormalizeFilename(RecentlyOpenedFiles[Idx]); OutProjectFileNames.AddUnique(RecentlyOpenedFiles[Idx]); } } // Find all the other projects that are in the search directories for(int Idx = 0; Idx < SearchDirectories.Num(); Idx++) { TArray<FString> ProjectFolders; IFileManager::Get().FindFiles(ProjectFolders, *(SearchDirectories[Idx] / TEXT("*")), false, true); for(int32 FolderIdx = 0; FolderIdx < ProjectFolders.Num(); FolderIdx++) { TArray<FString> ProjectFiles; IFileManager::Get().FindFiles(ProjectFiles, *(SearchDirectories[Idx] / ProjectFolders[FolderIdx] / TEXT("*.uproject")), true, false); for(int32 FileIdx = 0; FileIdx < ProjectFiles.Num(); FileIdx++) { OutProjectFileNames.AddUnique(SearchDirectories[Idx] / ProjectFolders[FolderIdx] / ProjectFiles[FileIdx]); } } } // Find all the native projects, and either add or remove them from the list depending on whether we want native projects const FUProjectDictionary &Dictionary = GetCachedProjectDictionary(RootDir); if(bIncludeNativeProjects) { TArray<FString> NativeProjectPaths = Dictionary.GetProjectPaths(); for(int Idx = 0; Idx < NativeProjectPaths.Num(); Idx++) { if(!NativeProjectPaths[Idx].Contains(TEXT("/Templates/"))) { OutProjectFileNames.AddUnique(NativeProjectPaths[Idx]); } } } else { TArray<FString> NativeProjectPaths = Dictionary.GetProjectPaths(); for(int Idx = 0; Idx < NativeProjectPaths.Num(); Idx++) { OutProjectFileNames.Remove(NativeProjectPaths[Idx]); } } return true; }
int IntFromString(const FString& InStr) { return std::atoi(InStr.c_str()); }
bool FAssetEditorManager::OpenEditorForAsset(UObject* Asset, const EToolkitMode::Type ToolkitMode, TSharedPtr< IToolkitHost > OpenedFromLevelEditor ) { check(Asset); // @todo toolkit minor: When "Edit Here" happens in a different level editor from the one that an asset is already // being edited within, we should decide whether to disallow "Edit Here" in that case, or to close the old asset // editor and summon it in the new level editor, or to just foreground the old level editor (current behavior) const bool bBringToFrontIfOpen = true; // Don't open asset editors for cooked packages if (UPackage* Package = Asset->GetOutermost()) { if (Package->bIsCookedForEditor) { return false; } } AssetEditorRequestOpenEvent.Broadcast(Asset); if( FindEditorForAsset(Asset, bBringToFrontIfOpen) != nullptr ) { // This asset is already open in an editor! (the call to FindEditorForAsset above will bring it to the front) return true; } else { GWarn->BeginSlowTask( LOCTEXT("OpenEditor", "Opening Editor..."), true); } FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>(TEXT("AssetTools")); TWeakPtr<IAssetTypeActions> AssetTypeActions = AssetToolsModule.Get().GetAssetTypeActionsForClass( Asset->GetClass() ); auto ActualToolkitMode = ToolkitMode; if( AssetTypeActions.IsValid() ) { if( AssetTypeActions.Pin()->ShouldForceWorldCentric() ) { // This asset type prefers a specific toolkit mode ActualToolkitMode = EToolkitMode::WorldCentric; if( !OpenedFromLevelEditor.IsValid() ) { // We don't have a level editor to spawn in world-centric mode, so we'll find one now // @todo sequencer: We should eventually eliminate this code (incl include dependencies) or change it to not make assumptions about a single level editor OpenedFromLevelEditor = FModuleManager::LoadModuleChecked< FLevelEditorModule >( "LevelEditor" ).GetFirstLevelEditor(); } } } if( ActualToolkitMode != EToolkitMode::WorldCentric && OpenedFromLevelEditor.IsValid() ) { // @todo toolkit minor: Kind of lame use of a static variable here to prime the new asset editor. This was done to avoid refactoring a few dozen files for a very minor change. FAssetEditorToolkit::SetPreviousWorldCentricToolkitHostForNewAssetEditor( OpenedFromLevelEditor.ToSharedRef() ); } // Disallow opening an asset editor for classes bool bCanSummonSimpleAssetEditor = !Asset->IsA<UClass>(); if( AssetTypeActions.IsValid() ) { TArray<UObject*> AssetsToEdit; AssetsToEdit.Add(Asset); // Some assets (like UWorlds) may be destroyed and recreated as part of opening. To protect against this, keep the path to the asset and try to re-find it if it disappeared. TWeakObjectPtr<UObject> WeakAsset = Asset; const FString AssetPath = Asset->GetPathName(); AssetTypeActions.Pin()->OpenAssetEditor(AssetsToEdit, ActualToolkitMode == EToolkitMode::WorldCentric ? OpenedFromLevelEditor : TSharedPtr<IToolkitHost>()); // If the Asset was destroyed, attempt to find it if it was recreated if ( !WeakAsset.IsValid() && !AssetPath.IsEmpty() ) { Asset = FindObject<UObject>(nullptr, *AssetPath); } AssetEditorOpenedEvent.Broadcast(Asset); } else if( bCanSummonSimpleAssetEditor ) { // No asset type actions for this asset. Just use a properties editor. FSimpleAssetEditor::CreateEditor(ActualToolkitMode, ActualToolkitMode == EToolkitMode::WorldCentric ? OpenedFromLevelEditor : TSharedPtr<IToolkitHost>(), Asset); } GWarn->EndSlowTask(); return true; }
bool RemoveUniformBuffersFromSource(FString& SourceCode) { static const FString StaticStructToken(TEXT("static const struct")); int32 StaticStructTokenPos = SourceCode.Find(StaticStructToken, ESearchCase::CaseSensitive, ESearchDir::FromStart); while (StaticStructTokenPos != INDEX_NONE) { static const FString CloseBraceSpaceToken(TEXT("} ")); int32 CloseBraceSpaceTokenPos = SourceCode.Find(CloseBraceSpaceToken, ESearchCase::CaseSensitive, ESearchDir::FromStart, StaticStructTokenPos + StaticStructToken.Len()); if (CloseBraceSpaceTokenPos == INDEX_NONE) { check(0); //@todo-rco: ERROR return false; } int32 NamePos = CloseBraceSpaceTokenPos + CloseBraceSpaceToken.Len(); static const FString SpaceEqualsToken(TEXT(" =")); int32 SpaceEqualsTokenPos = SourceCode.Find(SpaceEqualsToken, ESearchCase::CaseSensitive, ESearchDir::FromStart, NamePos); if (SpaceEqualsTokenPos == INDEX_NONE) { check(0); //@todo-rco: ERROR return false; } FString UniformBufferName = SourceCode.Mid(NamePos, SpaceEqualsTokenPos - NamePos); check(UniformBufferName.Len() > 0); static const FString CloseBraceSemicolorToken(TEXT("};")); int32 CloseBraceSemicolonTokenPos = SourceCode.Find(CloseBraceSemicolorToken, ESearchCase::CaseSensitive, ESearchDir::FromStart, SpaceEqualsTokenPos + SpaceEqualsToken.Len()); if (CloseBraceSemicolonTokenPos == INDEX_NONE) { check(0); //@todo-rco: ERROR return false; } // Comment out this UB auto& SourceCharArray = SourceCode.GetCharArray(); SourceCharArray[StaticStructTokenPos] = TCHAR('/'); SourceCharArray[StaticStructTokenPos + 1] = TCHAR('*'); SourceCharArray[CloseBraceSemicolonTokenPos] = TCHAR('*'); SourceCharArray[CloseBraceSemicolonTokenPos + 1] = TCHAR('/'); // Find & Replace this UB FString UBSource = UniformBufferName + FString(TEXT(".")); FString UBDest = UniformBufferName + FString(TEXT("_")); SourceCode.ReplaceInline(*UBSource, *UBDest, ESearchCase::CaseSensitive); // Find next UB StaticStructTokenPos = SourceCode.Find(StaticStructToken, ESearchCase::CaseSensitive, ESearchDir::FromStart, CloseBraceSemicolonTokenPos + 2); } return true; }
void FMapInfoParser::ParseDoomEdNums() { TMap<int, bool> defined; int error = 0; MapinfoEdMapItem editem; editem.filename = sc.ScriptName; ParseOpenBrace(); while (true) { if (sc.CheckString("}")) return; else if (sc.CheckNumber()) { int ednum = sc.Number; sc.MustGetStringName("="); sc.MustGetString(); bool *def = defined.CheckKey(ednum); if (def != NULL) { sc.ScriptMessage("Editor Number %d defined more than once", ednum); error++; } defined[ednum] = true; if (sc.String[0] == '$') { // todo: add special stuff like playerstarts and sound sequence overrides here, too. editem.classname = NAME_None; editem.special = sc.MustMatchString(SpecialMapthingNames) + 1; // todo: assign proper constants } else { editem.classname = sc.String; editem.special = -1; } memset(editem.args, 0, sizeof(editem.args)); editem.argsdefined = 0; int minargs = 0; int maxargs = 5; FString specialname; if (sc.CheckString(",")) { editem.argsdefined = 5; // mark args as used - if this is done we need to prevent assignment of map args in P_SpawnMapThing. if (editem.special < 0) editem.special = 0; if (!sc.CheckNumber()) { sc.MustGetString(); specialname = sc.String; // save for later error reporting. editem.special = P_FindLineSpecial(sc.String, &minargs, &maxargs); if (editem.special == 0 || minargs == -1) { sc.ScriptMessage("Invalid special %s for Editor Number %d", sc.String, ednum); error++; minargs = 0; maxargs = 5; } if (!sc.CheckString(",")) { // special case: Special without arguments if (minargs != 0) { sc.ScriptMessage("Incorrect number of args for special %s, min = %d, max = %d, found = 0", specialname.GetChars(), minargs, maxargs); error++; } DoomEdFromMapinfo.Insert(ednum, editem); continue; } sc.MustGetNumber(); } int i = 0; while (i < 5) { editem.args[i] = sc.Number; i++; if (!sc.CheckString(",")) break; // special check for the ambient sounds which combine the arg being set here with the ones on the mapthing. if (sc.CheckString("+")) { editem.argsdefined = i; break; } sc.MustGetNumber(); } if (specialname.IsNotEmpty() && (i < minargs || i > maxargs)) { sc.ScriptMessage("Incorrect number of args for special %s, min = %d, max = %d, found = %d", specialname.GetChars(), minargs, maxargs, i); error++; } } DoomEdFromMapinfo.Insert(ednum, editem); } else { sc.ScriptError("Number expected"); } } if (error > 0) { sc.ScriptError("%d errors encountered in DoomEdNum definition", error); } }
MapData *P_OpenMapData(const char * mapname, bool justcheck) { MapData * map = new MapData; FileReader * wadReader = nullptr; bool externalfile = !strnicmp(mapname, "file:", 5); if (externalfile) { mapname += 5; if (!FileExists(mapname)) { delete map; return NULL; } map->resource = FResourceFile::OpenResourceFile(mapname, true); wadReader = map->resource->GetReader(); } else { FString fmt; int lump_wad; int lump_map; int lump_name = -1; // Check for both *.wad and *.map in order to load Build maps // as well. The higher one will take precedence. // Names with more than 8 characters will only be checked as .wad and .map. if (strlen(mapname) <= 8) lump_name = Wads.CheckNumForName(mapname); fmt.Format("maps/%s.wad", mapname); lump_wad = Wads.CheckNumForFullName(fmt); fmt.Format("maps/%s.map", mapname); lump_map = Wads.CheckNumForFullName(fmt); if (lump_name > lump_wad && lump_name > lump_map && lump_name != -1) { int lumpfile = Wads.GetLumpFile(lump_name); int nextfile = Wads.GetLumpFile(lump_name+1); map->lumpnum = lump_name; if (lumpfile != nextfile) { // The following lump is from a different file so whatever this is, // it is not a multi-lump Doom level so let's assume it is a Build map. map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); if (!P_IsBuildMap(map)) { delete map; return NULL; } return map; } // This case can only happen if the lump is inside a real WAD file. // As such any special handling for other types of lumps is skipped. map->MapLumps[0].Reader = Wads.ReopenLumpReader(lump_name); strncpy(map->MapLumps[0].Name, Wads.GetLumpFullName(lump_name), 8); map->Encrypted = Wads.IsEncryptedFile(lump_name); map->InWad = true; if (map->Encrypted) { // If it's encrypted, then it's a Blood file, presumably a map. if (!P_IsBuildMap(map)) { delete map; return NULL; } return map; } int index = 0; if (stricmp(Wads.GetLumpFullName(lump_name + 1), "TEXTMAP") != 0) { for(int i = 1;; i++) { // Since levels must be stored in WADs they can't really have full // names and for any valid level lump this always returns the short name. const char * lumpname = Wads.GetLumpFullName(lump_name + i); try { index = GetMapIndex(mapname, index, lumpname, !justcheck); } catch(...) { delete map; throw; } if (index == -2) { delete map; return NULL; } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore if (index < 0) break; map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } else { map->isText = true; map->MapLumps[1].Reader = Wads.ReopenLumpReader(lump_name + 1); for(int i = 2;; i++) { const char * lumpname = Wads.GetLumpFullName(lump_name + i); if (lumpname == NULL) { I_Error("Invalid map definition for %s", mapname); } else if (!stricmp(lumpname, "ZNODES")) { index = ML_GLZNODES; } else if (!stricmp(lumpname, "BLOCKMAP")) { // there is no real point in creating a blockmap but let's use it anyway index = ML_BLOCKMAP; } else if (!stricmp(lumpname, "REJECT")) { index = ML_REJECT; } else if (!stricmp(lumpname, "DIALOGUE")) { index = ML_CONVERSATION; } else if (!stricmp(lumpname, "BEHAVIOR")) { index = ML_BEHAVIOR; map->HasBehavior = true; } else if (!stricmp(lumpname, "ENDMAP")) { break; } else continue; map->MapLumps[index].Reader = Wads.ReopenLumpReader(lump_name + i); strncpy(map->MapLumps[index].Name, lumpname, 8); } } return map; } else { if (lump_map > lump_wad) { lump_wad = lump_map; } if (lump_wad == -1) { delete map; return NULL; } map->lumpnum = lump_wad; auto reader = Wads.ReopenLumpReader(lump_wad); map->resource = FResourceFile::OpenResourceFile(Wads.GetLumpFullName(lump_wad), reader, true); wadReader = map->resource->GetReader(); } } uint32_t id; // Although we're using the resource system, we still want to be sure we're // reading from a wad file. wadReader->Seek(0, FileReader::SeekSet); wadReader->Read(&id, sizeof(id)); if (id == IWAD_ID || id == PWAD_ID) { char maplabel[9]=""; int index=0; map->MapLumps[0].Reader = map->resource->GetLump(0)->NewReader(); strncpy(map->MapLumps[0].Name, map->resource->GetLump(0)->Name, 8); for(uint32_t i = 1; i < map->resource->LumpCount(); i++) { const char* lumpname = map->resource->GetLump(i)->Name; if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8)) { map->isText = true; map->MapLumps[ML_TEXTMAP].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[ML_TEXTMAP].Name, lumpname, 8); for(int i = 2;; i++) { lumpname = map->resource->GetLump(i)->Name; if (!strnicmp(lumpname, "ZNODES",8)) { index = ML_GLZNODES; } else if (!strnicmp(lumpname, "BLOCKMAP",8)) { // there is no real point in creating a blockmap but let's use it anyway index = ML_BLOCKMAP; } else if (!strnicmp(lumpname, "REJECT",8)) { index = ML_REJECT; } else if (!strnicmp(lumpname, "DIALOGUE",8)) { index = ML_CONVERSATION; } else if (!strnicmp(lumpname, "BEHAVIOR",8)) { index = ML_BEHAVIOR; map->HasBehavior = true; } else if (!strnicmp(lumpname, "ENDMAP",8)) { return map; } else continue; map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } if (i>0) { try { index = GetMapIndex(maplabel, index, lumpname, !justcheck); } catch(...) { delete map; throw; } if (index == -2) { delete map; return NULL; } if (index == ML_BEHAVIOR) map->HasBehavior = true; // The next lump is not part of this map anymore if (index < 0) break; } else { strncpy(maplabel, lumpname, 8); maplabel[8]=0; } map->MapLumps[index].Reader = map->resource->GetLump(i)->NewReader(); strncpy(map->MapLumps[index].Name, lumpname, 8); } } else { // This is a Build map and not subject to WAD consistency checks. //map->MapLumps[0].Size = wadReader->GetLength(); if (!P_IsBuildMap(map)) { delete map; return NULL; } } return map; }
void UJanusExporterTool::Export() { TArray<UObject*> ObjectsToExport; FString Root = FString(ExportPath); // copy so we dont mess with the original reference FString Index = "<html>\n\t<head>\n\t\t<title>Unreal Export</title>\n\t</head>\n\t<body>\n\t\t<FireBoxRoom>\n\t\t\t<Assets>"; TArray<AActor*> ActorsExported; TArray<UStaticMesh*> StaticMeshesExp; TArray<FString> TexturesExp; TArray<FString> MaterialsExported; for (TObjectIterator<AActor> Itr; Itr; ++Itr) { AActor *Actor = *Itr; FString Name = Actor->GetName(); /*if (!Name.StartsWith("SM_Floor_R")) { continue; }*/ if (Actor->IsHiddenEd()) { continue; } ActorsExported.Add(Actor); TArray<UStaticMeshComponent*> StaticMeshes; Actor->GetComponents<UStaticMeshComponent>(StaticMeshes); for (int32 i = 0; i < StaticMeshes.Num(); i++) { UStaticMeshComponent* Component = StaticMeshes[i]; UStaticMesh *Mesh = Component->StaticMesh; if (!Mesh) { continue; } if (Component->LODData.Num() > 0) //if (false) { FStaticMeshComponentLODInfo* LODInfo = &Component->LODData[0]; FLightMap* LightMap = LODInfo->LightMap; FShadowMap* ShadowMap = LODInfo->ShadowMap; if (LightMap != NULL) { FLightMap2D* LightMap2D = LightMap->GetLightMap2D(); UTexture2D* Texture = LightMap2D->GetTexture(0); // 0 = HQ LightMap FString TexName = Texture->GetName(); if (TexturesExp.Contains(TexName)) { continue; } TexturesExp.Add(TexName); ExportPNG(Texture, Root); } if (ShadowMap != NULL) { FShadowMap2D* ShadowMap2D = ShadowMap->GetShadowMap2D(); UShadowMapTexture2D* ShadowTex = ShadowMap2D->GetTexture(); FString TexName = ShadowTex->GetName(); if (TexturesExp.Contains(TexName)) { continue; } TexturesExp.Add(TexName); ExportPNG(ShadowTex, Root); } } if (!StaticMeshesExp.Contains(Mesh)) { StaticMeshesExp.Add(Mesh); ExportFBX(Mesh, Root); } TArray<UMaterialInterface*> Materials = Component->GetMaterials(); for (int32 j = 0; j < Materials.Num(); j++) { UMaterialInterface* Material = Materials[j]; if (!Material) { continue; } FString MatName = Material->GetName(); if (MaterialsExported.Contains(MatName)) { continue; } MaterialsExported.Add(MatName); ExportMaterial(Root, Material, &TexturesExp); } } } // Models before textures so we can start showing the scene faster (textures take too long to load) for (int32 i = 0; i < StaticMeshesExp.Num(); i++) { UStaticMesh *mesh = StaticMeshesExp[i]; Index.Append("\n\t\t\t\t<AssetObject id=\"" + mesh->GetName() + "\" src=\"" + mesh->GetName() + ".fbx\" />"); } for (int32 i = 0; i < TexturesExp.Num(); i++) { FString Path = TexturesExp[i]; Index.Append("\n\t\t\t\t<AssetImage id=\"" + Path + "\" src=\"" + Path + ".png\" />"); } Index.Append("\n\t\t\t</Assets>\n\t\t\t<Room>"); for (int32 i = 0; i < ActorsExported.Num(); i++) { AActor *Actor = ActorsExported[i]; TArray<UStaticMeshComponent*> StaticMeshes; Actor->GetComponents<UStaticMeshComponent>(StaticMeshes); for (int32 i = 0; i < StaticMeshes.Num(); i++) { UStaticMeshComponent* Component = StaticMeshes[i]; UStaticMesh *Mesh = Component->StaticMesh; if (!Mesh) { continue; } FString ImageID = ""; TArray<UMaterialInterface*> Materials = Component->GetMaterials(); for (int32 j = 0; j < Materials.Num(); j++) { UMaterialInterface* Material = Materials[j]; if (!Material) { continue; } ImageID = Material->GetName() + "_BaseColor"; break; } if (ImageID == "") { Index.Append("\n\t\t\t\t<Object collision_id=\"" + Mesh->GetName() + "\" id=\"" + Mesh->GetName() + "\" lighting=\"true\" pos=\""); } else { Index.Append("\n\t\t\t\t<Object collision_id=\"" + Mesh->GetName() + "\" id=\"" + Mesh->GetName() + "\" image_id=\"" + ImageID + "\" lighting=\"true\" pos=\""); } FRotator Rot = Actor->GetActorRotation(); FVector XDir = Rot.RotateVector(FVector::RightVector); FVector YDir = Rot.RotateVector(FVector::UpVector); FVector ZDir = Rot.RotateVector(FVector::ForwardVector); FVector Pos = Actor->GetActorLocation() * UniformScale; FVector Sca = Actor->GetActorScale(); Pos = ChangeSpace(Pos); Sca = ChangeSpaceScalar(Sca) * UniformScale; XDir = ChangeSpace(XDir); YDir = ChangeSpace(YDir); ZDir = ChangeSpace(ZDir); FVector Sign = GetSignVector(Sca); Index.Append(FString::SanitizeFloat(Pos.X) + " " + FString::SanitizeFloat(Pos.Y) + " " + FString::SanitizeFloat(Pos.Z)); if (Sca.X < 0 || Sca.Y < 0 || Sca.Z < 0) { Index.Append("\" cull_face=\"front"); } Index.Append("\" scale=\""); Index.Append(FString::SanitizeFloat(Sca.X) + " " + FString::SanitizeFloat(Sca.Y) + " " + FString::SanitizeFloat(Sca.Z)); Index.Append("\" xdir=\""); Index.Append(FString::SanitizeFloat(XDir.X) + " " + FString::SanitizeFloat(XDir.Y) + " " + FString::SanitizeFloat(XDir.Z)); Index.Append("\" ydir=\""); Index.Append(FString::SanitizeFloat(YDir.X) + " " + FString::SanitizeFloat(YDir.Y) + " " + FString::SanitizeFloat(YDir.Z)); Index.Append("\" zdir=\""); Index.Append(FString::SanitizeFloat(ZDir.X) + " " + FString::SanitizeFloat(ZDir.Y) + " " + FString::SanitizeFloat(ZDir.Z)); Index.Append("\" />"); } } Index.Append("\n\t\t\t</Room>\n\t\t</FireBoxRoom>\n\t</body>\n</html>"); FString IndexPath = FString(ExportPath).Append("index.html"); FFileHelper::SaveStringToFile(Index, *IndexPath); }
bool UOnlineHotfixManager::HotfixIniFile(const FString& FileName, const FString& IniData) { FConfigFile* ConfigFile = GetConfigFile(FileName); // Merge the string into the config file ConfigFile->CombineFromBuffer(IniData); TArray<UClass*> Classes; TArray<UObject*> PerObjectConfigObjects; int32 StartIndex = 0; int32 EndIndex = 0; // Find the set of object classes that were affected while (StartIndex >= 0 && StartIndex < IniData.Len() && EndIndex >= StartIndex) { // Find the next section header StartIndex = IniData.Find(TEXT("["), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex); if (StartIndex > -1) { // Find the ending section identifier EndIndex = IniData.Find(TEXT("]"), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex); if (EndIndex > StartIndex) { int32 PerObjectNameIndex = IniData.Find(TEXT(" "), ESearchCase::IgnoreCase, ESearchDir::FromStart, StartIndex); // Per object config entries will have a space in the name, but classes won't if (PerObjectNameIndex == -1 || PerObjectNameIndex > EndIndex) { if (IniData.StartsWith(TEXT("[/Script/"), ESearchCase::IgnoreCase)) { const int32 ScriptSectionTag = 9; // Snip the text out and try to find the class for that const FString PackageClassName = IniData.Mid(StartIndex + ScriptSectionTag, EndIndex - StartIndex - ScriptSectionTag); // Find the class for this so we know what to update UClass* Class = FindObject<UClass>(nullptr, *PackageClassName, true); if (Class) { // Add this to the list to check against Classes.Add(Class); } } } // Handle the per object config case by finding the object for reload else { const int32 Count = PerObjectNameIndex - StartIndex - 1; const FString PerObjectName = IniData.Mid(StartIndex + 1, Count); // Explicitly search the transient package (won't update non-transient objects) UObject* PerObject = FindObject<UObject>(ANY_PACKAGE, *PerObjectName, false); if (PerObject != nullptr) { PerObjectConfigObjects.Add(PerObject); } } StartIndex = EndIndex; } } } int32 NumObjectsReloaded = 0; const double StartTime = FPlatformTime::Seconds(); if (Classes.Num()) { // Now that we have a list of classes to update, we can iterate objects and reload for (FObjectIterator It; It; ++It) { UClass* Class = It->GetClass(); if (Class->HasAnyClassFlags(CLASS_Config)) { // Check to see if this class is in our list (yes, potentially n^2, but not in practice) for (int32 ClassIndex = 0; ClassIndex < Classes.Num(); ClassIndex++) { if (It->IsA(Classes[ClassIndex])) { // Force a reload of the config vars It->ReloadConfig(); NumObjectsReloaded++; break; } } } } } // Reload any PerObjectConfig objects that were affected for (auto ReloadObject : PerObjectConfigObjects) { ReloadObject->ReloadConfig(); NumObjectsReloaded++; } UE_LOG(LogHotfixManager, Log, TEXT("Updating config from %s took %f seconds and reloaded %d objects"), *FileName, FPlatformTime::Seconds() - StartTime, NumObjectsReloaded); return true; }
bool FAndroidMediaPlayer::Open(const FString& Url) { if (Url.IsEmpty()) { return false; } if (MediaState != EMediaState::Idle) { return false; } if (Url.StartsWith(TEXT("http:")) || Url.StartsWith(TEXT("https:")) || Url.StartsWith(TEXT("rtsp:")) || Url.StartsWith(TEXT("file:"))) { // Direct open media at a "remote" URL. JavaMediaPlayer->SetDataSource(Url); MediaState = EMediaState::Initialized; } else { // Use the platform file layer to open the media file. We // need to access Android specific information to allow // for playing media that is embedded in the APK, OBBs, // and/or PAKs. // Construct a canonical path for the movie. FString MoviePath = Url; FPaths::NormalizeFilename(MoviePath); // Don't bother trying to play it if we can't find it. if (!IAndroidPlatformFile::GetPlatformPhysical().FileExists(*MoviePath)) { return false; } // Get information about the movie. int64 FileOffset = IAndroidPlatformFile::GetPlatformPhysical().FileStartOffset(*MoviePath); int64 FileSize = IAndroidPlatformFile::GetPlatformPhysical().FileSize(*MoviePath); FString FileRootPath = IAndroidPlatformFile::GetPlatformPhysical().FileRootPath(*MoviePath); // Play the movie as a file or asset. if (IAndroidPlatformFile::GetPlatformPhysical().IsAsset(*MoviePath)) { if (JavaMediaPlayer->SetDataSource( IAndroidPlatformFile::GetPlatformPhysical().GetAssetManager(), FileRootPath, FileOffset, FileSize)) { MediaState = EMediaState::Initialized; } } else { if (JavaMediaPlayer->SetDataSource(FileRootPath, FileOffset, FileSize)) { MediaState = EMediaState::Initialized; } } } if (MediaState == EMediaState::Initialized) { MediaUrl = Url; JavaMediaPlayer->Prepare(); MediaState = EMediaState::Prepared; } if (MediaState == EMediaState::Prepared) { // Use the extension as a rough guess as to what tracks // to use. FString Extension = FPaths::GetExtension(MediaUrl); if (Extension.Equals(TEXT("3gpp"), ESearchCase::IgnoreCase) || Extension.Equals(TEXT("mp4"), ESearchCase::IgnoreCase)) { // For video we add video track and disable audio JavaMediaPlayer->SetAudioEnabled(false); // AudioTracks.Add(MakeShareable(new AudioTrack(*this, AudioTracks.Num()))); VideoTracks.Add(MakeShareable(new VideoTrack(*this, VideoTracks.Num()))); } else if (Extension.Equals(TEXT("aac"), ESearchCase::IgnoreCase)) { AudioTracks.Add(MakeShareable(new AudioTrack(*this, AudioTracks.Num()))); } TracksChangedEvent.Broadcast(); } if (MediaState == EMediaState::Prepared) { OpenedEvent.Broadcast(MediaUrl); } return MediaState == EMediaState::Prepared; }
bool NUTNet::CreateFakePlayer(UWorld* InWorld, UNetDriver*& InNetDriver, FString ServerIP, FNetworkNotify* InNotify/*=NULL*/, bool bSkipJoin/*=false*/, FUniqueNetIdRepl* InNetID/*=NULL*/, bool bBeaconConnect/*=false*/, FString InBeaconType/*=TEXT("")*/) { bool bSuccess = false; if (InNetDriver == NULL) { InNetDriver = (InWorld != NULL ? NUTNet::CreateUnitTestNetDriver(InWorld) : NULL); } if (InNetDriver != NULL) { if (InNotify == NULL) { FNetworkNotifyHook* NotifyHook = new FNetworkNotifyHook(); InNotify = NotifyHook; auto DefaultRejectChan = [](UChannel* Channel) { UE_LOG(LogUnitTest, Log, TEXT("UnitTestNetDriver: NotifyAcceptingChannel: %s"), *Channel->Describe()); return false; }; NotifyHook->NotifyAcceptingChannelDelegate.BindLambda(DefaultRejectChan); } FURL DefaultURL; FURL TravelURL(&DefaultURL, *ServerIP, TRAVEL_Absolute); FString ConnectionError; if (InNetDriver->InitConnect(InNotify, TravelURL, ConnectionError)) { UNetConnection* TargetConn = InNetDriver->ServerConnection; UE_LOG(LogUnitTest, Log, TEXT("Successfully kicked off connect to IP '%s'"), *ServerIP); int ControlBunchSequence = 0; FOutBunch* ControlChanBunch = NUTNet::CreateChannelBunch(ControlBunchSequence, TargetConn, CHTYPE_Control, 0); // Need to send 'NMT_Hello' to start off the connection (the challenge is not replied to) uint8 IsLittleEndian = uint8(PLATFORM_LITTLE_ENDIAN); // We need to construct the NMT_Hello packet manually, for the initial connection uint8 MessageType = NMT_Hello; *ControlChanBunch << MessageType; *ControlChanBunch << IsLittleEndian; #if TARGET_UE4_CL >= CL_FNETWORKVERSION // Starting with 4.8.0, the network protocol has changed slightly // @todo JohnB: Refactor this, to toggle at compile time only, based on CL (might require more accurate UT integrate CLs) FString VersionStr = GEngineVersion.ToString(EVersionComponent::Minor); int32 VersionDelim = VersionStr.Find(TEXT(".")); int32 MajorVersion = FCString::Atoi(*VersionStr.Left(VersionDelim)); int32 MinorVersion = FCString::Atoi(*VersionStr.Right(VersionDelim)); bool bOldProtocol = (MajorVersion <= 4 && MinorVersion <= 7) && /** Exception for UT (treat 4.7 as having the new protocol) */ (FString(FApp::GetGameName()) != TEXT("UnrealTournament") || (MajorVersion <= 4 && MinorVersion <= 6)); if (bOldProtocol) #endif { *ControlChanBunch << GEngineMinNetVersion; *ControlChanBunch << GEngineNetVersion; *ControlChanBunch << (FGuid&)GetDefault<UGeneralProjectSettings>()->ProjectID; } #if TARGET_UE4_CL >= CL_FNETWORKVERSION else { uint32 LocalNetworkVersion = FNetworkVersion::GetLocalNetworkVersion(); *ControlChanBunch << LocalNetworkVersion; } #endif if (bBeaconConnect) { if (!bSkipJoin) { MessageType = NMT_BeaconJoin; *ControlChanBunch << MessageType; *ControlChanBunch << InBeaconType; // Also immediately ack the beacon GUID setup; we're just going to let the server setup the client beacon, // through the actor channel MessageType = NMT_BeaconNetGUIDAck; *ControlChanBunch << MessageType; *ControlChanBunch << InBeaconType; } } else { // Then send NMT_Login TSharedPtr<FUniqueNetId> DudPtr = MakeShareable(new FUniqueNetIdString(TEXT("Dud"))); FUniqueNetIdRepl PlayerUID(DudPtr); FString BlankStr = TEXT(""); FString ConnectURL = UUnitTest::UnitEnv->GetDefaultClientConnectURL(); if (InNetID != NULL) { PlayerUID = *InNetID; } MessageType = NMT_Login; *ControlChanBunch << MessageType; *ControlChanBunch << BlankStr; *ControlChanBunch << ConnectURL; *ControlChanBunch << PlayerUID; // Now send NMT_Join, to trigger a fake player, which should then trigger replication of basic actor channels if (!bSkipJoin) { MessageType = NMT_Join; *ControlChanBunch << MessageType; } } // Big hack: Store OutRec value on the unit test control channel, to enable 'retry-send' code TargetConn->Channels[0]->OutRec = ControlChanBunch; TargetConn->SendRawBunch(*ControlChanBunch, true); bSuccess = true; } else { UE_LOG(LogUnitTest, Log, TEXT("Failed to kickoff connect to IP '%s', error: %s"), *ServerIP, *ConnectionError); } } else if (InNetDriver == NULL) { UE_LOG(LogUnitTest, Log, TEXT("Failed to create an instance of the unit test net driver")); } else { UE_LOG(LogUnitTest, Log, TEXT("Failed to get a reference to WorldContext")); } return bSuccess; }
virtual bool SupportedByExtensionsString( const FString& ExtensionsString, const int GLESVersion ) const override { return ExtensionsString.Contains(TEXT("GL_KHR_texture_compression_astc_ldr")); }
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag, bool force) { AWeapon *beastweap; APlayerPawn *mo; APlayerPawn *pmo; pmo = player->mo; // [MH] // Checks pmo as well; the PowerMorph destroyer will // try to unmorph the player; if the destroyer runs // because the level or game is ended while morphed, // by the time it gets executed the morphed player // pawn instance may have already been destroyed. if (pmo == nullptr || pmo->alternative == nullptr) { return false; } bool DeliberateUnmorphIsOkay = !!(MORPH_STANDARDUNDOING & unmorphflag); if ((pmo->flags2 & MF2_INVULNERABLE) // If the player is invulnerable && ((player != activator) // and either did not decide to unmorph, || (!((player->MorphStyle & MORPH_WHENINVULNERABLE) // or the morph style does not allow it || (DeliberateUnmorphIsOkay))))) // (but standard morph styles always allow it), { // Then the player is immune to the unmorph. return false; } mo = barrier_cast<APlayerPawn *>(pmo->alternative); mo->SetOrigin (pmo->Pos(), false); mo->flags |= MF_SOLID; pmo->flags &= ~MF_SOLID; if (!force && !P_TestMobjLocation (mo)) { // Didn't fit mo->flags &= ~MF_SOLID; pmo->flags |= MF_SOLID; player->morphTics = 2*TICRATE; return false; } // No longer using tracer as morph storage. That is what 'alternative' is for. // If the tracer has changed on the morph, change the original too. mo->target = pmo->target; mo->tracer = pmo->tracer; pmo->player = nullptr; // Remove the morph power if the morph is being undone prematurely. for (AInventory *item = pmo->Inventory, *next = nullptr; item != nullptr; item = next) { next = item->Inventory; if (item->IsKindOf(RUNTIME_CLASS(APowerMorph))) { static_cast<APowerMorph *>(item)->SetNoCallUndoMorph(); item->Destroy(); } } EndAllPowerupEffects(pmo->Inventory); mo->ObtainInventory (pmo); DObject::StaticPointerSubstitution (pmo, mo); if ((pmo->tid != 0) && (player->MorphStyle & MORPH_NEWTIDBEHAVIOUR)) { mo->tid = pmo->tid; mo->AddToHash (); } mo->Angles.Yaw = pmo->Angles.Yaw; mo->player = player; mo->reactiontime = 18; mo->flags = ActorFlags::FromInt (pmo->special2) & ~MF_JUSTHIT; mo->Vel.X = mo->Vel.Y = 0; player->Vel.Zero(); mo->Vel.Z = pmo->Vel.Z; if (!(pmo->special2 & MF_JUSTHIT)) { mo->renderflags &= ~RF_INVISIBLE; } mo->flags = (mo->flags & ~(MF_SHADOW|MF_NOGRAVITY)) | (pmo->flags & (MF_SHADOW|MF_NOGRAVITY)); mo->flags2 = (mo->flags2 & ~MF2_FLY) | (pmo->flags2 & MF2_FLY); mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST); mo->Score = pmo->Score; InitAllPowerupEffects(mo->Inventory); PClassActor *exit_flash = player->MorphExitFlash; bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON); bool undobydeathsaves = !!(player->MorphStyle & MORPH_UNDOBYDEATHSAVES); player->morphTics = 0; player->MorphedPlayerClass = 0; player->MorphStyle = 0; player->MorphExitFlash = nullptr; player->viewheight = mo->ViewHeight; AInventory *level2 = mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2), true); if (level2 != nullptr) { level2->Destroy (); } if ((player->health > 0) || undobydeathsaves) { player->health = mo->health = mo->SpawnHealth(); } else // killed when morphed so stay dead { mo->health = player->health; } player->mo = mo; if (player->camera == pmo) { player->camera = mo; } // [MH] // If the player that was morphed is the one // taking events, reset up the face, if any; // this is only needed for old-skool skins // and for the original DOOM status bar. if (player == &players[consoleplayer]) { FString face = pmo->GetClass()->Face; if (face.IsNotEmpty() && strcmp(face, "None") != 0) { // Assume root-level base skin to begin with size_t skinindex = 0; // If a custom skin was in use, then reload it // or else the base skin for the player class. if ((unsigned int)player->userinfo.GetSkin() >= PlayerClasses.Size () && (size_t)player->userinfo.GetSkin() < numskins) { skinindex = player->userinfo.GetSkin(); } else if (PlayerClasses.Size () > 1) { const PClass *whatami = player->mo->GetClass(); for (unsigned int i = 0; i < PlayerClasses.Size (); ++i) { if (PlayerClasses[i].Type == whatami) { skinindex = i; break; } } } } } AActor *eflash = nullptr; if (exit_flash != nullptr) { eflash = Spawn(exit_flash, pmo->Vec3Angle(20., mo->Angles.Yaw, TELEFOGHEIGHT), ALLOW_REPLACE); if (eflash) eflash->target = mo; } mo->SetupWeaponSlots(); // Use original class's weapon slots. beastweap = player->ReadyWeapon; if (player->PremorphWeapon != nullptr) { player->PremorphWeapon->PostMorphWeapon (); } else { player->ReadyWeapon = player->PendingWeapon = nullptr; } if (correctweapon) { // Better "lose morphed weapon" semantics PClassActor *morphweapon = PClass::FindActor(pmo->MorphWeapon); if (morphweapon != nullptr && morphweapon->IsDescendantOf(RUNTIME_CLASS(AWeapon))) { AWeapon *OriginalMorphWeapon = static_cast<AWeapon *>(mo->FindInventory (morphweapon)); if ((OriginalMorphWeapon != nullptr) && (OriginalMorphWeapon->GivenAsMorphWeapon)) { // You don't get to keep your morphed weapon. if (OriginalMorphWeapon->SisterWeapon != nullptr) { OriginalMorphWeapon->SisterWeapon->Destroy (); } OriginalMorphWeapon->Destroy (); } } } else // old behaviour (not really useful now) { // Assumptions made here are no longer valid if (beastweap != nullptr) { // You don't get to keep your morphed weapon. if (beastweap->SisterWeapon != nullptr) { beastweap->SisterWeapon->Destroy (); } beastweap->Destroy (); } } mo->alternative = nullptr; pmo->alternative = nullptr; pmo->Destroy (); // Restore playerclass armor to its normal amount. AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>(); if (hxarmor != nullptr) { hxarmor->Slots[4] = mo->GetClass()->HexenArmor[0]; } return true; }
void gl_InitModels() { int Lump, lastLump; FString path; int index; int i; FSpriteModelFrame smf; lastLump = 0; memset(&smf, 0, sizeof(smf)); while ((Lump = Wads.FindLump("MODELDEF", &lastLump)) != -1) { FScanner sc(Lump); while (sc.GetString()) { if (sc.Compare("model")) { sc.MustGetString(); memset(&smf, 0, sizeof(smf)); smf.xscale=smf.yscale=smf.zscale=1.f; smf.type = PClass::FindClass(sc.String); if (!smf.type || smf.type->Defaults == NULL) { sc.ScriptError("MODELDEF: Unknown actor type '%s'\n", sc.String); } GetDefaultByType(smf.type)->hasmodel=true; sc.MustGetStringName("{"); while (!sc.CheckString("}")) { sc.MustGetString(); if (sc.Compare("path")) { sc.MustGetString(); FixPathSeperator(sc.String); path = sc.String; if (path[(int)path.Len()-1]!='/') path+='/'; } else if (sc.Compare("model")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); smf.models[index] = FindModel(path.GetChars(), sc.String); if (!smf.models[index]) { Printf("%s: model not found\n", sc.String); } } else if (sc.Compare("scale")) { sc.MustGetFloat(); smf.xscale=sc.Float; sc.MustGetFloat(); smf.yscale=sc.Float; sc.MustGetFloat(); smf.zscale=sc.Float; } // [BB] Added zoffset reading. else if (sc.Compare("zoffset")) { sc.MustGetFloat(); smf.zoffset=sc.Float; } // [BB] Added model flags reading. else if (sc.Compare("ignoretranslation")) { smf.flags |= MDL_IGNORETRANSLATION; } else if (sc.Compare("pitchfrommomentum")) { smf.flags |= MDL_PITCHFROMMOMENTUM; } else if (sc.Compare("rotating")) { smf.flags |= MDL_ROTATING; smf.xrotate = 0.; smf.yrotate = 1.; smf.zrotate = 0.; smf.rotationCenterX = 0.; smf.rotationCenterY = 0.; smf.rotationCenterZ = 0.; smf.rotationSpeed = 1.; } else if (sc.Compare("rotation-speed")) { sc.MustGetFloat(); smf.rotationSpeed = sc.Float; } else if (sc.Compare("rotation-vector")) { sc.MustGetFloat(); smf.xrotate = sc.Float; sc.MustGetFloat(); smf.yrotate = sc.Float; sc.MustGetFloat(); smf.zrotate = sc.Float; } else if (sc.Compare("rotation-center")) { sc.MustGetFloat(); smf.rotationCenterX = sc.Float; sc.MustGetFloat(); smf.rotationCenterY = sc.Float; sc.MustGetFloat(); smf.rotationCenterZ = sc.Float; } else if (sc.Compare("interpolatedoubledframes")) { smf.flags |= MDL_INTERPOLATEDOUBLEDFRAMES; } else if (sc.Compare("nointerpolation")) { smf.flags |= MDL_NOINTERPOLATION; } else if (sc.Compare("alignangle")) { smf.flags |= MDL_ALIGNANGLE; } else if (sc.Compare("alignpitch")) { smf.flags |= MDL_ALIGNPITCH; } else if (sc.Compare("rollagainstangle")) { smf.flags |= MDL_ROLLAGAINSTANGLE; } else if (sc.Compare("skin")) { sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } sc.MustGetString(); FixPathSeperator(sc.String); if (sc.Compare("")) { smf.skins[index]=NULL; } else { smf.skins[index]=LoadSkin(path.GetChars(), sc.String); if (smf.skins[index] == NULL) { Printf("Skin '%s' not found in '%s'\n", sc.String, smf.type->TypeName.GetChars()); } } } else if (sc.Compare("frameindex") || sc.Compare("frame")) { bool isframe=!!sc.Compare("frame"); sc.MustGetString(); smf.sprite = -1; for (i = 0; i < (int)sprites.Size (); ++i) { if (strncmp (sprites[i].name, sc.String, 4) == 0) { if (sprites[i].numframes==0) { //sc.ScriptError("Sprite %s has no frames", sc.String); } smf.sprite = i; break; } } if (smf.sprite==-1) { sc.ScriptError("Unknown sprite %s in model definition for %s", sc.String, smf.type->TypeName.GetChars()); } sc.MustGetString(); FString framechars = sc.String; sc.MustGetNumber(); index=sc.Number; if (index<0 || index>=MAX_MODELS_PER_FRAME) { sc.ScriptError("Too many models in %s", smf.type->TypeName.GetChars()); } if (isframe) { sc.MustGetString(); if (smf.models[index]!=NULL) { smf.modelframes[index] = smf.models[index]->FindFrame(sc.String); if (smf.modelframes[index]==-1) sc.ScriptError("Unknown frame '%s' in %s", sc.String, smf.type->TypeName.GetChars()); } else smf.modelframes[index] = -1; } else { sc.MustGetNumber(); smf.modelframes[index] = sc.Number; } for(i=0; framechars[i]>0; i++) { char map[29]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; int c = toupper(framechars[i])-'A'; if (c<0 || c>=29) { sc.ScriptError("Invalid frame character %c found", c+'A'); } if (map[c]) continue; smf.frame=c; SpriteModelFrames.Push(smf); map[c]=1; } } } } } } // create a hash table for quick access SpriteModelHash = new int[SpriteModelFrames.Size ()]; atterm(DeleteModelHash); memset(SpriteModelHash, 0xff, SpriteModelFrames.Size () * sizeof(int)); for (i = 0; i < (int)SpriteModelFrames.Size (); i++) { int j = ModelFrameHash(&SpriteModelFrames[i]) % SpriteModelFrames.Size (); SpriteModelFrames[i].hashnext = SpriteModelHash[j]; SpriteModelHash[j]=i; } }
FString FCulture::FICUCultureImplementation::GetName() const { FString Result = ICULocale.getName(); Result.ReplaceInline(TEXT("_"), TEXT("-")); return Result; }
bool FDesktopPlatformBase::BuildUnrealBuildTool(const FString& RootDir, FOutputDevice& Ar) { Ar.Logf(TEXT("Building UnrealBuildTool in %s..."), *RootDir); // Check the project file exists FString CsProjLocation = GetUnrealBuildToolProjectFileName(RootDir); if(!FPaths::FileExists(CsProjLocation)) { Ar.Logf(TEXT("Project file not found at %s"), *CsProjLocation); return false; } FString CompilerExecutableFilename; FString CmdLineParams; if (PLATFORM_WINDOWS) { // To build UBT for windows, we must assemble a batch file that first registers the environment variable necessary to run msbuild then run it // This can not be done in a single invocation of CMD.exe because the environment variables do not transfer between subsequent commands when using the "&" syntax // devenv.exe can be used to build as well but it takes several seconds to start up so it is not desirable // First determine the appropriate vcvars batch file to launch FString VCVarsBat; #if PLATFORM_WINDOWS #if _MSC_VER >= 1800 FPlatformMisc::GetVSComnTools(12, VCVarsBat); #else FPlatformMisc::GetVSComnTools(11, VCVarsBat); #endif #endif // PLATFORM_WINDOWS VCVarsBat = FPaths::Combine(*VCVarsBat, L"../../VC/bin/x86_amd64/vcvarsx86_amd64.bat"); // Check to make sure we found one. if (VCVarsBat.IsEmpty() || !FPaths::FileExists(VCVarsBat)) { Ar.Logf(TEXT("Couldn't find %s; skipping."), *VCVarsBat); return false; } // Now make a batch file in the intermediate directory to invoke the vcvars batch then msbuild FString BuildBatchFile = RootDir / TEXT("Engine/Intermediate/Build/UnrealBuildTool/BuildUBT.bat"); BuildBatchFile.ReplaceInline(TEXT("/"), TEXT("\\")); FString BatchFileContents; BatchFileContents = FString::Printf(TEXT("call \"%s\"") LINE_TERMINATOR, *VCVarsBat); BatchFileContents += FString::Printf(TEXT("msbuild /nologo /verbosity:quiet \"%s\" /property:Configuration=Development /property:Platform=AnyCPU"), *CsProjLocation); FFileHelper::SaveStringToFile(BatchFileContents, *BuildBatchFile); TCHAR CmdExePath[MAX_PATH]; FPlatformMisc::GetEnvironmentVariable(TEXT("ComSpec"), CmdExePath, ARRAY_COUNT(CmdExePath)); CompilerExecutableFilename = CmdExePath; CmdLineParams = FString::Printf(TEXT("/c \"%s\""), *BuildBatchFile); } else if (PLATFORM_MAC) { FString ScriptPath = FPaths::ConvertRelativePathToFull(RootDir / TEXT("Engine/Build/BatchFiles/Mac/RunXBuild.sh")); CompilerExecutableFilename = TEXT("/bin/sh"); CmdLineParams = FString::Printf(TEXT("\"%s\" /property:Configuration=Development %s"), *ScriptPath, *CsProjLocation); } else if (PLATFORM_LINUX) { FString ScriptPath = FPaths::ConvertRelativePathToFull(RootDir / TEXT("Engine/Build/BatchFiles/Linux/RunXBuild.sh")); CompilerExecutableFilename = TEXT("/bin/bash"); CmdLineParams = FString::Printf(TEXT("\"%s\" /property:Configuration=Development /property:TargetFrameworkVersion=v4.0 %s"), *ScriptPath, *CsProjLocation); } else { Ar.Log(TEXT("Unknown platform, unable to build UnrealBuildTool.")); return false; } // Spawn the compiler Ar.Logf(TEXT("Running: %s %s"), *CompilerExecutableFilename, *CmdLineParams); const bool bLaunchDetached = false; const bool bLaunchHidden = true; const bool bLaunchReallyHidden = bLaunchHidden; FProcHandle ProcHandle = FPlatformProcess::CreateProc(*CompilerExecutableFilename, *CmdLineParams, bLaunchDetached, bLaunchHidden, bLaunchReallyHidden, NULL, 0, NULL, NULL); if (!ProcHandle.IsValid()) { Ar.Log(TEXT("Failed to start process.")); return false; } FPlatformProcess::WaitForProc(ProcHandle); FPlatformProcess::CloseProc(ProcHandle); // If the executable appeared where we expect it, then we were successful FString UnrealBuildToolExePath = GetUnrealBuildToolExecutableFilename(RootDir); if(!FPaths::FileExists(UnrealBuildToolExePath)) { Ar.Logf(TEXT("Missing %s after build"), *UnrealBuildToolExePath); return false; } return true; }
void SFlareNewGameMenu::Construct(const FArguments& InArgs) { // Data MenuManager = InArgs._MenuManager; const FFlareStyleCatalog& Theme = FFlareStyleSet::GetDefaultTheme(); Game = MenuManager->GetPC()->GetGame(); // Game starts ScenarioList.Add(MakeShareable(new FString(TEXT("Freighter")))); //ScenarioList.Add(MakeShareable(new FString(TEXT("Fighter")))); //ScenarioList.Add(MakeShareable(new FString(TEXT("Debug")))); // Color FLinearColor Color = Theme.NeutralColor; Color.A = Theme.DefaultAlpha; // Name FText DefaultName = LOCTEXT("CompanyName", "Player Inc"); FString PlayerName = MenuManager->GetPC()->PlayerState->PlayerName; if (PlayerName.Len()) { DefaultName = FText::Format(LOCTEXT("CompanyNameFormat", "{0} Corp"), FText::FromString(PlayerName)); } // Build structure ChildSlot .HAlign(HAlign_Fill) .VAlign(VAlign_Fill) .Padding(FMargin(0, AFlareMenuManager::GetMainOverlayHeight(), 0, 0)) [ SNew(SVerticalBox) // Main form + SVerticalBox::Slot() .AutoHeight() .Padding(Theme.ContentPadding) .HAlign(HAlign_Center) [ SNew(SBox) .WidthOverride(Theme.ContentWidth / 2) .HAlign(HAlign_Fill) [ SNew(SVerticalBox) // Company name + SVerticalBox::Slot() .Padding(Theme.ContentPadding) .AutoHeight() [ SNew(SBorder) .BorderImage(&Theme.BackgroundBrush) .Padding(Theme.ContentPadding) [ SAssignNew(CompanyName, SEditableText) .Text(DefaultName) .Style(&Theme.TextInputStyle) ] ] // Color picker //+ SVerticalBox::Slot() //.Padding(Theme.ContentPadding) //.AutoHeight() //[ // SAssignNew(ColorBox, SFlareColorPanel) // .MenuManager(MenuManager) //] // Scenario + SVerticalBox::Slot() .AutoHeight() .Padding(Theme.ContentPadding) [ SAssignNew(ScenarioSelector, SComboBox<TSharedPtr<FString>>) .OptionsSource(&ScenarioList) .InitiallySelectedItem(ScenarioList[0]) .OnGenerateWidget(this, &SFlareNewGameMenu::OnGenerateComboLine) .OnSelectionChanged(this, &SFlareNewGameMenu::OnComboLineSelectionChanged) .ComboBoxStyle(&Theme.ComboBoxStyle) .ForegroundColor(FLinearColor::White) [ SNew(STextBlock) .Text(this, &SFlareNewGameMenu::OnGetCurrentComboLine) .TextStyle(&Theme.TextFont) ] ] // Tutorial + SVerticalBox::Slot() .AutoHeight() .Padding(Theme.ContentPadding) .HAlign(HAlign_Right) [ SAssignNew(TutorialButton, SFlareButton) .Text(LOCTEXT("Tutorial", "Play tutorial")) .HelpText(LOCTEXT("TutorialInfo", "Start with a few tutorial missions")) .Toggle(true) ] // Start + SVerticalBox::Slot() .AutoHeight() .Padding(Theme.ContentPadding) .HAlign(HAlign_Right) [ SNew(SFlareButton) .Text(LOCTEXT("Start", "Start the game")) .HelpText(LOCTEXT("StartInfo", "Confirm the creation of a new game and start playing")) .Icon(FFlareStyleSet::GetIcon("Load")) .OnClicked(this, &SFlareNewGameMenu::OnLaunch) ] ] ] ]; TutorialButton->SetActive(true); }
int32 BuildPatchToolMain( const TCHAR* CommandLine ) { // Initialize the command line FCommandLine::Set(CommandLine); // Add log devices if (FParse::Param(FCommandLine::Get(), TEXT("stdout"))) { GLog->AddOutputDevice(new FBuildPatchOutputDevice()); } if (FPlatformMisc::IsDebuggerPresent()) { GLog->AddOutputDevice(new FOutputDeviceDebug()); } GLog->Logf(TEXT("BuildPatchToolMain ran with: %s"), CommandLine); FPlatformProcess::SetCurrentWorkingDirectoryToBaseDir(); bool bSuccess = false; FString RootDirectory; FString CloudDirectory; uint32 AppID=0; FString AppName; FString BuildVersion; FString LaunchExe; FString LaunchCommand; FString IgnoreListFile; FString AttributeListFile; FString PrereqName; FString PrereqPath; FString PrereqArgs; FString ManifestsList; FString ManifestsFile; float DataAgeThreshold = 0.0f; FString IniFile; TMap<FString, FVariant> CustomFields; bool bCompactify = false; bool bPatchGeneration = true; bool bPreview = false; bool bNoPatchDelete = false; bool bPatchWithReuseAgeThreshold = true; // Collect all the info from the CommandLine TArray< FString > Tokens, Switches; FCommandLine::Parse(FCommandLine::Get(), Tokens, Switches); if (Switches.Num() > 0) { int32 BuildRootIdx; int32 CloudDirIdx; int32 AppIDIdx; int32 AppNameIdx; int32 BuildVersionIdx; int32 AppLaunchIdx; int32 AppArgsIdx; int32 FileIgnoreListIdx; int32 FileAttributeListIdx; int32 PrereqNameIdx; int32 PrereqPathIdx; int32 PrereqArgsIdx; int32 ManifestsListIdx; int32 ManifestsFileIdx; int32 DataAgeThresholdIdx; FCommandLineMatcher Matcher; bSuccess = true; Matcher.Command = TEXT("compactify"); bCompactify = Switches.IndexOfByPredicate(Matcher) != INDEX_NONE; bPatchGeneration = !bCompactify; Matcher.Command = TEXT("preview"); bPreview = bCompactify && Switches.IndexOfByPredicate(Matcher) != INDEX_NONE; Matcher.Command = TEXT("nopatchdelete"); bNoPatchDelete = bCompactify && Switches.IndexOfByPredicate(Matcher) != INDEX_NONE; Matcher.Command = TEXT( "BuildRoot" ); BuildRootIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "CloudDir" ); CloudDirIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "AppID" ); AppIDIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "AppName" ); AppNameIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "BuildVersion" ); BuildVersionIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "AppLaunch" ); AppLaunchIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "AppArgs" ); AppArgsIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "FileIgnoreList" ); FileIgnoreListIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT("FileAttributeList"); FileAttributeListIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "PrereqName" ); PrereqNameIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "PrereqPath" ); PrereqPathIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT( "PrereqArgs" ); PrereqArgsIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT("ManifestsList"); ManifestsListIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT("ManifestsFile"); ManifestsFileIdx = Switches.IndexOfByPredicate(Matcher); Matcher.Command = TEXT("DataAgeThreshold"); DataAgeThresholdIdx = Switches.IndexOfByPredicate(Matcher); // Check required param indexes bSuccess = bSuccess && CloudDirIdx != INDEX_NONE; if (bPatchGeneration) { bSuccess = bSuccess && BuildRootIdx != INDEX_NONE; bSuccess = bSuccess && AppIDIdx != INDEX_NONE; bSuccess = bSuccess && AppNameIdx != INDEX_NONE; bSuccess = bSuccess && BuildVersionIdx != INDEX_NONE; bSuccess = bSuccess && AppLaunchIdx != INDEX_NONE; bSuccess = bSuccess && AppArgsIdx != INDEX_NONE; } // Get required param values bSuccess = bSuccess && FParse::Value( *Switches[CloudDirIdx], TEXT( "CloudDir=" ), CloudDirectory ); if (bPatchGeneration) { bSuccess = bSuccess && FParse::Value(*Switches[BuildRootIdx], TEXT("BuildRoot="), RootDirectory); bSuccess = bSuccess && FParse::Value(*Switches[AppIDIdx], TEXT("AppID="), AppID); bSuccess = bSuccess && FParse::Value(*Switches[AppNameIdx], TEXT("AppName="), AppName); bSuccess = bSuccess && FParse::Value(*Switches[BuildVersionIdx], TEXT("BuildVersion="), BuildVersion); bSuccess = bSuccess && FParse::Value(*Switches[AppLaunchIdx], TEXT("AppLaunch="), LaunchExe); bSuccess = bSuccess && FParse::Value(*Switches[AppArgsIdx], TEXT("AppArgs="), LaunchCommand); } // Get optional param values if( FileIgnoreListIdx != INDEX_NONE ) { FParse::Value( *Switches[ FileIgnoreListIdx ], TEXT( "FileIgnoreList=" ), IgnoreListFile ); } if( FileAttributeListIdx != INDEX_NONE ) { FParse::Value( *Switches[ FileAttributeListIdx ], TEXT( "FileAttributeList=" ), AttributeListFile ); } if( PrereqNameIdx != INDEX_NONE ) { FParse::Value( *Switches[ PrereqNameIdx ], TEXT( "PrereqName=" ), PrereqName ); } if( PrereqPathIdx != INDEX_NONE ) { FParse::Value( *Switches[ PrereqPathIdx ], TEXT( "PrereqPath=" ), PrereqPath ); } if( PrereqArgsIdx != INDEX_NONE ) { FParse::Value( *Switches[ PrereqArgsIdx ], TEXT( "PrereqArgs=" ), PrereqArgs ); } if (ManifestsListIdx != INDEX_NONE) { bool bShouldStopOnComma = false; FParse::Value(*Switches[ManifestsListIdx], TEXT("ManifestsList="), ManifestsList, bShouldStopOnComma); } else if (ManifestsFileIdx != INDEX_NONE) { FParse::Value( *Switches[ ManifestsFileIdx ], TEXT( "ManifestsFile=" ), ManifestsFile); } FString CustomValue; FString Left; FString Right; for (const auto& Switch : Switches) { if (FParse::Value(*Switch, TEXT("custom="), CustomValue)) { if (CustomValue.Split(TEXT("="), &Left, &Right)) { Left.Trim(); Left.TrimTrailing(); Right.Trim(); Right.TrimTrailing(); CustomFields.Add(Left, FVariant(Right)); } } else if (FParse::Value(*Switch, TEXT("customfloat="), CustomValue)) { if (CustomValue.Split(TEXT("="), &Left, &Right)) { Left.Trim(); Left.TrimTrailing(); Right.Trim(); Right.TrimTrailing(); if (!Right.IsNumeric()) { GLog->Log(ELogVerbosity::Error, TEXT("An error occurred processing token -customfloat. Non Numeric character found right of =")); bSuccess = false; } CustomFields.Add(Left, FVariant(TCString<TCHAR>::Atod(*Right))); } } else if (FParse::Value(*Switch, TEXT("customint="), CustomValue)) { if (CustomValue.Split(TEXT("="), &Left, &Right)) { Left.Trim(); Left.TrimTrailing(); Right.Trim(); Right.TrimTrailing(); if (!Right.IsNumeric()) { GLog->Log(ELogVerbosity::Error, TEXT("An error occurred processing token -customint. Non Numeric character found right of =")); bSuccess = false; } CustomFields.Add(Left, FVariant(TCString<TCHAR>::Atoi64(*Right))); } } } FPaths::NormalizeDirectoryName( RootDirectory ); FPaths::NormalizeDirectoryName( CloudDirectory ); if (bSuccess) { // Initialize the configuration system, we can only do this reliably if we have CloudDirectory (i.e. bSuccess is true) IniFile = CloudDirectory / TEXT("BuildPatchTool.ini"); GConfig->InitializeConfigSystem(); } if (DataAgeThresholdIdx != INDEX_NONE) { FParse::Value(*Switches[DataAgeThresholdIdx], TEXT("DataAgeThreshold="), DataAgeThreshold); } else if (bSuccess && bCompactify) { // For compactification, if we don't pass in DataAgeThreshold, and it's not in BuildPatchTool.ini, // then we set it to zero, to indicate that any unused chunks are valid for deletion if (!GConfig->GetFloat(TEXT("Compactify"), TEXT("DataAgeThreshold"), DataAgeThreshold, IniFile)) { GLog->Log(ELogVerbosity::Warning, TEXT("DataAgeThreshold not supplied, so all unreferenced data is eliglble for deletion. Note that this process is NOT compatible with any concurrently running patch generaiton processes")); DataAgeThreshold = 0.0f; } } else if (bSuccess && bPatchGeneration) { // For patch generation, if we don't pass in DataAgeThreshold, and it's not specified in BuildPatchTool.ini, // then we set bChunkWithReuseAgeThreshold to false, which indicates that *all* patch data is valid for reuse if (!GConfig->GetFloat(TEXT("PatchGeneration"), TEXT("DataAgeThreshold"), DataAgeThreshold, IniFile)) { GLog->Log(ELogVerbosity::Warning, TEXT("DataAgeThreshold not supplied, so all existing data is eligible for reuse. Note that this process is NOT compatible with any concurrently running compactify processes")); DataAgeThreshold = 0.0f; bPatchWithReuseAgeThreshold = false; } } } // Initialize the file manager IFileManager::Get().ProcessCommandLineOptions(); // Check for argument error if( !bSuccess ) { GLog->Log(ELogVerbosity::Error, TEXT("An error occurred processing arguments")); return 1; } if (bCompactify && bPreview && bNoPatchDelete) { GLog->Log(ELogVerbosity::Error, TEXT("Only one of -preview and -nopatchdelete can be specified")); return 5; } if (!IgnoreListFile.IsEmpty() && !FPaths::FileExists(IgnoreListFile)) { GLog->Logf(ELogVerbosity::Error, TEXT("Provided file ignore list was not found %s"), *IgnoreListFile); return 6; } if (!AttributeListFile.IsEmpty() && !FPaths::FileExists(AttributeListFile)) { GLog->Logf(ELogVerbosity::Error, TEXT("Provided file attribute list was not found %s"), *AttributeListFile); return 7; } // Load the BuildPatchServices Module TSharedPtr<IBuildPatchServicesModule> BuildPatchServicesModule = StaticCastSharedPtr<IBuildPatchServicesModule>( FModuleManager::Get().LoadModule( TEXT( "BuildPatchServices" ) ) ); // Initialise the UObject system and process our uobject classes FModuleManager::Get().LoadModule(TEXT("CoreUObject")); FCoreDelegates::OnInit.Broadcast(); ProcessNewlyLoadedUObjects(); // Setup the module BuildPatchServicesModule->SetCloudDirectory( CloudDirectory + TEXT( "/" ) ); if (bCompactify) { // Split out our manifests to keep arg (if any) into an array of manifest filenames TArray<FString> ManifestsArr; if (ManifestsList.Len() > 0) { ManifestsList.ParseIntoArray(&ManifestsArr, TEXT(","), true); } else if (ManifestsFile.Len() > 0) { FString ManifestsFilePath = CloudDirectory / ManifestsFile; FString Temp; if (FFileHelper::LoadFileToString(Temp, *ManifestsFilePath)) { Temp.ReplaceInline(TEXT("\r"), TEXT("\n")); Temp.ParseIntoArray(&ManifestsArr, TEXT("\n"), true); } else { GLog->Log(ELogVerbosity::Error, TEXT("Could not open specified manifests to keep file")); BuildPatchServicesModule.Reset(); FCoreDelegates::OnExit.Broadcast(); return 2; } } // Determine our mode of operation ECompactifyMode::Type CompactifyMode = ECompactifyMode::Full; if (bPreview) { CompactifyMode = ECompactifyMode::Preview; } else if (bNoPatchDelete) { CompactifyMode = ECompactifyMode::NoPatchDelete; } // Run the compactify routine bSuccess = BuildPatchServicesModule->CompactifyCloudDirectory(ManifestsArr, DataAgeThreshold, CompactifyMode); } else if (bPatchGeneration) { FBuildPatchSettings Settings; Settings.RootDirectory = RootDirectory + TEXT("/"); Settings.AppID = AppID; Settings.AppName = AppName; Settings.BuildVersion = BuildVersion; Settings.LaunchExe = LaunchExe; Settings.LaunchCommand = LaunchCommand; Settings.IgnoreListFile = IgnoreListFile; Settings.AttributeListFile = AttributeListFile; Settings.PrereqName = PrereqName; Settings.PrereqPath = PrereqPath; Settings.PrereqArgs = PrereqArgs; Settings.DataAgeThreshold = DataAgeThreshold; Settings.bShouldHonorReuseThreshold = bPatchWithReuseAgeThreshold; Settings.CustomFields = CustomFields; // Run the build generation if (FParse::Param(FCommandLine::Get(), TEXT("nochunks"))) { bSuccess = BuildPatchServicesModule->GenerateFilesManifestFromDirectory(Settings); } else { bSuccess = BuildPatchServicesModule->GenerateChunksManifestFromDirectory(Settings); } } else { GLog->Log(ELogVerbosity::Error, TEXT("Unknown tool mode")); BuildPatchServicesModule.Reset(); FCoreDelegates::OnExit.Broadcast(); return 3; } // Release the module ptr BuildPatchServicesModule.Reset(); // Check for processing error if (!bSuccess) { GLog->Log(ELogVerbosity::Error, TEXT("A fatal error occurred executing BuildPatchTool.exe")); FCoreDelegates::OnExit.Broadcast(); return 4; } FCoreDelegates::OnExit.Broadcast(); GLog->Log(TEXT("BuildPatchToolMain completed successfuly")); return 0; }
bool FDefaultValueHelper::StringFromCppString(const FString& Source, const FString& TypeName, FString& OutForm) { int32 Pos = 0, PendingParentheses = 0; if( !Trim(Pos, Source) ) { return false; } // remove "TypeName ( " if (Source.Find(TypeName, ESearchCase::CaseSensitive) == Pos) { Pos += TypeName.Len(); if( !Trim(Pos, Source) ) { return false; } if (Source.Find(FString("::"), ESearchCase::CaseSensitive) == Pos) { Pos += 2; if (!Trim(Pos, Source)) { return false; } const FString AllowedFunctionName(TEXT("FromString")); if (Source.Find(AllowedFunctionName, ESearchCase::CaseSensitive, ESearchDir::FromStart, Pos) == Pos) { Pos += AllowedFunctionName.Len(); } else { return false; } if (!Trim(Pos, Source)) { return false; } } if( TS(TEXT("(")) != Source[Pos++] ) { return false; } PendingParentheses++; if( !Trim(Pos, Source) ) { return false; } } // remove "TEXT ( " const TCHAR* TextStr = TEXT("TEXT"); if (Source.Find(TextStr, ESearchCase::CaseSensitive) == Pos) { Pos += FCString::Strlen(TextStr); if( !Trim(Pos, Source) ) { return false; } if( TS(TEXT("(")) != Source[Pos++] ) { return false; } PendingParentheses++; if( !Trim(Pos, Source) ) { return false; } } // ensure the beginning of actual string is found if( TS(TEXT("\"")) != Source[Pos++] ) { return false; } const int32 StartPos = Pos; int32 EndPos = -1; // find end of the actual string for(; Pos < Source.Len(); ++Pos) { if( ( TS(TEXT("\"")) == Source[Pos] ) && ( TS(TEXT("\\")) != Source[Pos-1] ) ) { EndPos = Pos; Pos++; break; } } for(; Pos < Source.Len(); ++Pos) { if( TS(TEXT(")")) == Source[Pos] ) { PendingParentheses--; } else if(!IsWhitespace(Source[Pos])) { return false; } } if(EndPos < 0 || 0 != PendingParentheses) { return false; } OutForm = Source.Mid(StartPos, EndPos - StartPos); return true; }
void FSceneView::ConfigureBufferVisualizationSettings() { bool bBufferDumpingRequired = (FScreenshotRequest::IsScreenshotRequested() || GIsHighResScreenshot || GIsDumpingMovie); bool bVisualizationRequired = Family->EngineShowFlags.VisualizeBuffer; if (bVisualizationRequired || bBufferDumpingRequired) { FinalPostProcessSettings.bBufferVisualizationDumpRequired = bBufferDumpingRequired; FinalPostProcessSettings.BufferVisualizationOverviewMaterials.Empty(); if (bBufferDumpingRequired) { FinalPostProcessSettings.BufferVisualizationDumpBaseFilename = FPaths::GetBaseFilename(FScreenshotRequest::GetFilename(), false); } // Get the list of requested buffers from the console static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable(TEXT("r.BufferVisualizationOverviewTargets")); FString SelectedMaterialNames = CVar->GetString(); FBufferVisualizationData& BufferVisualizationData = GetBufferVisualizationData(); if (BufferVisualizationData.IsDifferentToCurrentOverviewMaterialNames(SelectedMaterialNames)) { FString Left, Right; // Update our record of the list of materials we've been asked to display BufferVisualizationData.SetCurrentOverviewMaterialNames(SelectedMaterialNames); BufferVisualizationData.GetOverviewMaterials().Empty(); // Note - This will re-parse the list of names from the console variable every frame. It could be cached and only updated when // the variable value changes if this turns out to be a performance issue. // Extract each material name from the comma separated string while (SelectedMaterialNames.Len()) { // Detect last entry in the list if (!SelectedMaterialNames.Split(TEXT(","), &Left, &Right)) { Left = SelectedMaterialNames; Right = FString(); } // Lookup this material from the list that was parsed out of the global ini file Left = Left.Trim(); UMaterial* Material = BufferVisualizationData.GetMaterial(*Left); if (Material == NULL && Left.Len() > 0) { UE_LOG(LogBufferVisualization, Warning, TEXT("Unknown material '%s'"), *Left); } // Add this material into the material list in the post processing settings so that the render thread // can pick them up and draw them into the on-screen tiles BufferVisualizationData.GetOverviewMaterials().Add(Material); SelectedMaterialNames = Right; } } // Copy current material list into settings material list for (TArray<UMaterial*>::TConstIterator It = BufferVisualizationData.GetOverviewMaterials().CreateConstIterator(); It; ++It) { FinalPostProcessSettings.BufferVisualizationOverviewMaterials.Add(*It); } } }
bool FDefaultValueHelper::Trim(int32& Pos, const FString& Source) { for(; Pos < Source.Len() && IsWhitespace(Source[Pos]); ++Pos) { } return (Pos < Source.Len()); }
bool UGatherTextFromSourceCommandlet::ParseSourceText(const FString& Text, const TArray<UGatherTextFromSourceCommandlet::FParsableDescriptor*>& Parsables, FSourceFileParseContext& ParseCtxt) { // Create array of ints, one for each parsable we're looking for. TArray<int32> ParsableMatchCounters; ParsableMatchCounters.AddZeroed(Parsables.Num()); // Cache array of tokens TArray<FString> ParsableTokens; for (int32 ParIdx=0; ParIdx<Parsables.Num(); ParIdx++) { ParsableTokens.Add(Parsables[ParIdx]->GetToken()); } // Split the file into lines of TArray<FString> TextLines; Text.ParseIntoArray(&TextLines, LINE_TERMINATOR, false); // Move through the text lines looking for the tokens that denote the items in the Parsables list for (int32 LineIdx = 0; LineIdx < TextLines.Num(); LineIdx++) { const FString& Line = TextLines[LineIdx].TrimTrailing(); if( Line.IsEmpty() ) continue; // Use these pending vars to defer parsing a token hit until longer tokens can't hit too int32 PendingParseIdx = -1; const TCHAR* ParsePoint = NULL; ParsableMatchCounters.Empty(Parsables.Num()); ParsableMatchCounters.AddZeroed(Parsables.Num()); ParseCtxt.LineNumber = LineIdx + 1; ParseCtxt.LineText = Line; ParseCtxt.EndParsingCurrentLine = false; const TCHAR* Cursor = *Line; bool EndOfLine = false; while (!EndOfLine && !ParseCtxt.EndParsingCurrentLine) { // Check if we're starting comments. Begins *at* "//" or "/*". if(!ParseCtxt.WithinLineComment && !ParseCtxt.WithinBlockComment) { const TCHAR* ForwardCursor = Cursor; if(*ForwardCursor == TEXT('/')) { ++ForwardCursor; switch(*ForwardCursor) { case TEXT('/'): { ParseCtxt.WithinLineComment = true; } break; case TEXT('*'): { ParseCtxt.WithinBlockComment = true; } break; } } } // Check if we're ending comments. Ends *after* "*/". if(ParseCtxt.WithinBlockComment) { const TCHAR* ReverseCursor = Cursor; if(*ReverseCursor == TEXT('/') && ReverseCursor >= *Line) { --ReverseCursor; if(*ReverseCursor == TEXT('*') && ReverseCursor >= *Line) { ParseCtxt.WithinBlockComment = false; } } } for (int32 ParIdx=0; ParIdx<Parsables.Num(); ParIdx++) { FString& Token = ParsableTokens[ParIdx]; if (*Cursor == Token[ParsableMatchCounters[ParIdx]]) { // Char at cursor matches the next char in the parsable's identifying token if (Token.Len() == ++(ParsableMatchCounters[ParIdx])) { // don't immediately parse - this parsable has seen its entire token but a longer one could be about to hit too const TCHAR* TokenStart = Cursor + 1 - Token.Len(); if (0 > PendingParseIdx || ParsePoint >= TokenStart) { PendingParseIdx = ParIdx; ParsePoint = TokenStart; } } } else { // Char at cursor doesn't match the next char in the parsable's identifying token // Reset the counter to start of the token ParsableMatchCounters[ParIdx] = 0; } } // Now check PendingParse and only run it if there are no better candidates if (0 <= PendingParseIdx) { bool MustDefer = false; // pending will be deferred if another parsable has a equal and greater number of matched chars if( !Parsables[PendingParseIdx]->OverridesLongerTokens() ) { for (int32 ParIdx=0; ParIdx<Parsables.Num(); ParIdx++) { if (PendingParseIdx != ParIdx) { if (ParsableMatchCounters[ParIdx] >= ParsableTokens[PendingParseIdx].Len()) { // a longer token is matching so defer MustDefer = true; } } } } if (!MustDefer) { // Do the parse now Parsables[PendingParseIdx]->TryParse(FString(ParsePoint), ParseCtxt); ParsableMatchCounters[PendingParseIdx] = 0; PendingParseIdx = -1; ParsePoint = NULL; } } EndOfLine = ('\0' == *(++Cursor)) ? true : false; if(EndOfLine) { ParseCtxt.WithinLineComment = false; } } } return true; }
bool FAutoReimportDirectoryConfig::ParseSourceDirectoryAndMountPoint(FString& SourceDirectory, FString& MountPoint, const FParseContext& InContext) { SourceDirectory.ReplaceInline(TEXT("\\"), TEXT("/")); // Check if the source directory is actually a mount point if (!FPackageName::GetPackageMountPoint(SourceDirectory).IsNone()) { MountPoint = SourceDirectory; SourceDirectory = FString(); } if (!SourceDirectory.IsEmpty() && !MountPoint.IsEmpty()) { // We have both a source directory and a mount point. Verify that the source dir exists, and that the mount point is valid. if (!IFileManager::Get().DirectoryExists(*SourceDirectory)) { UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to watch directory %s as it doesn't exist."), *SourceDirectory); return false; } if (FPackageName::GetPackageMountPoint(MountPoint).IsNone()) { UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to setup directory %s to map to %s, as it's not a valid mounted path. Continuing without mounted path (auto reimports will still work, but auto add won't)."), *SourceDirectory, *MountPoint); } } else if(!MountPoint.IsEmpty()) { // We have just a mount point - validate it, and find its source directory if (FPackageName::GetPackageMountPoint(MountPoint).IsNone()) { UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to setup directory monitor for %s, as it's not a valid mounted path."), *MountPoint); return false; } SourceDirectory = FPackageName::LongPackageNameToFilename(MountPoint); } else if(!SourceDirectory.IsEmpty()) { // We have just a source directory - verify whether it's a mounted path, and set up the mount point if so if (!IFileManager::Get().DirectoryExists(*SourceDirectory)) { UE_CLOG(InContext.bEnableLogging, LogAutoReimportManager, Warning, TEXT("Unable to watch directory %s as it doesn't exist."), *SourceDirectory); return false; } // Set the mounted path if necessary auto* Pair = InContext.MountedPaths.FindByPredicate([&](const TPair<FString, FString>& InPair){ return SourceDirectory.StartsWith(InPair.Key); }); if (Pair) { MountPoint = Pair->Value / SourceDirectory.RightChop(Pair->Key.Len()); MountPoint.ReplaceInline(TEXT("\\"), TEXT("/")); } } else { // Don't have any valid settings return false; } return true; }
void UGatherTextFromSourceCommandlet::FCommandMacroDescriptor::TryParse(const FString& Text, FSourceFileParseContext& Context) const { // Attempt to parse something of the format // UI_COMMAND(LocKey, DefaultLangString, DefaultLangTooltipString, <IgnoredParam>, <IgnoredParam>) if (!Context.ExcludedRegion && (Context.Filename.EndsWith(TEXT(".inl")) || (!Context.WithinBlockComment && !Context.WithinLineComment)) ) { TArray<FString> Arguments; if (ParseArgsFromMacro(Text, Arguments, Context)) { if (Arguments.Num() != 5) { UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("Too many arguments in command %s macro in %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *MungeLogOutput(Context.LineText)); } else { FString Identifier = Arguments[0].Trim(); FString Namespace = TEXT("UICommands"); FString SourceLocation = FString( Context.Filename + TEXT(" - line ") + FString::FromInt(Context.LineNumber) ); FString SourceText = Arguments[1].Trim(); if ( Identifier.IsEmpty() ) { //The command doesn't have an identifier so we can't gather it UE_LOG(LogGatherTextFromSourceCommandlet, Warning, TEXT("UICOMMAND macro doesn't have unique identifier. %s"), *SourceLocation ); return; } // parse DefaultLangString argument - this arg will be in quotes without TEXT macro bool HasQuotes; FString MacroDesc = FString::Printf(TEXT("\"FriendlyName\" argument in %s macro %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *Context.LineText); if ( PrepareArgument(SourceText, true, MacroDesc, HasQuotes) ) { if ( HasQuotes && !Identifier.IsEmpty() && !SourceText.IsEmpty() ) { // First create the command entry FContext CommandContext; CommandContext.Key = Identifier; CommandContext.SourceLocation = SourceLocation; Context.AddManifestText( GetToken(), Namespace, SourceText, CommandContext ); // parse DefaultLangTooltipString argument - this arg will be in quotes without TEXT macro FString TooltipSourceText = Arguments[2].Trim(); MacroDesc = FString::Printf(TEXT("\"InDescription\" argument in %s macro %s(%d):%s"), *GetToken(), *Context.Filename, Context.LineNumber, *Context.LineText); if (PrepareArgument(TooltipSourceText, true, MacroDesc, HasQuotes)) { if (HasQuotes && !TooltipSourceText.IsEmpty()) { // Create the tooltip entry FContext CommandTooltipContext; CommandTooltipContext.Key = Identifier + TEXT("_ToolTip"); CommandTooltipContext.SourceLocation = SourceLocation; Context.AddManifestText( GetToken(), Namespace, TooltipSourceText, CommandTooltipContext ); } } } } } } } }
FPropertyAccess::Result SPropertyEditorAsset::GetValue( FObjectOrAssetData& OutValue ) const { // Potentially accessing the value while garbage collecting or saving the package could trigger a crash. // so we fail to get the value when that is occurring. if ( GIsSavingPackage || IsGarbageCollecting() ) { return FPropertyAccess::Fail; } FPropertyAccess::Result Result = FPropertyAccess::Fail; if( PropertyEditor.IsValid() && PropertyEditor->GetPropertyHandle()->IsValidHandle() ) { UObject* Object = NULL; Result = PropertyEditor->GetPropertyHandle()->GetValue(Object); if (Object == NULL) { // Check to see if it's pointing to an unloaded object FString CurrentObjectPath; PropertyEditor->GetPropertyHandle()->GetValueAsFormattedString( CurrentObjectPath ); if (CurrentObjectPath.Len() > 0 && CurrentObjectPath != TEXT("None")) { if( !CachedAssetData.IsValid() || CachedAssetData.ObjectPath.ToString() != CurrentObjectPath ) { static FName AssetRegistryName("AssetRegistry"); FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName); CachedAssetData = AssetRegistryModule.Get().GetAssetByObjectPath( *CurrentObjectPath ); } Result = FPropertyAccess::Success; OutValue = FObjectOrAssetData( CachedAssetData ); return Result; } } #if !UE_BUILD_SHIPPING if (Object && !Object->IsValidLowLevel()) { const UProperty* Property = PropertyEditor->GetProperty(); UE_LOG(LogPropertyNode, Fatal, TEXT("Property \"%s\" (%s) contains invalid data."), *Property->GetName(), *Property->GetCPPType()); } #endif OutValue = FObjectOrAssetData( Object ); } else { UObject* Object = NULL; if (PropertyHandle.IsValid()) { Result = PropertyHandle->GetValue(Object); } if (Object != NULL) { #if !UE_BUILD_SHIPPING if (!Object->IsValidLowLevel()) { const UProperty* Property = PropertyEditor->GetProperty(); UE_LOG(LogPropertyNode, Fatal, TEXT("Property \"%s\" (%s) contains invalid data."), *Property->GetName(), *Property->GetCPPType()); } #endif OutValue = FObjectOrAssetData(Object); } else { const FString CurrentObjectPath = ObjectPath.Get(); Result = FPropertyAccess::Success; if (CurrentObjectPath != TEXT("None") && (!CachedAssetData.IsValid() || CachedAssetData.ObjectPath.ToString() != CurrentObjectPath)) { static FName AssetRegistryName("AssetRegistry"); FAssetRegistryModule& AssetRegistryModule = FModuleManager::Get().LoadModuleChecked<FAssetRegistryModule>(AssetRegistryName); CachedAssetData = AssetRegistryModule.Get().GetAssetByObjectPath(*CurrentObjectPath); if (PropertyHandle.IsValid()) { // No property editor was specified so check if multiple property values are associated with the property handle TArray<FString> ObjectValues; PropertyHandle->GetPerObjectValues(ObjectValues); if (ObjectValues.Num() > 1) { for (int32 ObjectIndex = 1; ObjectIndex < ObjectValues.Num() && Result == FPropertyAccess::Success; ++ObjectIndex) { if (ObjectValues[ObjectIndex] != ObjectValues[0]) { Result = FPropertyAccess::MultipleValues; } } } } } else if (CurrentObjectPath == TEXT("None")) { CachedAssetData = FAssetData(); } OutValue = FObjectOrAssetData(CachedAssetData); } } return Result; }