Skip to content

Instantly share code, notes, and snippets.

@michidk
Created April 6, 2016 20:21
Show Gist options
  • Save michidk/106ea2e5253279aa78d123c507082a7a to your computer and use it in GitHub Desktop.
Save michidk/106ea2e5253279aa78d123c507082a7a to your computer and use it in GitHub Desktop.
Unity3D Tree Randomizer
using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEditor;
using Random = UnityEngine.Random;
namespace BrokenVector.TreeRandomizer
{
public class TreeRandomizerWindow : EditorWindow
{
private const string OUTPUT_FOLDER = "Generated";
private const int SLIDER_TREE_COUNT_MAX = 50;
private Tree treeTemplate = null;
private int treeCount = 5;
[MenuItem("Tools/Tree Randomizer")]
private static void ShowWindow()
{
var window = GetWindow(typeof(TreeRandomizerWindow));
window.titleContent = new GUIContent("Tree Randomizer");
window.Show();
}
void OnGUI()
{
if (EditorApplication.isPlaying)
{
EditorGUILayout.HelpBox("You can only generate trees while not in playmode!", MessageType.Info);
return;
}
treeTemplate = EditorGUILayout.ObjectField("Tree Template", treeTemplate, typeof(Tree), true) as Tree;
treeCount = EditorGUILayout.IntSlider("Tree Count", treeCount, 1, SLIDER_TREE_COUNT_MAX);
if (GUILayout.Button("Generate Trees"))
{
Generate(treeTemplate, treeCount);
}
}
private void Generate(Tree treeTemplate, int treeCount)
{
Debug.Log("Starting generation of " + treeCount + " trees.");
if (!AssetDatabase.Contains(treeTemplate))
{
Debug.LogError("Couldn't find the tree in the AssetDatabase.", treeTemplate);
return;
}
string path = AssetDatabase.GetAssetPath(treeTemplate);
string dir = Path.GetDirectoryName(path);
string name = Path.GetFileNameWithoutExtension(path);
string ext = Path.GetExtension(path);
string copyFolder = dir + "/" + OUTPUT_FOLDER;
if (!AssetDatabase.IsValidFolder(copyFolder))
AssetDatabase.CreateFolder(dir, OUTPUT_FOLDER);
var treeobj = new SerializedObject(treeTemplate.data);
Material barkmat = treeobj.FindProperty("optimizedSolidMaterial").objectReferenceValue as Material;
if (barkmat == null)
{
Debug.LogError("bark material not found!");
return;
}
Material leafmat = treeobj.FindProperty("optimizedCutoutMaterial").objectReferenceValue as Material;
if (leafmat == null)
{
Debug.LogError("leaf material not found");
return;
}
List<Tree> generatedTrees = new List<Tree>();
for (int i = 0; i < treeCount; i++)
{
string copyFile = name + " " + i + ext;
string copyPath = copyFolder + "/" + copyFile;
bool result = AssetDatabase.CopyAsset(path, copyPath);
AssetDatabase.Refresh();
if (!result)
{
Debug.LogError("Couldn't copy the tree from " + path + " to " + copyPath);
return;
}
AssetDatabase.ImportAsset(copyPath);
Tree tree = AssetDatabase.LoadAssetAtPath(copyPath, (typeof(Tree))) as Tree;
if (tree == null)
{
Debug.LogError("Couldn't load tree.");
return;
}
foreach (Material mat in tree.GetComponent<MeshRenderer>().sharedMaterials)
{
DestroyImmediate(mat, true);
}
AssetDatabase.SaveAssets();
//Is material order fixed?
tree.GetComponent<MeshRenderer>().sharedMaterials = new[] { barkmat, leafmat };
var obj = new SerializedObject(tree.data);
int randomSeed = Random.Range(0, 9999999);
obj.FindProperty("root.seed").intValue = randomSeed;
obj.FindProperty("optimizedSolidMaterial").objectReferenceValue = barkmat;
obj.FindProperty("optimizedCutoutMaterial").objectReferenceValue = leafmat;
obj.ApplyModifiedProperties();
MethodInfo meth = tree.data.GetType().GetMethod("UpdateMesh", new[] { typeof(Matrix4x4), typeof(Material[]).MakeByRefType() });
object[] arguments = new object[] { tree.transform.worldToLocalMatrix, null };
meth.Invoke(tree.data, arguments);
AssetDatabase.DeleteAsset(copyFolder + "/" + name + " " + i + "_Textures");
generatedTrees.Add(tree);
}
//To fix template becoming white
MethodInfo templatemeth = treeTemplate.data.GetType().GetMethod("UpdateMesh", new[] { typeof(Matrix4x4), typeof(Material[]).MakeByRefType() });
object[] templatearguments = new object[] { treeTemplate.transform.worldToLocalMatrix, null };
templatemeth.Invoke(treeTemplate.data, templatearguments);
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(treeTemplate));
foreach (Tree tree in generatedTrees)
{
AssetDatabase.ImportAsset(AssetDatabase.GetAssetPath(tree));
}
Debug.Log("Generated " + treeCount + " Trees!");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment