How to add custom editor to AssetPostProcessor?

I have an AssetPostProcessor for .obj files

I would like to add some options in the inspector of such assets that my AssetPostProcessor can use.

How can this be achieved?

Im not sure that you can, extend it, there is a option if you have your own scriptable importer and then have ui for that but that different then just post processing the imported asset.

If I understand correctly, scriptable importer can’t be used for formats that unity supports already natively. I just want to give some per object settings to my PostProcessor - that must be possible somehow.

Okay I found a way to do it. It’s a bit hacky though since I need to use reflection to call an internal method of AssetImporterEditor in order to prevent some errors from happening. Also, it’s using an editor instead of an AssetImporterEditor, but it does seem to work. If someone has a better solution, please let me know:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEditor.AssetImporters;
using UnityEngine;

[CustomEditor(typeof(ModelImporter))]
[CanEditMultipleObjects]
public class CustomModelImporterEditor : Editor
{
  private AssetImporterEditor defaultEditor;

  private static readonly string TILE_COMPRESSION_ON = "tileCompressionOn";

  void OnEnable()
  {
    if(defaultEditor == null)
    {
      defaultEditor = (AssetImporterEditor)AssetImporterEditor.CreateEditor(targets,
          Type.GetType("UnityEditor.ModelImporterEditor, UnityEditor"));
      MethodInfo dynMethod = Type.GetType("UnityEditor.ModelImporterEditor, UnityEditor")
                             .GetMethod("InternalSetAssetImporterTargetEditor",
                                        BindingFlags.NonPublic | BindingFlags.Instance);
      dynMethod.Invoke(defaultEditor, new object[] { this });
    }
  }

  void OnDisable()
  {
    defaultEditor.OnDisable();
  }

  void OnDestroy()
  {
    defaultEditor.OnEnable();
    DestroyImmediate(defaultEditor);
  }

  public override void OnInspectorGUI()
  {
    defaultEditor.OnInspectorGUI();

    bool mixedValues = false;
    bool tileCompressionOn =
        Array.IndexOf(((ModelImporter)targets[0]).extraUserProperties, TILE_COMPRESSION_ON) > -1;
    for (int i = 1; i < targets.Length; i++)
    {
      if(tileCompressionOn !=
         (Array.IndexOf(((ModelImporter)targets[i]).extraUserProperties, TILE_COMPRESSION_ON) > -1))
      {
        mixedValues = true;
        tileCompressionOn = true;
        break;
      }
    }

    bool updateProperties = false;
    if(mixedValues)
    {
      EditorGUI.showMixedValue = mixedValues;
      updateProperties = EditorGUILayout.Toggle("Tile Compression", false);
      EditorGUI.showMixedValue = false;
    }
    else
    {
      tileCompressionOn = EditorGUILayout.Toggle("Tile Compression", tileCompressionOn);
      updateProperties = true;
    }
    if(updateProperties)
    {
      for (int i = 0; i < targets.Length; i++)
      {
        string[] extraUserProperties = ((ModelImporter)targets[i]).extraUserProperties;
        if(tileCompressionOn && Array.IndexOf(extraUserProperties, TILE_COMPRESSION_ON) == -1)
        {
          // Add TILE_COMPRESSION_ON
          List<string> props = new List<string>(extraUserProperties);
          props.Add(TILE_COMPRESSION_ON);
          ((ModelImporter)targets[i]).extraUserProperties = props.ToArray();
        }
        else if(!tileCompressionOn && Array.IndexOf(extraUserProperties, TILE_COMPRESSION_ON) > -1)
        {
          // Remove TILE_COMPRESSION_ON
          List<string> props = new List<string>(extraUserProperties);
          props.RemoveAll((string s) => { return s == TILE_COMPRESSION_ON; });
          ((ModelImporter)targets[i]).extraUserProperties = props.ToArray();
        }
      }
    }

    serializedObject.ApplyModifiedProperties();
  }
}
5 Likes

This seems to be the best solution so far (it doesn’t have the issues from https://discussions.unity.com/t/809220 )

However, I’m not sure why you enable the default editor in OnDestroy.

I get a perfectly fine behaviour without that hack, and with a simpler approach of just destroying the default editor in OnDisable:

private AssetImporterEditor defaultEditor;

public void OnEnable()
{
    defaultEditor = (AssetImporterEditor)CreateEditor(targets, Type.GetType("UnityEditor.ModelImporterEditor, UnityEditor"));
    defaultEditor.AsDynamic().InternalSetAssetImporterTargetEditor(this); // AsDynamic() = ReflectionMagic library
}

public void OnDisable()
{
    if (defaultEditor != null)
    {
        DestroyImmediate(defaultEditor);
        defaultEditor = null;
    }
}

I tried this out and it’s working well, except that the imported object preview window is not displayed. Is this consistent with your experience? Any advice you can provide?