Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

not all members in PixelWizards.PackageUtil.PackageUtilModel are marked [System.Serializable] #1

Open
darbotron opened this issue Apr 9, 2022 · 1 comment

Comments

@darbotron
Copy link

darbotron commented Apr 9, 2022

First, thanks for making this in the first place - much appreciated :)

    /// <summary>
    /// Json serializable package manifest
    /// </summary>
    [System.Serializable]
    public class PackageUtilModel
    {
        public string name = "com.mycompany.mypackage";
        public string displayName;
        public string version = "0.1.0-preview.1";
        public string unity = "2018.4";
        public string description;
        public string category;
        public Author author = new Author();               // <- type not marked [System.Serializable]
        public List<string> keywords = new List<string>();                     
        public DependencyList dependencies = new DependencyList();  // <- type(s) not marked [System.Serializable]
    }

Since PackageUtilController essentially takes an instance of PackageUtilModel and uses it to create a package I thought - oh, I'll just store PackageUtilModel in a ScriptableObject and then I can add a button to the asset's inspector to use PackageUtilController to export the package.

However, because PackageDependency, DependencyList, and Author aren't marked [System.Serializable] they don't show up in the inspector for a PackageUtilModel property or get saved in the asset so this super easy extension was a non-starter.

I know this is all MIT licensed so I could just modify it locally and do what I want but I thought this tiny change might be generally helpful to other people using this package :)

I figured it was such a small change there wasn't any point making a pull request...

Again, thanks for sharing all of these packages - super super lovely of you :)

@darbotron
Copy link
Author

darbotron commented Apr 10, 2022

Incidentally here's a "V0.0.1" of the asset I mentioned above which you should feel free to adapt for the package.
(note: this needs the [System.Serializable] attribute added to the types called out too...)

The inspector UI in this is very "no frills", personally I would probably address this by using the Unity attributes like [Space],[Heading()] etc. in PackageUtilModel & included types rather than writing custom inspector code cos I'm lazy ;)

I wanted this for a few reasons but here are the main two:

  1. the existing editor re-inits all its fields every time you open the window, losing all the settings
  2. I'm making a multiplatform framework which is split across per-platform packages (TL;DR: something like com.unity.inputsystem) and I wanted to be able to configure all the sub-packages once and then just export them at the press of a button...
using System.IO;

using PixelWizards.PackageUtil;

using UnityEngine;

#if UNITY_EDITOR
	using UnityEditor;
#endif

[CreateAssetMenu( menuName = "Package Tools/Pckage Model", fileName = "PackageModelFileName.asset" )]
public class PackageModelAsset : ScriptableObject
{
	public string PackageSourceFolder					= "Assets/Package";
	public string DestinationPackageParentFolder		= "../Packages";
	public bool   OverwriteExistingDestinationOnExport	= true;

	public PackageUtilModel m_model = new PackageUtilModel();
}


#if UNITY_EDITOR

[CustomEditor( typeof(PackageModelAsset) )]
class PackageModelAssetInspector : Editor
{
	const string k_ChooseSourcePathPrompt = "Choose Package Source Path";
	const string k_ChooseDestPathPrompt   = "Choose Package Export Path (Parent Folder)";

	public override void OnInspectorGUI()
	{
		var packageModelAsset = serializedObject.targetObject as PackageModelAsset;

		serializedObject.Update();

		using( new GUILayout.VerticalScope( EditorStyles.helpBox ) )
		{
			EditorGUILayout.LabelField( "Package Definition Actions", EditorStyles.largeLabel );

			EditorGUILayout.Space();
			
			using( new EditorGUILayout.HorizontalScope() )
			{
				if( GUILayout.Button( k_ChooseSourcePathPrompt ) )
				{
					var absolutePath = GetAbsolutePathFromPathRelativeToProjectFolder( packageModelAsset.PackageSourceFolder );
					var newPath      = EditorUtility.OpenFolderPanel( k_ChooseSourcePathPrompt, Path.GetDirectoryName( absolutePath ), Path.GetFileName( packageModelAsset.m_model.name ) );

					if( ! string.IsNullOrEmpty( newPath ) )
					{
						var property        = serializedObject.FindProperty( nameof(PackageModelAsset.PackageSourceFolder) );
						var newPathRelative = GetPathRelativeToProjectFolder( newPath );
						property.stringValue = newPathRelative;
					}
				}

				if( GUILayout.Button( k_ChooseDestPathPrompt ) )
				{
					var absolutePath = GetAbsolutePathFromPathRelativeToProjectFolder( packageModelAsset.DestinationPackageParentFolder );
					var newPath      = EditorUtility.OpenFolderPanel( k_ChooseDestPathPrompt, Path.GetDirectoryName( absolutePath ), Path.GetFileName( absolutePath ) );

					if( ! string.IsNullOrEmpty( newPath ) )
					{
						var property        = serializedObject.FindProperty( nameof(PackageModelAsset.DestinationPackageParentFolder) );
						var newPathRelative = GetPathRelativeToProjectFolder( newPath );
						property.stringValue = newPathRelative;
					}
				}
			}

			EditorGUILayout.Space();

			if( GUILayout.Button( "Export Package" ) )
			{
				var packageSourceFolder       = GetAbsolutePathFromPathRelativeToProjectFolder( packageModelAsset.PackageSourceFolder );
				var packageOutputFolder       = Path.Combine( GetAbsolutePathFromPathRelativeToProjectFolder( packageModelAsset.DestinationPackageParentFolder ), packageModelAsset.m_model.name ).Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar );
				var packageOutputFolderParent = GetAbsolutePathFromPathRelativeToProjectFolder( packageModelAsset.DestinationPackageParentFolder ).Replace( Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar );

				if( packageModelAsset.OverwriteExistingDestinationOnExport && Directory.Exists( packageOutputFolder ) )
				{
					Directory.Delete( packageOutputFolder, true );
				}

				PackageUtilController.Init();
				PackageUtilController.Model                  = packageModelAsset.m_model;
				PackageUtilController.packageSourcePath      = packageSourceFolder;
				PackageUtilController.packageDestinationPath = packageOutputFolderParent;
				PackageUtilController.ExportPackage();

				Debug.Log( PackageUtilController.outputLog.ToString() );
			}
			
			EditorGUILayout.Space();
		}

		EditorGUILayout.Space();

		serializedObject.ApplyModifiedProperties();
		
		DrawDefaultInspector();
	}

	static string GetPathRelativeToProjectFolder( string absolutePath )
	{
		var uriProjectFolder = new System.Uri( GetProjectFolderPath() );
		var uriAbsolutePath  = new System.Uri( absolutePath );
		var relativeUri      = uriProjectFolder.MakeRelativeUri( uriAbsolutePath );
		var relativePath     = System.Uri.UnescapeDataString( relativeUri.ToString() );

		return relativePath;
	}

	private static string GetProjectFolderPath() => Path.GetDirectoryName( Application.dataPath ) + "/";

	static string GetAbsolutePathFromPathRelativeToProjectFolder( string pathRelativeToProjectFolder )
	{
		var projectFolder                = Path.GetDirectoryName( GetProjectFolderPath() );
		var combinedPathWrtProjectFolder = Path.Combine( projectFolder, pathRelativeToProjectFolder );
		var absolutePath                 = Path.GetFullPath( combinedPathWrtProjectFolder );
		return absolutePath;
	}
}

#endif

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant