diff --git a/simulation_parameters/Constants.cs b/simulation_parameters/Constants.cs index bf2fc8b9204..74bd6b9d919 100644 --- a/simulation_parameters/Constants.cs +++ b/simulation_parameters/Constants.cs @@ -654,6 +654,11 @@ public static class Constants /// public const string SPECIES_NAME_REGEX = "^(?[^ ]+) (?[^ ]+)$"; + /// + /// Minimum hex distance before the same render priority. + /// + public const int HEX_RENDER_PRIORITY_DISTANCE = 4; + /// /// The duration for which a save is considered recently performed. /// diff --git a/src/engine/NodeHelpers.cs b/src/engine/NodeHelpers.cs index 445875e662c..71eaa1d21c3 100644 --- a/src/engine/NodeHelpers.cs +++ b/src/engine/NodeHelpers.cs @@ -115,4 +115,27 @@ public static void ReParent(this Node node, Node newParent) node.GetParent().RemoveChild(node); newParent.AddChild(node); } + + /// + /// Get the material of this scene's model. + /// + /// Node to get material from. + /// Path to model within the scene. If null takes scene root as model. + /// ShaderMaterial of the GeometryInstance. + public static ShaderMaterial GetMaterial(this Node node, NodePath modelPath = null) + { + GeometryInstance geometry; + + // Fetch the actual model from the scene + if (string.IsNullOrEmpty(modelPath)) + { + geometry = (GeometryInstance)node; + } + else + { + geometry = node.GetNode(modelPath); + } + + return (ShaderMaterial)geometry.MaterialOverride; + } } diff --git a/src/general/Hex.cs b/src/general/Hex.cs index ee858005621..6ff13b72735 100644 --- a/src/general/Hex.cs +++ b/src/general/Hex.cs @@ -231,12 +231,15 @@ public static Hex FlipHorizontally(Hex hex) return new Hex(-hex.Q, hex.Q + hex.R); } - public override bool Equals(object obj) + /// + /// Returns the RenderPriority for the hex. + /// Between 1 and HEX_RENDER_PRIORITY_DISTANCE^2. + /// + /// RenderPriority + public static int GetRenderPriority(Hex hex) { - if (!(obj is Hex hex)) - return false; - - return Equals(hex); + return hex.Q.PositiveModulo(Constants.HEX_RENDER_PRIORITY_DISTANCE) * Constants.HEX_RENDER_PRIORITY_DISTANCE + + hex.R.PositiveModulo(Constants.HEX_RENDER_PRIORITY_DISTANCE) + 1; } public bool Equals(Hex other) @@ -244,6 +247,14 @@ public bool Equals(Hex other) return Q == other.Q && R == other.R; } + public override bool Equals(object obj) + { + if (!(obj is Hex hex)) + return false; + + return Equals(hex); + } + public override int GetHashCode() { var hashCode = -1997189103; diff --git a/src/general/MathUtils.cs b/src/general/MathUtils.cs index 612548d1e1a..03ff71683e3 100644 --- a/src/general/MathUtils.cs +++ b/src/general/MathUtils.cs @@ -74,4 +74,15 @@ public static float Lerp(float from, float to, float weight, float tolerance = M return Mathf.Lerp(from, to, weight); } + + /// + /// Standard modulo for negative values in C# produces negative results. + /// This function returns modulo values between 0 and mod-1. + /// + /// The positive modulo + public static int PositiveModulo(this int val, int mod) + { + int result = val % mod; + return (result < 0) ? result + mod : result; + } } diff --git a/src/general/SceneDisplayer.cs b/src/general/SceneDisplayer.cs index 3bbaf4f59a5..8edb64c6fc3 100644 --- a/src/general/SceneDisplayer.cs +++ b/src/general/SceneDisplayer.cs @@ -21,6 +21,16 @@ public string Scene } } + /// + /// Get the material of this scene's model. + /// + /// Path to model within the scene. If null takes scene root as model. + /// ShaderMaterial of the GeometryInstance. Null if no scene. + public ShaderMaterial GetMaterial(NodePath modelPath = null) + { + return currentlyShown?.GetMaterial(modelPath); + } + private void LoadNewScene() { if (currentlyShown != null) diff --git a/src/microbe_stage/Membrane.tscn b/src/microbe_stage/Membrane.tscn index d161c7de9bb..d8e0c0abebf 100644 --- a/src/microbe_stage/Membrane.tscn +++ b/src/microbe_stage/Membrane.tscn @@ -10,7 +10,7 @@ size = Vector3( 2, 0.539, 2 ) [sub_resource type="ShaderMaterial" id=2] resource_local_to_scene = true -render_priority = 1 +render_priority = 18 shader = ExtResource( 2 ) shader_param/wigglyNess = 1.0 shader_param/movementWigglyNess = 1.0 diff --git a/src/microbe_stage/Microbe.tscn b/src/microbe_stage/Microbe.tscn index b1a78e68c54..d83d712e363 100644 --- a/src/microbe_stage/Microbe.tscn +++ b/src/microbe_stage/Microbe.tscn @@ -10,7 +10,7 @@ [sub_resource type="ShaderMaterial" id=1] resource_local_to_scene = true -render_priority = 1 +render_priority = 18 shader = ExtResource( 4 ) shader_param/wigglyNess = 1.0 shader_param/movementWigglyNess = 1.0 diff --git a/src/microbe_stage/PlacedOrganelle.cs b/src/microbe_stage/PlacedOrganelle.cs index c55eae95230..f2256c83020 100644 --- a/src/microbe_stage/PlacedOrganelle.cs +++ b/src/microbe_stage/PlacedOrganelle.cs @@ -574,26 +574,15 @@ private void SetupOrganelleGraphics() { var organelleSceneInstance = (Spatial)Definition.LoadedScene.Instance(); - // Store the material of the organelle to be updated - GeometryInstance geometry; - - // Fetch the actual model from the scene to get at the material we set the tint on - if (string.IsNullOrEmpty(Definition.DisplaySceneModelPath)) - { - geometry = (GeometryInstance)organelleSceneInstance; - } - else - { - geometry = organelleSceneInstance.GetNode(Definition.DisplaySceneModelPath); - } - // Store animation player for later use if (!string.IsNullOrEmpty(Definition.DisplaySceneAnimation)) { OrganelleAnimation = organelleSceneInstance.GetNode(Definition.DisplaySceneAnimation); } - organelleMaterial = (ShaderMaterial)geometry.MaterialOverride; + // Store the material of the organelle to be updated + organelleMaterial = organelleSceneInstance.GetMaterial(Definition.DisplaySceneModelPath); + organelleMaterial.RenderPriority = Hex.GetRenderPriority(Position); // There is an intermediate node so that the organelle scene root rotation and scale work OrganelleGraphics = new Spatial(); @@ -607,6 +596,7 @@ private void SetupOrganelleGraphics() // Position the intermediate node relative to origin of cell var transform = new Transform(Quat.Identity, Hex.AxialToCartesian(Position) + Definition.CalculateModelOffset()); + OrganelleGraphics.Transform = transform; // For some reason MathUtils.CreateRotationForOrganelle(Orientation) in the above transform doesn't work diff --git a/src/microbe_stage/editor/MicrobeEditor.cs b/src/microbe_stage/editor/MicrobeEditor.cs index 119ee9b97f2..1b51a7f63e6 100644 --- a/src/microbe_stage/editor/MicrobeEditor.cs +++ b/src/microbe_stage/editor/MicrobeEditor.cs @@ -1734,7 +1734,8 @@ private void RenderHighlightedOrganelle(int q, int r, int rotation, OrganelleDef organelleModel.Visible = true; - UpdateOrganellePlaceHolderScene(organelleModel, shownOrganelle.DisplayScene); + UpdateOrganellePlaceHolderScene(organelleModel, shownOrganelle.DisplayScene, + shownOrganelle, Hex.GetRenderPriority(new Hex(q, r))); } } @@ -2283,7 +2284,7 @@ private void UpdateAlreadyPlacedVisuals() organelleModel.Visible = !MicrobePreviewMode; UpdateOrganellePlaceHolderScene(organelleModel, - organelle.Definition.DisplayScene); + organelle.Definition.DisplayScene, organelle.Definition, Hex.GetRenderPriority(organelle.Position)); } } @@ -2304,9 +2305,15 @@ private void UpdateAlreadyPlacedVisuals() /// /// Updates the organelle model displayer to have the specified scene in it /// - private void UpdateOrganellePlaceHolderScene(SceneDisplayer organelleModel, string displayScene) + private void UpdateOrganellePlaceHolderScene(SceneDisplayer organelleModel, + string displayScene, OrganelleDefinition definition, int renderPriority) { organelleModel.Scene = displayScene; + var material = organelleModel.GetMaterial(definition.DisplaySceneModelPath); + if (material != null) + { + material.RenderPriority = renderPriority; + } } [DeserializedCallbackAllowed]