コード例 #1
0
    private void AddSceneMappings(CatalogItem catalogItem)
    {
        LoadParcelScenesMessage.UnityParcelScene data = sceneToEdit.sceneData;
        data.baseUrl = BIWUrlUtils.GetUrlSceneObjectContent();
        if (data.contents == null)
        {
            data.contents = new List <ContentServerUtils.MappingPair>();
        }
        foreach (KeyValuePair <string, string> content in catalogItem.contents)
        {
            ContentServerUtils.MappingPair mappingPair = new ContentServerUtils.MappingPair();
            mappingPair.file = content.Key;
            mappingPair.hash = content.Value;
            bool found = false;
            foreach (ContentServerUtils.MappingPair mappingPairToCheck in data.contents)
            {
                if (mappingPairToCheck.file == mappingPair.file)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                data.contents.Add(mappingPair);
            }
        }

        DCL.Environment.i.world.sceneController.UpdateParcelScenesExecute(data);
    }
コード例 #2
0
ファイル: ParcelScene.cs プロジェクト: menduz/explorer
 public virtual void SetUpdateData(LoadParcelScenesMessage.UnityParcelScene data)
 {
     contentProvider          = new ContentProvider();
     contentProvider.baseUrl  = data.baseUrl;
     contentProvider.contents = data.contents;
     contentProvider.BakeHashes();
 }
コード例 #3
0
        public override void SetData(LoadParcelScenesMessage.UnityParcelScene data)
        {
            this.sceneData = data;

            contentProvider         = new ContentProvider_Dummy();
            contentProvider.baseUrl = data.baseUrl;
        }
コード例 #4
0
ファイル: BIWCreatorShould.cs プロジェクト: useit015/explorer
    public void CatalogItemAddMapings()
    {
        //Arrange
        BIWCatalogManager.Init();
        BuilderInWorldTestHelper.CreateTestCatalogLocalSingleObject();
        CatalogItem item = DataStore.i.builderInWorld.catalogItemDict.GetValues()[0];

        //Act
        biwCreatorController.CreateCatalogItem(item);

        //Assert
        LoadParcelScenesMessage.UnityParcelScene data = scene.sceneData;
        foreach (KeyValuePair <string, string> content in item.contents)
        {
            ContentServerUtils.MappingPair mappingPair = new ContentServerUtils.MappingPair();
            mappingPair.file = content.Key;
            mappingPair.hash = content.Value;
            bool found = false;
            foreach (ContentServerUtils.MappingPair mappingPairToCheck in data.contents)
            {
                if (mappingPairToCheck.file == mappingPair.file)
                {
                    found = true;
                    break;
                }
            }
            Assert.IsTrue(found);
        }
    }
コード例 #5
0
        public ParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
        {
            if (data == null)
            {
                data = new LoadParcelScenesMessage.UnityParcelScene();
            }

            if (data.basePosition == null)
            {
                data.basePosition = new Vector2Int(0, 0);
            }

            if (data.parcels == null)
            {
                data.parcels = new Vector2Int[] { data.basePosition };
            }

            if (string.IsNullOrEmpty(data.id))
            {
                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
            }

            if (loadedScenes.ContainsKey(data.id))
            {
                Debug.LogWarning($"Scene {data.id} is already loaded.");
                return(loadedScenes[data.id]);
            }

            var go       = new GameObject();
            var newScene = go.AddComponent <ParcelScene>();

            newScene.ownerController = this;
            newScene.isTestScene     = true;
            newScene.useBlockers     = false;
            newScene.SetData(data);

            if (DCLCharacterController.i != null)
            {
                newScene.InitializeDebugPlane();
            }

            scenesSortedByDistance.Add(newScene);

            if (!MessagingControllersManager.i.ContainsController(data.id))
            {
                MessagingControllersManager.i.AddController(this, data.id);
            }

            loadedScenes.Add(data.id, newScene);

            return(newScene);
        }
コード例 #6
0
        public void UpdateParcelScenesExecute(LoadParcelScenesMessage.UnityParcelScene scene)
        {
            if (scene == null || scene.id == null)
            {
                return;
            }

            var sceneToLoad = scene;

            ProfilingEvents.OnMessageProcessStart?.Invoke(MessagingTypes.SCENE_UPDATE);
            Environment.i.world.state.loadedScenes[sceneToLoad.id].SetUpdateData(sceneToLoad);
            ProfilingEvents.OnMessageProcessEnds?.Invoke(MessagingTypes.SCENE_UPDATE);
        }
コード例 #7
0
    public IEnumerator SceneObjectFloorObject()
    {
        SceneObject sceneObject = BuilderInWorldUtils.CreateFloorSceneObject();

        LoadParcelScenesMessage.UnityParcelScene data = scene.sceneData;
        data.contents = new List <ContentServerUtils.MappingPair>();
        data.baseUrl  = BuilderInWorldSettings.BASE_URL_CATALOG;

        foreach (KeyValuePair <string, string> content in sceneObject.contents)
        {
            ContentServerUtils.MappingPair mappingPair = new ContentServerUtils.MappingPair();
            mappingPair.file = content.Key;
            mappingPair.hash = content.Value;
            bool found = false;
            foreach (ContentServerUtils.MappingPair mappingPairToCheck in data.contents)
            {
                if (mappingPairToCheck.file == mappingPair.file)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                data.contents.Add(mappingPair);
            }
        }

        Environment.i.world.sceneController.UpdateParcelScenesExecute(data);


        string entityId = "1";

        TestHelpers.CreateSceneEntity(scene, entityId);

        TestHelpers.CreateAndSetShape(scene, entityId, DCL.Models.CLASS_ID.GLTF_SHAPE, JsonConvert.SerializeObject(
                                          new
        {
            assetId = BuilderInWorldSettings.FLOOR_TEXTURE_VALUE,
            src     = BuilderInWorldSettings.FLOOR_MODEL
        }));;

        LoadWrapper gltfShape = GLTFShape.GetLoaderForEntity(scene.entities[entityId]);

        yield return(new WaitUntil(() => gltfShape.alreadyLoaded));

        Assert.IsTrue(
            scene.entities[entityId].gameObject.GetComponentInChildren <UnityGLTF.InstantiatedGLTFObject>() != null,
            "Floor should be loaded, is the SceneObject not working anymore?");
    }
コード例 #8
0
        public override void SetData(LoadParcelScenesMessage.UnityParcelScene data)
        {
            this.sceneData = data;

            contentProvider          = new ContentProvider();
            contentProvider.baseUrl  = data.baseUrl;
            contentProvider.contents = data.contents;
            contentProvider.BakeHashes();

            if (DCLCharacterController.i != null)
            {
                gameObject.transform.position = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(data.basePosition.x, data.basePosition.y));
            }
        }
コード例 #9
0
        public void CreateUIScene(string json)
        {
#if UNITY_EDITOR
            DebugConfig debugConfig = DataStore.i.debugConfig;

            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
            {
                return;
            }
#endif
            CreateUISceneMessage uiScene = Utils.SafeFromJson <CreateUISceneMessage>(json);

            string uiSceneId = uiScene.id;

            IWorldState worldState = Environment.i.world.state;

            if (worldState.loadedScenes.ContainsKey(uiSceneId))
            {
                return;
            }

            var newGameObject = new GameObject("UI Scene - " + uiSceneId);

            var newScene = newGameObject.AddComponent <GlobalScene>();
            newScene.ownerController    = this;
            newScene.unloadWithDistance = false;
            newScene.isPersistent       = true;

            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
            {
                id           = uiSceneId,
                basePosition = new Vector2Int(0, 0),
                baseUrl      = uiScene.baseUrl
            };

            newScene.SetData(data);

            worldState.loadedScenes.Add(uiSceneId, newScene);
            OnNewSceneAdded?.Invoke(newScene);

            worldState.globalSceneId = uiSceneId;

            Environment.i.messaging.manager.AddControllerIfNotExists(this, worldState.globalSceneId, isGlobal: true);

            if (VERBOSE)
            {
                Debug.Log($"Creating UI scene {uiSceneId}");
            }
        }
コード例 #10
0
        public void CreateUIScene(string json)
        {
#if UNITY_EDITOR
            if (debugScenes && ignoreGlobalScenes)
            {
                return;
            }
#endif
            CreateUISceneMessage uiScene = SafeFromJson <CreateUISceneMessage>(json);

            string uiSceneId = uiScene.id;

            if (loadedScenes.ContainsKey(uiSceneId))
            {
                return;
            }

            var newGameObject = new GameObject("UI Scene - " + uiSceneId);

            var newScene = newGameObject.AddComponent <GlobalScene>();
            newScene.ownerController    = this;
            newScene.unloadWithDistance = false;
            newScene.isPersistent       = true;

            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
            {
                id           = uiSceneId,
                basePosition = new Vector2Int(0, 0),
                baseUrl      = uiScene.baseUrl
            };

            newScene.SetData(data);

            loadedScenes.Add(uiSceneId, newScene);

            globalSceneId = uiSceneId;

            if (!MessagingControllersManager.i.ContainsController(globalSceneId))
            {
                MessagingControllersManager.i.AddController(this, globalSceneId, isGlobal: true);
            }

            if (VERBOSE)
            {
                Debug.Log($"Creating UI scene {uiSceneId}");
            }
        }
コード例 #11
0
        private void CalcSceneBoundaries(LoadParcelScenesMessage.UnityParcelScene scene)
        {
            sceneBoundaryMin = Vector2.zero;
            sceneBoundaryMax = Vector2.zero;

            if (scene.parcels.Length > 0)
            {
                foreach (Vector2Int parcel in scene.parcels)
                {
                    Vector3 parcelPosition = new Vector3(parcel.x, 0, parcel.y);
                    sceneBoundaryMin.x = Mathf.Min(sceneBoundaryMin.x, parcelPosition.x);
                    sceneBoundaryMin.y = Mathf.Min(sceneBoundaryMin.y, parcelPosition.z);
                    sceneBoundaryMax.x = Mathf.Max(sceneBoundaryMax.x, parcelPosition.x);
                    sceneBoundaryMax.y = Mathf.Max(sceneBoundaryMax.y, parcelPosition.z);
                }
            }
        }
コード例 #12
0
        public IParcelScene CreateTestScene(LoadParcelScenesMessage.UnityParcelScene data = null)
        {
            if (data == null)
            {
                data = new LoadParcelScenesMessage.UnityParcelScene();
            }

            if (data.parcels == null)
            {
                data.parcels = new Vector2Int[] { data.basePosition };
            }

            if (string.IsNullOrEmpty(data.id))
            {
                data.id = $"(test):{data.basePosition.x},{data.basePosition.y}";
            }

            if (Environment.i.world.state.loadedScenes.ContainsKey(data.id))
            {
                Debug.LogWarning($"Scene {data.id} is already loaded.");
                return(Environment.i.world.state.loadedScenes[data.id]);
            }

            var go       = new GameObject();
            var newScene = go.AddComponent <ParcelScene>();

            newScene.ownerController = this;
            newScene.isTestScene     = true;
            newScene.isPersistent    = true;
            newScene.SetData(data);

            if (DCLCharacterController.i != null)
            {
                newScene.InitializeDebugPlane();
            }

            Environment.i.world.state.scenesSortedByDistance.Add(newScene);

            Environment.i.messaging.manager.AddControllerIfNotExists(this, data.id);

            Environment.i.world.state.loadedScenes.Add(data.id, newScene);
            OnNewSceneAdded?.Invoke(newScene);

            return(newScene);
        }
