commit 808aee880a34b035a4b225f8954283c1918d4d20 Author: subversion23 Date: Sun Dec 31 06:19:36 2023 +0100 init diff --git a/camera2D.gd b/camera2D.gd new file mode 100644 index 0000000..8eeef4a --- /dev/null +++ b/camera2D.gd @@ -0,0 +1,50 @@ +extends Camera2D + +var velocity = Vector2(0, 0) +var mouse_down_pos = Vector2.ZERO + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +func _process(delta): + var dir = Vector2(0,0) + + if Input.is_key_pressed(KEY_W): + dir.y -= 1 + if Input.is_key_pressed(KEY_S): + dir.y += 1 + if Input.is_key_pressed(KEY_A): + dir.x -= 1 + if Input.is_key_pressed(KEY_D): + dir.x += 1 + + position += dir * delta * 100 + + +func _input(event): + if event is InputEventMouseButton: + if event.button_index == 1: + if event.pressed: + mouse_down_pos = event.position + else: + var move = mouse_down_pos - event.position + position += move + + var zoomf = 0 + var nzoom = 0 + if event.button_index == 4: + zoomf += 0.1 + + if event.button_index == 5: + zoomf -= 0.1 + + nzoom = zoom + Vector2(zoomf, zoomf) + if nzoom.length() != 0 and zoomf != 0: + zoom = nzoom + + + + # print( event.button_index) diff --git a/camera_2d.tscn b/camera_2d.tscn new file mode 100644 index 0000000..e850ff5 --- /dev/null +++ b/camera_2d.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://bnsf7lnm8elui"] + +[ext_resource type="Script" path="res://camera2D.gd" id="1_exvdf"] + +[node name="Camera2D" type="Camera2D"] +position_smoothing_enabled = true +script = ExtResource("1_exvdf") diff --git a/main.tscn b/main.tscn new file mode 100644 index 0000000..97b8f8d --- /dev/null +++ b/main.tscn @@ -0,0 +1,10 @@ +[gd_scene load_steps=3 format=3 uid="uid://d2rgfedikyr2w"] + +[ext_resource type="PackedScene" uid="uid://ixy2rotcnjk2" path="res://plant.tscn" id="1_mv10f"] +[ext_resource type="PackedScene" path="res://camera_2d.tscn" id="2_pvpm2"] + +[node name="Main" type="Node2D"] + +[node name="Plant" parent="." instance=ExtResource("1_mv10f")] + +[node name="Camera2D" parent="." instance=ExtResource("2_pvpm2")] diff --git a/plant.tscn b/plant.tscn new file mode 100644 index 0000000..9cedceb --- /dev/null +++ b/plant.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://ixy2rotcnjk2"] + +[ext_resource type="Script" path="res://src/Plant.cs" id="1_3shty"] + +[node name="Plant" type="MeshInstance2D"] +script = ExtResource("1_3shty") diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..7431287 --- /dev/null +++ b/project.godot @@ -0,0 +1,20 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="PlantLife2D" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.2", "C#", "Forward Plus") +config/icon="res://icon.svg" + +[dotnet] + +project/assembly_name="PlantLife2D" diff --git a/src/BaseLifeComponent.cs b/src/BaseLifeComponent.cs new file mode 100644 index 0000000..fc13cc4 --- /dev/null +++ b/src/BaseLifeComponent.cs @@ -0,0 +1,93 @@ +namespace DrawingDemo; + +using Godot; + +public delegate void DiedEventHandler(); + +public class BaseLifeComponent +{ + public float Energy = 1000; + public float Age = 0; + public int MaxAge = 150; + public float Health = 100; + private float MaxHealth = 100; + public bool Alive = true; + public event DiedEventHandler OnDied; + + + public void Tick(float timeDelta) + { + Age += timeDelta; + ConsumeEnergy(0.1f); //Baseconsumption + + if (Age > MaxAge || Health <= 0) + { + Die(); + return; + } + + + } + + public void Born() + { + Alive = true; + } + public void AddEnergy(float amount) + { + if (Alive) + Energy += amount; + } + public void Heal(float amount) + { + if (Health + amount >= MaxHealth) + Health = MaxHealth; + else + Health += amount; + } + + + + public float ConsumeEnergy(float amount, float costFactor = 1) + { + if (!Alive) + return 0; + float cost = amount * costFactor; + float consume = amount; + + if (Energy > 5) + { + consume = Mathf.Clamp(consume, 0, Energy - 5); + Energy -= consume; + float energy = consume; + return energy; + } + else + return 0; + } + private void Die() + { + Alive = false; + Health = 0; + Energy = 0; + if (OnDied != null) OnDied(); + } + + public string Stats() + { + string stats = $"Health: {Health}\nEnergy:{Energy}\nAge: {Age}"; + return stats; + } + + public bool CanReproduce => (Age > 5 && Energy > 100 && Health > 50); + + public void Reproduce() + { + if (CanReproduce) + { + Energy -= 50; + + } + + } +} \ No newline at end of file diff --git a/src/Genetics.cs b/src/Genetics.cs new file mode 100644 index 0000000..3e81314 --- /dev/null +++ b/src/Genetics.cs @@ -0,0 +1,92 @@ +using Godot; +using Color = Godot.Color; + +namespace DrawingDemo; + +public static class ColorHelper +{ + public static Color ColorFrom6Bit(byte colorcode) + { + // 64 Colors - 2 bit for farbe A... mal schaun + // oder 256 farben / 4 = 64 Values + float bitsPerColor = 2; + float colorperBit = 4; + + byte value1 = (byte)((colorcode & 0b11000000) >> 6); + byte value2 = (byte)((colorcode & 0b00110000) >> 4); + byte value3 = (byte)((colorcode & 0b00001100) >> 2); + byte value4 = (byte)(colorcode & 0b00000011); + + return new Color(value1 / colorperBit, value2 / colorperBit, value3 / colorperBit, value4 / colorperBit); + } +} +public class Genetics +{ + public GenStorage DNA = new GenStorage(); + + public Color MainColor + { + get + { + var codon = DNA.GetCodon(GenMapper.MainColor); + + return ColorHelper.ColorFrom6Bit(codon); + } + } + +} + +public enum GenMapper +{ + // 1. byte - 1 codon - 1. phenotyp + + MainColor, + Color2, + Color3, + GrowSpeed, + + +} + +public struct GenStorage +{ + public byte[] Codons; + + public GenStorage() + { + Codons = new byte[4] {42,0,0,0}; + } + + + public void Randomize() + { + for (int i = 0; i <= Codons.Length-1; i++) + { + Codons[i] = (byte)(GD.Randi() % 255); + } + + } + + public byte[] GetMutatedGenome(float mutationRate) + { + var ri = GD.Randi() % 32; + byte[] mut = Codons; + + for (int i = 0; i < Codons.Length-1; i++) + { + //mut[i] += (byte)ri; + } + + return mut; + } + + public byte GetCodon(GenMapper codon) + { + return Codons[(int)codon]; + } + public byte GetCodon(int codon) + { + return Codons[codon]; + } + +} \ No newline at end of file diff --git a/src/Helper.cs b/src/Helper.cs new file mode 100644 index 0000000..f2b9bb3 --- /dev/null +++ b/src/Helper.cs @@ -0,0 +1,28 @@ + +using Godot; + +public static class Helper +{ + public static Color[] myColors = new[] + { + Colors.Red, Colors.Blue, Colors.Green, Colors.Yellow, Colors.Purple, Colors.Orange, Colors.Indigo, Colors.White + }; + + public static Color[] MakeColorArray(int vertexCount, int verticePerColor) + { + Color[] vertices = new Color[vertexCount]; + int ci = -1; + for (int i = 0; i < vertexCount; i++) + { + if (i % verticePerColor == 0) + { + ci++; + } + + vertices[i] = myColors[ci % myColors.Length]; + } + return vertices; + } + + +} \ No newline at end of file diff --git a/src/Plant.cs b/src/Plant.cs new file mode 100644 index 0000000..b1349d9 --- /dev/null +++ b/src/Plant.cs @@ -0,0 +1,300 @@ +using System; +using Godot; +using System.Collections.Generic; +using System.Linq; +public partial class Plant : MeshInstance2D +{ + public Dictionary Segments; + public Vector2 Origin; + private int _segmentIdCounter = 0; + public PlantSegmentNode RootNode; + public Rect2 ClientRectangle = new Rect2(Vector2.Zero, new Vector2(-80, 80)); + + public override void _Ready() + { + Start(); + + + + } + + public void Start() + { + Segments = new Dictionary(); + PlantSegmentNode root = new PlantSegmentNode(null, maxChildren:1); + root.Direction = Vector2.Up; + root.NodeType = SegmentNodeTypes.Trunk; + RootNode = root; + Segments.Add(_segmentIdCounter, root); + _segmentIdCounter++; + GrowDemo(4096); + + this.Mesh = CreateMesh(); + + } + + public Mesh CreateMesh() + { + ArrayMesh arrMesh = new ArrayMesh(); + var arrays = new Godot.Collections.Array(); + arrays.Resize((int)Mesh.ArrayType.Max); + + //Vector2[] vertices = CalculateVertices(); + Vector2[] vertices = CalculateLineVertices(); + Color[] colors = Helper.MakeColorArray(vertices.Length, 3); + + arrays[(int)Mesh.ArrayType.Vertex] = vertices; + arrays[(int)Mesh.ArrayType.Color] = colors; + + //arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays); + arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Lines, arrays); + return arrMesh; + } + + // Called every frame. 'delta' is the elapsed time since the previous frame. + public override void _Process(double delta) + { + } + public void GrowDemo(int nodes) + { + for (int i = 0; i < nodes -1; i++) + { + GrowNode(); + } + } + + + public void GrowNewNode(PlantNodeParams p) + { + //var randAngle = (float)GD.RandRange(-p.AllowedParentDiv/2, p.AllowedParentDiv/2); + var randAngleZeroDiv = (float)GD.RandRange(20, 45); + + float randF = (0.5f - GD.Randf()); + int randI = GD.RandRange(0, 10); + + int maxChildren = p.MaxChildren; + int maxDescentants = 4096; + var parent = GetFreeSlotSegment(false); + PlantSegmentNode seg; + Vector2 dir = parent.Direction; + + + var freeindex = parent.FreeNodeIndex(); + if (freeindex == -1) + throw new System.Exception("Now free index, trotz free slot"); + switch (freeindex) + { + case 0: // Center + dir = dir.Rotated(randF); + maxChildren = 2; + maxDescentants = 4096; + break; + case 1: // left + dir = dir.Rotated(-randAngleZeroDiv); + break; + case 2: + dir = dir.Rotated(+randAngleZeroDiv); + break; + // 3D... + + } + seg = new PlantSegmentNode(parent, p.MaxChildren); + if (parent.AddChild(seg, freeindex)) + { + Segments.Add(_segmentIdCounter, seg); + _segmentIdCounter++; + } + else + { + GD.PrintErr("Error bei Add"); + } + } + public void GrowNode() + { + // Config + float minAngleDiv =Mathf.DegToRad(23); + float maxAngleDiv = Mathf.DegToRad(48); + int maxChildren = 2; + int maxDescentants = 128; + float maxRootDeviationAngle = Mathf.DegToRad(180); + + // Params + var randAngle = (float)GD.RandRange(minAngleDiv, maxAngleDiv); + float randF = (0.5f - GD.Randf()); + int randI = GD.RandRange(0, 10); + // Get lowest free node + var parent = GetFreeSlotSegment(false); + PlantSegmentNode seg; + Vector2 dir = parent.Direction; + + var freeindex = parent.FreeNodeIndex(); + if (freeindex == -1) + throw new System.Exception("Now free index, trotz free slot"); + + switch (freeindex) + { + case 0: // Center + dir = dir.Rotated(randF); + maxChildren = 2; + maxDescentants = 4096; + break; + case 1: // left + dir = dir.Rotated(-randAngle); + break; + case 2: + dir = dir.Rotated(+randAngle); + break; + // 3D... + + } + if (randI < 6) + maxChildren = 1; + + if (RootNode.Direction.Dot(dir) < 0) // ..<0 = 180 grad maxRootDeviationAngle) + maxChildren = 0; // wenn überhang -> branach ende + + seg = new PlantSegmentNode(parent, maxChildren); + seg.Direction = dir; + + + if (freeindex == 0) // center node + { + seg.Size = parent.Size * 0.95f; + } + else + { + seg.Size = parent.Size * (0.88f + randF/10); + if (randI < 6) + maxChildren = 2; + + } + + // if (CheckShootCollided(seg)) + // { + // //GD.Print("Collision ", seg); + // // Add stump dummy - so slot is ignored + // seg.NodeType = SegmentNodeTypes.Stump; + // seg.MaxChildren = seg.ChildrenCount; + // seg.Size = Vector2.Zero;//seg.Size * 0.4f; + // } + + if (parent.AddChild(seg, freeindex)) + { + Segments.Add(_segmentIdCounter, seg); + _segmentIdCounter++; + } + else + { + GD.PrintErr("Error bei Add"); + } + } + + public Vector2[] CalculateLineVertices() + { + int vertexCount = 2 * Segments.Count; + Vector2[] vertices = new Vector2[vertexCount]; + + for (int i = 0; i < _segmentIdCounter; i++) + { + PlantSegmentNode segment = Segments[i]; + + Vector2 pos = segment.VecToRoot; + Vector2 par = segment.PositionRelativeParent; + Vector2 dir = segment.Direction; + Vector2 line = segment.Line; + Vector2 size = segment.Size; + + Vector2 start = pos; + Vector2 end = pos + line; + int j = i * 2; + vertices[j] = start; + vertices[j+1] = end; + + } + return vertices; + } + + public Vector2[] CalculateVertices() + { + Vector2[] vertices = new Vector2[6 * _segmentIdCounter]; + + for (int i = 0; i < Segments.Count; i++) + { + PlantSegmentNode segment = Segments[i]; + + Vector2 pos = segment.VecToRoot; + Vector2 par = segment.PositionRelativeParent; + Vector2 dir = segment.Direction; + Vector2 line = segment.Line; + Vector2 size = segment.Size; + float width = size.X; + + Vector2 a = pos; + //Vector2 b = new Vector2(a.X, a.Y + size.Y); + //Vector2 c = new Vector2(b.X + width, b.Y); + Vector2 b = a + line; + Vector2 c = new Vector2(b.X + width, b.Y); + Vector2 d = new Vector2(a.X + width, a.Y); + + int j = i * 6; + vertices[j] = a; + vertices[j+1] = b; + vertices[j+2] = c; + vertices[j+3] = a; + vertices[j+4] = c; + vertices[j+5] = d; + } + return vertices; + } + + public bool CheckCollision(PlantSegmentNode node) + { + + + return false; + + } + private PlantSegmentNode GetFreeSlotSegment(bool descending = false) + { + + Dictionary elements = Segments; + //List list = elements.OrderBy(x => x.Key).ToList(); + + if (descending) + elements = elements.OrderByDescending(x => x.Key).ToDictionary(x => x.Key, x => x.Value); + else + { + elements = elements.OrderBy(x => x.Key).ToDictionary(x => x.Key, x => x.Value); + + } + + foreach (var item in elements) + { + if (item.Value.HasFreeChildSlot) + return item.Value; + } + return null; + } + +} + +public struct PlantNodeParams +{ + // Angle to grow - calculated from 0°(front) localspace + public float AllowedParentDiv = Mathf.DegToRad(80); + public float AllowedRootDiv = Mathf.DegToRad(180); + //public float MinAngleParentDiv = 0; + //public float MaxAngleParentDiv = 1f; + //public float MaxRootDeviationAngle = 3.14f; + public int MaxChildren = 3; + public Vector2 Size = Vector2.One; + public Vector2 Direction = Vector2.Up; + public string ConfigName = "default"; + public SegmentNodeTypes NodeType = SegmentNodeTypes.Trunk; + + public PlantNodeParams() + { + + } + +} diff --git a/src/SegmentNodes.cs b/src/SegmentNodes.cs new file mode 100644 index 0000000..119acd7 --- /dev/null +++ b/src/SegmentNodes.cs @@ -0,0 +1,414 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Godot; + + +public enum SegmentNodeTypes +{ + Trunk, + Branch, + Leave, + Fruit, + Stump, // basically blocks growth +} + +public class PlantSegmentNode : LifeFormSegmentNode +{ + //public LifeformNodeConfiguration Settings; + public Vector2 Size; + public Vector2 PositionRelativeParent; + public Vector2 VecToRoot; + public Vector2 Direction; + + private SegmentNodeTypes _nodeType = SegmentNodeTypes.Branch; + + public SegmentNodeTypes NodeType + { + get { return _nodeType; } + set { + if (value == SegmentNodeTypes.Stump) + { + Size = Vector2.Zero; + MaxChildren = ChildrenCount; + Direction = ((PlantSegmentNode)Parent).Direction.Normalized(); + _nodeType = value; + } + + } + } + public float Rotation + { + get { return Mathf.RadToDeg(Direction.Angle()); } + } + + public PlantSegmentNode(PlantSegmentNode parent, int maxChildren = 2, int maxRecursiveChildren = 4096) : base(parent, maxChildren, maxRecursiveChildren) + { + if (parent != null) // is child + { + Direction = parent.Direction.Normalized(); + Size = parent.Size / parent.MaxChildren; + PositionRelativeParent = parent.PositionRelativeParent + parent.Line; + VecToRoot = parent.VecToRoot + parent.Line; + } + else // is root + { + // must be root + Direction = Vector2.Up; + VecToRoot = Vector2.Zero; + Size = new Vector2(5, 20); + PositionRelativeParent = Vector2.Zero; //new Vector2() + Line; + + } + } + + public void UpdateSelfToParent() + { + if (IsRoot) + return; + + var parent = (PlantSegmentNode)Parent; + PositionRelativeParent = parent.PositionRelativeParent + parent.Line; + } + + public Vector2 Line + { + get { return Direction.Normalized() * Size.Length(); } + } + + // public Vector2[] GetPoints() + // { + // //Polygon2D polygon = new Polygon2D(); + // float width = Size.X; + // float height = Size.Y; + // + // Vector2 leftbottom = new Vector2(0 - width/2, 0); + // Vector2 rightbottom = new Vector2(width / 2, 0); + // + // Vector2 lefttop = leftbottom + new Vector2(0, height); + // Vector2 righttop = rightbottom + new Vector2(0, height); + // + // var points = new Vector2[] + // { + // leftbottom, lefttop, righttop, rightbottom, leftbottom + // }; + // return points; + // //return polygon; + // } + public PlantSegmentNode Get_Child(int index) + { + if (Children[index] is PlantSegmentNode) + { + return (PlantSegmentNode)Children[index]; + } + + return null; + } + + /// + /// Calls recursive through all Children + /// + public override void UpdateChildren() + { + UpdateSelfToParent(); + if (HasChildren) + { + foreach (var child in Children) + { + child?.UpdateChildren(); + } + } + } + public List GetChildren() + { + List result = new List(); + + for (int i = 0; i < Children.Length; i++) + { + if (Children[i] != null) + result.Add((PlantSegmentNode)Children[i]); + } + return result; + } + + public bool AddChild(PlantSegmentNode child, SegmentDirections dir = SegmentDirections.center) + { + return base.AddChild(child, dir); + } +} + + +public enum SegmentDirections +{ + center, + left, + right, + forward, + back, +} + +// Neu: Fixe vorgabe der Childnodes - wildwuchs bringt nix. +// Für 2D node maximal 3 childnodes. mitte(rauf), links, rechts +// 3D max 5 - mitte(rauf), links, rechts, vorn, hinten, vll. mehr +// index 0 = immer: mitte(rauf) +// array wird max. init bei max_child kein adden mehr + + +public abstract class LifeFormSegmentNode +{ + public static int NodeCounter = 0; + public LifeFormSegmentNode Parent; + protected LifeFormSegmentNode[] Children; + public int Order = 1; // 1 = root, 2 - child of root, 3.... + public readonly bool IsRoot = false; + private int _maxChildren; + private int _maxRecursiveChildren; + private int _childCount = 0; + + public int Id; + // reduce macht im moment noch nix. Nodes bleiben.... + public int MaxChildren + { + get { return _maxChildren; } + set + { + if (value > 0) + { + _maxChildren = value; + } + else + { + value = 0; + } + } + } + + public LifeFormSegmentNode(LifeFormSegmentNode parent, int maxChildren = 3, int maxRecursiveChildren = 4096) + { + _maxChildren = maxChildren; + + if (parent == null) + { + IsRoot = true; + Order = 1; + _maxRecursiveChildren = maxRecursiveChildren; + GD.Print("Root Node erstellt"); + } + else + { + Parent = parent; + Order = parent.Order + 1; + // Count down the values through the child nodes + _maxRecursiveChildren = parent._maxRecursiveChildren - _maxChildren; + + if (_maxRecursiveChildren <= 0) + { + _maxRecursiveChildren = 0; + _maxChildren = 0; + } + else if (_maxRecursiveChildren < _maxChildren) + _maxChildren = maxRecursiveChildren; + } + + Children = new LifeFormSegmentNode[_maxChildren]; + + // Iterate ID + Id = LifeFormSegmentNode.NodeCounter; + LifeFormSegmentNode.NodeCounter++; + } + + public bool AddChild(LifeFormSegmentNode childNode, int index) + { + if (!HasFreeChildSlot || Children[index] != null || index > _maxChildren -1) + return false; + + if (childNode.Parent != this) + throw new Exception("Kukuk Error: Child is not of this node."); + + //childNode.Parent = this; + childNode.Order = this.Order + 1; + Children[index] = childNode; + _childCount++; + return true; + } + + public bool AddChild(LifeFormSegmentNode childNode, SegmentDirections dir) + { + return AddChild(childNode, (int)dir); + } + + + public LifeFormSegmentNode GetChild(SegmentDirections dir) + { + return GetChild((int)dir); + } + + public LifeFormSegmentNode GetChild(int index) + { + if (ChildrenCount < index || index > ChildrenCount) + return null; + + return Children[index]; + + if (index < _maxChildren - 1 && Children[index] != null) + return Children[index]; + else + { + return null; + } + } + public bool HasChildren + { + get { return ChildrenCount > 0; } + } + public int ChildrenCount + { + //get { return Children.Count(x => x != null); } + get { return _childCount; } + } + + public bool HasFreeChildSlot + { + get { return ChildrenCount < _maxChildren; } + } + + public int FreeNodeIndex() + { + // nur first ist immer rechtslastig -> rand? + + int i = 0; + if (!HasFreeChildSlot) + return -1; + + if (Children[0] == null) // center zuerst + return 0; + if (_maxChildren > 1) // 1 rechts oder 2 links + { + List nodes = new List(); + for (int j = 0; j < _maxChildren; j++) + { + if (Children[j] == null) + nodes.Add(j); + } + + int li = 0; + li = GD.RandRange(0, nodes.Count-1); + return nodes[li]; + } + return -1; + } + + public abstract void UpdateChildren(); +} + +// public abstract class LifeFormSegmentNode +// { +// +// public LifeFormSegmentNode Parent; +// protected LifeFormSegmentNode[] Children; +// public readonly int Order = 1; // 1 = root, 2 - child of root, 3.... +// public readonly bool IsRoot = false; +// private int _maxChildren; +// private int _maxRecursiveChildren; +// private int _lastChildIndex = 0; +// +// public bool HasChildren +// { +// get { return (_lastChildIndex > 0); } +// } +// +// public LifeFormSegmentNode(LifeFormSegmentNode parent, int maxChildren = 3, int maxRecursiveChildren = 4096) +// { +// _maxChildren = maxChildren; +// +// if (parent == null) +// { +// IsRoot = true; +// Order = 1; +// _maxRecursiveChildren = maxRecursiveChildren; +// GD.Print("Root Node erstellt"); +// } +// else +// { +// Parent = parent; +// Order = parent.Order + 1; +// // Count down the values through the child nodes +// _maxRecursiveChildren = parent._maxRecursiveChildren - _maxChildren; +// +// if (_maxRecursiveChildren <= 0) +// { +// _maxRecursiveChildren = 0; +// _maxChildren = 0; +// } +// else if (_maxRecursiveChildren < _maxChildren) +// _maxChildren = maxRecursiveChildren; +// } +// Children = new LifeFormSegmentNode[_maxChildren]; +// +// } +// +// public bool HasFreeChildSlot +// { +// get { return (_lastChildIndex <= _maxChildren - 1); } +// } +// public int ChildrenCount +// { +// get { return _lastChildIndex + 1; } +// } +// +// protected bool AddChild(LifeFormSegmentNode child) +// { +// if (HasFreeChildSlot) +// { +// if (child.Parent != this) +// throw new Exception("Kukuk Error: Child is not of this node."); +// if (Children[_lastChildIndex] == null) +// { +// Children[_lastChildIndex] = child; +// _lastChildIndex++; +// return true; +// } +// } +// return false; +// } +// +// public abstract void UpdateChildren(); +// +// +// } + +// public struct LifeformNodeConfiguration +// { +// public float MaxSegmentAngle; +// public int MaxChildren; +// public Vector2 Size; +// public Vector2 Direction; +// public string ConfigName = "empty"; +// +// public LifeformNodeConfiguration(string name, Vector2 direction, Vector2 size, int maxChildren = 3) +// { +// ConfigName = name; +// Direction = direction; +// Size = size; +// MaxChildren = maxChildren; +// MaxSegmentAngle = Mathf.DegToRad(45f); +// } + + + + // public static LifeformNodeConfiguration GetTree() + // { + // Vector2 size = new Vector2(10, 50); + // return new LifeformNodeConfiguration("tree", Vector2.Up, size); + // } + // public static LifeformNodeConfiguration GetDefault() + // { + // LifeformNodeConfiguration conf = new LifeformNodeConfiguration(); + // conf.MaxSegmentAngle = Mathf.DegToRad(45f); + // conf.MaxChildren = 3; + // conf.ConfigName = "default"; + // conf.Size = Vector2.One; + // conf.Direction = Vector2.Up; + // return conf; + // } +//}