diff --git a/Assets/SEE/Controls/Actions/ShowLabel.cs b/Assets/SEE/Controls/Actions/ShowLabel.cs
index 94e773a985..0aba08e383 100644
--- a/Assets/SEE/Controls/Actions/ShowLabel.cs
+++ b/Assets/SEE/Controls/Actions/ShowLabel.cs
@@ -181,9 +181,12 @@ private void On()
///
private void Off()
{
- LabelAttributes settings = GetLabelSettings(nodeOperator.Node, nodeOperator.City);
- nodeOperator.FadeLabel(0f, settings.AnimationFactor);
- DisplayedLabelOperators.Remove(nodeOperator);
+ if (nodeOperator.Node != null)
+ {
+ LabelAttributes settings = GetLabelSettings(nodeOperator.Node, nodeOperator.City);
+ nodeOperator.FadeLabel(0f, settings.AnimationFactor);
+ DisplayedLabelOperators.Remove(nodeOperator);
+ }
}
///
diff --git a/Assets/SEE/Game/HolisticMetrics/WidgetsManager.cs b/Assets/SEE/Game/HolisticMetrics/WidgetsManager.cs
index d5d5225751..e434f5f7eb 100644
--- a/Assets/SEE/Game/HolisticMetrics/WidgetsManager.cs
+++ b/Assets/SEE/Game/HolisticMetrics/WidgetsManager.cs
@@ -155,8 +155,8 @@ internal void Create(WidgetConfig widgetConfiguration)
{
ShowNotification.Error("Metric-board error",
"There was an error when displaying the metric on the newly created "
- + $"widget, this is the exception: {exception.Message}");
- throw exception;
+ + $"widget, this is the exception: {exception.Message}", log: false);
+ throw;
}
}
}
diff --git a/Assets/SEE/Game/LabelAttributes.cs b/Assets/SEE/Game/LabelAttributes.cs
index 39261f966f..f4c9f1ca8d 100644
--- a/Assets/SEE/Game/LabelAttributes.cs
+++ b/Assets/SEE/Game/LabelAttributes.cs
@@ -14,6 +14,16 @@ namespace SEE.Game
[HideReferenceObjectPicker]
public class LabelAttributes
{
+ ///
+ /// The default value for .
+ ///
+ public const float DEFAULT_FONT_SIZE = 0.4f;
+
+ ///
+ /// The default value for .
+ ///
+ public const float DEFAULT_DISTANCE = 0.2f;
+
///
/// If true, a label with the node's SourceName will be displayed above each node.
///
@@ -24,13 +34,13 @@ public class LabelAttributes
/// The distance between the top of the node and its label.
///
[Tooltip("The distance between the top of the node and its label.")]
- public float Distance = 0.2f;
+ public float Distance = DEFAULT_DISTANCE;
///
/// The font size of the node's label.
///
[Tooltip("The font size of the label.")]
- public float FontSize = 0.4f;
+ public float FontSize = DEFAULT_FONT_SIZE;
///
/// How fast the label should (dis)appear.
@@ -90,4 +100,4 @@ internal void Restore(Dictionary attributes, string label)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Assets/SEE/Game/Operator/LabelOperator.cs b/Assets/SEE/Game/Operator/LabelOperator.cs
index a3210735ca..fbffda5c79 100644
--- a/Assets/SEE/Game/Operator/LabelOperator.cs
+++ b/Assets/SEE/Game/Operator/LabelOperator.cs
@@ -60,7 +60,7 @@ private void PrepareLabel()
Color textColor = UnityEngine.Color.white;
Color lineColor = UnityEngine.Color.white;
- string shownText = Node.SourceName;
+ string shownText = Node?.SourceName ?? gameObject.name;
nodeLabel = transform.Find(labelPrefix + shownText)?.gameObject;
if (nodeLabel == null)
@@ -71,9 +71,10 @@ private void PrepareLabel()
// First we create the label.
// We define starting and ending positions for the animation.
Vector3 startLabelPosition = gameObject.GetTop();
+ float fontSize = Node != null ? City.NodeTypes[Node.Type].LabelSettings.FontSize : LabelAttributes.DEFAULT_FONT_SIZE;
nodeLabel = TextFactory.GetTextWithSize(shownText,
startLabelPosition,
- City.NodeTypes[Node.Type].LabelSettings.FontSize,
+ fontSize,
lift: true,
textColor: textColor);
nodeLabel.name = labelPrefix + shownText;
@@ -132,7 +133,7 @@ private Vector3 DesiredLabelTextPosition
if (labelAlpha.TargetValue > 0)
{
// Only put line and label up if the label should actually be shown.
- endLabelPosition.y += City.NodeTypes[Node.Type].LabelSettings.Distance;
+ endLabelPosition.y += Node != null ? City.NodeTypes[Node.Type].LabelSettings.Distance : LabelAttributes.DEFAULT_DISTANCE;
}
return endLabelPosition;
@@ -185,4 +186,4 @@ private Vector3 DesiredLabelEndLinePosition
nodeLabel.transform.DOMove(position, duration).Play()
};
}
-}
\ No newline at end of file
+}
diff --git a/Assets/SEE/Game/Operator/NodeOperator.cs b/Assets/SEE/Game/Operator/NodeOperator.cs
index 4d6f94f33f..27b4b991ba 100644
--- a/Assets/SEE/Game/Operator/NodeOperator.cs
+++ b/Assets/SEE/Game/Operator/NodeOperator.cs
@@ -78,6 +78,8 @@ public partial class NodeOperator : GraphElementOperator
///
/// The node to which this node operator belongs.
+ ///
+ /// Be aware that this may be null if the node operator is attached to an artificial node.
///
public Node Node
{
@@ -461,7 +463,8 @@ Tween[] BlinkAction(int count, float duration)
static Node GetNode(GameObject gameObject)
{
- if (!gameObject.TryGetComponent(out NodeRef nodeRef) || nodeRef.Value == null)
+ // We allow a null value for artificial nodes, but at least a NodeRef must be attached.
+ if (!gameObject.TryGetComponent(out NodeRef nodeRef))
{
throw new InvalidOperationException($"NodeOperator-operated object {gameObject.FullName()} must have {nameof(NodeRef)} attached!");
}
@@ -525,4 +528,4 @@ private void Update()
}
}
}
-}
\ No newline at end of file
+}