Search Unity

Help with creating a realtime animated texture preview in a custom inspector

Discussion in 'Scripting' started by nullstar, Dec 14, 2012.

  1. nullstar

    nullstar

    Joined:
    Jul 2, 2010
    Posts:
    186
    I've created a custom inspector for a custom animated texture asset and what I'd really like is for the editor to show me a preview of the texture updating in realtime within the editor inspector panel. I'm struggling to find a way to do this however.

    Currently I'm updating the texture preview from within 'OnInspectorGUI()' using 'Time.realtimeSinceStartup' to update the texture at the correct rate and then I'm previewing it using 'EditorGUI.DrawPreviewTexture(...)'. The problem here is that OnInspectorGUI is only called when the user clicks on the inspector panel somewhere so that's no good for a realtime preview. I've also tried using the 'OnPreviewGUI' function and related functions but again these are only called when the user interacts with the inspector panel. Finally I worked out I can get a realtime update callback to my editor script by adding my own delegate into 'EditorApplication.update' but I cant use 'EditorGUI.DrawPreviewTexture(...)' from here so that's no good either.

    Does anyone have a solution for this issue?
     
    Last edited: Dec 14, 2012
  2. awesomedata

    awesomedata

    Joined:
    Oct 8, 2014
    Posts:
    1,419
    Yeah... nobody. :(
     
  3. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    OnInteractivePreviewGUI will work (OnPreviewGUI should too). I'm currently using the AnimationClip's built-in Editor and using its OnInteractivePreviewGUI (and its HasPreviewGUI and OnPreviewSettings) so that I can show animation previews (which you would see in the FBX importer) inside my StateMachineBehaviour in Mecanim's Animator panel

    it works exactly as it does in the FBX importer and animates a rendertexture even when the mouse is not over the inspector.

    the way I believe the AnimationClipEditor pulls this off is that OnInteractivePreview it checks if the current event is a repaint event and if so (and if the clip is playing) it sends an update command to the avatar thats running the clip. with the Avatar's state changing (a serialized field gets modified) unity detects that the object is dirty, as in its serialized state has changed. I didn't look into it but I think unity only checks for dirty UnityObjects tied to any open inspector tab in view. suffice to say all this really means is that via previewGUI if you make sure that the asset is set dirty during a repaint event then the inspector should redraw automatically. via

    Code (CSharp):
    1.  
    2. if(Event.current.type == EventType.Repaint)
    3. {
    4.     EditorUtility.SetDirty(renderTextureAsset);
    5. }
    6.  
    if you're more curious on how unity did it for the fbx importer you can look into the UnityDecompiled github. its quite a rabbit hole if you want to see the full C# implementation (you also pay visit to AvatarPreview and other classes it references as well).
     
  4. unityplanetarium

    unityplanetarium

    Joined:
    Apr 15, 2020
    Posts:
    16
    Was anyone able to come up with a solution for this? @JoshuaMcKenzie your solution didnt work for me - for my situation I have applied an animated shader/material to a sphere and saved as a prefab.
    I have then loaded this prefab into the preview editor and have set this to dirty as suggested above but I have the exact same issue as nullstar in his original post.

    I have a feeling this may be due to the gameobject loaded while set to dirty no settings have been changed - the change is applied to the texture (procedural) and to the shader so the sphere it is applied has no settings changed.

    Here is the code I am using

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEditor;
    4. public class TextureGen : EditorWindow
    5. {
    6.     GameObject texturePreview;
    7.     Editor goPreviewer;
    8.     GUIStyle bgColour;
    9.     void OnEnable()
    10.     {
    11.         bgColour = new GUIStyle();
    12.         bgColour.normal.background = EditorGUIUtility.whiteTexture;
    13.         texturePreview = (GameObject)AssetDatabase.LoadAssetAtPath("Assets/preview.prefab", typeof(GameObject));
    14.     }
    15.     void OnGUI()
    16.     {
    17.         if (texturePreview != null)
    18.         {
    19.             if (goPreviewer == null)
    20.             {
    21.                 goPreviewer = Editor.CreateEditor(texturePreview);
    22.             }
    23.         }
    24.         goPreviewer.OnInteractivePreviewGUI(GUILayoutUtility.GetRect(350, 350), bgColour);
    25.     }
    26. }
    27.  
    This loads the object and its texture just fine but will not update any changes or play the shader animation until the user clicks the interactive preview window and moves the object around.