bool FEditTextureLatentCommand::Update() { // make a minor edit to the texture in the package we are passed UPackage* Package = LoadPackage(NULL, *PackageName, LOAD_None); if(Package != NULL) { UTexture2D* Texture = FindObject<UTexture2D>(Package, TEXT("SourceControlTest")); check(Texture); Texture->AdjustBrightness = FMath::FRand(); Package->SetDirtyFlag(true); if(!UPackage::SavePackage(Package, NULL, RF_Standalone, *FPackageName::LongPackageNameToFilename(PackageName, FPackageName::GetAssetPackageExtension()))) { UE_LOG(LogSourceControl, Error, TEXT("Could not save package: '%s'"), *PackageName); } TArray<UPackage*> Packages; Packages.Add(Package); PackageTools::UnloadPackages(Packages); } else { UE_LOG(LogSourceControl, Error, TEXT("Could not find package for edit: '%s'"), *PackageName); } return true; }
/** * Saves the duplicated asset */ void SaveDuplicatedAsset() { if (DuplicatedPackage && DuplicatedAsset) { DuplicatedPackage->SetDirtyFlag(true); const FString PackagePath = FString::Printf(TEXT("%s/%s_Copy"), *GetGamePath(), *AssetName); if (UPackage::SavePackage(DuplicatedPackage, NULL, RF_Standalone, *FPackageName::LongPackageNameToFilename(PackagePath, FPackageName::GetAssetPackageExtension()), GError, nullptr, false, true, SAVE_NoError)) { TestStats->NumDuplicatesSaved++; UE_LOG(LogEditorAssetAutomationTests, Display, TEXT("Saved asset %s (%s)"), *DuplicatedAsset->GetName(), *Class->GetName()); } else { UE_LOG(LogEditorAssetAutomationTests, Display, TEXT("Unable to save asset %s (%s)"), *DuplicatedAsset->GetName(), *Class->GetName()); } } }
/** * Removes a level from the world. Returns true if the level was removed successfully. * * @param Level The level to remove from the world. * @return true if the level was removed successfully, false otherwise. */ bool PrivateRemoveLevelFromWorld(ULevel* Level) { if ( !Level || Level->IsPersistentLevel() ) { return false; } if ( FLevelUtils::IsLevelLocked(Level) ) { FMessageDialog::Open( EAppMsgType::Ok, NSLOCTEXT("UnrealEd", "Error_OperationDisallowedOnLockedLevelRemoveLevelFromWorld", "RemoveLevelFromWorld: The requested operation could not be completed because the level is locked.") ); return false; } int32 StreamingLevelIndex = INDEX_NONE; for( int32 LevelIndex = 0 ; LevelIndex < Level->OwningWorld->StreamingLevels.Num() ; ++LevelIndex ) { ULevelStreaming* StreamingLevel = Level->OwningWorld->StreamingLevels[ LevelIndex ]; if( StreamingLevel && StreamingLevel->GetLoadedLevel() == Level ) { StreamingLevelIndex = LevelIndex; break; } } if (StreamingLevelIndex != INDEX_NONE) { Level->OwningWorld->StreamingLevels[StreamingLevelIndex]->MarkPendingKill(); Level->OwningWorld->StreamingLevels.RemoveAt( StreamingLevelIndex ); Level->OwningWorld->RefreshStreamingLevels(); } else if (Level->bIsVisible) { Level->OwningWorld->RemoveFromWorld(Level); check(Level->bIsVisible == false); } const bool bSuccess = EditorDestroyLevel(Level); // Since we just removed all the actors from this package, we do not want it to be saved out now // and the user was warned they would lose any changes from before removing, so we're good to clear // the dirty flag UPackage* LevelPackage = Level->GetOutermost(); LevelPackage->SetDirtyFlag(false); return bSuccess; }
/** * Finds the outermost package and marks it dirty */ bool UObjectBaseUtility::MarkPackageDirty() const { // since transient objects will never be saved into a package, there is no need to mark a package dirty // if we're transient if ( !HasAnyFlags(RF_Transient) ) { UPackage* Package = GetOutermost(); if( Package != NULL ) { // It is against policy to dirty a map or package during load in the Editor, to enforce this policy // we explicitly disable the ability to dirty a package or map during load. Commandlets can still // set the dirty state on load. if( IsRunningCommandlet() || (GIsEditor && !GIsEditorLoadingPackage && !GIsPlayInEditorWorld && !IsInAsyncLoadingThread() #if WITH_HOT_RELOAD && !GIsHotReload #endif // WITH_HOT_RELOAD #if WITH_EDITORONLY_DATA && !Package->bIsCookedForEditor // Cooked packages can't be modified nor marked as dirty #endif )) { const bool bIsDirty = Package->IsDirty(); // We prevent needless re-dirtying as this can be an expensive operation. if( !bIsDirty ) { Package->SetDirtyFlag(true); } // Always call PackageMarkedDirtyEvent, even when the package is already dirty Package->PackageMarkedDirtyEvent.Broadcast(Package, bIsDirty); return true; } else { // notify the caller that the request to mark the package as dirty was suppressed return false; } } } return true; }
/** * Deletes the asset */ void DeleteAsset() { if (CreatedAsset) { bool bSuccessful = false; bSuccessful = ObjectTools::DeleteSingleObject(CreatedAsset, false); //If we failed to delete this object manually clear any references and try again if (!bSuccessful) { //Clear references to the object so we can delete it AutomationEditorCommonUtils::NullReferencesToObject(CreatedAsset); bSuccessful = ObjectTools::DeleteSingleObject(CreatedAsset, false); } //Delete the package if (bSuccessful) { FString PackageFilename; if (FPackageName::DoesPackageExist(AssetPackage->GetName(), NULL, &PackageFilename)) { TArray<UPackage*> PackagesToDelete; PackagesToDelete.Add(AssetPackage); // Let the package auto-saver know that it needs to ignore the deleted packages GUnrealEd->GetPackageAutoSaver().OnPackagesDeleted(PackagesToDelete); AssetPackage->SetDirtyFlag(false); // Unload the packages and collect garbage. PackageTools::UnloadPackages(PackagesToDelete); IFileManager::Get().Delete(*PackageFilename); TestStats->NumDeleted++; UE_LOG(LogEditorAssetAutomationTests, Display, TEXT("Deleted asset %s (%s)"), *AssetName, *Class->GetName()); } } else { UE_LOG(LogEditorAssetAutomationTests, Error, TEXT("Unable to delete asset: %s (%s)"), *AssetName, *Class->GetName()); } } }
void USoundClassGraph::RebuildGraph() { check(RootSoundClass); // Don't allow initial graph rebuild to affect package dirty state; remember current state... UPackage* Package = GetOutermost(); const bool bIsDirty = Package->IsDirty(); Modify(); RemoveAllNodes(); ConstructNodes(RootSoundClass, 0, 0); NotifyGraphChanged(); // ...and restore it Package->SetDirtyFlag(bIsDirty); }
/** * Finds the outermost package and marks it dirty */ void UObjectBaseUtility::MarkPackageDirty() const { // since transient objects will never be saved into a package, there is no need to mark a package dirty // if we're transient if ( !HasAnyFlags(RF_Transient) ) { UPackage* Package = GetOutermost(); if( Package != NULL ) { // It is against policy to dirty a map or package during load in the Editor, to enforce this policy // we explicitly disable the ability to dirty a package or map during load. Commandlets can still // set the dirty state on load. // We also prevent needless re-dirtying as this can be an expensive operation. if( !Package->IsDirty() && (!GIsEditor || IsRunningCommandlet() || (GIsEditor && !GIsEditorLoadingPackage))) { Package->SetDirtyFlag(true); } } } }
UTexture* UnFbx::FFbxImporter::ImportTexture( FbxFileTexture* FbxTexture, bool bSetupAsNormalMap ) { // create an unreal texture asset UTexture* UnrealTexture = NULL; FString Filename1 = ANSI_TO_TCHAR(FbxTexture->GetFileName()); FString Extension = FPaths::GetExtension(Filename1).ToLower(); // name the texture with file name FString TextureName = FPaths::GetBaseFilename(Filename1); TextureName = ObjectTools::SanitizeObjectName(TextureName); // set where to place the textures FString NewPackageName = FPackageName::GetLongPackagePath(Parent->GetOutermost()->GetName()) + TEXT("/") + TextureName; NewPackageName = PackageTools::SanitizePackageName(NewPackageName); UPackage* Package = CreatePackage(NULL, *NewPackageName); bool AlreadyExistTexture = (FindObject<UTexture>(Package,*TextureName/*textureName.GetName()*/) != NULL); // try opening from absolute path FString Filename = Filename1; TArray<uint8> DataBinary; if ( ! FFileHelper::LoadFileToArray( DataBinary, *Filename )) { // try fbx file base path + relative path FString Filename2 = FileBasePath / ANSI_TO_TCHAR(FbxTexture->GetRelativeFileName()); Filename = Filename2; if ( ! FFileHelper::LoadFileToArray( DataBinary, *Filename )) { // try fbx file base path + texture file name (no path) FString Filename3 = ANSI_TO_TCHAR(FbxTexture->GetRelativeFileName()); FString FileOnly = FPaths::GetCleanFilename(Filename3); Filename3 = FileBasePath / FileOnly; Filename = Filename3; if ( ! FFileHelper::LoadFileToArray( DataBinary, *Filename )) { UE_LOG(LogFbxMaterialImport, Warning,TEXT("Unable to find TEXTure file %s. Tried:\n - %s\n - %s\n - %s"),*FileOnly,*Filename1,*Filename2,*Filename3); } } } if (DataBinary.Num()>0) { UE_LOG(LogFbxMaterialImport, Warning, TEXT("Loading texture file %s"),*Filename); const uint8* PtrTexture = DataBinary.GetTypedData(); UTextureFactory* TextureFact = new UTextureFactory(FPostConstructInitializeProperties()); // save texture settings if texture exist TextureFact->SuppressImportOverwriteDialog(); const TCHAR* TextureType = *Extension; // Unless the normal map setting is used during import, // the user has to manually hit "reimport" then "recompress now" button if ( bSetupAsNormalMap ) { if (!AlreadyExistTexture) { TextureFact->LODGroup = TEXTUREGROUP_WorldNormalMap; TextureFact->CompressionSettings = TC_Normalmap; } else { UE_LOG(LogFbxMaterialImport, Warning, TEXT("Manual texture reimport and recompression may be needed for %s"), *TextureName); } } UnrealTexture = (UTexture*)TextureFact->FactoryCreateBinary( UTexture2D::StaticClass(), Package, *TextureName, RF_Standalone|RF_Public, NULL, TextureType, PtrTexture, PtrTexture+DataBinary.Num(), GWarn ); if ( UnrealTexture != NULL ) { // Notify the asset registry FAssetRegistryModule::AssetCreated(UnrealTexture); // Set the dirty flag so this package will get saved later Package->SetDirtyFlag(true); } } return UnrealTexture; }
void UnFbx::FFbxImporter::CreateUnrealMaterial(FbxSurfaceMaterial* FbxMaterial, TArray<UMaterialInterface*>& OutMaterials, TArray<FString>& UVSets) { FString MaterialFullName = ANSI_TO_TCHAR(MakeName(FbxMaterial->GetName())); // check for a 'skinXX' suffix in the material name int32 MaterialNameLen = FCString::Strlen(*MaterialFullName) + 1; char* MaterialNameANSI = new char[MaterialNameLen]; FCStringAnsi::Strcpy(MaterialNameANSI, MaterialNameLen, TCHAR_TO_ANSI(*MaterialFullName)); if (FCStringAnsi::Strlen(MaterialNameANSI) > 6) { const char* SkinXX = MaterialNameANSI + FCStringAnsi::Strlen(MaterialNameANSI) - 6; if (FCharAnsi::ToUpper(*SkinXX) == 'S' && FCharAnsi::ToUpper(*(SkinXX+1)) == 'K' && FCharAnsi::ToUpper(*(SkinXX+2)) == 'I' && FCharAnsi::ToUpper(*(SkinXX+3)) == 'N') { if (FCharAnsi::IsDigit(*(SkinXX+4)) && FCharAnsi::IsDigit(*(SkinXX+5))) { // remove the 'skinXX' suffix from the material name MaterialFullName = MaterialFullName.Left(MaterialNameLen - 7); } } } MaterialFullName = ObjectTools::SanitizeObjectName(MaterialFullName); // Make sure we have a parent if ( !ensure(Parent) ) { return; } // set where to place the materials FString NewPackageName = FPackageName::GetLongPackagePath(Parent->GetOutermost()->GetName()) + TEXT("/") + MaterialFullName; NewPackageName = PackageTools::SanitizePackageName(NewPackageName); UPackage* Package = CreatePackage(NULL, *NewPackageName); UMaterialInterface* UnrealMaterialInterface = FindObject<UMaterialInterface>(Package,*MaterialFullName); // does not override existing materials if (UnrealMaterialInterface != NULL) { OutMaterials.Add(UnrealMaterialInterface); return; } // create an unreal material asset UMaterialFactoryNew* MaterialFactory = new UMaterialFactoryNew(FPostConstructInitializeProperties()); UMaterial* UnrealMaterial = (UMaterial*)MaterialFactory->FactoryCreateNew( UMaterial::StaticClass(), Package, *MaterialFullName, RF_Standalone|RF_Public, NULL, GWarn ); // TODO : need this ? UnrealMaterial->bUsedWithStaticLighting = true; if ( UnrealMaterial != NULL ) { // Notify the asset registry FAssetRegistryModule::AssetCreated(UnrealMaterial); // Set the dirty flag so this package will get saved later Package->SetDirtyFlag(true); } // textures and properties CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sDiffuse, UnrealMaterial->DiffuseColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sEmissive, UnrealMaterial->EmissiveColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecular, UnrealMaterial->SpecularColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecularFactor, UnrealMaterial->SpecularColor, false, UVSets); // SpecularFactor modulates the SpecularColor value if there's one //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sShininess, UnrealMaterial->SpecularPower, false, UVSets); if (!CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sNormalMap, UnrealMaterial->Normal, true, UVSets)) { CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sBump, UnrealMaterial->Normal, true, UVSets); // no bump in unreal, use as normal map } //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparentColor, UnrealMaterial->Opacity, false, UVSets); //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparencyFactor, UnrealMaterial->OpacityMask, false, UVSets); FixupMaterial( *FbxMaterial, UnrealMaterial); // add random diffuse if none exists // compile shaders for PC (from UPrecompileShadersCommandlet::ProcessMaterial // and FMaterialEditor::UpdateOriginalMaterial) // make sure that any static meshes, etc using this material will stop using the FMaterialResource of the original // material, and will use the new FMaterialResource created when we make a new UMaterial in place FGlobalComponentReregisterContext RecreateComponents; // let the material update itself if necessary UnrealMaterial->PreEditChange(NULL); UnrealMaterial->PostEditChange(); OutMaterials.Add(UnrealMaterial); }
/** * Runs compile-on-load test against all unloaded, and optionally loaded, blueprints * See the TestAllBlueprints config key in the [Automation.Blueprint] config sections */ bool FBlueprintCompileOnLoadTest::RunTest(const FString& BlueprintAssetPath) { FCompilerResultsLog Results; UBlueprint* ExistingBP = nullptr; // if this blueprint was already loaded, then these tests are invalidated // (because dependencies have already been loaded) if (FBlueprintAutomationTestUtilities::IsBlueprintLoaded(BlueprintAssetPath, &ExistingBP)) { if (FBlueprintAutomationTestUtilities::IsAssetUnsaved(BlueprintAssetPath)) { AddError(FString::Printf(TEXT("You have unsaved changes made to '%s', please save them before running this test."), *BlueprintAssetPath)); return false; } else { AddWarning(FString::Printf(TEXT("Test may be invalid (the blueprint is already loaded): '%s'"), *BlueprintAssetPath)); FBlueprintAutomationTestUtilities::UnloadBlueprint(ExistingBP); } } // tracks blueprints that were already loaded (and cleans up any that were // loaded in its lifetime, once it is destroyed) FScopedBlueprintUnloader NewBlueprintUnloader(/*bAutoOpenScope =*/true, /*bRunGCOnCloseIn =*/true); // We load the blueprint twice and compare the two for discrepancies. This is // to bring dependency load issues to light (among other things). If a blueprint's // dependencies are loaded too late, then this first object is the degenerate one. UBlueprint* InitialBlueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *BlueprintAssetPath)); // if we failed to load it the first time, then there is no need to make a // second attempt, leave them to fix up this issue first if (InitialBlueprint == NULL) { AddError(*FString::Printf(TEXT("Unable to load blueprint for: '%s'"), *BlueprintAssetPath)); return false; } if (!InitialBlueprint->SkeletonGeneratedClass || !InitialBlueprint->GeneratedClass) { AddError(*FString::Printf(TEXT("Unable to load blueprint for: '%s'. Probably it derives from an invalid class."), *BlueprintAssetPath)); return false; } // GATHER SUBOBJECTS TArray<TWeakObjectPtr<UObject>> InitialBlueprintSubobjects; { TArray<UObject*> InitialBlueprintSubobjectsPtr; GetObjectsWithOuter(InitialBlueprint, InitialBlueprintSubobjectsPtr); for (auto Obj : InitialBlueprintSubobjectsPtr) { InitialBlueprintSubobjects.Add(Obj); } } // GATHER DEPENDENCIES TSet<TWeakObjectPtr<UBlueprint>> BlueprintDependencies; { TArray<UBlueprint*> DependentBlueprints; FBlueprintEditorUtils::GetDependentBlueprints(InitialBlueprint, DependentBlueprints); for (auto BP : DependentBlueprints) { BlueprintDependencies.Add(BP); } } BlueprintDependencies.Add(InitialBlueprint); // GATHER DEPENDENCIES PERSISTENT DATA struct FReplaceInnerData { TWeakObjectPtr<UClass> Class; FStringAssetReference BlueprintAsset; }; TArray<FReplaceInnerData> ReplaceInnerData; for (auto BPToUnloadWP : BlueprintDependencies) { auto BPToUnload = BPToUnloadWP.Get(); auto OldClass = BPToUnload ? *BPToUnload->GeneratedClass : NULL; if (OldClass) { FReplaceInnerData Data; Data.Class = OldClass; Data.BlueprintAsset = FStringAssetReference(BPToUnload); ReplaceInnerData.Add(Data); } } // store off data for the initial blueprint so we can unload it (and reconstruct // later to compare it with a second one) TArray<uint8> InitialLoadData; FObjectWriter(InitialBlueprint, InitialLoadData); // grab the name before we unload the blueprint FName const BlueprintName = InitialBlueprint->GetFName(); // unload the blueprint so we can reload it (to catch any differences, now // that all its dependencies should be loaded as well) //UNLOAD DEPENDENCIES, all circular dependencies will be loaded again // unload the blueprint so we can reload it (to catch any differences, now // that all its dependencies should be loaded as well) for (auto BPToUnloadWP : BlueprintDependencies) { if (auto BPToUnload = BPToUnloadWP.Get()) { FBlueprintAutomationTestUtilities::UnloadBlueprint(BPToUnload); } } // this blueprint is now dead (will be destroyed next garbage-collection pass) UBlueprint* UnloadedBlueprint = InitialBlueprint; InitialBlueprint = NULL; // load the blueprint a second time; if the two separately loaded blueprints // are different, then this one is most likely the choice one (it has all its // dependencies loaded) UBlueprint* ReloadedBlueprint = Cast<UBlueprint>(StaticLoadObject(UBlueprint::StaticClass(), NULL, *BlueprintAssetPath)); UPackage* TransientPackage = GetTransientPackage(); FName ReconstructedName = MakeUniqueObjectName(TransientPackage, UBlueprint::StaticClass(), BlueprintName); // reconstruct the initial blueprint (using the serialized data from its initial load) EObjectFlags const StandardBlueprintFlags = RF_Public | RF_Standalone | RF_Transactional; InitialBlueprint = ConstructObject<UBlueprint>(UBlueprint::StaticClass(), TransientPackage, ReconstructedName, StandardBlueprintFlags | RF_Transient); FObjectReader(InitialBlueprint, InitialLoadData); { TMap<UObject*, UObject*> ClassRedirects; for (auto& Data : ReplaceInnerData) { UClass* OriginalClass = Data.Class.Get(); UBlueprint* NewBlueprint = Cast<UBlueprint>(Data.BlueprintAsset.ResolveObject()); UClass* NewClass = NewBlueprint ? *NewBlueprint->GeneratedClass : NULL; if (OriginalClass && NewClass) { ClassRedirects.Add(OriginalClass, NewClass); } } // REPLACE OLD DATA FArchiveReplaceObjectRef<UObject>(InitialBlueprint, ClassRedirects, /*bNullPrivateRefs=*/false, /*bIgnoreOuterRef=*/true, /*bIgnoreArchetypeRef=*/false); for (auto SubobjWP : InitialBlueprintSubobjects) { if (auto Subobj = SubobjWP.Get()) { FArchiveReplaceObjectRef<UObject>(Subobj, ClassRedirects, /*bNullPrivateRefs=*/false, /*bIgnoreOuterRef=*/true, /*bIgnoreArchetypeRef=*/false); } } UPackage* AssetPackage = ReloadedBlueprint->GetOutermost(); bool bHasUnsavedChanges = AssetPackage->IsDirty(); FBlueprintEditorUtils::RefreshAllNodes(ReloadedBlueprint); AssetPackage->SetDirtyFlag(bHasUnsavedChanges); } // look for diffs between subsequent loads and log them as errors TArray<FDiffSingleResult> BlueprintDiffs; bool bDiffsFound = FBlueprintAutomationTestUtilities::DiffBlueprints(InitialBlueprint, ReloadedBlueprint, BlueprintDiffs); if (bDiffsFound) { FBlueprintAutomationTestUtilities::ResolveCircularDependencyDiffs(ReloadedBlueprint, BlueprintDiffs); // if there are still diffs after resolving any the could have been from unloaded circular dependencies if (BlueprintDiffs.Num() > 0) { AddError(FString::Printf(TEXT("Inconsistencies between subsequent blueprint loads for: '%s' (was a dependency not preloaded?)"), *BlueprintAssetPath)); } else { bDiffsFound = false; } // list all the differences (so as to help identify what dependency was missing) for (auto DiffIt(BlueprintDiffs.CreateIterator()); DiffIt; ++DiffIt) { // will be presented in the context of "what changed between the initial load and the second?" FString DiffDescription = DiffIt->ToolTip; if (DiffDescription != DiffIt->DisplayString) { DiffDescription = FString::Printf(TEXT("%s (%s)"), *DiffDescription, *DiffIt->DisplayString); } const UEdGraphNode* NodeFromPin = DiffIt->Pin1 ? Cast<const UEdGraphNode>(DiffIt->Pin1->GetOuter()) : NULL; const UEdGraphNode* Node = DiffIt->Node1 ? DiffIt->Node1 : NodeFromPin; const UEdGraph* Graph = Node ? Node->GetGraph() : NULL; const FString GraphName = Graph ? Graph->GetName() : FString(TEXT("Unknown Graph")); AddError(FString::Printf(TEXT("%s.%s differs between subsequent loads: %s"), *BlueprintName.ToString(), *GraphName, *DiffDescription)); } } // At the close of this function, the FScopedBlueprintUnloader should prep // for following tests by unloading any blueprint dependencies that were // loaded for this one (should catch InitialBlueprint and ReloadedBlueprint) // // The FScopedBlueprintUnloader should also run garbage-collection after, // in hopes that the imports for this blueprint get destroyed so that they // don't invalidate other tests that share the same dependencies return !bDiffsFound; }
UObject* USspjFactory::FactoryCreateBinary(UClass* InClass, UObject* InParent, FName InName, EObjectFlags Flags, UObject* Context, const TCHAR* Type, const uint8*& Buffer, const uint8* InBufferEnd, FFeedbackContext* Warn) { bool bReimport = this->IsA(UReimportSspjFactory::StaticClass()); TMap<FString, UTexture*>* ExistImages = NULL; if(bReimport) { ExistImages = &(Cast<UReimportSspjFactory>(this)->ExistImages); } FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools"); FString ProjectNameStr = InName.ToString(); FName ProjectName = InName; UPackage* InParentPackage = Cast<UPackage>(InParent); if(InParentPackage && !bReimport) { FString ProjectPackageName; FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / ProjectNameStr; AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), ProjectPackageName, ProjectNameStr); InParentPackage->Rename(*ProjectPackageName); } // インポート設定の取得 const USsImportSettings* ImportSettings = GetDefault<USsImportSettings>(); // インポート開始 FEditorDelegates::OnAssetPreImport.Broadcast(this, InClass, InParent, ProjectName, Type); // sspj USsProject* NewProject = FSsLoader::LoadSsProject(InParent, ProjectName, Flags, Buffer, (InBufferEnd - Buffer) + 1); NewProject->SetFilepath( GetCurrentFilename() ); if(NewProject) { if(NewProject->AssetImportData == nullptr) { NewProject->AssetImportData = NewObject<UAssetImportData>(NewProject); } NewProject->AssetImportData->Update(CurrentFilename); FString CurPath = FPaths::GetPath(GetCurrentFilename()); TArray<FString> ImagePaths; TArray<SsTexWrapMode::Type> ImageWrapModes; TArray<SsTexFilterMode::Type> ImageFilterModes; // ssce NewProject->CellmapList.Empty(); NewProject->CellmapList.AddZeroed(NewProject->CellmapNames.Num()); for(int i = 0; i < NewProject->CellmapNames.Num(); ++i) { FString FileName = GetFilePath(CurPath, NewProject->Settings.CellMapBaseDirectory, NewProject->CellmapNames[i].ToString()); TArray<uint8> Data; if(FFileHelper::LoadFileToArray(Data, *FileName)) { const uint8* BufferBegin = Data.GetData(); const uint8* BufferEnd = BufferBegin + Data.Num() - 1; if(FSsLoader::LoadSsCellMap(&(NewProject->CellmapList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1)) { NewProject->CellmapList[i].FileName = NewProject->CellmapNames[i]; if(0 < NewProject->CellmapList[i].ImagePath.Len()) { if(INDEX_NONE == ImagePaths.Find(NewProject->CellmapList[i].ImagePath)) { ImagePaths.Add(NewProject->CellmapList[i].ImagePath); if(NewProject->CellmapList[i].OverrideTexSettings) { ImageWrapModes.Add(NewProject->CellmapList[i].WrapMode); ImageFilterModes.Add(NewProject->CellmapList[i].FilterMode); } else { ImageWrapModes.Add(NewProject->Settings.WrapMode); ImageFilterModes.Add(NewProject->Settings.FilterMode); } } } } } } // ssae NewProject->AnimeList.Empty(); NewProject->AnimeList.AddZeroed(NewProject->AnimepackNames.Num()); for(int i = 0; i < NewProject->AnimepackNames.Num(); ++i) { FString FileName = GetFilePath(CurPath, NewProject->Settings.AnimeBaseDirectory, NewProject->AnimepackNames[i].ToString()); TArray<uint8> Data; if(FFileHelper::LoadFileToArray(Data, *FileName)) { const uint8* BufferBegin = Data.GetData(); const uint8* BufferEnd = BufferBegin + Data.Num() - 1; FSsLoader::LoadSsAnimePack(&(NewProject->AnimeList[i]), BufferBegin, (BufferEnd - BufferBegin) + 1); } } // texture for(int i = 0; i < ImagePaths.Num(); ++i) { FString FileName = GetFilePath(CurPath, NewProject->Settings.ImageBaseDirectory, ImagePaths[i]); UTexture* ImportedTexture = NULL; if(ExistImages && ExistImages->Contains(ImagePaths[i])) { ImportedTexture = ExistImages->FindChecked(ImagePaths[i]); } TArray<uint8> Data; if(FFileHelper::LoadFileToArray(Data, *FileName)) { UTextureFactory* TextureFact = NewObject<UTextureFactory>(); TextureFact->AddToRoot(); FString TextureName = FPaths::GetBaseFilename(ImagePaths[i]); UPackage* TexturePackage = NULL; if(ImportedTexture) { TexturePackage = ImportedTexture->GetOutermost(); } else { FString TexturePackageName; FString BasePackageName = FPackageName::GetLongPackagePath(InParent->GetOutermost()->GetName()) / TextureName; AssetToolsModule.Get().CreateUniqueAssetName(BasePackageName, TEXT(""), TexturePackageName, TextureName); TexturePackage = CreatePackage(NULL, *TexturePackageName); } const uint8* BufferBegin = Data.GetData(); const uint8* BufferEnd = BufferBegin + Data.Num(); UTexture2D* NewTexture = (UTexture2D*)TextureFact->FactoryCreateBinary( UTexture2D::StaticClass(), TexturePackage, FName(*TextureName), Flags, NULL, *FPaths::GetExtension(ImagePaths[i]), BufferBegin, BufferEnd, Warn ); if(NewTexture) { if(ImportSettings->bOverwriteMipGenSettings) { NewTexture->MipGenSettings = TMGS_NoMipmaps; } if(ImportSettings->bOverwriteTextureGroup) { NewTexture->LODGroup = ImportSettings->TextureGroup; } if(ImportSettings->bOverwriteCompressionSettings) { NewTexture->CompressionSettings = TextureCompressionSettings::TC_EditorIcon; } if(ImportSettings->bOverwriteTilingMethodFromSspj) { switch(ImageWrapModes[i]) { case SsTexWrapMode::Clamp: { NewTexture->AddressX = NewTexture->AddressY = TA_Clamp; } break; case SsTexWrapMode::Repeat: { NewTexture->AddressX = NewTexture->AddressY = TA_Wrap; } break; case SsTexWrapMode::Mirror: { NewTexture->AddressX = NewTexture->AddressY = TA_Mirror; } break; } } if(ImportSettings->bOverwriteNeverStream) { NewTexture->NeverStream = true; } if(ImportSettings->bOverwriteFilterFromSspj) { switch(ImageFilterModes[i]) { case SsTexFilterMode::Nearest: { NewTexture->Filter = TF_Nearest; } break; case SsTexFilterMode::Linear: { NewTexture->Filter = TF_Bilinear; } break; } } NewTexture->UpdateResource(); FAssetRegistryModule::AssetCreated(NewTexture); TexturePackage->SetDirtyFlag(true); TextureFact->RemoveFromRoot(); ImportedTexture = NewTexture; } } if(ImportedTexture) { for(int ii = 0; ii < NewProject->CellmapList.Num(); ++ii) { if(NewProject->CellmapList[ii].ImagePath == ImagePaths[i]) { NewProject->CellmapList[ii].Texture = ImportedTexture; } } } } } // インポート終了 FEditorDelegates::OnAssetPostImport.Broadcast(this, NewProject); return NewProject; }