Skip to content

Commit

Permalink
Added null checking code for missing process runtime (#286)
Browse files Browse the repository at this point in the history
* Added checking of not existing runtime configuration on 'ProcessSceneObjects' (runtime and editor time)
* Added missing description of the FillGroupListItem function
  • Loading branch information
poetter-sebastian authored Feb 10, 2025
1 parent e938e43 commit fda319a
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 40 deletions.
13 changes: 8 additions & 5 deletions Source/Core/Editor/UI/ProcessSceneObjectEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ public override VisualElement CreateInspectorGUI()
{
VisualElement root = new VisualElement();
manageGroupsPanel.CloneTree(root);
SetupGroupManagement(root);
if (RuntimeConfigurator.Exists)
{
SetupGroupManagement(root);
}
return root;
}

Expand Down Expand Up @@ -271,9 +274,10 @@ private void AddGroupElement(VisualElement container, SceneObjectGroups.SceneObj
ProcessSceneObject processSceneObject = (ProcessSceneObject)target;

bool isPreviewInContext = AssetUtility.IsInPreviewContext(((ProcessSceneObject)target).gameObject);
IEnumerable<ISceneObject> referencedSceneObjects = RuntimeConfigurator.Configuration.SceneObjectRegistry.GetObjects(group.Guid);
GroupListItem.FillGroupListItem(groupListElement, group.Label, isPreviewInContext: isPreviewInContext,
referencedSceneObjects: referencedSceneObjects, elementIsUniqueIdDisplayName: elementIsUniqueIdDisplayName);
IEnumerable<ISceneObject> referencedSceneObjects = RuntimeConfigurator.Configuration?.SceneObjectRegistry?.GetObjects(group.Guid);

GroupListItem.FillGroupListItem(groupListElement, group.Label, isPreviewInContext: isPreviewInContext,
referencedSceneObjects: referencedSceneObjects, elementIsUniqueIdDisplayName: elementIsUniqueIdDisplayName);

VisualElement removableGroupContainer = removableGroupListItem.Q<VisualElement>("RemovableGroupContainer");
removableGroupListItem.Q<Button>("Button").clicked += () => RemoveGroupElement(container, removableGroupListItem, group);
Expand All @@ -282,7 +286,6 @@ private void AddGroupElement(VisualElement container, SceneObjectGroups.SceneObj
container.Add(removableGroupListItem);
ValidateGroupListContainer(container);


EditorUtility.SetDirty(processSceneObject);
}

Expand Down
36 changes: 20 additions & 16 deletions Source/Core/Editor/UI/Views/GroupListItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ public class GroupListItem
public const string GroupCountNotAvailableText = "n/a";

/// <summary>
/// Fills a GroupListItem.xml View with the data from <seealso cref="SceneObjectGroups.SceneObjectGroup"> data.
/// Fills a GroupListItem.xml View with the data from <seealso cref="SceneObjectGroups.SceneObjectGroup"/> data.
/// </summary>
/// <param name="groupListItem">The VisualElement representing the group list item.</param>
/// <param name="name">The name of the Group or Gamobject containing Process Scene Object.</param>
/// <param name="isPreviewInContext">A flag indicating whether <see cref="GroupCountNotAvailableText"/> should be display instead of <see cref="groupCount"> .</param>
/// <param name="groupReferenceCount">The count of <seealso cref="ProcessSceneObject"/>s in the group. Default value is -1.</param>
/// <param name="elementIsUniqueIdDisplayName">A flag indicating whether the element represents a unique <see cref="ProcessSceneObject"/> and not a <seealso cref="SceneObjectGroups.SceneObjectGroup">. Default value is false.</param>
/// <param name="name">The name of the Group or GameObject containing Process Scene Object.</param>
/// <param name="isPreviewInContext">A flag indicating whether <see cref="GroupCountNotAvailableText"/> should be display instead of <see cref="groupCount"/> .</param>
/// <param name="referencedSceneObjects">Collection of scene objects to check group assignment</param>
/// <param name="elementIsUniqueIdDisplayName">A flag indicating whether the element represents a unique <see cref="ProcessSceneObject"/> and not a <seealso cref="SceneObjectGroups.SceneObjectGroup"/>. Default value is false.</param>
public static void FillGroupListItem(VisualElement groupListItem, string name, bool isPreviewInContext = false, IEnumerable<ISceneObject> referencedSceneObjects = null, bool elementIsUniqueIdDisplayName = false)
{
Label groupReferenceCountLabel = groupListItem.Q<Label>("RefCount");
Expand All @@ -41,21 +41,25 @@ public static void FillGroupListItem(VisualElement groupListItem, string name, b
}
else
{
int count = referencedSceneObjects.Count();
groupReferenceCountLabel.text = count.ToString();
if (count == 0)
//check if the enumerable is null
if (referencedSceneObjects != null)
{
groupListElement.tooltip = $"Group contains no objects.";
//fixed possible multiple enumeration
var sceneObjects = referencedSceneObjects as ISceneObject[] ?? referencedSceneObjects.ToArray();
int count = sceneObjects.Length;
groupReferenceCountLabel.text = count.ToString();
if (count == 0)
{
groupListElement.tooltip = "Group contains no objects.";
}
else
{
groupListElement.tooltip = $"Group is assigned to: {sceneObjects.Aggregate("", (acc, sceneObject) => acc + "\n- " + sceneObject.GameObject.name)}";
}
}
else
{
groupListElement.tooltip = $"Group is assigned to:";
groupListElement.tooltip += referencedSceneObjects.Aggregate("", (acc, sceneObject) => acc + "\n- " + sceneObject.GameObject.name);
}

if (isPreviewInContext)
{
groupListElement.tooltip += $"\nNote: Object count might be inaccurate if object is outside of scene context.";
groupListElement.tooltip += "\nNote: Object count might be inaccurate if object is outside of scene context.";
}
}
}
Expand Down
22 changes: 12 additions & 10 deletions Source/Core/Runtime/Configuration/RuntimeConfigurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,22 @@ public static BaseRuntimeConfiguration Configuration
{
get
{
if (Instance.runtimeConfiguration != null)
if (Instance?.runtimeConfiguration != null)
{
return Instance.runtimeConfiguration;
}

Type type = ReflectionUtils.GetTypeFromAssemblyQualifiedName(Instance.runtimeConfigurationName);
Type type = ReflectionUtils.GetTypeFromAssemblyQualifiedName(Instance?.runtimeConfigurationName);

if (type == null)
{
Debug.LogErrorFormat("IRuntimeConfiguration type '{0}' cannot be found. Using '{1}' instead.", Instance.runtimeConfigurationName, typeof(DefaultRuntimeConfiguration).AssemblyQualifiedName);
Debug.LogError($"IRuntimeConfiguration type '{Instance?.runtimeConfigurationName}' cannot be found. Using '{typeof(DefaultRuntimeConfiguration).AssemblyQualifiedName}' instead.");
type = typeof(DefaultRuntimeConfiguration);
}

Configuration = (BaseRuntimeConfiguration)ReflectionUtils.CreateInstanceOfType(type);

return Instance.runtimeConfiguration;
return Instance?.runtimeConfiguration;
}
set
{
Expand All @@ -158,22 +158,25 @@ public static BaseRuntimeConfiguration Configuration
return;
}

if (Instance.runtimeConfiguration == value)
if (Instance?.runtimeConfiguration == value)
{
return;
}

if (Instance.runtimeConfiguration != null)
if (Instance?.runtimeConfiguration != null)
{
Instance.runtimeConfiguration.Modes.ModeChanged -= RuntimeConfigurationModeChanged;
}

value.Modes.ModeChanged += RuntimeConfigurationModeChanged;

Instance.runtimeConfigurationName = value.GetType().AssemblyQualifiedName;
Instance.runtimeConfiguration = value;
if (Instance)
{
Instance.runtimeConfigurationName = value.GetType().AssemblyQualifiedName;
Instance.runtimeConfiguration = value;

EmitRuntimeConfigurationChanged();
EmitRuntimeConfigurationChanged();
}
}
}

Expand All @@ -189,7 +192,6 @@ public static RuntimeConfigurator Instance
{
throw new NullReferenceException("Process runtime configurator is not set in the scene. Create an empty game object with the 'RuntimeConfigurator' script attached to it.");
}

return instance;
}
}
Expand Down
43 changes: 34 additions & 9 deletions Source/Core/Runtime/SceneObjects/ProcessSceneObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ public ICollection<ISceneObjectProperty> Properties
/// Needs to be static to keep track of the state between different instances of ProcessSceneObject
/// </remarks>
private static bool hasDirtySceneObject = false;
/// <summary>
/// Tracks the warning log if the RuntimeConfigurator does not exist
/// </summary>
/// <remarks>
/// This can be removed if the CheckRefreshRegistry is not called in update function anymore
/// </remarks>
private bool loggedWarning = false;