コード例 #13
0
        public SceneDebugPlane(LoadParcelScenesMessage.UnityParcelScene sceneData, Transform parent)
        {
            int sceneDataParcelsLength = sceneData.parcels.Length;

            sceneParcelPlanes = new GameObject[sceneDataParcelsLength];

            for (int j = 0; j < sceneDataParcelsLength; j++)
            {
                GameObject plane = GameObject.CreatePrimitive(PrimitiveType.Plane);
                sceneParcelPlanes[j] = plane;

                UnityEngine.Object.Destroy(plane.GetComponent <MeshCollider>());

                plane.name = $"parcel:{sceneData.parcels[j].x},{sceneData.parcels[j].y}";

                plane.transform.SetParent(parent);

                // the plane mesh with scale 1 occupies a 10 units space
                plane.transform.localScale = new Vector3(ParcelSettings.PARCEL_SIZE * 0.1f, 1f,
                                                         ParcelSettings.PARCEL_SIZE * 0.1f);

                Vector3 position = Utils.GridToWorldPosition(sceneData.parcels[j].x, sceneData.parcels[j].y);
                // SET TO A POSITION RELATIVE TO basePosition

                position.Set(position.x + ParcelSettings.PARCEL_SIZE / 2, ParcelSettings.DEBUG_FLOOR_HEIGHT,
                             position.z + ParcelSettings.PARCEL_SIZE / 2);

                plane.transform.position = PositionUtils.WorldToUnityPosition(position);

                if (DCL.Configuration.ParcelSettings.VISUAL_LOADING_ENABLED)
                {
                    Material finalMaterial = Utils.EnsureResourcesMaterial("Materials/DefaultPlane");
                    var      matTransition = plane.AddComponent <MaterialTransitionController>();
                    matTransition.delay         = 0;
                    matTransition.useHologram   = false;
                    matTransition.fadeThickness = 20;
                    matTransition.OnDidFinishLoading(finalMaterial);
                }
                else
                {
                    plane.GetComponent <MeshRenderer>().sharedMaterial =
                        Utils.EnsureResourcesMaterial("Materials/DefaultPlane");
                }
            }
        }
コード例 #14
0
ファイル: ParcelScene.cs プロジェクト: menduz/explorer
        public virtual void SetData(LoadParcelScenesMessage.UnityParcelScene data)
        {
            this.sceneData = data;

            contentProvider          = new ContentProvider();
            contentProvider.baseUrl  = data.baseUrl;
            contentProvider.contents = data.contents;
            contentProvider.BakeHashes();

            state = State.WAITING_FOR_INIT_MESSAGES;
            RefreshName();

            parcels.Clear();
            for (int i = 0; i < sceneData.parcels.Length; i++)
            {
                parcels.Add(sceneData.parcels[i]);
            }

            if (useBlockers)
            {
                blockerHandler = new BlockerHandler();
            }

            if (DCLCharacterController.i != null)
            {
                gameObject.transform.position = DCLCharacterController.i.characterPosition.WorldToUnityPosition(Utils.GridToWorldPosition(data.basePosition.x, data.basePosition.y));
            }

#if UNITY_EDITOR
            //NOTE(Brian): Don't generate parcel blockers if debugScenes is active and is not the desired scene.
            if (SceneController.i.debugScenes && SceneController.i.debugSceneCoords != data.basePosition)
            {
                SetSceneReady();
                return;
            }
#endif
            blockerHandler?.SetupBlockers(parcels, metricsController.GetLimits().sceneHeight, this.transform);

            if (isTestScene)
            {
                SetSceneReady();
            }
        }
