Exemple #1
0
 ///<summary>
 /// Update the Sensor attributes with given SApiObject.
 ///</summary>
 ///<param name="_src">The SApiObject used to update attributes</param>
 public override void UpdateFromSApiObject(SApiObject _src)
 {
     name        = _src.name;
     id          = _src.id;
     parentId    = _src.parentId;
     category    = _src.category;
     domain      = _src.domain;
     description = _src.description;
     attributes  = _src.attributes;
 }
Exemple #2
0
 ///<summary>
 /// Parse a nested SApiObject and add each item to a given list.
 ///</summary>
 ///<param name="_list">The list of objects to complete</param>
 ///<param name="_src">The head of nested SApiObjects</param>
 public static void ParseNestedObjects(List <SApiObject> _list, SApiObject _src)
 {
     _list.Add(_src);
     if (_src.children != null)
     {
         foreach (SApiObject obj in _src.children)
         {
             ParseNestedObjects(_list, obj);
         }
     }
 }
Exemple #3
0
    ///<summary>
    /// Create an PUT request from _input.
    ///</summary>
    ///<param name="_obj">The OgreeObject to put</param>
    public void CreatePutRequest(OgreeObject _obj)
    {
        SRequest request = new SRequest();

        request.type = "put";

        SApiObject apiObj = new SApiObject(_obj);

        request.path = $"/{apiObj.category}s/{apiObj.id}";
        request.json = JsonConvert.SerializeObject(apiObj);
        requestsToSend.Enqueue(request);
    }
Exemple #4
0
    ///<summary>
    /// Create an OgreeObject of "site" category and assign given values to it
    ///</summary>
    ///<param name="_si">The site data to apply</param>
    ///<param name="_parent">The parent of the created site. Leave null if _bd contains the parendId</param>
    ///<returns>The created Site</returns>
    public OgreeObject CreateSite(SApiObject _si, Transform _parent = null)
    {
        Transform tn = Utils.FindParent(_parent, _si.parentId);

        if (!tn || tn.GetComponent <OgreeObject>().category != "tenant")
        {
            GameManager.gm.AppendLogLine($"Parent tenant not found", true, eLogtype.error);
            return(null);
        }

        string hierarchyName = $"{tn.GetComponent<OgreeObject>().hierarchyName}.{_si.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        GameObject newSite = new GameObject(_si.name);

        newSite.transform.parent = tn;

        OgreeObject site = newSite.AddComponent <OgreeObject>();

        site.UpdateFromSApiObject(_si);

        switch (site.attributes["orientation"])
        {
        case "EN":
            newSite.transform.localEulerAngles = new Vector3(0, 0, 0);
            break;

        case "WS":
            newSite.transform.localEulerAngles = new Vector3(0, 180, 0);
            break;

        case "NW":
            newSite.transform.localEulerAngles = new Vector3(0, -90, 0);
            break;

        case "SE":
            newSite.transform.localEulerAngles = new Vector3(0, 90, 0);
            break;
        }

        string hn = site.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newSite);

        return(site);
    }
Exemple #5
0
    ///<summary>
    /// Instantiate a buildingModel (from GameManager) and apply the given data to it.
    ///</summary>
    ///<param name="_bd">The building data to apply</param>
    ///<param name="_parent">The parent of the created building. Leave null if _bd contains the parendId</param>
    ///<returns>The created Building</returns>
    public Building CreateBuilding(SApiObject _bd, Transform _parent = null)
    {
        Transform si = Utils.FindParent(_parent, _bd.parentId);

        if (!si || si.GetComponent <OgreeObject>().category != "site")
        {
            GameManager.gm.AppendLogLine($"Parent site not found", true, eLogtype.error);
            return(null);
        }
        string hierarchyName = $"{si.GetComponent<OgreeObject>().hierarchyName}.{_bd.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        // Position and size data from _bd.attributes
        Vector2 posXY  = JsonUtility.FromJson <Vector2>(_bd.attributes["posXY"]);
        Vector2 size   = JsonUtility.FromJson <Vector2>(_bd.attributes["size"]);
        float   height = float.Parse(_bd.attributes["height"]);

        GameObject newBD = Instantiate(GameManager.gm.buildingModel);

        newBD.name                       = _bd.name;
        newBD.transform.parent           = si;
        newBD.transform.localEulerAngles = Vector3.zero;

        // originalSize
        Vector3 originalSize = newBD.transform.GetChild(0).localScale;

        newBD.transform.GetChild(0).localScale = new Vector3(originalSize.x * size.x, originalSize.y, originalSize.z * size.y);

        Vector3 origin = newBD.transform.GetChild(0).localScale / 0.2f;

        newBD.transform.localPosition  = new Vector3(origin.x, 0, origin.z);
        newBD.transform.localPosition += new Vector3(posXY.x, 0, posXY.y);

        Building building = newBD.GetComponent <Building>();

        building.UpdateFromSApiObject(_bd);

        BuildWalls(building.walls, new Vector3(newBD.transform.GetChild(0).localScale.x * 10, height, newBD.transform.GetChild(0).localScale.z * 10), 0);

        string hn = building.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newBD);

        return(building);
    }
Exemple #6
0
    ///<summary>
    /// Move the given Transform to given position in tiles in a room.
    ///</summary>
    ///<param name="_obj">The object to move</param>
    ///<param name="_apiObj">The SApiObject with posXY and posU data</param>
    private void PlaceInRoom(Transform _obj, SApiObject _apiObj, out Vector2 _orient)
    {
        float floorUnit = GetUnitFromRoom(_obj.parent.GetComponent <Room>());

        Vector2 pos    = JsonUtility.FromJson <Vector2>(_apiObj.attributes["posXY"]);
        Vector3 origin = _obj.parent.GetChild(0).localScale / 0.2f;

        _obj.position = _obj.parent.GetChild(0).position;

        _orient = new Vector2();
        if (_obj.parent.GetComponent <Room>().attributes.ContainsKey("orientation"))
        {
            if (Regex.IsMatch(_obj.parent.GetComponent <Room>().attributes["orientation"], "\\+[ENSW]{1}\\+[ENSW]{1}$"))
            {
                // Lower Left corner of the room
                _orient = new Vector2(1, 1);
            }
            else if (Regex.IsMatch(_obj.parent.GetComponent <Room>().attributes["orientation"], "\\-[ENSW]{1}\\+[ENSW]{1}$"))
            {
                // Lower Right corner of the room
                _orient = new Vector2(-1, 1);
                if (_apiObj.category == "rack")
                {
                    _obj.localPosition -= new Vector3(_obj.GetChild(0).localScale.x, 0, 0);
                }
            }
            else if (Regex.IsMatch(_obj.parent.GetComponent <Room>().attributes["orientation"], "\\-[ENSW]{1}\\-[ENSW]{1}$"))
            {
                // Upper Right corner of the room
                _orient = new Vector2(-1, -1);
                if (_apiObj.category == "rack")
                {
                    _obj.localPosition -= new Vector3(_obj.GetChild(0).localScale.x, 0, _obj.GetChild(0).localScale.z);
                }
            }
            else if (Regex.IsMatch(_obj.parent.GetComponent <Room>().attributes["orientation"], "\\+[ENSW]{1}\\-[ENSW]{1}$"))
            {
                // Upper Left corner of the room
                _orient = new Vector2(1, -1);
                if (_apiObj.category == "rack")
                {
                    _obj.localPosition -= new Vector3(0, 0, _obj.GetChild(0).localScale.z);
                }
            }
        }
        // Go to the right corner of the room & apply pos
        _obj.localPosition += new Vector3(origin.x * -_orient.x, 0, origin.z * -_orient.y);
        _obj.localPosition += new Vector3(pos.x * _orient.x, 0, pos.y * _orient.y) * floorUnit;
    }
Exemple #7
0
    ///<summary>
    /// Set temperature attribute and create/update related sensor object.
    ///</summary>
    ///<param name="_value">The temperature value</param>
    public async void SetTemperature(string _value)
    {
        if (category == "corridor")
        {
            if (Regex.IsMatch(_value, "^(cold|warm)$"))
            {
                attributes["temperature"] = _value;
            }
            else
            {
                GameManager.gm.AppendLogLine("Temperature must be \"cold\" or \"warm\"", true, eLogtype.warning);
            }
        }
        else
        {
            if (Regex.IsMatch(_value, "^[0-9.]+$"))
            {
                attributes["temperature"] = _value;
                GameObject sensor = GameManager.gm.FindByAbsPath($"{hierarchyName}.sensor");
                if (sensor)
                {
                    sensor.GetComponent <Sensor>().SetAttribute("temperature", _value);
                }
                else
                {
                    SApiObject se = new SApiObject
                    {
                        description = new List <string>(),
                        attributes  = new Dictionary <string, string>(),

                        name     = "sensor", // ?
                        category = "sensor",
                        parentId = id,
                        domain   = domain
                    };
                    se.attributes["formFactor"]  = "ext";
                    se.attributes["temperature"] = _value;

                    await OgreeGenerator.instance.CreateItemFromSApiObject(se, transform);
                }
            }
            else
            {
                GameManager.gm.AppendLogLine("Temperature must be a numeral value", true, eLogtype.warning);
            }
        }
    }
Exemple #8
0
    ///<summary>
    /// Create OgreeObject of "tenant" category from given data.
    ///</summary>
    ///<param name="_tn">The tenant data to apply</param>
    ///<returns>The created Tenant</returns>
    public OgreeObject CreateTenant(SApiObject _tn)
    {
        if (GameManager.gm.allItems.Contains(_tn.name))
        {
            GameManager.gm.AppendLogLine($"{_tn.name} already exists.", true, eLogtype.error);
            return(null);
        }

        GameObject  newTenant = new GameObject(_tn.name);
        OgreeObject tenant    = newTenant.AddComponent <OgreeObject>();

        tenant.UpdateFromSApiObject(_tn);
        tenant.UpdateHierarchyName();
        GameManager.gm.allItems.Add(_tn.name, newTenant);

        return(tenant);
    }
Exemple #9
0
    ///<summary>
    /// Deserialize given SApiObject and call the good generator.
    ///</summary>
    ///<param name="_input">The SApiObject to deserialize</param>
    private async void CreateObjectFromData(string _input)
    {
        SApiObject        src             = JsonConvert.DeserializeObject <SApiObject>(_input);
        List <SApiObject> physicalObjects = new List <SApiObject>();
        List <SApiObject> logicalObjects  = new List <SApiObject>();

        Utils.ParseNestedObjects(physicalObjects, logicalObjects, src);

        foreach (SApiObject obj in physicalObjects)
        {
            await OgreeGenerator.instance.CreateItemFromSApiObject(obj);
        }

        foreach (SApiObject obj in logicalObjects)
        {
            await OgreeGenerator.instance.CreateItemFromSApiObject(obj);
        }
    }
Exemple #10
0
    ///<summary>
    /// Update the OObject attributes with given SApiObject.
    ///</summary>
    ///<param name="_src">The SApiObject used to update attributes</param>
    public override void UpdateFromSApiObject(SApiObject _src)
    {
        name     = _src.name;
        id       = _src.id;
        parentId = _src.parentId;
        category = _src.category;
        if (domain != _src.domain)
        {
            domain = _src.domain;
            UpdateColorByTenant();
        }
        description = _src.description;

        if (attributes.ContainsKey("temperature") && _src.attributes.ContainsKey("temperature") &&
            attributes["temperature"] != _src.attributes["temperature"])
        {
            SetTemperature(_src.attributes["temperature"]);
        }
        else if (!attributes.ContainsKey("temperature") && _src.attributes.ContainsKey("temperature"))
        {
            SetTemperature(_src.attributes["temperature"]);
        }
        else if (attributes.ContainsKey("temperature") && !_src.attributes.ContainsKey("temperature"))
        {
            Destroy(transform.Find("sensor").gameObject);
        }

        attributes = _src.attributes;

        if (transform.parent?.GetComponent <OgreeObject>().category == "room")
        {
            referent = this;
        }
        else if (transform.parent.GetComponent <OObject>().referent != null)
        {
            referent = transform.parent.GetComponent <OObject>().referent;
        }
        else
        {
            referent = null;
        }
    }
Exemple #11
0
    ///<summary>
    /// Deserialize given SApiObject and apply modification to corresponding object.
    ///</summary>
    ///<param name="_input">The SApiObject to deserialize</param>
    private void ModifyObject(string _input)
    {
        SApiObject  newData = JsonConvert.DeserializeObject <SApiObject>(_input);
        OgreeObject obj     = Utils.GetObjectById(newData.id).GetComponent <OgreeObject>();

        // Case domain for all OgreeObjects
        bool tenantColorChanged = false;

        if (newData.category == "tenant" && obj.attributes["color"] != newData.attributes["color"])
        {
            tenantColorChanged = true;
        }

        // Case color/temperature for racks & devices
        if (newData.category == "rack" || newData.category == "device")
        {
            OObject item = (OObject)obj;
            if (newData.attributes.ContainsKey("color"))
            {
                if ((obj.attributes.ContainsKey("color") && obj.attributes["color"] != newData.attributes["color"]) ||
                    !item.attributes.ContainsKey("color"))
                {
                    item.SetColor(newData.attributes["color"]);
                }
            }
            if (newData.attributes.ContainsKey("temperature"))
            {
                if ((obj.attributes.ContainsKey("temperature") && obj.attributes["temperature"] != newData.attributes["temperature"]) ||
                    !item.attributes.ContainsKey("temperature"))
                {
                    item.SetTemperature(newData.attributes["temperature"]);
                }
            }
        }

        // Case of a separator/areas modification in a room
        if (newData.category == "room")
        {
            Room room = (Room)obj;
            if (newData.attributes.ContainsKey("separators"))
            {
                if ((room.attributes.ContainsKey("separators") && room.attributes["separators"] != newData.attributes["separators"]) ||
                    !room.attributes.ContainsKey("separators"))
                {
                    foreach (Transform wall in room.walls)
                    {
                        if (wall.name.Contains("separator"))
                        {
                            Object.Destroy(wall.gameObject);
                        }
                    }
                    List <ReadFromJson.SSeparator> separators = JsonConvert.DeserializeObject <List <ReadFromJson.SSeparator> >(newData.attributes["separators"]);
                    foreach (ReadFromJson.SSeparator sep in separators)
                    {
                        room.AddSeparator(sep);
                    }
                }
            }
            if (newData.attributes.ContainsKey("reserved"))
            {
                if ((room.attributes.ContainsKey("reserved") && room.attributes["reserved"] != newData.attributes["reserved"]) ||
                    !room.attributes.ContainsKey("reserved"))
                {
                    SMargin reserved  = JsonUtility.FromJson <SMargin>(newData.attributes["reserved"]);
                    SMargin technical = JsonUtility.FromJson <SMargin>(newData.attributes["technical"]);
                    room.SetAreas(reserved, technical);
                }
            }
        }

        obj.UpdateFromSApiObject(newData);
        if (tenantColorChanged)
        {
            EventManager.Instance.Raise(new UpdateTenantEvent {
                name = newData.name
            });
        }
    }
Exemple #12
0
    ///<summary>
    /// Call the good CreateX function according to the item's category.
    ///</summary>
    ///<param name="_obj">The item to generate</param>
    public async Task <OgreeObject> CreateItemFromSApiObject(SApiObject _obj, Transform _parent = null)
    {
        OgreeObject newItem;

        // Get dependencies from API
        if (_obj.category != "tenant" && !string.IsNullOrEmpty(_obj.domain) &&
            !GameManager.gm.allItems.Contains(_obj.domain))
        {
            await ApiManager.instance.GetObject($"tenants?name={_obj.domain}", ApiManager.instance.DrawObject);
        }

        if (_obj.category == "room" && !string.IsNullOrEmpty(_obj.attributes["template"]) &&
            !GameManager.gm.roomTemplates.ContainsKey(_obj.attributes["template"]))
        {
            Debug.Log($"Get template \"{_obj.attributes["template"]}\" from API");
            await ApiManager.instance.GetObject($"room-templates/{_obj.attributes["template"]}", ApiManager.instance.DrawObject);
        }

        if ((_obj.category == "rack" || _obj.category == "device") && !string.IsNullOrEmpty(_obj.attributes["template"]) &&
            !GameManager.gm.objectTemplates.ContainsKey(_obj.attributes["template"]))
        {
            Debug.Log($"Get template \"{_obj.attributes["template"]}\" from API");
            await ApiManager.instance.GetObject($"obj-templates/{_obj.attributes["template"]}", ApiManager.instance.DrawObject);
        }

        // Call Create function
        switch (_obj.category)
        {
        case "tenant":
            newItem = customerGenerator.CreateTenant(_obj);
            break;

        case "site":
            newItem = customerGenerator.CreateSite(_obj, _parent);
            break;

        case "building":
            newItem = buildingGenerator.CreateBuilding(_obj, _parent);
            break;

        case "room":
            newItem = buildingGenerator.CreateRoom(_obj, _parent);
            break;

        case "rack":
            newItem = objectGenerator.CreateRack(_obj, _parent);
            break;

        case "device":
            newItem = objectGenerator.CreateDevice(_obj, _parent);
            break;

        case "corridor":
            newItem = objectGenerator.CreateCorridor(_obj, _parent);
            break;

        case "group":
            newItem = objectGenerator.CreateGroup(_obj, _parent);
            break;

        case "sensor":
            newItem = objectGenerator.CreateSensor(_obj, _parent);
            break;

        default:
            newItem = null;
            GameManager.gm.AppendLogLine($"Unknown object type ({_obj.category})", true, eLogtype.error);
            break;
        }
        ResetCoroutine();
        return(newItem);
    }
Exemple #13
0
    ///<summary>
    /// Generate a sensor (from GameManager.sensorExtModel/sensorIntModel) with defined temperature.
    ///</summary>
    ///<param name="_se">The sensor data to apply</param>
    ///<param name="_parent">The parent of the created sensor. Leave null if _se contains the parendId</param>
    ///<returns>The created sensor</returns>
    public Sensor CreateSensor(SApiObject _se, Transform _parent = null)
    {
        Transform parent = Utils.FindParent(_parent, _se.parentId);

        if (!parent)
        {
            GameManager.gm.AppendLogLine($"Parent not found", true, eLogtype.error);
            return(null);
        }
        string parentCategory = parent.GetComponent <OgreeObject>().category;

        if (_se.attributes["formFactor"] == "ext" &&
            (parentCategory != "rack" && parentCategory != "device"))
        {
            GameManager.gm.AppendLogLine("An external sensor must be child of a rack or a device", true, eLogtype.error);
            return(null);
        }
        if (_se.attributes["formFactor"] == "int" &&
            (parentCategory != "room" && parentCategory != "rack" && parentCategory != "device"))
        {
            GameManager.gm.AppendLogLine("An internal sensor must be child of a room, a rack or a device", true, eLogtype.error);
            return(null);
        }

        string hierarchyName = $"{parent.GetComponent<OgreeObject>().hierarchyName}.{_se.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        GameObject newSensor;

        if (_se.attributes["formFactor"] == "ext") //Dimensions : 80 x 26 x 18 mm
        {
            newSensor      = Instantiate(GameManager.gm.sensorExtModel, _parent);
            newSensor.name = "sensor";

            Vector3 parentSize = _parent.GetChild(0).localScale;
            Vector3 boxSize    = newSensor.transform.GetChild(0).localScale;
            newSensor.transform.localPosition  = new Vector3(-parentSize.x, parentSize.y, parentSize.z) / 2;
            newSensor.transform.localPosition += new Vector3(boxSize.x, -boxSize.y, 0) / 2;
        }
        else
        {
            newSensor      = Instantiate(GameManager.gm.sensorIntModel, _parent);
            newSensor.name = _se.name;
            if (parentCategory == "room")
            {
                PlaceInRoom(newSensor.transform, _se, out Vector2 orient);

                // Adjust position
                float floorUnit = GetUnitFromRoom(parent.GetComponent <Room>());
                newSensor.transform.localPosition   += new Vector3(floorUnit * orient.x, 0, floorUnit * orient.y) / 2;
                newSensor.transform.localEulerAngles = new Vector3(0, 180, 0);

                float posU = float.Parse(_se.attributes["posU"]);
                if (posU == 0)
                {
                    newSensor.transform.localPosition += Vector3.up;
                }
                else
                {
                    newSensor.transform.localScale     = 5 * GameManager.gm.uSize * Vector3.one;
                    newSensor.transform.localPosition += Vector3.up * (posU * GameManager.gm.uSize);
                }
            }
            else
            {
                newSensor.transform.localPosition = parent.GetChild(0).localScale / -2;
                // Assuming given pos is in mm
                Vector2 posXY  = JsonUtility.FromJson <Vector2>(_se.attributes["posXY"]);
                Vector3 newPos = new Vector3(posXY.x, float.Parse(_se.attributes["posU"]), posXY.y) / 1000;
                newSensor.transform.localPosition += newPos;

                newSensor.transform.GetChild(0).localScale = Vector3.one * 0.05f;
                newSensor.transform.localEulerAngles       = Vector3.zero;
            }
        }

        Sensor sensor = newSensor.GetComponent <Sensor>();

        sensor.UpdateFromSApiObject(_se);

        sensor.UpdateSensorColor();
        newSensor.GetComponent <DisplayObjectData>().PlaceTexts("front");
        newSensor.GetComponent <DisplayObjectData>().SetLabel("#temperature");



        string hn = sensor.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newSensor);

        return(sensor);
    }
Exemple #14
0
    ///<summary>
    /// Instantiate a deviceModel or a deviceTemplate (from GameManager) and apply given data to it.
    ///</summary>
    ///<param name="_dv">The device data to apply</param>
    ///<param name="_parent">The parent of the created device. Leave null if _dv contains the parendId</param>
    ///<returns>The created Device</returns>
    public OObject CreateDevice(SApiObject _dv, Transform _parent = null)
    {
        // Check parent & parent category
        Transform parent = Utils.FindParent(_parent, _dv.parentId);

        if (!parent || parent.GetComponent <OObject>() == null)
        {
            GameManager.gm.AppendLogLine($"Device must be child of a Rack or another Device", true, eLogtype.error);
            return(null);
        }

        // Check parent for subdevice
        if (parent.GetComponent <Rack>() == null &&
            (string.IsNullOrEmpty(_dv.attributes["slot"]) || string.IsNullOrEmpty(_dv.attributes["template"])))
        {
            GameManager.gm.AppendLogLine("A sub-device needs to be declared with a parent's slot and a template", true, eLogtype.error);
            return(null);
        }

        // Check if parent not hidden in a group
        if (parent.gameObject.activeSelf == false)
        {
            GameManager.gm.AppendLogLine("The parent object must be active (not hidden in a group)", true, eLogtype.error);
            return(null);
        }

        // Check if unique hierarchyName
        string hierarchyName = $"{parent.GetComponent<OgreeObject>().hierarchyName}.{_dv.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        // Check template
        if (!string.IsNullOrEmpty(_dv.attributes["template"]) && !GameManager.gm.objectTemplates.ContainsKey(_dv.attributes["template"]))
        {
            GameManager.gm.AppendLogLine($"Unknown template \"{_dv.attributes["template"]}\"", true, eLogtype.error);
            return(null);
        }

        // Check slot
        Transform slot = null;

        if (!string.IsNullOrEmpty(_dv.attributes["slot"]))
        {
            List <Slot> takenSlots = new List <Slot>();
            int         i          = 0;
            float       max;
            if (string.IsNullOrEmpty(_dv.attributes["template"]))
            {
                max = float.Parse(_dv.attributes["sizeU"]);
            }
            else
            {
                max = float.Parse(GameManager.gm.objectTemplates[_dv.attributes["template"]].GetComponent <OgreeObject>().attributes["height"]) / 1000 / GameManager.gm.uSize;
            }
            foreach (Transform child in parent)
            {
                if ((child.name == _dv.attributes["slot"] || (i > 0 && i < max)) && child.GetComponent <Slot>())
                {
                    takenSlots.Add(child.GetComponent <Slot>());
                    i++;
                }
            }

            if (takenSlots.Count > 0)
            {
                foreach (Slot s in takenSlots)
                {
                    s.SlotTaken(true);
                }
                slot = takenSlots[0].transform;
            }
            else
            {
                GameManager.gm.AppendLogLine($"Slot {_dv.attributes["slot"]} not found in {parent.name}", true, eLogtype.error);
                return(null);
            }
        }

        // Generate device
        GameObject newDevice;
        Vector2    size;
        float      height;

        if (string.IsNullOrEmpty(_dv.attributes["template"]))
        {
            newDevice = GenerateBasicDevice(parent, Utils.ParseDecFrac(_dv.attributes["height"]), slot);
            Vector3 boxSize = newDevice.transform.GetChild(0).localScale;
            size   = new Vector2(boxSize.x, boxSize.z);
            height = boxSize.y;
        }
        else
        {
            newDevice = GenerateTemplatedDevice(parent, _dv.attributes["template"]);
            OgreeObject tmp = newDevice.GetComponent <OgreeObject>();
            size   = JsonUtility.FromJson <Vector2>(tmp.attributes["size"]) / 1000;
            height = float.Parse(tmp.attributes["height"]) / 1000;
        }

        // Place the device
        if (!string.IsNullOrEmpty(_dv.attributes["slot"]))
        {
            newDevice.transform.localEulerAngles = slot.localEulerAngles;
            newDevice.transform.localPosition    = slot.localPosition;

            if (height > slot.GetChild(0).localScale.y)
            {
                newDevice.transform.localPosition += new Vector3(0, height / 2 - GameManager.gm.uSize / 2, 0);
            }

            float deltaZ = slot.GetChild(0).localScale.z - size.y;
            switch (_dv.attributes["orientation"])
            {
            case "front":
                newDevice.transform.localPosition += new Vector3(0, 0, deltaZ / 2);
                break;

            case "rear":
                newDevice.transform.localPosition    -= new Vector3(0, 0, deltaZ / 2);
                newDevice.transform.localEulerAngles += new Vector3(0, 180, 0);
                break;

            case "frontflipped":
                newDevice.transform.localPosition    += new Vector3(0, 0, deltaZ / 2);
                newDevice.transform.localEulerAngles += new Vector3(0, 0, 180);
                break;

            case "rearflipped":
                newDevice.transform.localPosition    -= new Vector3(0, 0, deltaZ / 2);
                newDevice.transform.localEulerAngles += new Vector3(180, 0, 0);
                break;
            }

            // if slot, color
            Material mat       = newDevice.transform.GetChild(0).GetComponent <Renderer>().material;
            Color    slotColor = slot.GetChild(0).GetComponent <Renderer>().material.color;
            mat.color = new Color(slotColor.r, slotColor.g, slotColor.b);
            newDevice.GetComponent <OObject>().color = mat.color;
        }
        else
        {
            newDevice.transform.localEulerAngles = Vector3.zero;
            newDevice.transform.localPosition    = new Vector3(0, (-parent.GetChild(0).localScale.y + height) / 2, 0);
            if (_dv.attributes.ContainsKey("posU"))
            {
                newDevice.transform.localPosition += new Vector3(0, (float.Parse(_dv.attributes["posU"]) - 1) * GameManager.gm.uSize, 0);
            }

            float deltaZ = parent.GetChild(0).localScale.z - size.y;
            newDevice.transform.localPosition       += new Vector3(0, 0, deltaZ / 2);
            newDevice.GetComponent <OObject>().color = Color.white;
        }

        // Fill OObject class
        newDevice.name = _dv.name;
        OObject dv = newDevice.GetComponent <OObject>();

        dv.UpdateFromSApiObject(_dv);

        // Set labels
        if (string.IsNullOrEmpty(dv.attributes["slot"]))
        {
            newDevice.GetComponent <DisplayObjectData>().PlaceTexts("frontrear");
        }
        else
        {
            newDevice.GetComponent <DisplayObjectData>().PlaceTexts(slot?.GetComponent <Slot>().labelPos);
        }
        newDevice.GetComponent <DisplayObjectData>().SetLabel("#name");

        string hn = dv.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newDevice);

        if (!string.IsNullOrEmpty(_dv.attributes["template"]))
        {
            OObject[] components = newDevice.transform.GetComponentsInChildren <OObject>();
            foreach (OObject comp in components)
            {
                if (comp.gameObject != newDevice)
                {
                    comp.domain = dv.domain;
                    string compHn = comp.UpdateHierarchyName();
                    GameManager.gm.allItems.Add(compHn, comp.gameObject);
                    comp.referent = dv.referent;
                }
            }
        }
        return(dv);
    }
Exemple #15
0
    ///<summary>
    /// Instantiate a rackModel or a rackTemplate (from GameManager) and apply the given data to it.
    ///</summary>
    ///<param name="_rk">The rack data to apply</param>
    ///<param name="_parent">The parent of the created rack. Leave null if _rk contains the parendId</param>
    ///<returns>The created Rack</returns>
    public Rack CreateRack(SApiObject _rk, Transform _parent = null)
    {
        Transform parent = Utils.FindParent(_parent, _rk.parentId);

        if (!parent || parent.GetComponent <OgreeObject>().category != "room")
        {
            GameManager.gm.AppendLogLine($"Parent room not found", true, eLogtype.error);
            return(null);
        }

        string hierarchyName = $"{parent.GetComponent<OgreeObject>().hierarchyName}.{_rk.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        GameObject newRack;

        if (string.IsNullOrEmpty(_rk.attributes["template"]))
        {
            newRack = Instantiate(GameManager.gm.rackModel);
        }
        else
        {
            if (GameManager.gm.objectTemplates.ContainsKey(_rk.attributes["template"]))
            {
                newRack = Instantiate(GameManager.gm.objectTemplates[_rk.attributes["template"]]);
            }
            else
            {
                GameManager.gm.AppendLogLine($"Unknown template \"{_rk.attributes["template"]}\"", true, eLogtype.error);
                return(null);
            }
            Renderer[] renderers = newRack.GetComponentsInChildren <Renderer>();
            foreach (Renderer r in renderers)
            {
                r.enabled = true;
            }
            newRack.transform.GetChild(0).GetComponent <Collider>().enabled = true;
        }

        newRack.name             = _rk.name;
        newRack.transform.parent = parent;

        if (string.IsNullOrEmpty(_rk.attributes["template"]))
        {
            Vector2 size   = JsonUtility.FromJson <Vector2>(_rk.attributes["size"]);
            float   height = float.Parse(_rk.attributes["height"]);
            if (_rk.attributes["heightUnit"] == "U")
            {
                height *= GameManager.gm.uSize;
            }
            else if (_rk.attributes["heightUnit"] == "cm")
            {
                height /= 100;
            }
            newRack.transform.GetChild(0).localScale = new Vector3(size.x / 100, height, size.y / 100);
        }

        PlaceInRoom(newRack.transform, _rk, out Vector2 orient);

        Rack rack = newRack.GetComponent <Rack>();

        rack.UpdateFromSApiObject(_rk);

        // Correct position according to rack size & rack orientation
        Vector3   boxOrigin;
        Transform box = newRack.transform.GetChild(0);

        if (box.childCount == 0)
        {
            boxOrigin = box.localScale / 2;
        }
        else
        {
            boxOrigin = box.GetComponent <BoxCollider>().size / 2;
        }
        float   floorUnit = GetUnitFromRoom(parent.GetComponent <Room>());
        Vector3 fixPos    = Vector3.zero;

        switch (rack.attributes["orientation"])
        {
        case "front":
            newRack.transform.localEulerAngles = new Vector3(0, 180, 0);
            if (orient.y == 1)
            {
                fixPos = new Vector3(boxOrigin.x, boxOrigin.y, boxOrigin.z);
            }
            else
            {
                fixPos = new Vector3(boxOrigin.x, boxOrigin.y, boxOrigin.z + floorUnit);
            }
            break;

        case "rear":
            newRack.transform.localEulerAngles = new Vector3(0, 0, 0);
            if (orient.y == 1)
            {
                fixPos = new Vector3(boxOrigin.x, boxOrigin.y, -boxOrigin.z + floorUnit);
            }
            else
            {
                fixPos = new Vector3(boxOrigin.x, boxOrigin.y, boxOrigin.z);
            }
            break;

        case "left":
            newRack.transform.localEulerAngles = new Vector3(0, 90, 0);
            if (orient.x == 1)
            {
                fixPos = new Vector3(-boxOrigin.z + floorUnit, boxOrigin.y, boxOrigin.x);
            }
            else
            {
                fixPos = new Vector3(boxOrigin.z, boxOrigin.y, boxOrigin.x);
            }
            break;

        case "right":
            newRack.transform.localEulerAngles = new Vector3(0, -90, 0);
            if (orient.x == 1)
            {
                fixPos = new Vector3(boxOrigin.z, boxOrigin.y, -boxOrigin.x + floorUnit);
            }
            else
            {
                fixPos = new Vector3(-boxOrigin.z + floorUnit, boxOrigin.y, -boxOrigin.x + floorUnit);
            }
            break;
        }
        newRack.transform.localPosition += fixPos;

        newRack.GetComponent <DisplayObjectData>().PlaceTexts("frontrear");
        newRack.GetComponent <DisplayObjectData>().SetLabel("#name");

        rack.UpdateColorByTenant();

        string hn = rack.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newRack);

        if (!string.IsNullOrEmpty(rack.attributes["template"]))
        {
            OObject[] components = rack.transform.GetComponentsInChildren <OObject>();
            foreach (OObject comp in components)
            {
                if (comp.gameObject != rack.gameObject)
                {
                    comp.domain = rack.domain;
                    string compHn = comp.UpdateHierarchyName();
                    GameManager.gm.allItems.Add(compHn, comp.gameObject);
                    comp.referent = rack;
                }
            }
        }
        return(rack);
    }
Exemple #16
0
    ///<summary>
    /// Instantiate a roomModel (from GameManager) and apply given data to it.
    ///</summary>
    ///<param name="_ro">The room data to apply</param>
    ///<param name="_parent">The parent of the created room. Leave null if _bd contains the parendId</param>
    ///<returns>The created Room</returns>
    public Room CreateRoom(SApiObject _ro, Transform _parent = null)
    {
        Transform bd = Utils.FindParent(_parent, _ro.parentId);

        if (!bd || bd.GetComponent <OgreeObject>().category != "building")
        {
            GameManager.gm.AppendLogLine($"Parent building not found", true, eLogtype.error);
            return(null);
        }
        string hierarchyName = $"{bd.GetComponent<OgreeObject>().hierarchyName}.{_ro.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        // Position and size data from _ro.attributes
        Vector2 posXY  = JsonUtility.FromJson <Vector2>(_ro.attributes["posXY"]);
        Vector2 size   = JsonUtility.FromJson <Vector2>(_ro.attributes["size"]);
        float   height = float.Parse(_ro.attributes["height"]);

        GameObject newRoom = Instantiate(GameManager.gm.roomModel);

        newRoom.name             = _ro.name;
        newRoom.transform.parent = bd;

        Room room = newRoom.GetComponent <Room>();

        room.UpdateFromSApiObject(_ro);

        Vector3 originalSize = room.usableZone.localScale;

        room.usableZone.localScale    = new Vector3(originalSize.x * size.x, originalSize.y, originalSize.z * size.y);
        room.reservedZone.localScale  = room.usableZone.localScale;
        room.technicalZone.localScale = room.usableZone.localScale;
        room.tilesEdges.localScale    = room.usableZone.localScale;
        room.tilesEdges.GetComponent <Renderer>().material.mainTextureScale  = size / 0.6f;
        room.tilesEdges.GetComponent <Renderer>().material.mainTextureOffset = new Vector2(size.x / 0.6f % 1, size.y / 0.6f % 1);
        BuildWalls(room.walls, new Vector3(room.usableZone.localScale.x * 10, height, room.usableZone.localScale.z * 10), -0.001f);

        Vector3 bdOrigin = bd.GetChild(0).localScale / -0.2f;
        Vector3 roOrigin = room.usableZone.localScale / 0.2f;

        newRoom.transform.position       = bd.position;
        newRoom.transform.localPosition += new Vector3(bdOrigin.x, 0, bdOrigin.z);
        newRoom.transform.localPosition += new Vector3(posXY.x, 0, posXY.y);

        if (Regex.IsMatch(room.attributes["orientation"], "(\\+|\\-)E(\\+|\\-)N"))
        {
            newRoom.transform.eulerAngles = new Vector3(0, 0, 0);
            newRoom.transform.position   += new Vector3(roOrigin.x, 0, roOrigin.z);
        }
        else if (Regex.IsMatch(room.attributes["orientation"], "(\\+|\\-)W(\\+|\\-)S"))
        {
            newRoom.transform.eulerAngles = new Vector3(0, 180, 0);
            newRoom.transform.position   += new Vector3(-roOrigin.x, 0, -roOrigin.z);
        }
        else if (Regex.IsMatch(room.attributes["orientation"], "(\\+|\\-)N(\\+|\\-)W"))
        {
            newRoom.transform.eulerAngles = new Vector3(0, -90, 0);
            newRoom.transform.position   += new Vector3(-roOrigin.z, 0, roOrigin.x);
        }
        else if (Regex.IsMatch(room.attributes["orientation"], "(\\+|\\-)S(\\+|\\-)E"))
        {
            newRoom.transform.eulerAngles = new Vector3(0, 90, 0);
            newRoom.transform.position   += new Vector3(roOrigin.z, 0, -roOrigin.x);
        }

        // Set UI room's name
        room.nameText.text = newRoom.name;
        room.nameText.rectTransform.sizeDelta = size;
        room.UpdateZonesColor();

        string hn = room.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newRoom);

        if (_ro.attributes.ContainsKey("reserved") && _ro.attributes.ContainsKey("technical") &&
            !string.IsNullOrEmpty(_ro.attributes["reserved"]) && !string.IsNullOrEmpty(_ro.attributes["technical"]))
        {
            SMargin reserved  = JsonUtility.FromJson <SMargin>(_ro.attributes["reserved"]);
            SMargin technical = JsonUtility.FromJson <SMargin>(_ro.attributes["technical"]);
            room.SetAreas(reserved, technical);
        }

        if (!string.IsNullOrEmpty(_ro.attributes["template"]) && GameManager.gm.roomTemplates.ContainsKey(_ro.attributes["template"]))
        {
            ReadFromJson.SRoomFromJson template = GameManager.gm.roomTemplates[_ro.attributes["template"]];

            room.SetAreas(new SMargin(template.reservedArea), new SMargin(template.technicalArea));

            if (template.separators != null)
            {
                foreach (ReadFromJson.SSeparator sep in template.separators)
                {
                    room.AddSeparator(sep);
                }
            }

            if (template.tiles != null)
            {
                List <ReadFromJson.STile> tiles = new List <ReadFromJson.STile>();
                foreach (ReadFromJson.STile t in template.tiles)
                {
                    tiles.Add(t);
                }
                room.attributes["tiles"] = JsonConvert.SerializeObject(tiles);
            }

            if (template.rows != null)
            {
                List <ReadFromJson.SRow> rows = new List <ReadFromJson.SRow>();
                foreach (ReadFromJson.SRow r in template.rows)
                {
                    rows.Add(r);
                }
                room.attributes["rows"] = JsonConvert.SerializeObject(rows);
            }

            if (template.colors != null)
            {
                List <ReadFromJson.SColor> colors = new List <ReadFromJson.SColor>();
                foreach (ReadFromJson.SColor c in template.colors)
                {
                    colors.Add(c);
                }
                room.attributes["customColors"] = JsonConvert.SerializeObject(colors);
            }
        }

        return(room);
    }
