Repository URL to install this package:
Version:
1.0.0 ▾
|
using System;
using System.Collections.Generic;
using Fluctio.FluctioSim.Utils.General;
using UnityEngine;
using Object = UnityEngine.Object;
#if UNITY_EDITOR
using Fluctio.FluctioSim.EditorCore.EditorGeneral;
using UnityEditor;
#endif
namespace Fluctio.FluctioSim.Core.Components.Base
{
/// <summary>
/// Base class for editor components which have dependent components/objects.
/// Has ability to show/hide dependents and automatic enable/disable/destroy management.
/// </summary>
public abstract class InternalsEditorComponent : EditorComponent
{
[SerializeField] public bool showInternals;
#if UNITY_EDITOR
public override void InitializePrefab()
{
base.InitializePrefab();
showInternals = GeneralSettings.DefaultShowInternals;
}
public override void OnSelfChanged()
{
base.OnSelfChanged();
SetInternalComponentsVisible(showInternals);
SetInternalObjectsVisible(showInternals);
}
#endif
// Reset breaks saved references to created objects
[ContextMenu("Reset", true)]
private bool ResetValidate() => false;
[ContextMenu("Reset", false)]
private void ResetMenu() => throw new InvalidOperationException("Reset is not available on this component");
/**
* Should return objects which would be enabled/disabled together with the main component
* and shown/hidden depending on <see cref="showInternals"/> value
*/
protected virtual IEnumerable<GameObject> GetInternalObjects()
{
return Array.Empty<GameObject>();
}
/**
* Should return components which would be enabled/disabled together with the main component
* and shown/hidden depending on <see cref="showInternals"/> value
*/
protected virtual IEnumerable<MonoBehaviour> GetInternalComponents()
{
return Array.Empty<MonoBehaviour>();
}
/**
* Should return objects which were created inside <see cref="EditorComponent.InitializeOnce"/>
* and therefore should be deleted when user removes this component
*/
protected virtual IEnumerable<Object> GetCreatedInternals()
{
return Array.Empty<MonoBehaviour>();
}
#if UNITY_EDITOR
private void SetInternalComponentsVisible(bool isVisible)
{
var internalComponents = GetInternalComponents();
foreach (var internalComponent in internalComponents)
{
internalComponent.hideFlags = Flags.GetUpdatedFlags(internalComponent.hideFlags, HideFlags.HideInInspector, !isVisible);
// There is a bug where hideFlags are not applied immediately
// The following workarounds did not work:
// * EditorSceneManagement.MarkSceneDirty() (https://issuetracker.unity3d.com/issues/gameobjects-in-hierarchy-window-are-not-hidden-when-using-hideflags-dot-hideinhierarchy)
// * gameObject.SetActive(false); gameObject.SetActive(true); (https://forum.unity.com/threads/hideflags-hideinhierarchy-not-working-broken.428056/, https://forum.unity.com/threads/hideflags-still-broken.107975/)
// * internalComponent.enabled = false; internalComponent.enabled = true;
// * UnityEditorInternal.InternalEditorUtility.RepaintAllViews() and EditorApplication.RepaintHierarchyWindow() (https://forum.unity.com/threads/bug-g-gameobject-hideflags-hideflags-hideinhierarchy-does-nut-update-hierarchy.704078/)
// * EditorApplication.RepaintHierarchyWindow() and EditorApplication.DirtyHierarchyWindowSorting() (https://discussions.unity.com/t/hideflags-hideinhierarchy-not-updating-hierarchy-in-edit-mode/177089)
// * ActiveEditorTracker.sharedTracker.activeEditors to repaint all active editors (https://discussions.unity.com/t/how-to-repaint-from-a-property-drawer/77599/7)
// * InspectorWindow.RepaintAllInsepctors() via reflection
// Do you want to try one more time or is it time to file a bug report already?
EditorApplication.delayCall += () =>
{
if (internalComponent == null)
{
return;
}
internalComponent.hideFlags = Flags.GetUpdatedFlags(internalComponent.hideFlags, HideFlags.HideInInspector, !isVisible);
};
}
}
private void SetInternalObjectsVisible(bool isVisible)
{
var internalObjects = GetInternalObjects();
foreach (var internalObject in internalObjects)
{
internalObject.hideFlags = Flags.GetUpdatedFlags(internalObject.hideFlags, HideFlags.HideInHierarchy, !isVisible);
}
}
private void SetInternalComponentsEnabled(bool isEnabled)
{
var internalComponents = GetInternalComponents();
foreach (var internalComponent in internalComponents)
{
internalComponent.enabled = isEnabled;
}
}
private void SetInternalObjectsEnabled(bool isEnabled)
{
var internalObjects = GetInternalObjects();
foreach (var internalObject in internalObjects)
{
internalObject.SetActive(isEnabled);
}
}
protected virtual void OnEnable()
{
if (!ShouldExecute(allowInPlayMode: true))
{
return;
}
SetInternalComponentsEnabled(true);
SetInternalObjectsEnabled(true);
}
protected virtual void OnDisable()
{
if (!ShouldExecute(allowInPlayMode: true))
{
return;
}
SetInternalComponentsEnabled(false);
SetInternalObjectsEnabled(false);
}
protected virtual void OnDestroy()
{
var internalsToDestroy = GetCreatedInternals();
var isPlaying = Application.isPlaying;
EditorApplication.delayCall += () =>
{
if (Application.isPlaying != isPlaying)
{
// Skip destroys caused by play mode change
// Without this check everything would be deleted in wrong mode due to delayCall
return;
}
foreach (var internalToDestroy in internalsToDestroy)
{
if (internalToDestroy != null)
{
DestroyImmediate(internalToDestroy);
}
}
};
}
#endif
}
}