コード例 #15
0
        private void OnSceneSetData(LoadParcelScenesMessage.UnityParcelScene data)
        {
            state = State.WAITING_FOR_INIT_MESSAGES;
            owner.RefreshLoadingState();

#if UNITY_EDITOR
            DebugConfig debugConfig = DataStore.i.debugConfig;
            //NOTE(Brian): Don't generate parcel blockers if debugScenes is active and is not the desired scene.
            if (debugConfig.soloScene && debugConfig.soloSceneCoords != data.basePosition)
            {
                SetSceneReady();
                return;
            }
#endif

            if (owner.isTestScene)
            {
                SetSceneReady();
            }
        }
コード例 #16
0
ファイル: ParcelScene.cs プロジェクト: useit015/explorer
        public virtual void SetData(LoadParcelScenesMessage.UnityParcelScene data)
        {
            this.sceneData = data;

            contentProvider          = new ContentProvider();
            contentProvider.baseUrl  = data.baseUrl;
            contentProvider.contents = data.contents;
            contentProvider.BakeHashes();

            parcels.Clear();
            for (int i = 0; i < sceneData.parcels.Length; i++)
            {
                parcels.Add(sceneData.parcels[i]);
            }

            if (DCLCharacterController.i != null)
            {
                gameObject.transform.position = PositionUtils.WorldToUnityPosition(Utils.GridToWorldPosition(data.basePosition.x, data.basePosition.y));
            }

            OnSetData?.Invoke(data);
        }
