private static object ConvertValue(Type type, string value) { if (type.IsArray) { var split = value.Split(new string[] { Environment.NewLine, "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); var t = type.GetElementType(); var arr = Array.CreateInstance(t, split.Length); for (var i = 0; i < split.Length; i++) { arr.SetValue(ConvertValue(t, split[i]), i); } return(arr); } if (type == typeof(Color)) { return(SVector3.Deserialize(value).ToColor()); } if (type == typeof(Vector3)) { return(SVector3.Deserialize(value).ToVector3()); } if (type == typeof(Vector2)) { return(SVector3.Deserialize(value).ToVector2()); } if (type == typeof(Quaternion)) { return(Quaternion.Euler(SVector3.Deserialize(value))); } return(TypeDescriptor.GetConverter(type).ConvertFrom(value)); }
public GameObject CreateFurnitureObject(string furnName, XMLParser.XMLNode root, string rootFolder, StringBuilder output, out bool success) { GameObject go; var existing = root.TryGetAttribute("Base"); Furniture furn; if (existing != null) { var xFurn = ObjectDatabase.Instance.GetFurniture(existing); if (xFurn != null) { go = Instantiate(xFurn); //Remove existing renderers foreach (var child in go.GetComponentsInChildren <Renderer>()) { child.transform.SetParent(null); Destroy(child.gameObject); } furn = go.GetComponent <Furniture>(); furn.Colorable.Clear(); } else { output.AppendLine("\tFailed loading furniture " + existing + " using default"); go = new GameObject(); furn = go.AddComponent <Furniture>(); } } else { go = new GameObject(); furn = go.AddComponent <Furniture>(); } //Since this mod only uses standard material, optimize using mesh combine furn.UseStandardMat = true; //Furniture are identified by their MonoBehavior names (Really dumb, I know) go.name = FindUniqueFurnitureName(furnName); var thumb = new Texture2D(128, 128); thumb.LoadImage(File.ReadAllBytes(Path.Combine(rootFolder, root.GetAttribute("Thumbnail")))); furn.Thumbnail = Sprite.Create(thumb, new Rect(0, 0, 128, 128), Vector2.zero); GameObject compTrans = null; GameObject[] models = null; foreach (var node in root.Children) { if (node.Name.Equals("Models")) { models = new GameObject[node.Children.Count]; var i = 0; foreach (var model in node.Children) { try { //Load obj model using script from Unity Wiki var m = ObjImporter.ImportFile(Path.Combine(rootFolder, model.GetNodeValue("File"))); var newMesh = new GameObject("SubMesh"); newMesh.AddComponent <MeshFilter>().sharedMesh = m; models[i] = newMesh; var rend = newMesh.AddComponent <MeshRenderer>(); rend.material = ObjectDatabase.Instance.DefaultFurnitureMaterial; if (Convert.ToBoolean(GetNodeValue(model, "Computer", "False"))) { compTrans = newMesh; } //Make sure the mesh has outline when highlighted newMesh.tag = "Highlight"; var parent = Convert.ToInt32(GetNodeValue(model, "Parent", "-1")); newMesh.transform.SetParent(parent >= 0 ? models[parent].transform : go.transform); newMesh.transform.localPosition = SVector3.Deserialize(model.GetNodeValue("Position")); newMesh.transform.localRotation = Quaternion.Euler(SVector3.Deserialize(model.GetNodeValue("Rotation"))); newMesh.transform.localScale = SVector3.Deserialize(model.GetNodeValue("Scale")); //Make sure mesh gets colored when player changes colors furn.Colorable.Add(rend); } catch (Exception ex) { var fName = GetNodeValue(model, "File", "Undefined"); output.AppendLine("\tFailed loading mesh " + fName + " with error:"); output.AppendLine("\t" + ex.Message); success = false; return(go); } i++; } continue; } if (node.Name.Equals("InteractionPoints")) { try { for (var i = 0; i < furn.InteractionPoints.Length; i++) { Destroy(furn.InteractionPoints[i].gameObject); } var newIps = new List <InteractionPoint>(); var links = new int[node.Children.Count]; var k = 0; foreach (var ip in node.Children) { var ipGo = new GameObject("InteractionPoint"); ipGo.transform.SetParent(go.transform); var ipC = ipGo.AddComponent <InteractionPoint>(); ipC.transform.localPosition = SVector3.Deserialize(ip.GetNodeValue("Position")); ipC.transform.localRotation = Quaternion.Euler(SVector3.Deserialize(ip.GetNodeValue("Rotation"))); ipC.Name = ip.GetNodeValue("Name"); ipC.Animation = GetNodeValue(ip, "Animation", 0); ipC.subAnimation = GetNodeValue(ip, "SubAnimation", 0); ipC.MinimumNeeded = GetNodeValue(ip, "MinimumNeeded", 1); ipC.NeedsReachCheck = GetNodeValue(ip, "ReachCheck", true); ipC.Parent = furn; links[k] = GetNodeValue(ip, "Child", -1); newIps.Add(ipC); k++; } furn.InteractionPoints = newIps.ToArray(); for (var i = 0; i < furn.InteractionPoints.Length; i++) { if (links[i] > -1) { furn.InteractionPoints[i].Child = furn.InteractionPoints[links[i]]; } furn.InteractionPoints[i].Id = i; } } catch (Exception ex) { output.AppendLine("\tFailed loading interaction points with error:"); output.AppendLine("\t" + ex.Message); success = false; return(go); } continue; } if (node.Name.Equals("SnapPoints")) { try { for (var i = 0; i < furn.SnapPoints.Length; i++) { Destroy(furn.SnapPoints[i].gameObject); } var newSnaps = new List <SnapPoint>(); var links = new int[node.Children.Count][]; var k = 0; foreach (var snap in node.Children) { var snapGo = new GameObject("SnapPoint"); if (models != null) { var parent = Convert.ToInt32(GetNodeValue(snap, "MeshParent", "-1")); snapGo.transform.SetParent(parent >= 0 ? models[parent].transform : go.transform); } else { snapGo.transform.SetParent(go.transform); } var snapC = snapGo.AddComponent <SnapPoint>(); snapC.transform.localPosition = SVector3.Deserialize(snap.GetNodeValue("Position")); snapC.transform.localRotation = Quaternion.Euler(SVector3.Deserialize(snap.GetNodeValue("Rotation"))); snapC.Name = snap.GetNodeValue("Name"); snapC.CheckValid = GetNodeValue(snap, "CheckValid", true); snapC.Parent = furn; var n = snap.GetNode("Links", false); links[k] = n != null?n.Value.Split(',').Select(x => Convert.ToInt32(x)).ToArray() : new int[0]; newSnaps.Add(snapC); k++; } furn.SnapPoints = newSnaps.ToArray(); for (var i = 0; i < furn.SnapPoints.Length; i++) { furn.SnapPoints[i].InitLinks = links[i].Select(x => furn.SnapPoints[x]).ToArray(); furn.SnapPoints[i].Id = i; } } catch (Exception ex) { output.AppendLine("\tFailed loading snap points with error:"); output.AppendLine("\t" + ex.Message); success = false; return(go); } continue; } //Use reflection and string->type converters to create components and modify them //These need to be set if we're loading scripts from another mod, otherwise try defaults var nameSpace = node.TryGetAttribute("Namespace"); var assembly = node.TryGetAttribute("Assembly"); Type t; if (nameSpace != null && assembly != null) { t = Type.GetType(nameSpace + node.Name + ", " + assembly); } else { t = Type.GetType(node.Name) ?? Type.GetType(node.Name + ", Assembly-CSharp") ?? Type.GetType("UnityEngine." + node.Name + ", UnityEngine"); } if (t != null) { if (node.TryGetAttribute("Destroy") != null) { var comp = go.GetComponent(t); if (comp != null) { DestroyImmediate(comp); } } else { var comp = go.GetComponent(t) ?? go.AddComponent(t); if (comp != null) { foreach (var element in node.Children) { var field = t.GetField(element.Name); if (field != null) { try { var val = ConvertValue(field.FieldType, element.Value); field.SetValue(comp, val); } catch (Exception ex) { output.AppendLine("\tFailed setting field " + element.Name + ":"); output.AppendLine("\t" + ex.Message); } } else { var prop = t.GetProperty(element.Name); if (prop != null) { try { var val = ConvertValue(prop.PropertyType, element.Value); prop.SetValue(comp, val, null); } catch (Exception ex) { output.AppendLine("\tFailed setting property " + element.Name + ":"); output.AppendLine("\t" + ex.Message); } } else { output.AppendLine("\tUndefined variable " + element.Name); } } } } else { output.AppendLine("\tCouldn't create type " + node.Name); } } } else { output.AppendLine("\tUndefined type " + node.Name); } } if (furn.Colorable.Count == 0) { output.AppendLine("\tFurniture needs at least one mesh"); success = false; return(go); } //If needed, project vertices to floor, convex hull and set as boundary to avoid wall clipping if (!furn.WallFurn && furn.BuildBoundary != null && furn.BuildBoundary.Length > 0) { furn.MeshBoundary = furn.CalculateBoundary().ToArray(); } furn.ComputerTransform = compTrans == null ? null : compTrans.transform; furn.upg = go.GetComponent <Upgradable>(); furn.Table = go.GetComponent <TableScript>(); success = true; return(go); }