Skip to content

Commit

Permalink
Rewrote AssetDatabase, New Asset Renaming & Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsakharov committed Mar 21, 2024
1 parent 9fdb5d9 commit 94d7670
Show file tree
Hide file tree
Showing 46 changed files with 1,417 additions and 1,309 deletions.
467 changes: 467 additions & 0 deletions Prowl.Editor/Assets/AssetDatabase.Core.cs

Large diffs are not rendered by default.

108 changes: 108 additions & 0 deletions Prowl.Editor/Assets/AssetDatabase.FileOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
namespace Prowl.Editor.Assets
{
public static partial class AssetDatabase
{

#region Public Methods

/// <summary>
/// Moves a file to a new location.
/// </summary>
/// <param name="source">The source file.</param>
/// <param name="destination">The destination file.</param>
/// <returns>True if the file was moved successfully, false otherwise.</returns>
public static bool Move(FileInfo source, FileInfo destination)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(destination);
if (!File.Exists(source.FullName)) return false;
if (File.Exists(destination.FullName)) return false; // Destination already exists

if (source.FullName.Equals(destination.FullName, StringComparison.OrdinalIgnoreCase)) return false;

if (source.Extension.Equals(".meta", StringComparison.OrdinalIgnoreCase)) return false;

// Move Asset file & meta file if it exists
source.MoveTo(destination.FullName, true);
var metaFile = new FileInfo(source.FullName + ".meta");
if (File.Exists(metaFile.FullName))
metaFile.MoveTo(destination.FullName + ".meta", true);
return true;
}

/// <summary>
/// Copies a file to a new location.
/// </summary>
/// <param name="source">The source file.</param>
/// <param name="destination">The destination file.</param>
/// <returns>True if the file was copied successfully, false otherwise.</returns>
public static bool Copy(FileInfo source, FileInfo destination)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(destination);
if (!File.Exists(source.FullName)) return false;
if (File.Exists(destination.FullName)) return false; // Destination already exists

if (source.FullName.Equals(destination.FullName, StringComparison.OrdinalIgnoreCase)) return false;

if (source.Extension.Equals(".meta", StringComparison.OrdinalIgnoreCase)) return false;

// Copy Asset file, don't copy meta file as that would create a duplicate asset, instead let refresh handle it
source.CopyTo(destination.FullName, true);
return true;
}

/// <summary>
/// Renames a file.
/// </summary>
/// <param name="file">The file to rename.</param>
/// <param name="newName">The new name of the file.</param>
/// <returns>True if the file was renamed successfully, false otherwise.</returns>
public static bool Rename(FileInfo file, string newName)
{
ArgumentNullException.ThrowIfNull(file);
ArgumentNullException.ThrowIfNullOrEmpty(newName);
if (!File.Exists(file.FullName)) return false;

if (file.Extension.Equals(".meta", StringComparison.OrdinalIgnoreCase)) return false;

var newFile = new FileInfo(Path.Combine(file.DirectoryName!, newName + file.Extension));
if (File.Exists(newFile.FullName)) return false; // Destination already exists

// Rename Asset file & meta file if it exists
file.MoveTo(newFile.FullName, true);
var metaFile = new FileInfo(file.FullName + ".meta");
if (File.Exists(metaFile.FullName))
{
var newMetaFile = new FileInfo(newFile.FullName + ".meta");
metaFile.MoveTo(newMetaFile.FullName, true);
}
return true;
}

/// <summary>
/// Deletes a file.
/// </summary>
/// <param name="file">The file to delete.</param>
/// <returns>True if the file was deleted successfully, false otherwise.</returns>
public static bool Delete(FileInfo file)
{
ArgumentNullException.ThrowIfNull(file);

if (file.Extension.Equals(".meta", StringComparison.OrdinalIgnoreCase)) return false;

// Just deleting the files should be enough for the AssetDatabase to pick it up
if(File.Exists(file.FullName))
file.Delete();
var metaFile = new FileInfo(file.FullName + ".meta");
if (File.Exists(metaFile.FullName))
metaFile.Delete();

return true;
}

#endregion

}

}
145 changes: 145 additions & 0 deletions Prowl.Editor/Assets/AssetDatabase.Packages.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
using Prowl.Runtime;
using Prowl.Runtime.Utils;
using System.IO.Compression;

namespace Prowl.Editor.Assets
{
public static partial class AssetDatabase
{

#region Public Methods

/// <summary>
/// Exports all assets to build packages at the specified destination directory.
/// </summary>
/// <param name="destination">The destination directory.</param>
public static void ExportAllBuildPackages(DirectoryInfo destination)
{
if (!destination.Exists)
{
Debug.LogError("Cannot export package, Folder does not exist.");
return;
}

// Get all assets
var assets = assetGuidToMeta.Keys.ToArray();
ExportBuildPackages(assets, destination);
}

/// <summary>
/// Exports build packages for the specified assets to the destination directory.
/// </summary>
/// <param name="assetsToExport">The assets to export.</param>
/// <param name="destination">The destination directory.</param>
public static void ExportBuildPackages(Guid[] assetsToExport, DirectoryInfo destination)
{
if (!destination.Exists)
{
Debug.LogError("Cannot export package, Folder does not exist.");
return;
}

int packageIndex = 0;
Debug.Log($"Creating First Package {packageIndex}");
FileInfo firstPackage = new(Path.Combine(destination.FullName, $"Data{packageIndex++}.prowl"));

// Create the package
var package = AssetBuildPackage.CreateNew(firstPackage);
int count = 0;
int maxCount = assetsToExport.Length;
foreach (var assetGuid in assetsToExport)
{
var asset = LoadAsset(assetGuid);
if (asset == null)
{
Debug.LogError($"Failed to load asset {assetGuid}!");
continue;
}

#warning TODO: We need to do (package.SizeInGB + SizeOfAsset > 4f) instead of just SizeInGB but for now this works
if (package.SizeInGB > 3f)
{
Debug.Log($"Packing, Reached 4GB...");
package.Dispose();
Debug.Log($"Creating New Package {packageIndex}");
FileInfo next = new(Path.Combine(destination.FullName, $"Data{packageIndex++}.prowl"));
package = AssetBuildPackage.CreateNew(next);
}

if (TryGetFile(assetGuid, out var assetPath))
{
package.AddAsset(ToRelativePath(assetPath), assetGuid, asset);
}

count++;
if (count % 10 == 0 || count >= maxCount - 5)
{
float percentComplete = ((float)count / (float)maxCount) * 100f;
Debug.Log($"Exporting Assets To Stream: {count}/{maxCount} - {percentComplete}%");
}
}
Debug.Log($"Packing...");
package.Dispose();
}

/// <summary>
/// Exports a package from the specified directory.
/// </summary>
/// <param name="directory">The directory to export the package from.</param>
/// <param name="includeDependencies">Whether to include dependencies in the package.</param>
public static void ExportPackage(DirectoryInfo directory, bool includeDependencies = false)
{
#warning TODO: Handle Dependencies
if (includeDependencies) throw new NotImplementedException("Dependency tracking is not implemented yet.");

ImFileDialogInfo imFileDialogInfo = new() {
title = "Export Package",
directoryPath = new DirectoryInfo(Project.ProjectDirectory),
fileName = "New Package.prowlpackage",
type = ImGuiFileDialogType.SaveFile,
OnComplete = (path) => {
var file = new FileInfo(path);
if (File.Exists(file.FullName))
{
Debug.LogError("Cannot export package, File already exists.");
return;
}

// If no extension (or wrong extension) add .scene
if (!file.Extension.Equals(".prowlpackage", StringComparison.OrdinalIgnoreCase))
file = new FileInfo(file.FullName + ".prowlpackage");

// Create the package
// Shh, but packages are just zip files ;)
using Stream destination = file.OpenWrite();
ZipFile.CreateFromDirectory(directory.FullName, destination);
}
};
}

/// <summary>
/// Imports a package from the specified file.
/// </summary>
/// <param name="packageFile">The package file to import.</param>
public static void ImportPackage(FileInfo packageFile)
{
if (!File.Exists(packageFile.FullName))
{
Debug.LogError("Cannot import package, File does not exist.");
return;
}

// Extract the package
using Stream source = packageFile.OpenRead();
ZipFile.ExtractToDirectory(packageFile.FullName, Project.ProjectPackagesDirectory);

#warning TODO: Handle if we already have the asset in our asset database (just dont import it)

Update();
}

#endregion

}

}
Loading

0 comments on commit 94d7670

Please sign in to comment.