using System; using UnityEngine; namespace Mtree { [Serializable] public class TreeFunction { public static int positionOffset = 30; public static int height = 37; public static int width = 200; public static int margin = -3; public static int deleteButtonSize = 18; public GUIStyle nodeStyle; public GUIStyle selectedNodeStyle; public GUIStyle deleteButtonStyle; public int seed; public FunctionType type; public int id; public int position; public Rect rect; public Rect deleteRect; public int parentId; public TreeFunction parent; public string name; public float TradiusMultiplier = 0.3f; public AnimationCurve Tradius; public float Tlength = 10f; public int Tnumber = 1; public float Trandomness = 0.1f; public float ToriginAttraction = 0.1f; public float Tresolution = 1.5f; public AnimationCurve TrootShape; public float TrootRadius = 0.25f; public float TrootInnerRadius = 0.2f; public float TrootHeight = 1f; public float TrootResolution = 3f; public int TflareNumber = 5; public float TspinAmount = 0.1f; public float TdisplacementStrength = 1f; public float TdisplacementSize = 2.5f; public float TheightOffset = 0.5f; public float Glength = 10f; public AnimationCurve GlengthCurve = AnimationCurve.Linear(0f, 1f, 1f, 0.8f); public float Gresolution = 1f; public float GsplitProba = 0.1f; public float GsplitAngle = 0.5f; public int GmaxSplits = 2; public AnimationCurve Gradius = AnimationCurve.EaseInOut(0f, 1f, 1f, 0f); public AnimationCurve GsplitProbaCurve = AnimationCurve.Linear(0f, 0.5f, 1f, 1f); public float GsplitRadius = 0.8f; public float Grandomness = 0.25f; public float GupAttraction = 0.5f; public float GgravityStrength = 0.1f; public int Snumber = 25; public float SsplitAngle = 0.5f; public float SsplitRadius = 0.6f; public float Sstart = 0.2f; public float Sspread = 1f; public float Blength = 7f; public AnimationCurve BlengthCurve = AnimationCurve.Linear(0f, 1f, 1f, 0.8f); public float Bresolution = 1f; public int Bnumber = 25; public float BsplitProba = 0.2f; public float Bangle = 0.7f; public float Brandomness = 0.3f; public AnimationCurve Bshape = AnimationCurve.Linear(0f, 1f, 1f, 0f); public AnimationCurve BsplitProbaCurve = AnimationCurve.Linear(0f, 0.5f, 1f, 1f); public float Bradius = 0.7f; public float BupAttraction = 0.7f; public float Bstart = 0.2f; public float BgravityStrength = 0.1f; public int LleafType = 4; public string[] LleafTypesNames = new string[7] { "cross", "diamond cross", "diamond", "long", "plane", "Procedural", "custom" }; public Mesh[] LleafMesh = new Mesh[1] { Resources.LoadAll("Mtree/branches")[6] }; public int Lnumber = 250; public float LmaxRadius = 0.25f; public float Lsize = 2f; public bool LoverrideNormals = true; public float LminWeight = 0.2f; public float LmaxWeight = 0.5f; public float Llength = 2f; public AnimationCurve LlengthCurve = AnimationCurve.Linear(0f, 1f, 1f, 0.5f); public int LuLoops = 2; public float Lresolution = 1f; public float LgravityStrength = 1f; public bool Lprocedural; public TreeFunction(int id, FunctionType type, TreeFunction parent) { UpdateStyle(); this.id = id; this.type = type; this.parent = parent; parentId = ((parent != null) ? parent.id : (-1)); name = type.ToString(); position = ((parent != null) ? (parent.position + positionOffset) : 0); seed = UnityEngine.Random.Range(0, 1000); rect = default(Rect); deleteRect = default(Rect); if (type == FunctionType.Grow) { Keyframe[] keys = new Keyframe[2] { new Keyframe(0f, 1f, 0f, 0f), new Keyframe(1f, 0f, -0.5f, -1f) }; Gradius = new AnimationCurve(keys); } if (type == FunctionType.Branch && parent != null && parent.type != FunctionType.Trunk) { Blength = 3f; Bstart = 0.2f; Bangle = 0.5f; Bnumber = 55; Bresolution = 1f; } if (type == FunctionType.Trunk) { Keyframe[] keys2 = new Keyframe[2] { new Keyframe(0f, 1f, 0f, 0f), new Keyframe(1f, 0f, -1f, -1f) }; Tradius = new AnimationCurve(keys2); Keyframe[] keys3 = new Keyframe[2] { new Keyframe(0f, 1f, -2f, -2f), new Keyframe(1f, 0f, 0f, 0f) }; TrootShape = new AnimationCurve(keys3); } } public void Execute(MTree tree) { int selection = ((parent != null) ? parent.id : 0); UnityEngine.Random.InitState(seed); if (type == FunctionType.Trunk) { tree.AddTrunk(Vector3.down * TheightOffset, Vector3.up, Tlength, Tradius, TradiusMultiplier, Tresolution, Trandomness, id, TrootShape, TrootRadius, TrootHeight, TrootResolution, ToriginAttraction); } if (type == FunctionType.Grow) { tree.Grow(Glength, GlengthCurve, Gresolution, GsplitProba, GsplitProbaCurve, GsplitAngle, GmaxSplits, selection, id, Grandomness, Gradius, GsplitRadius, GupAttraction, GgravityStrength, 0f, 0.001f); } if (type == FunctionType.Split) { tree.Split(selection, Snumber, SsplitAngle, id, SsplitRadius, Sstart, Sspread, 0f); } if (type == FunctionType.Branch) { tree.AddBranches(selection, Blength, BlengthCurve, Bresolution, Bnumber, BsplitProba, BsplitProbaCurve, Bangle, Brandomness, Bshape, Bradius, BupAttraction, id, Bstart, BgravityStrength, 0f, 0.001f); } if (type == FunctionType.Leaf) { tree.AddLeafs(LmaxRadius, Lnumber, LleafMesh, Lsize, LoverrideNormals, LminWeight, LmaxWeight, selection, 70f, Lprocedural, Llength, Lresolution, LuLoops, LgravityStrength); } } public void UpdateRect(int offset) { position = ((parent != null) ? (parent.position + positionOffset) : 0); int num = offset * (height + margin); rect.Set(position, num, width, height); deleteRect.Set(position + width - 12 - deleteButtonSize, num + (height - deleteButtonSize) / 2, deleteButtonSize, deleteButtonSize); } public void UpdateStyle() { } public void Draw(bool isSelected = false) { } public void RevertOutOfBoundValues() { if (Bstart > 1f) { Bstart = 0.2f; } if (Sstart > 1f) { Sstart = 0.2f; } if (LmaxRadius > 1f) { LmaxRadius = 0.25f; } } public TreeFunctionAsset ToFunctionAsset(TreeFunctionAsset parent) { switch (type) { case FunctionType.Trunk: return ToTrunkFunction(parent); case FunctionType.Grow: return ToGrowFunction(parent); case FunctionType.Split: return ToSplitFunction(parent); case FunctionType.Branch: return ToBranchFunction(parent); case FunctionType.Leaf: return ToLeafFunction(parent); default: return null; } } private TreeFunctionAsset ToTrunkFunction(TreeFunctionAsset parent) { TrunkFunction trunkFunction = ScriptableObject.CreateInstance(); trunkFunction.Init(parent); trunkFunction.number = Tnumber; trunkFunction.displacementSize = TdisplacementSize; trunkFunction.displacementStrength = TdisplacementStrength; trunkFunction.seed = seed; trunkFunction.flareNumber = TflareNumber; trunkFunction.heightOffset = TheightOffset; trunkFunction.length = Tlength; trunkFunction.originAttraction = ToriginAttraction; trunkFunction.radius = Tradius; trunkFunction.radiusMultiplier = TradiusMultiplier; trunkFunction.randomness = Trandomness; trunkFunction.resolution = Tresolution; trunkFunction.rootHeight = TrootHeight; trunkFunction.rootInnerRadius = TrootInnerRadius; trunkFunction.rootRadius = TrootRadius; trunkFunction.rootResolution = TrootResolution; trunkFunction.rootShape = TrootShape; trunkFunction.spinAmount = TspinAmount; return trunkFunction; } private TreeFunctionAsset ToGrowFunction(TreeFunctionAsset parent) { GrowFunction growFunction = ScriptableObject.CreateInstance(); growFunction.Init(parent); growFunction.gravityStrength = GgravityStrength; growFunction.length = Glength; growFunction.lengthCurve = GlengthCurve; growFunction.maxSplits = GmaxSplits; growFunction.radius = Gradius; growFunction.randomness = Grandomness; growFunction.resolution = Gresolution; growFunction.seed = seed; growFunction.splitAngle = GsplitAngle; growFunction.splitProba = GsplitProba; growFunction.splitProbaCurve = GsplitProbaCurve; growFunction.splitRadius = GsplitRadius; growFunction.upAttraction = GupAttraction; return growFunction; } private TreeFunctionAsset ToSplitFunction(TreeFunctionAsset parent) { SplitFunction splitFunction = ScriptableObject.CreateInstance(); splitFunction.Init(parent); splitFunction.number = Snumber * 3; splitFunction.seed = seed; splitFunction.splitAngle = SsplitAngle; splitFunction.splitRadius = SsplitRadius; splitFunction.spread = Sspread; splitFunction.start = Sstart; return splitFunction; } private TreeFunctionAsset ToBranchFunction(TreeFunctionAsset parent) { BranchFunction branchFunction = ScriptableObject.CreateInstance(); branchFunction.Init(parent); branchFunction.angle = Bangle; branchFunction.gravityStrength = BgravityStrength; branchFunction.length = Blength; branchFunction.lengthCurve = BlengthCurve; branchFunction.number = Bnumber * 3; branchFunction.radius = Bradius; branchFunction.randomness = Brandomness; branchFunction.resolution = Bresolution; branchFunction.seed = seed; branchFunction.shape = Bshape; branchFunction.splitProba = BsplitProba; branchFunction.splitProbaCurve = BsplitProbaCurve; branchFunction.start = Bstart; branchFunction.upAttraction = BupAttraction; return branchFunction; } private TreeFunctionAsset ToLeafFunction(TreeFunctionAsset parent) { LeafFunction leafFunction = ScriptableObject.CreateInstance(); leafFunction.Init(parent); leafFunction.gravityStrength = LgravityStrength; leafFunction.leafType = LleafType; leafFunction.length = Llength; leafFunction.lengthCurve = LlengthCurve; leafFunction.maxRadius = LmaxRadius; leafFunction.maxWeight = LmaxWeight; leafFunction.minWeight = LminWeight; leafFunction.number = Lnumber; leafFunction.overrideNormals = LoverrideNormals; leafFunction.resolution = Lresolution; leafFunction.seed = seed; leafFunction.size = Lsize; leafFunction.uLoops = LuLoops; return leafFunction; } } }