예제 #1
0
 // TTQMM Ref: JsonToGameObject.GetValueFromString
 // This function is for setting a value based on a reference
 public static object DeserializeValueReference(string search, string searchFull, Type outType)
 {
     if (searchFull.StartsWith("Reference"))
     {
         if (TTReferences.GetReferenceFromBlockResource(search, out var result))                 // Get value from a block in the game
         {
             return(result);
         }
     }
     else if (TTReferences.TryFind(search, null, outType, out object result))
     {
         return(result);                // Get value from a value in the user database
     }
     else
     {
         try
         {
             // Last fallback, we try searching our current working tree
             var recursive = GetCurrentSearchTransform().RecursiveFindWithProperties(searchFull, GetRootSearchTransform());
             if (recursive != null)
             {
                 return(recursive);                        // Get value from this block
             }
         }
         catch
         { }
     }
     return(null);
 }
예제 #2
0
        // TTQMM Ref: JsonToGameObject.CreateGameObject_Internal(JObject json, GameObject GameObjectToPopulate, string Spacing, Component instantiated = null, Type instantiatedType = null)
        private static GameObject DeserializeIntoGameObject_Internal(JObject jObject, GameObject target)
        {
            // Ensure we have a target object
            if (target == null)
            {
                target = new GameObject("Deserialized Object");
            }

            // Then read each JSON property and act accordingly
            foreach (JProperty jProperty in jObject.Properties())
            {
                string[] split = jProperty.Name.Split('|');
                if (split.Length == 1)                 // "ModuleVision", "UnityEngine.Transform" etc.
                {
                    Debug.Log($"[Nuterra] Deserializer adding component {split[0]}");

                    // Format will be "{ComponentType} {Index}" where the index specifies the child index if there are multiple targets
                    string typeNameAndIndex = split[0];
                    string typeName         = typeNameAndIndex.Split(' ')[0];
                    Type   type             = TTReferences.GetType(typeName);

                    if (type != null)
                    {
                        Debug.Log($"[Nuterra] Deserializer ready to find or create instance of type {type}");

                        // See if we have an existing component
                        Component component = target.GetComponentWithIndex(typeNameAndIndex);

                        // A null JSON token means we should delete this object
                        if (jProperty.Value.Type == JTokenType.Null)
                        {
                            if (component != null)
                            {
                                Component.DestroyImmediate(component);
                            }
                            else
                            {
                                Debug.LogError($"[Nuterra] Could not find component of type {typeNameAndIndex} to destroy");
                            }
                        }
                        else                         // We have some data, let's process it
                        {
                            // If we couldn't find the component, make a new one
                            if (component == null)
                            {
                                component = target.gameObject.AddComponent(type);
                            }

                            // If we still can't find one, get it. This should like never happen, right?
                            if (component == null)
                            {
                                Debug.LogError($"[Nuterra] Failed to find {typeNameAndIndex}, failed to AddComponent, but trying GetComponent");
                                component = target.gameObject.GetComponent(type);
                            }

                            // If we still don't have one, exit
                            if (component == null)
                            {
                                Debug.LogError($"[Nuterra] Could not find component {typeNameAndIndex}");
                                continue;
                            }

                            // Now deserialize the JSON into the new Component
                            DeserializeJSONObject(component, type, jProperty.Value as JObject);
                        }
                    }
                    else
                    {
                        Debug.LogError($"[Nuterra] Could not find type {typeNameAndIndex}");
                    }
                }
                else if (split.Length == 2)                 //
                {
                    GameObject childObject = null;
                    string     name        = split[1];

                    switch (split[0])
                    {
                    case "Reference":                             // Copy a child object or component from another prefab
                    {
                        Debug.Log($"[Nuterra] Deserializing Reference {name}");
                        if (TTReferences.GetReferenceFromBlockResource(name, out object reference))
                        {
                            Debug.Log($"[Nuterra] Found reference {reference}");
                            if (reference is GameObject || reference is Transform)
                            {
                                // If the reference was to a GameObject or a Transform, then we just want to copy that whole object
                                GameObject referenceObject = reference is GameObject ? (GameObject)reference : ((Transform)reference).gameObject;

                                childObject = GameObject.Instantiate(referenceObject);
                                string newName = name.Substring(1 + name.LastIndexOfAny(new char[] { '/', '.' }));
                                int    count   = 1;
                                while (target.transform.Find(newName))
                                {
                                    newName = $"{name}_{++count}";
                                }
                                childObject.name = newName;
                                childObject.transform.SetParent(target.transform);
                                childObject.transform.localPosition = referenceObject.transform.localPosition;
                                childObject.transform.localRotation = referenceObject.transform.localRotation;
                                childObject.transform.localScale    = referenceObject.transform.localScale;
                            }
                            else if (reference is Component)
                            {
                                // If we referenced a Component, we want to place a copy of that component on our target
                                // However, if we already have a Component of the same type, we most likely want to override its values.
                                // This functionality is as per TTQMM
                                Type      type = reference.GetType();
                                Component existingComponent = target.GetComponent(type);
                                if (existingComponent == null)
                                {
                                    existingComponent = target.AddComponent(type);
                                }

                                // Copy the reference and then deserialize our JSON into it
                                ShallowCopy(type, reference, existingComponent, false);
                                DeserializeJSONObject(existingComponent, type, jProperty.Value as JObject);
                                continue;
                            }
                            else
                            {
                                Debug.LogError($"[Nuterra] Unknown object {reference} found as reference");
                                continue;
                            }
                        }
                        else
                        {
                            Debug.LogError($"[Nuterra] Could not find reference for {name} in deserialization");
                            continue;
                        }
                        break;
                    }

                    case "Duplicate":                             // Copy a child object from this prefab
                    {
                        Debug.Log($"[Nuterra] Deserializing Duplicate {name}");
                        if (name.Contains('/') || name.Contains('.'))
                        {
                            object foundObject = GetCurrentSearchTransform().RecursiveFindWithProperties(name);
                            if (foundObject != null)
                            {
                                if (foundObject is Component foundComponent)
                                {
                                    childObject = foundComponent.gameObject;
                                }
                                else if (foundObject is GameObject foundGameObject)
                                {
                                    childObject = foundGameObject;
                                }
                            }
                        }

                        if (childObject == null)
                        {
                            childObject = target.transform.Find(name)?.gameObject;
                        }

                        break;
                    }

                    case "GameObject":                             // Create a new child object
                    case "Instantiate":                            // Instantiate something
                    default:
                    {
                        Debug.Log($"[Nuterra] Deserializing {split[0]}|{name}");

                        if (childObject == null)
                        {
                            childObject = target.transform.Find(name)?.gameObject;
                        }

                        break;
                    }
                    }

                    // Fallback, just make an empty object
                    if (childObject == null)
                    {
                        if (jProperty.Value.Type == JTokenType.Null)
                        {
                            Debug.Log($"[Nuterra] Deserializing failed to find {name} to delete");
                            continue;
                        }
                        else
                        {
                            childObject = new GameObject(name);
                            childObject.transform.parent = target.transform;
                        }
                    }
                    else
                    {
                        // If we've got no JSON data, that means we want to delete this target
                        if (jProperty.Value.Type == JTokenType.Null)
                        {
                            GameObject.DestroyImmediate(childObject);
                            childObject = null;
                            continue;
                        }
                        else if (split[0] == "Duplicate")
                        {
                            childObject = GameObject.Instantiate(childObject);
                            name        = name.Substring(1 + name.LastIndexOfAny(new char[] { '/', '.' }));
                            string newName = $"{name}_copy";
                            int    count   = 1;
                            while (target.transform.Find(newName))
                            {
                                newName = $"{name}_copy_{(++count)}";
                            }
                            childObject.name                    = newName;
                            childObject.transform.parent        = target.transform;
                            childObject.transform.localPosition = Vector3.zero;
                            childObject.transform.localRotation = Quaternion.identity;
                            childObject.transform.localScale    = Vector3.one;
                        }
                    }

                    Debug.Log($"[Nuterra] Deserializing jProp {jProperty.Name} --- {jProperty.Value}");
                    DeserializeIntoGameObject_Internal((JObject)jProperty.Value, childObject);
                }
            }

            return(target);
        }