コード例 #17
0
    DCLBuilderInWorldEntity CreateSceneObject(SceneObject sceneObject, bool autoSelect = true, bool isFloor = false)
    {
        if (sceneObject.asset_pack_id == BuilderInWorldSettings.ASSETS_COLLECTIBLES && BuilderInWorldNFTController.i.IsNFTInUse(sceneObject.id))
        {
            return(null);
        }

        IsInsideTheLimits(sceneObject);

        //Note (Adrian): This is a workaround until the mapping is handle by kernel

        LoadParcelScenesMessage.UnityParcelScene data = sceneToEdit.sceneData;
        data.baseUrl = BuilderInWorldSettings.BASE_URL_CATALOG;

        foreach (KeyValuePair <string, string> content in sceneObject.contents)
        {
            ContentServerUtils.MappingPair mappingPair = new ContentServerUtils.MappingPair();
            mappingPair.file = content.Key;
            mappingPair.hash = content.Value;
            bool found = false;
            foreach (ContentServerUtils.MappingPair mappingPairToCheck in data.contents)
            {
                if (mappingPairToCheck.file == mappingPair.file)
                {
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                data.contents.Add(mappingPair);
            }
        }

        Environment.i.world.sceneController.UpdateParcelScenesExecute(data);


        DCLName         name         = (DCLName)sceneToEdit.SharedComponentCreate(Guid.NewGuid().ToString(), Convert.ToInt32(CLASS_ID.NAME));
        DCLLockedOnEdit entityLocked = (DCLLockedOnEdit)sceneToEdit.SharedComponentCreate(Guid.NewGuid().ToString(), Convert.ToInt32(CLASS_ID.LOCKED_ON_EDIT));

        DCLBuilderInWorldEntity entity = builderInWorldEntityHandler.CreateEmptyEntity(sceneToEdit, currentActiveMode.GetCreatedEntityPoint(), editionGO.transform.position);

        entity.isFloor = isFloor;

        if (entity.isFloor)
        {
            entityLocked.SetIsLocked(true);
        }
        else
        {
            entityLocked.SetIsLocked(false);
        }

        if (sceneObject.asset_pack_id == BuilderInWorldSettings.ASSETS_COLLECTIBLES)
        {
            NFTShape nftShape = (NFTShape)sceneToEdit.SharedComponentCreate(sceneObject.id, Convert.ToInt32(CLASS_ID.NFT_SHAPE));
            nftShape.model         = new NFTShape.Model();
            nftShape.model.color   = new Color(0.6404918f, 0.611472f, 0.8584906f);
            nftShape.model.src     = sceneObject.model;
            nftShape.model.assetId = sceneObject.id;

            sceneToEdit.SharedComponentAttach(entity.rootEntity.entityId, nftShape.id);
        }
        else
        {
            GLTFShape mesh = (GLTFShape)sceneToEdit.SharedComponentCreate(sceneObject.id, Convert.ToInt32(CLASS_ID.GLTF_SHAPE));
            mesh.model         = new LoadableShape.Model();
            mesh.model.src     = sceneObject.model;
            mesh.model.assetId = sceneObject.id;
            sceneToEdit.SharedComponentAttach(entity.rootEntity.entityId, mesh.id);
        }

        sceneToEdit.SharedComponentAttach(entity.rootEntity.entityId, name.id);
        sceneToEdit.SharedComponentAttach(entity.rootEntity.entityId, entityLocked.id);

        builderInWorldEntityHandler.SetEntityName(entity, sceneObject.name);

        if (sceneObject.IsSmartItem())
        {
            SmartItemComponent.Model model = new SmartItemComponent.Model();
            model.actions    = sceneObject.actions;
            model.parameters = sceneObject.parameters;

            string jsonModel = JsonUtility.ToJson(model);

            sceneToEdit.EntityComponentCreateOrUpdateFromUnity(entity.rootEntity.entityId, CLASS_ID_COMPONENT.SMART_ITEM, jsonModel);

            //Note (Adrian): This shouldn't work this way, we can't wait a frame to set the data of the component so we force it to update

            entity.rootEntity.TryGetBaseComponent(CLASS_ID_COMPONENT.SMART_ITEM, out BaseComponent baseComponent);
            ((SmartItemComponent)baseComponent).ForceUpdate(jsonModel);
        }

        if (sceneObject.asset_pack_id == BuilderInWorldSettings.VOXEL_ASSETS_PACK_ID)
        {
            entity.isVoxel = true;
        }

        if (autoSelect)
        {
            builderInWorldEntityHandler.DeselectEntities();
            builderInWorldEntityHandler.Select(entity.rootEntity);
        }

        entity.gameObject.transform.eulerAngles = Vector3.zero;

        currentActiveMode.CreatedEntity(entity);
        if (!isAdvancedModeActive)
        {
            Utils.LockCursor();
        }
        lastSceneObjectCreated = sceneObject;

        builderInWorldEntityHandler.NotifyEntityIsCreated(entity.rootEntity);
        InputDone();
        OnSceneObjectPlaced?.Invoke();

        return(entity);
    }
コード例 #18
0
        public void CreateGlobalScene(string json)
        {
#if UNITY_EDITOR
            DebugConfig debugConfig = DataStore.i.debugConfig;

            if (debugConfig.soloScene && debugConfig.ignoreGlobalScenes)
            {
                return;
            }
#endif
            CreateGlobalSceneMessage globalScene = Utils.SafeFromJson <CreateGlobalSceneMessage>(json);

            string newGlobalSceneId = globalScene.id;

            IWorldState worldState = Environment.i.world.state;

            if (worldState.loadedScenes.ContainsKey(newGlobalSceneId))
            {
                return;
            }

            var newGameObject = new GameObject("Global Scene - " + newGlobalSceneId);

            var newScene = newGameObject.AddComponent <GlobalScene>();
            newScene.ownerController      = this;
            newScene.unloadWithDistance   = false;
            newScene.isPersistent         = true;
            newScene.sceneName            = globalScene.name;
            newScene.isPortableExperience = globalScene.isPortableExperience;

            LoadParcelScenesMessage.UnityParcelScene data = new LoadParcelScenesMessage.UnityParcelScene
            {
                id           = newGlobalSceneId,
                basePosition = new Vector2Int(0, 0),
                baseUrl      = globalScene.baseUrl,
                contents     = globalScene.contents
            };

            newScene.SetData(data);

            if (!string.IsNullOrEmpty(globalScene.icon))
            {
                newScene.iconUrl = newScene.contentProvider.GetContentsUrl(globalScene.icon);
            }

            worldState.loadedScenes.Add(newGlobalSceneId, newScene);
            OnNewSceneAdded?.Invoke(newScene);

            if (newScene.isPortableExperience)
            {
                OnNewPortableExperienceSceneAdded?.Invoke(newScene);
            }

            worldState.globalSceneIds.Add(newGlobalSceneId);

            Environment.i.messaging.manager.AddControllerIfNotExists(this, newGlobalSceneId, isGlobal: true);

            if (VERBOSE)
            {
                Debug.Log($"Creating Global scene {newGlobalSceneId}");
            }
        }
コード例 #19
0
    public IEnumerator Initialize()
    {
        var sceneController = Environment.i.world.sceneController;

        DCLCharacterController.i.gravity = 0;
        DCLCharacterController.i.Teleport(JsonConvert.SerializeObject(new
        {
            x = 0f,
            y = 0f,
            z = 0f
        }));

        var scenesToLoad = new LoadParcelScenesMessage.UnityParcelScene()
        {
            id           = sceneName,
            basePosition = new Vector2Int(3, 3),
            parcels      = new[]
            {
                new Vector2Int(3, 3),
                new Vector2Int(3, 4)
            },
            baseUrl = "http://localhost:9991/local-ipfs/contents/"
        };

        Assert.IsTrue(sceneController != null, "Cannot find SceneController");

        sceneController.UnloadAllScenes();
        sceneController.LoadParcelScenes(JsonConvert.SerializeObject(scenesToLoad));

        yield return(new WaitForAllMessagesProcessed());

        var scene = Environment.i.world.state.loadedScenes[sceneName];

        //NOTE(Brian): This is making my eyes bleed.
        sceneController.SendSceneMessage(
            TestHelpers.CreateSceneMessage(
                sceneName,
                entityId,
                "CreateEntity",
                JsonConvert.SerializeObject(
                    new Protocol.CreateEntity()
        {
            entityId = entityId
        }))
            );

        //NOTE(Brian): This is making my eyes bleed. (Zak): Twice
        sceneController.SendSceneMessage(
            TestHelpers.CreateSceneMessage(
                sceneName,
                entityId,
                "SetEntityParent",
                JsonConvert.SerializeObject(
                    new
        {
            entityId = entityId,
            parentId = "0"
        })
                )
            );

        yield return(new WaitForAllMessagesProcessed());

        Assert.IsTrue(scene.entities[entityId].meshRootGameObject == null, "meshGameObject must be null");

        // 1st message
        TestHelpers.CreateAndSetShape(scene, entityId, CLASS_ID.BOX_SHAPE, "{}");

        {
            scene.EntityComponentCreateOrUpdate(
                entityId,
                CLASS_ID_COMPONENT.TRANSFORM,
                "{\"tag\":\"transform\",\"position\":{\"x\":0,\"y\":0,\"z\":0},\"rotation\":{\"x\":0,\"y\":0,\"z\":0,\"w\":1},\"scale\":{\"x\":1,\"y\":1,\"z\":1}}"
                , out CleanableYieldInstruction routine);
        }


        // 2nd message
        TestHelpers.CreateAndSetShape(scene, entityId, CLASS_ID.BOX_SHAPE, "{}");
        {
            scene.EntityComponentCreateOrUpdate(
                entityId,
                CLASS_ID_COMPONENT.TRANSFORM,
                "{\"tag\":\"transform\",\"position\":{\"x\":6,\"y\":0,\"z\":5},\"rotation\":{\"x\":0,\"y\":0.39134957508996265,\"z\":0,\"w\":0.9202420931897769},\"scale\":{\"x\":1,\"y\":1,\"z\":1}}"
                , out CleanableYieldInstruction routine);
        }

        TestHelpers.InstantiateEntityWithTextShape(scene, new Vector3(10, 10, 10),
                                                   new TextShape.Model()
        {
            value = "Hello World!!!"
        });
    }