using System.Collections;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
public class MtreeRandomizeTree : EditorWindow {
[SerializeField]public MtreeFunctionRandom TFR;
[SerializeField]public List<GameObject> MtreePrefabs = new List<GameObject>();
private static Texture2D texGreen,texRed,texBlack,texMtree;
private int tabSelected = 0;
private Vector2 PrefabScrollview,SettingsScrollview;
private bool AnimatedMaterial = false;
[MenuItem("Window/Mtree/Randomizer #m")]
static void OpenEditorWindow(){
MtreeRandomizeTree window = (MtreeRandomizeTree)EditorWindow.GetWindow(typeof(MtreeRandomizeTree));
window.maxSize = new Vector2(550,307);
window.minSize = new Vector2(550,307);
if(SceneView.lastActiveSceneView.sceneViewState.showMaterialUpdate){
if(EditorPrefs.HasKey("JSONDATA_MTREE")){
JsonUtility.FromJsonOverwrite(EditorPrefs.GetString("JSONDATA_MTREE"),this);
SceneView.lastActiveSceneView.sceneViewState.showMaterialUpdate = false;
var data = JsonUtility.ToJson(this,false);
EditorPrefs.SetString("JSONDATA_MTREE",data);
[UnityEditor.Callbacks.DidReloadScripts]
private static void OnScriptsReloaded() {
EditorPrefs.DeleteKey("JSONDATA_MTREE");
Texture2D texSelect = texRed;
tabSelected = GUILayout.Toolbar(tabSelected, new string[]{"Mtree Randomizer","Mtree Settings"});
gs.fontStyle = FontStyle.Bold;
EditorGUILayout.LabelField("Mtree Randomizer",gs);
GUI.DrawTexture(new Rect(0,GUILayoutUtility.GetLastRect().y,position.width,3),texBlack,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(position.width-74,position.height-74,64,64),texMtree,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(0,0,position.width,1),texBlack,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(0,0,1,position.height),texBlack,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(position.width-1,0,1,position.height),texBlack,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(0,position.height-1,position.width,1),texBlack,ScaleMode.StretchToFill);
private void TabMTreeRandom(){
gs.fontStyle = FontStyle.Bold;
float offset = (position.width/2 ) - 5;
#region [Random Tab Buttons]
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("Randomize Seed",GUILayout.Width(offset))){
if(GUILayout.Button("Randomize Selected Values",GUILayout.Width(offset))){
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("Save Prefabs",GUILayout.Width(offset))){
if(GUILayout.Button("Bake AO",GUILayout.Width(offset))){
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if(SceneView.lastActiveSceneView.sceneViewState.showMaterialUpdate){
wind = "Disable Editor Wind";
wind = "Enable Editor Wind";
if(GUILayout.Button(wind,GUILayout.Width(offset))){
SceneView.lastActiveSceneView.sceneViewState.showMaterialUpdate = !SceneView.lastActiveSceneView.sceneViewState.showMaterialUpdate;
if(GUILayout.Button("Get All Mtrees from Scene",GUILayout.Width(offset))){
var Mtrees = SceneManager.GetActiveScene().GetRootGameObjects();
for(int i = 0; i<Mtrees.Length;i++){
if(Mtrees[i].GetComponent<MtreeComponent>() && !MtreePrefabs.Contains(Mtrees[i])){
var mtree = Mtrees[i].GetComponent<MtreeComponent>();
MtreePrefabs.Add(Mtrees[i]);
EditorGUILayout.EndHorizontal();
#region [Random Tab Randomized Properties]
float yPos = GUILayoutUtility.GetLastRect().y;
GUI.DrawTexture(new Rect(0,yPos + 27,position.width,3),texBlack,ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(0,yPos+ 30, position.width / 2, position.height), texRed, ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(position.width / 2, yPos+ 30, position.width / 2, position.height), texGreen, ScaleMode.StretchToFill);
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Randomize Values",gs);
EditorGUILayout.LabelField("Select for Randomization",gs);
EditorGUILayout.EndHorizontal();
private void TabMTreePrefabs(){
gs.normal.textColor = Color.white;
gs.alignment = TextAnchor.LowerLeft;
GUI.DrawTexture(new Rect(0, GUILayoutUtility.GetLastRect().position.y+2, position.width, position.height), texRed, ScaleMode.StretchToFill);
GUI.DrawTexture(new Rect(0, GUILayoutUtility.GetLastRect().position.y+39, position.width, position.height), texGreen, ScaleMode.StretchToFill);
TFR.MTreeRandomMode = (MTreeRandomSelectionMode)EditorGUILayout.EnumPopup(TFR.MTreeRandomMode,GUILayout.Width(position.width-114));
EditorGUILayout.BeginHorizontal();
if(GUILayout.Button("Clear Mtree List",GUILayout.Width((position.width)/ 4))){
if(GUILayout.Button("Add Mtree Selection",GUILayout.Width((position.width)/ 4))){
MtreePrefabs = new List<GameObject>(Selection.gameObjects);
EditorGUILayout.LabelField("For Single remove, delete selected Prefab in List",gs);
EditorGUILayout.EndHorizontal();
PrefabScrollview = EditorGUILayout.BeginScrollView(PrefabScrollview,GUIStyle.none,GUIStyle.none);
for(int i = 0; i<MtreePrefabs.Count; i++){
if(MtreePrefabs.Count >0){
MtreePrefabs[i] = (GameObject)EditorGUILayout.ObjectField(MtreePrefabs[i],typeof(GameObject),true,GUILayout.Width(position.width-114));
for(int i = MtreePrefabs.Count-1;i>=0;i--){
if(MtreePrefabs[i] == null || !MtreePrefabs[i].scene.IsValid() || !MtreePrefabs[i].GetComponent<MtreeComponent>())
MtreePrefabs.RemoveAt(i);
EditorGUILayout.EndScrollView();
private void RandomPrefabsHeader(){
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Min",GUILayout.Width(62.5f));
EditorGUILayout.LabelField("Max",GUILayout.Width(62.5f));
var rectPos = GUILayoutUtility.GetLastRect();
rectPos.x = rectPos.x + 157.5f;
rectPos.y = rectPos.y + 2;
GUI.DrawTexture(rectPos,texSelect);
if(rectPos.Contains(Event.current.mousePosition)){
if(Event.current.type == EventType.MouseDown || Event.current.type == EventType.MouseDrag){
if(Event.current.type == EventType.MouseUp){
if(Event.current.type == EventType.MouseUp){
EditorGUILayout.LabelField("<color=white><i>Select All / None</i></color>",gs,GUILayout.Width(125));
EditorGUILayout.EndHorizontal();
private void ShowRandomValues(){
if(TFR.MTreeRandomMode == MTreeRandomSelectionMode.QuickSetup){
TFR.Tlength = TFR.Tlength.MTreeFloatSelect();
TFR.Trandomness = TFR.Trandomness.MTreeFloatSelect();
TFR.Bnumber = TFR.Bnumber.MTreeIntSelect();
TFR.Bangle = TFR.Bangle.MTreeFloatSelect();
TFR.BlengthMinHeight = TFR.BlengthMinHeight.MTreeMinHeightSlider("minimum height Of Branch",TFR.Blength.selected);
TFR.Blength = TFR.Blength.MTreeFloatSelect();
TFR.LWeight = TFR.LWeight.MTreeFloatSelect();
TFR.Lnumber = TFR.Lnumber.MTreeIntSelect();
if(TFR.MTreeRandomMode == MTreeRandomSelectionMode.Custom){
SettingsScrollview = EditorGUILayout.BeginScrollView(SettingsScrollview,GUIStyle.none,GUIStyle.none);
TFR.TradiusMultiplier = TFR.TradiusMultiplier.MTreeFloatSelect();
TFR.Tlength = TFR.Tlength.MTreeFloatSelect();
TFR.Trandomness = TFR.Trandomness.MTreeFloatSelect();
TFR.ToriginAttraction = TFR.ToriginAttraction.MTreeFloatSelect();
TFR.TspinAmount = TFR.TspinAmount.MTreeFloatSelect();
TFR.TrootRadius = TFR.TrootRadius.MTreeFloatSelect();
TFR.TrootHeight = TFR.TrootHeight.MTreeFloatSelect();
TFR.TflareNumber = TFR.TflareNumber.MTreeIntSelect();
TFR.Glength = TFR.Glength.MTreeFloatSelect();
TFR.GsplitProba = TFR.GsplitProba.MTreeFloatSelect();
TFR.GsplitAngle = TFR.GsplitAngle.MTreeFloatSelect();
TFR.GmaxSplits = TFR.GmaxSplits.MTreeIntSelect();
TFR.GsplitRadius = TFR.GsplitRadius.MTreeFloatSelect();
TFR.Grandomness = TFR.Grandomness.MTreeFloatSelect();
TFR.GupAttraction = TFR.GupAttraction.MTreeFloatSelect();
TFR.GgravityStrength = TFR.GgravityStrength.MTreeFloatSelect();
TFR.SsplitAngle = TFR.SsplitAngle.MTreeFloatSelect();
TFR.SmaxSplits = TFR.SmaxSplits.MTreeIntSelect();
TFR.SsplitRadius = TFR.SsplitRadius.MTreeFloatSelect();
TFR.Sstart = TFR.Sstart.MTreeFloatSelect();
TFR.Sspread = TFR.Sspread.MTreeFloatSelect();
TFR.BlengthMinHeight = TFR.BlengthMinHeight.MTreeMinHeightSlider("minimum height Of Branch",TFR.Blength.selected);
TFR.Blength = TFR.Blength.MTreeFloatSelect();
TFR.Bnumber = TFR.Bnumber.MTreeIntSelect();
TFR.BsplitProba = TFR.BsplitProba.MTreeFloatSelect();
TFR.Bangle = TFR.Bangle.MTreeFloatSelect();
TFR.Brandomness = TFR.Brandomness.MTreeFloatSelect();
TFR.Bradius = TFR.Bradius.MTreeFloatSelect();
TFR.BupAttraction = TFR.BupAttraction.MTreeFloatSelect();
TFR.Bstart = TFR.Bstart.MTreeFloatSelect();
TFR.BmaxSplits = TFR.BmaxSplits.MTreeIntSelect();
TFR.BgravityStrength = TFR.BgravityStrength.MTreeFloatSelect();
TFR.Lnumber = TFR.Lnumber.MTreeIntSelect();
TFR.LmaxRadius = TFR.LmaxRadius.MTreeFloatSelect();
TFR.Lsize = TFR.Lsize.MTreeFloatSelect();
TFR.LWeight = TFR.LWeight.MTreeFloatSelect();
EditorGUILayout.EndScrollView();
private void RandomizeAll(){
for(int i = 0; i<MtreePrefabs.Count;i++){
if(MtreePrefabs[i] != null && MtreePrefabs[i].GetComponent<MtreeComponent>() != null){
var mtree = MtreePrefabs[i].GetComponent<MtreeComponent>();
mtree.UpdateTreeFunctions();
private void RandomizeSelected(){
if(MtreePrefabs.Count > 0){
for(int i = 0; i<MtreePrefabs.Count;i++){
var mtree = MtreePrefabs[i].GetComponent<MtreeComponent>();
for(int ii = 0; ii<mtree.treeFunctions.Count;ii++){
TFR = TFR.RandomizeValues();
mtree.treeFunctions[ii] = mtree.treeFunctions[ii].ReturnRandomTreeFunction(TFR);
mtree.UpdateTreeFunctions();
if(MtreePrefabs.Count > 0){
for(int i = 0; i<MtreePrefabs.Count;i++){
if(MtreePrefabs[i] != null){
var mtree = MtreePrefabs[i].GetComponent<MtreeComponent>();
EditorUtility.DisplayProgressBar("Bake AO","Baking Ambient Occlusion for Tree " + counter +"/"+ MtreePrefabs.Count,Mathf.Lerp(0,1,(float)counter / (MtreePrefabs.Count )));
mtree.UpdateTreeFunctions();
mtree.GenerateTree(true);
EditorUtility.ClearProgressBar();
private void SaveMtreesAsPrefabs(){
if(!AssetDatabase.IsValidFolder("Assets/Mtree")){
AssetDatabase.CreateFolder("Assets","Mtree");
AssetDatabase.CreateFolder("Assets/Mtree","Randomized Prefabs");
if(!AssetDatabase.IsValidFolder("Assets/Mtree/Randomized Prefabs")){
AssetDatabase.CreateFolder("Assets/Mtree","Randomized Prefabs");
for(int i = 0; i<MtreePrefabs.Count;i++){
if(MtreePrefabs[i].GetComponent<MtreeComponent>() != null){
EditorUtility.DisplayProgressBar("Save Trees","Saving Tree Nr. " + counter + "/" + MtreePrefabs.Count,Mathf.Lerp(0,1,(float)counter / (MtreePrefabs.Count )));
var mtree = MtreePrefabs[i].GetComponent<MtreeComponent>();
mtree.name += "_Randomized_"+i;
mtree.saveTreeFolder = "Assets/Mtree/Randomized Prefabs/"+mtree.name;
mtree.UpdateTreeFunctions();
mtree.GenerateTree(true);
if(AssetDatabase.IsValidFolder("Assets/Mtree/Randomized Prefabs/" + mtree.name)){
AssetDatabase.DeleteAsset("Assets/Mtree/Randomized Prefabs/" + mtree.name);
AssetDatabase.CreateFolder("Assets/Mtree/Randomized Prefabs",mtree.name);
mtree.SaveAsPrefab(true);
EditorUtility.ClearProgressBar();
public MtreeFunctionRandom RandomSetup(MtreeFunctionRandom f){
f.TradiusMultiplier = f.TradiusMultiplier.FloatSetup( "Trunk Radius Multiplier",0.0001f,10);
f.Tlength = f.Tlength.FloatSetup("Trunk Length",0.01f,150);
f.Trandomness = f.Trandomness.FloatSetup("Trunk Randomness",0,0.5f);
f.ToriginAttraction = f.ToriginAttraction.FloatSetup("Trunk Axis Attraction",0,1);
f.TspinAmount = f.TspinAmount.FloatSetup("Trunk Spin Amount",-1,1);
f.TrootRadius = f.TrootRadius.FloatSetup("Root Radius",0,2);
f.TrootHeight = f.TrootHeight.FloatSetup("Root Height",0.01f,5);
f.TflareNumber = f.TflareNumber.IntSetup("Root Flare Numbers",0,10);
f.Glength = f.Glength.FloatSetup("Grow Length",0.001f,10);
f.GsplitProba = f.GsplitProba.FloatSetup("Grow Split Proba",0,1);
f.GsplitAngle = f.GsplitAngle.FloatSetup("Grow Split angle",0,2);
f.GmaxSplits = f.GmaxSplits.IntSetup("Grow Max Split",2,4);
f.GsplitRadius = f.GsplitRadius.FloatSetup("Grow Split Radius",0.5f,0.999f);
f.Grandomness = f.Grandomness.FloatSetup("Grow Randomness",0,1);
f.GupAttraction = f.GupAttraction.FloatSetup("Grow Up attraction",0,1);
f.GgravityStrength = f.GgravityStrength.FloatSetup("Grow Gravity strength",-15,15);
f.SsplitAngle = f.SsplitAngle.FloatSetup("Split angle",0,2);
f.SmaxSplits = f.SmaxSplits.IntSetup("Split max Splits",1,10);
f.SsplitRadius = f.SsplitRadius.FloatSetup("Split Radius",0.001f,1);
f.Sstart = f.Sstart.FloatSetup("Split Start",0,1);
f.Sspread = f.Sspread.FloatSetup("Split Spread",0,1);
f.Blength = f.Blength.FloatSetup("Branch Length",0.001f,10);
f.Bnumber = f.Bnumber.IntSetup("Branch Number",0,150);
f.BsplitProba = f.BsplitProba.FloatSetup("Branch Split Proba",0,1);
f.Bangle = f.Bangle.FloatSetup("Branch Angle",0,2);
f.Brandomness = f.Brandomness.FloatSetup("Branch Randomness", 0,1);
f.Bradius = f.Bradius.FloatSetup("Branch Radius", 0.001f,1);
f.BupAttraction = f.BupAttraction.FloatSetup("Branch Up attraction",0,1);
f.Bstart = f.Bstart.FloatSetup("Branch Start",0,1);
f.BmaxSplits = f.BmaxSplits.IntSetup("Branch max Split",1,5);
f.BgravityStrength = f.BgravityStrength.FloatSetup("Branch Gravity strength",-15,15);
f.Lnumber = f.Lnumber.IntSetup("Leaf Number",0,2000);
f.LmaxRadius = f.LmaxRadius.FloatSetup("Leaf max Radius",0.001f,1);
f.Lsize = f.Lsize.FloatSetup("Leaf Size", 0,25);
f.LWeight = f.LWeight.FloatSetup("Leaf Weight",-1,1);
static void SetupGUITextures(){
string StringMtreeTexture ="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";
texGreen = new Texture2D(1, 1, TextureFormat.RGBA32, false);
texRed = new Texture2D(1, 1, TextureFormat.RGBA32, false);
texBlack = new Texture2D(1,1,TextureFormat.RGBA32,false);
texMtree = new Texture2D(256,256,TextureFormat.RGBA32,false);
var bytes = Convert.FromBase64String(StringMtreeTexture);
texMtree.LoadImage(bytes);
ColorUtility.TryParseHtmlString("#CD3C3C",out red);
texGreen.SetPixel(0, 0,Color.green / 4);
texRed.SetPixel(0,0,red / 3);
texBlack.SetPixel(0,0,Color.black);
[Serializable] public struct MTreeFloatMinMax{
[SerializeField] public float MinValue;
[SerializeField] public float MinLimit;
[SerializeField] public float MaxValue;
[SerializeField] public float MaxLimit;
[SerializeField] public float Value;
[SerializeField] public bool selected;
[SerializeField] public string name;
Value = UnityEngine.Random.Range(MinValue,MaxValue);
[Serializable] public struct MTreeIntMinMax{
[SerializeField] public int MinValue;
[SerializeField] public int MinLimit;
[SerializeField] public int MaxValue;
[SerializeField] public int MaxLimit;
[SerializeField] public int Value;
[SerializeField] public bool selected;
[SerializeField] public string name;
Value = UnityEngine.Random.Range(MinValue,MaxValue);
[Serializable] public enum MTreeRandomSelectionMode
[Serializable] public struct MtreeFunctionRandom{
[SerializeField] public MTreeRandomSelectionMode MTreeRandomMode;
public MTreeFloatMinMax TradiusMultiplier;
public MTreeFloatMinMax Tlength;
public MTreeFloatMinMax Trandomness;
public MTreeFloatMinMax ToriginAttraction;
public MTreeFloatMinMax TspinAmount;
public MTreeFloatMinMax TrootRadius;
public MTreeFloatMinMax TrootHeight;
public MTreeIntMinMax TflareNumber;
public MTreeFloatMinMax Glength;
public MTreeFloatMinMax GsplitProba;
public MTreeFloatMinMax GsplitAngle;
public MTreeIntMinMax GmaxSplits;
public MTreeFloatMinMax GsplitRadius;
public MTreeFloatMinMax Grandomness;
public MTreeFloatMinMax GupAttraction;
public MTreeFloatMinMax GgravityStrength;
public MTreeFloatMinMax SsplitAngle;
public MTreeIntMinMax SmaxSplits;
public MTreeFloatMinMax SsplitRadius;
public MTreeFloatMinMax Sstart;
public MTreeFloatMinMax Sspread;
public float BlengthMinHeight;
public MTreeFloatMinMax Blength;
public MTreeIntMinMax Bnumber;
public MTreeFloatMinMax BsplitProba;
public MTreeFloatMinMax Bangle;
public MTreeFloatMinMax Brandomness;
public MTreeFloatMinMax Bradius;
public MTreeFloatMinMax BupAttraction;
public MTreeFloatMinMax Bstart;
public MTreeIntMinMax BmaxSplits;
public MTreeFloatMinMax BgravityStrength;
public MTreeIntMinMax Lnumber;
public MTreeFloatMinMax LmaxRadius;
public MTreeFloatMinMax Lsize;
public MTreeFloatMinMax LWeight;
[Serializable] public static class EditorSetups{
const float singlewidth = 50;
public static MTreeFloatMinMax FloatSetup(this MTreeFloatMinMax FMM,string name,float minLimit,float maxLimit){
FMM.MinValue = FMM.MaxLimit / 4 * 1;
FMM.MaxValue = FMM.MaxLimit / 4 * 2;
public static MTreeIntMinMax IntSetup(this MTreeIntMinMax IMM,string name,int minLimit,int maxLimit){
IMM.MinValue = maxLimit / 4 * 1;
IMM.MaxValue = maxLimit / 4 * 2;
public static float MTreeMinHeightSlider(this float floatProperty,string name,bool selected){
gs.fontStyle = FontStyle.Italic;
var gs_f = new GUIStyle(GUI.skin.box);
gs_f.alignment = TextAnchor.MiddleLeft;
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(!selected);
floatProperty = EditorGUILayout.Slider(floatProperty,0,1,GUILayout.Width(singlewidth*5.2f));
EditorGUI.EndDisabledGroup();
GUILayout.Space(singlewidth*1.05f);
EditorGUILayout.LabelField(name,gs);
EditorGUILayout.EndHorizontal();
public static MTreeFloatMinMax MTreeFloatSelect(this MTreeFloatMinMax floatProperty){
gs.fontStyle = FontStyle.Italic;
var gs_f = new GUIStyle(GUI.skin.box);
gs_f.alignment = TextAnchor.MiddleLeft;
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(!floatProperty.selected);
floatProperty.MinValue = EditorGUILayout.FloatField(floatProperty.MinValue,gs_f,GUILayout.Width(singlewidth*1.25f));
floatProperty.MaxValue = EditorGUILayout.FloatField(floatProperty.MaxValue,gs_f,GUILayout.Width(singlewidth*1.25f));
floatProperty.MinValue = (float)System.Math.Round(floatProperty.MinValue,6);
floatProperty.MaxValue = (float)System.Math.Round(floatProperty.MaxValue,6);
EditorGUILayout.MinMaxSlider(ref floatProperty.MinValue,ref floatProperty.MaxValue,floatProperty.MinLimit,floatProperty.MaxLimit,GUILayout.Width(singlewidth*2.5f));
EditorGUI.EndDisabledGroup();
GUILayout.Space(singlewidth/2);
floatProperty.selected = EditorGUILayout.Toggle(floatProperty.selected,GUILayout.MaxWidth(singlewidth/4));
GUILayout.Space(singlewidth/4);
EditorGUILayout.LabelField(floatProperty.name,gs);
EditorGUILayout.EndHorizontal();
public static MTreeIntMinMax MTreeIntSelect(this MTreeIntMinMax intProperty){
gs.fontStyle = FontStyle.Italic;
var gs_i = new GUIStyle(GUI.skin.box);
gs_i.alignment = TextAnchor.MiddleLeft;
EditorGUILayout.BeginHorizontal();
EditorGUI.BeginDisabledGroup(!intProperty.selected);
intProperty.MinValue = EditorGUILayout.IntField(intProperty.MinValue,gs_i,GUILayout.Width(singlewidth*1.25f));
intProperty.MaxValue = EditorGUILayout.IntField(intProperty.MaxValue,gs_i,GUILayout.Width(singlewidth*1.25f));
float minVal = intProperty.MinValue;
float maxVal = intProperty.MaxValue;
EditorGUILayout.MinMaxSlider(ref minVal,ref maxVal,intProperty.MinLimit,intProperty.MaxLimit,GUILayout.Width(singlewidth*2.5f));
intProperty.MinValue = Mathf.Clamp(Mathf.RoundToInt(minVal),intProperty.MinLimit,intProperty.MaxLimit);
intProperty.MaxValue = Mathf.Clamp(Mathf.RoundToInt(maxVal),intProperty.MinLimit,intProperty.MaxLimit);
EditorGUI.EndDisabledGroup();
GUILayout.Space(singlewidth/2);
intProperty.selected = EditorGUILayout.Toggle(intProperty.selected,GUILayout.MaxWidth(singlewidth/4));
GUILayout.Space(singlewidth/4);
EditorGUILayout.LabelField(intProperty.name,gs);
EditorGUILayout.EndHorizontal();
public static Mtree.TreeFunction ReturnRandomTreeFunction(this Mtree.TreeFunction f,MtreeFunctionRandom fr ){
if(fr.TradiusMultiplier.selected)
f.TradiusMultiplier = fr.TradiusMultiplier.Value;
f.Tlength = fr.Tlength.Value;
if(fr.Trandomness.selected)
f.Trandomness = fr.Trandomness.Value;
if(fr.ToriginAttraction.selected)
f.ToriginAttraction = fr.ToriginAttraction.Value;
if(fr.TrootRadius.selected)
f.TrootRadius = fr.TrootRadius.Value;
if(fr.TrootHeight.selected)
f.TrootHeight = fr.TrootHeight.Value;
if(fr.TflareNumber.selected)
f.TflareNumber = fr.TflareNumber.Value;
if(fr.TspinAmount.selected)
f.TspinAmount = fr.TspinAmount.Value;
f.Glength = fr.Glength.Value;
if(fr.GsplitProba.selected)
f.GsplitProba = fr.GsplitProba.Value;
if(fr.GsplitAngle.selected)
f.GsplitAngle = fr.GsplitAngle.Value;
if(fr.GmaxSplits.selected)
f.GmaxSplits = fr.GmaxSplits.Value;
if(fr.GsplitRadius.selected)
f.GsplitRadius = fr.GsplitRadius.Value;
if(fr.Grandomness.selected)
f.Grandomness = fr.Grandomness.Value;
if(fr.GupAttraction.selected)
f.GupAttraction = fr.GupAttraction.Value;
if(fr.GgravityStrength.selected)
f.GgravityStrength = fr.GgravityStrength.Value;
if(fr.SsplitAngle.selected)
f.SsplitAngle = fr.SsplitAngle.Value;
if(fr.SmaxSplits.selected)
f.SmaxSplits = fr.SmaxSplits.Value;
if(fr.SsplitRadius.selected)
f.SsplitRadius = fr.SsplitRadius.Value;
f.Sstart = fr.Sstart.Value;
f.Sspread = fr.Sspread.Value;
if(fr.Blength.selected && fr.BlengthMinHeight <= f.Bstart)
f.Blength = fr.Blength.Value;
f.Bnumber = fr.Bnumber.Value;
if(fr.BsplitProba.selected)
f.BsplitProba = fr.BsplitProba.Value;
f.Bangle = fr.Bangle.Value;
if(fr.Brandomness.selected)
f.Brandomness = fr.Brandomness.Value;
f.Bradius = fr.Bradius.Value;
if(fr.BupAttraction.selected)
f.BupAttraction = fr.BupAttraction.Value;
f.Bstart = fr.Bstart.Value;
if(fr.BmaxSplits.selected)
f.BmaxSplits = fr.BmaxSplits.Value;
if(fr.BgravityStrength.selected)
f.BgravityStrength = fr.BgravityStrength.Value;
f.Lnumber = fr.Lnumber.Value;
if(fr.LmaxRadius.selected)
f.LmaxRadius = fr.LmaxRadius.Value;
f.Lsize = fr.Lsize.Value;
f.LminWeight = fr.LWeight.MinValue;
f.LmaxWeight = fr.LWeight.MaxValue;
public static MtreeFunctionRandom RandomizeValues(this MtreeFunctionRandom fr){
fr.TradiusMultiplier.Randomize();
fr.Trandomness.Randomize();
fr.ToriginAttraction.Randomize();
fr.TspinAmount.Randomize();
fr.TrootRadius.Randomize();
fr.TrootHeight.Randomize();
fr.TflareNumber.Randomize();
fr.GsplitProba.Randomize();
fr.GsplitAngle.Randomize();
fr.GmaxSplits.Randomize();
fr.GsplitRadius.Randomize();
fr.Grandomness.Randomize();
fr.GupAttraction.Randomize();
fr.GgravityStrength.Randomize();
fr.SsplitAngle.Randomize();
fr.SmaxSplits.Randomize();
fr.SsplitRadius.Randomize();
fr.SsplitAngle.Randomize();
fr.BsplitProba.Randomize();
fr.Brandomness.Randomize();
fr.BupAttraction.Randomize();
fr.BmaxSplits.Randomize();
fr.BgravityStrength.Randomize();
fr.LmaxRadius.Randomize();
public static MtreeFunctionRandom IsSelected(this MtreeFunctionRandom f){
AllSelected = !AllSelected;
if(f.MTreeRandomMode == MTreeRandomSelectionMode.QuickSetup){
f.Tlength.selected = AllSelected;
f.ToriginAttraction.selected = AllSelected;
f.Trandomness.selected = AllSelected;
f.Bnumber.selected = AllSelected;
f.Bangle.selected = AllSelected;
f.Blength.selected = AllSelected;
f.LWeight.selected = AllSelected;
f.Lnumber.selected = AllSelected;
if(f.MTreeRandomMode == MTreeRandomSelectionMode.Custom){
f.TradiusMultiplier.selected = AllSelected;
f.Tlength.selected = AllSelected;
f.Trandomness.selected = AllSelected;
f.ToriginAttraction.selected = AllSelected;
f.TspinAmount.selected = AllSelected;
f.TrootRadius.selected = AllSelected;
f.TrootHeight.selected = AllSelected;
f.TflareNumber.selected = AllSelected;
f.Glength.selected = AllSelected;
f.GsplitProba.selected = AllSelected;
f.GsplitAngle.selected = AllSelected;
f.GmaxSplits.selected = AllSelected;
f.GsplitRadius.selected = AllSelected;
f.Grandomness.selected = AllSelected;
f.GupAttraction.selected = AllSelected;
f.GgravityStrength.selected = AllSelected;
f.SsplitAngle.selected = AllSelected;
f.SmaxSplits.selected = AllSelected;
f.SsplitRadius.selected = AllSelected;
f.Sstart.selected = AllSelected;
f.Sspread.selected = AllSelected;
f.Blength.selected = AllSelected;
f.Bnumber.selected = AllSelected;
f.BsplitProba.selected = AllSelected;
f.Bangle.selected = AllSelected;
f.Brandomness.selected = AllSelected;
f.Bradius.selected = AllSelected;
f.BupAttraction.selected = AllSelected;
f.Bstart.selected = AllSelected;
f.BmaxSplits.selected = AllSelected;
f.BgravityStrength.selected = AllSelected;
f.Lnumber.selected = AllSelected;
f.LmaxRadius.selected = AllSelected;
f.Lsize.selected = AllSelected;
f.LWeight.selected = AllSelected;