Exemple #17
0
 ///<summary>
 /// Parse a nested SApiObject and add each item to a given list.
 ///</summary>
 ///<param name="_physicalList">The list of physical objects to complete</param>
 ///<param name="_logicalList">The list of logical objects to complete</param>
 ///<param name="_src">The head of nested SApiObjects</param>
 public static void ParseNestedObjects(List <SApiObject> _physicalList, List <SApiObject> _logicalList, SApiObject _src)
 {
     if (_src.category == "group")
     {
         _logicalList.Add(_src);
     }
     else
     {
         _physicalList.Add(_src);
     }
     if (_src.children != null)
     {
         foreach (SApiObject obj in _src.children)
         {
             ParseNestedObjects(_physicalList, _logicalList, obj);
         }
     }
 }
Exemple #18
0
    ///<summary>
    /// Generate a corridor (from GameManager.labeledBoxModel) with defined corners and color.
    ///</summary>
    ///<param name="_co">The corridor data to apply</param>
    ///<param name="_parent">The parent of the created corridor. Leave null if _co contains the parendId</param>
    ///<returns>The created corridor</returns>
    public OObject CreateCorridor(SApiObject _co, Transform _parent = null)
    {
        Transform parent = Utils.FindParent(_parent, _co.parentId);

        if (!parent || parent.GetComponent <OgreeObject>().category != "room")
        {
            GameManager.gm.AppendLogLine($"Parent room not found", true, eLogtype.error);
            return(null);
        }

        string hierarchyName = $"{parent.GetComponent<OgreeObject>().hierarchyName}.{_co.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        string roomHierarchyName = parent.GetComponent <OgreeObject>().hierarchyName;

        string[]  rackNames  = _co.attributes["content"].Split(',');
        Transform lowerLeft  = GameManager.gm.FindByAbsPath($"{roomHierarchyName}.{rackNames[0]}")?.transform;
        Transform upperRight = GameManager.gm.FindByAbsPath($"{roomHierarchyName}.{rackNames[1]}")?.transform;

        if (lowerLeft == null || upperRight == null)
        {
            GameManager.gm.AppendLogLine($"{rackNames[0]} or {rackNames[1]} doesn't exist", true, eLogtype.error);
            return(null);
        }

        float maxHeight = lowerLeft.GetChild(0).localScale.y;

        if (upperRight.GetChild(0).localScale.y > maxHeight)
        {
            maxHeight = upperRight.GetChild(0).localScale.y;
        }

        GameObject newCo = Instantiate(GameManager.gm.labeledBoxModel);

        newCo.name             = _co.name;
        newCo.transform.parent = parent;

        float x = upperRight.localPosition.x - lowerLeft.localPosition.x;
        float z = upperRight.localPosition.z - lowerLeft.localPosition.z;

        if (lowerLeft.GetComponent <Rack>().attributes["orientation"] == "front" ||
            lowerLeft.GetComponent <Rack>().attributes["orientation"] == "rear")
        {
            x += (upperRight.GetChild(0).localScale.x + lowerLeft.GetChild(0).localScale.x) / 2;
            z -= (upperRight.GetChild(0).localScale.z + lowerLeft.GetChild(0).localScale.z) / 2;
        }
        else
        {
            x += (upperRight.GetChild(0).localScale.z + lowerLeft.GetChild(0).localScale.z) / 2;
            z -= (upperRight.GetChild(0).localScale.x + lowerLeft.GetChild(0).localScale.x) / 2;
        }
        newCo.transform.GetChild(0).localScale = new Vector3(x, maxHeight, z);

        newCo.transform.localEulerAngles = new Vector3(0, 180, 0);
        newCo.transform.localPosition    = new Vector3(lowerLeft.localPosition.x, maxHeight / 2, lowerLeft.localPosition.z);
        float xOffset = (newCo.transform.GetChild(0).localScale.x - lowerLeft.GetChild(0).localScale.x) / 2;
        float zOffset = (newCo.transform.GetChild(0).localScale.z + lowerLeft.GetChild(0).localScale.z) / 2;

        newCo.transform.localPosition += new Vector3(xOffset, 0, zOffset);

        OObject co = newCo.AddComponent <OObject>();

        co.UpdateFromSApiObject(_co);

        newCo.transform.GetChild(0).GetComponent <Renderer>().material = GameManager.gm.alphaMat;
        Material mat = newCo.transform.GetChild(0).GetComponent <Renderer>().material;

        mat.color = new Color(mat.color.r, mat.color.g, mat.color.b, 0.5f);
        if (_co.attributes["temperature"] == "cold")
        {
            co.SetAttribute("color", "000099");
        }
        else
        {
            co.SetAttribute("color", "990000");
        }

        newCo.GetComponent <DisplayObjectData>().PlaceTexts("top");
        newCo.GetComponent <DisplayObjectData>().SetLabel("#name");

        string hn = co.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newCo);

        return(co);
    }
Exemple #19
0
    ///<summary>
    /// Generate a group (from GameManager.labeledBoxModel) which contains all the given objects.
    ///</summary>
    ///<param name="_gr">The group data to apply</param>
    ///<param name="_parent">The parent of the created group. Leave null if _gr contains the parendId</param>
    ///<returns>The created rackGroup</returns>
    public Group CreateGroup(SApiObject _gr, Transform _parent = null)
    {
        Transform parent = Utils.FindParent(_parent, _gr.parentId);

        if (!parent)
        {
            GameManager.gm.AppendLogLine("Parent not found", true, eLogtype.error);
            return(null);
        }
        string parentCategory = parent.GetComponent <OgreeObject>().category;

        if (parentCategory != "room" && parentCategory != "rack")
        {
            GameManager.gm.AppendLogLine("A group must be a child of a room or a rack", true, eLogtype.error);
            return(null);
        }

        string hierarchyName = $"{parent.GetComponent<OgreeObject>().hierarchyName}.{_gr.name}";

        if (GameManager.gm.allItems.Contains(hierarchyName))
        {
            GameManager.gm.AppendLogLine($"{hierarchyName} already exists.", true, eLogtype.warning);
            return(null);
        }

        List <Transform> content = new List <Transform>();

        string[] contentNames = _gr.attributes["content"].Split(',');
        foreach (string cn in contentNames)
        {
            GameObject go = GameManager.gm.FindByAbsPath($"{parent.GetComponent<OgreeObject>().hierarchyName}.{cn}");
            if (go && go.GetComponent <OgreeObject>())
            {
                if ((parentCategory == "room" && (go.GetComponent <OgreeObject>().category == "rack" || go.GetComponent <OgreeObject>().category == "corridor")) ||
                    parentCategory == "rack" && go.GetComponent <OgreeObject>().category == "device")
                {
                    content.Add(go.transform);
                }
            }
            else
            {
                GameManager.gm.AppendLogLine($"{parent.GetComponent<OgreeObject>().hierarchyName}.{cn} doesn't exists.", true, eLogtype.warning);
            }
        }
        if (content.Count == 0)
        {
            return(null);
        }

        GameObject newGr = Instantiate(GameManager.gm.labeledBoxModel);

        newGr.name             = _gr.name;
        newGr.transform.parent = parent;

        // According to group type, set pos, rot & scale
        Vector3 pos   = Vector3.zero;
        Vector3 scale = Vector3.zero;

        if (parentCategory == "room")
        {
            RackGroupPosScale(content, out pos, out scale);
            newGr.transform.localEulerAngles = new Vector3(0, 180, 0);
        }
        else if (parentCategory == "rack")
        {
            DeviceGroupPosScale(content, out pos, out scale);
            newGr.transform.localEulerAngles = Vector3.zero;
        }
        newGr.transform.localPosition          = pos;
        newGr.transform.GetChild(0).localScale = scale;

        // Set Group component
        Group gr = newGr.AddComponent <Group>();

        gr.UpdateFromSApiObject(_gr);
        gr.UpdateColorByTenant();
        gr.DisplayContent(false);

        if (parentCategory == "room")
        {
            newGr.GetComponent <DisplayObjectData>().PlaceTexts("top");
        }
        else if (parentCategory == "rack")
        {
            newGr.GetComponent <DisplayObjectData>().PlaceTexts("frontrear");
        }
        newGr.GetComponent <DisplayObjectData>().SetLabel("#name");

        string hn = gr.UpdateHierarchyName();

        GameManager.gm.allItems.Add(hn, newGr);

        return(gr);
    }
