Skip to content
New issue

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

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

Already on GitHub? # to your account

Added null checking code for missing process runtime #286

Merged
merged 3 commits into from
Feb 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -273,9 +276,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 @@ -284,7 +288,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 @@ -281,7 +295,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 @@ -320,16 +334,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 @@ -510,5 +529,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;
}
}
}