public event EventHandler<LockStateChangedEventArgs> Locked;
public event EventHandler<LockStateChangedEventArgs> Unlocked;
Expand All @@ -123,7 +130,14 @@ private void Update()
{
#if UNITY_EDITOR
// TODO We need to move this to another update e.g. something in the RuntimeConfigurator
CheckRefreshRegistry();
if (CheckRefreshRegistry())
{
loggedWarning = false;
}
else if (!loggedWarning)
{
LogRuntimeConfigWarning();
}
#endif
}

Expand Down Expand Up @@ -279,7 +293,7 @@ protected void Init()
{
if (RuntimeConfigurator.Exists == false)
{
Debug.LogWarning($"Not registering {gameObject.name} due to runtime configurator not present.");
LogRuntimeConfigWarning();
return;
}

Expand Down Expand Up @@ -318,16 +332,21 @@ private bool IsInTheScene()
/// <summary>
/// Refreshes the scene object registry when we have <see cref="hasDirtySceneObject"/ and are in the main scene>
/// </summary>
private static void CheckRefreshRegistry()
private static bool CheckRefreshRegistry()
{
bool isMainStage = StageUtility.GetCurrentStageHandle() == StageUtility.GetMainStageHandle();

if (isMainStage && hasDirtySceneObject)
if (RuntimeConfigurator.Exists)
{
RuntimeConfigurator.Configuration.SceneObjectRegistry.Refresh();
hasDirtySceneObject = false;
//TODO if we have an open PSO in the Inspector we should redraw it
bool isMainStage = StageUtility.GetCurrentStageHandle() == StageUtility.GetMainStageHandle();

if (isMainStage && hasDirtySceneObject)
{
RuntimeConfigurator.Configuration?.SceneObjectRegistry?.Refresh();
hasDirtySceneObject = false;
//TODO if we have an open PSO in the Inspector we should redraw it
return true;
}
}
return false;
}

/// <summary>
Expand Down Expand Up @@ -508,5 +527,11 @@ public override string ToString()
{
return GameObject.name;
}

private void LogRuntimeConfigWarning()
{
Debug.LogWarning($"Not registering {gameObject.name} due to runtime configurator not present.");
loggedWarning = true;
}
}
}

0 comments on commit fda319a

Please # to comment.