Exemple #20
0
    ///<summary>
    /// Create a rack or a device from received data and add it to correct GameManager list
    ///</summary>
    ///<param name="_data">The data template</param>
    public async Task CreateObjectTemplate(STemplate _data)
    {
        if (_data.category != "rack" && _data.category != "device")
        {
            GameManager.gm.AppendLogLine($"Unknown category for {_data.slug} template.", true, eLogtype.error);
            return;
        }
        if (GameManager.gm.objectTemplates.ContainsKey(_data.slug))
        {
            GameManager.gm.AppendLogLine($"{_data.slug} already exists.", false, eLogtype.warning);
            return;
        }

        // Build SApiObject
        SApiObject obj = new SApiObject
        {
            description = new List <string>(),
            attributes  = new Dictionary <string, string>(),

            name     = _data.slug,
            category = _data.category
        };

        obj.description.Add(_data.description);
        if (obj.category == "rack")
        {
            Vector3 tmp = new Vector3(_data.sizeWDHmm[0], _data.sizeWDHmm[1], _data.sizeWDHmm[2]) / 10;
            obj.attributes["posXY"]       = JsonUtility.ToJson(Vector2.zero);
            obj.attributes["posXYUnit"]   = "tile";
            obj.attributes["size"]        = JsonUtility.ToJson(new Vector2(tmp.x, tmp.y));
            obj.attributes["sizeUnit"]    = "cm";
            obj.attributes["height"]      = ((int)tmp.z).ToString();
            obj.attributes["heightUnit"]  = "cm";
            obj.attributes["orientation"] = "front";
        }
        else if (obj.category == "device")
        {
            if (_data.attributes.ContainsKey("type") &&
                (_data.attributes["type"] == "chassis" || _data.attributes["type"] == "server"))
            {
                int sizeU = Mathf.CeilToInt((_data.sizeWDHmm[2] / 1000) / GameManager.gm.uSize);
                obj.attributes["sizeU"] = sizeU.ToString();
            }
            obj.attributes["size"]       = JsonUtility.ToJson(new Vector2(_data.sizeWDHmm[0], _data.sizeWDHmm[1]));
            obj.attributes["sizeUnit"]   = "mm";
            obj.attributes["height"]     = _data.sizeWDHmm[2].ToString();
            obj.attributes["heightUnit"] = "mm";
            obj.attributes["slot"]       = "";
        }
        obj.attributes["template"] = "";
        obj.attributes["fbxModel"] = (!string.IsNullOrEmpty(_data.fbxModel)).ToString();
        if (_data.attributes != null)
        {
            foreach (KeyValuePair <string, string> kvp in _data.attributes)
            {
                obj.attributes[kvp.Key] = kvp.Value;
            }
        }

        // Generate the 3D object
        OgreeObject newObject;

        if (obj.category == "rack")
        {
            newObject = OgreeGenerator.instance.CreateItemFromSApiObject(obj, GameManager.gm.templatePlaceholder).Result;
            if (!string.IsNullOrEmpty(_data.fbxModel))
            {
                await ModelLoader.instance.ReplaceBox(newObject.gameObject, _data.fbxModel);
            }
        }
        else// if (obj.category == "device")
        {
            newObject = OgreeGenerator.instance.CreateItemFromSApiObject(obj, GameManager.gm.templatePlaceholder.GetChild(0)).Result;
            if (string.IsNullOrEmpty(_data.fbxModel))
            {
                newObject.transform.GetChild(0).localScale = new Vector3(_data.sizeWDHmm[0], _data.sizeWDHmm[2], _data.sizeWDHmm[1]) / 1000;
            }
            else
            {
                await ModelLoader.instance.ReplaceBox(newObject.gameObject, _data.fbxModel);
            }
        }
        newObject.transform.localPosition = Vector3.zero;

        newObject.GetComponent <OObject>().color = newObject.transform.GetChild(0).GetComponent <Renderer>().material.color;

        // Retrieve custom colors
        Dictionary <string, string> customColors = new Dictionary <string, string>();

        if (_data.colors != null)
        {
            foreach (SColor color in _data.colors)
            {
                customColors.Add(color.name, color.value);
            }
        }

        // Generate components & slots
        if (_data.components != null)
        {
            foreach (STemplateChild compData in _data.components)
            {
                PopulateSlot(false, compData, newObject, customColors);
            }
        }
        if (_data.slots != null)
        {
            foreach (STemplateChild slotData in _data.slots)
            {
                PopulateSlot(true, slotData, newObject, customColors);
            }
        }

        // For rack, update height counting
        if (newObject.category == "rack")
        {
            Slot[] slots = newObject.GetComponentsInChildren <Slot>();
            if (slots.Length > 0)
            {
                int height = 0;
                foreach (Slot s in slots)
                {
                    if (s.orient == "horizontal")
                    {
                        height++;
                    }
                }
                newObject.attributes["height"]     = height.ToString();
                newObject.attributes["heightUnit"] = "U";
            }
        }

        // Toggle renderers & put newObj in GameManager.objectTemplates
#if PROD
        Renderer[] renderers = newObject.transform.GetComponentsInChildren <Renderer>();
        foreach (Renderer r in renderers)
        {
            r.enabled = false;
        }
        newObject.transform.GetChild(0).GetComponent <Collider>().enabled = false;
#endif
        GameManager.gm.allItems.Remove(newObject.hierarchyName);
        GameManager.gm.objectTemplates.Add(newObject.name, newObject.gameObject);
    }