public void TestRelativeAccessor_ParentGet()
        {
            var root     = RandomTransform();
            var child    = RandomTransform(root, 2);
            var AsParent = new TransformExtensions.RelativeAccessor(child.parent);

            // If the more precise implementation is used, Assert.AreEqual works
            VeryLooseEqual(TrTransform.FromLocalTransform(child), AsParent[child]);
            UnityEngine.Object.DestroyImmediate(root.gameObject);
        }
        public void TestRelativeAccessor_UnrelatedGet()
        {
            var root    = RandomTransform();
            var left    = RandomTransform(root, 2);
            var right   = RandomTransform(root);
            var AsRight = new TransformExtensions.RelativeAccessor(right);

            VeryLooseEqual(TrTransform.FromTransform(right) * AsRight[left],
                           TrTransform.FromTransform(left));
        }
Example #3
0
        // Init unless already initialized. Safe to call zero or multiple times.
        public void Init()
        {
            if (m_bInitialized)
            {
                return;
            }
            m_bInitialized = true;

            AsCanvas = new TransformExtensions.RelativeAccessor(transform);
        }
        public void TestRelativeAccessor_AncestorGet()
        {
            var root       = RandomTransform();
            var child      = RandomTransform(root, 2);
            var AsAncestor = new TransformExtensions.RelativeAccessor(child.parent.parent);

            VeryLooseEqual(TrTransform.FromLocalTransform(child.parent) *
                           TrTransform.FromLocalTransform(child),
                           AsAncestor[child]);
            UnityEngine.Object.DestroyImmediate(root.gameObject);
        }
        public void TestRelativeAccessor_SameSet()
        {
            var root    = RandomTransform();
            var child   = RandomTransform(root, 2);
            var AsChild = new TransformExtensions.RelativeAccessor(child);

            try {
                Assert.That(() => AsChild[child] = RandomTr(), Throws.InvalidOperationException);
            } finally {
                UnityEngine.Object.DestroyImmediate(root.gameObject);
            }
        }
        public void TestRelativeAccessor_ParentSet()
        {
            var root     = RandomTransform();
            var child    = RandomTransform(root, 2);
            var AsParent = new TransformExtensions.RelativeAccessor(child.parent);
            var xf       = RandomTr();

            AsParent[child] = xf;
            VeryLooseEqual(AsParent[child], xf);
            VeryLooseEqual(TrTransform.FromTransform(child),
                           TrTransform.FromTransform(child.parent) * xf);
            UnityEngine.Object.DestroyImmediate(root.gameObject);
        }
Example #7
0
 // Init unless already initialized. Safe to call zero or multiple times.
 public void Init()
 {
     if (m_bInitialized)
     {
         return;
     }
     m_bInitialized  = true;
     m_LayerCanvases = new List <CanvasScript>();
     AsScene         = new TransformExtensions.RelativeAccessor(transform);
     m_ActiveCanvas  = m_MainCanvas;
     foreach (var c in AllCanvases)
     {
         c.Init();
     }
 }
Example #8
0
        private static void BuildModelsAsModelMeshes(
            SceneStatePayload payload, IEnumerable <ModelWidget> modelWidgets)
        {
            // This is a quadruple-nested loop that's triply flattened into a single IEnumerable.
            // The structure of the data is is:
            // 1. There are 1+ Models (which I'll call "prefab" because Model is a loaded term here)
            // 2. Each "prefab" is used by 1+ ModelWidgets ("instance")
            // 3. Each ModelWidget, and the "prefab", contains 1+ GameObjects (which has a single Mesh)
            // 4. Each Mesh has 1+ unity submeshes (almost always exactly 1)
            //    These are converted to ModelMeshPayload
            //
            // The resulting ModelMeshPayloads are a mixture of data from all 4 levels, for example
            // - ModelMeshPayload.model comes from level 1
            // - ModelMeshPayload.modelId comes from level 2
            // - ModelMeshPayload.xform comes from level 3
            // - ModelMeshPayload.pool comes from level 4
            //
            // Orthogonal to this nesting, some data comes from the "prefab" and some from the "instance",
            // since we don't want to have to convert a mesh into GeometryPool once per instance.
            // So we iterate level 3 for the Model once, up front; then each ModelWidget level 3 is
            // a parallel iteration with that Model's pre-computed iteration.
            foreach (var group in modelWidgets.GroupBy(widget => widget.Model))
            {
                Model prefab = group.Key;
                // Each element represents a GameObject in the "prefab"
                List <PrefabGeometry[]> prefabObjs = GetPrefabGameObjs(payload, prefab).ToList();

                foreach ((ModelWidget widget, int widgetIndex) in group.WithIndex())
                {
                    Matrix4x4 widgetXform = ExportUtils.ChangeBasis(widget.transform, payload);
                    // Acts like our AsScene[], AsCanvas[] accessors
                    var AsWidget = new TransformExtensions.RelativeAccessor(widget.transform);

                    // Verify that it's okay to parallel-iterate over the prefab and instance gameObjs.
                    // It should be, unless one or the other has mucked with their m_MeshChildren.
                    MeshFilter[] instanceObjs = widget.GetMeshes();
                    if (prefabObjs.Count != instanceObjs.Length)
                    {
                        Debug.LogError($"Bad Model instance: {prefabObjs.Count} {instanceObjs.Length}");
                        // TODO: check order as well, somehow
                        continue;
                    }

                    // Parallel iterate, taking shared things (GeometryPool, material, name) from the
                    // "prefab" and xforms, unique ids, etc from the "instance".
                    for (int objIndex = 0; objIndex < prefabObjs.Count; ++objIndex)
                    {
                        PrefabGeometry[] prefabSubMeshes = prefabObjs[objIndex];
                        GameObject       instanceObj     = instanceObjs[objIndex].gameObject;
                        Matrix4x4        localXform      = ExportUtils.ChangeBasis(AsWidget[instanceObj.transform], payload);

                        int       objId = payload.idGenerator.GetIdFromInstanceId(instanceObj);
                        Matrix4x4 xform = ExportUtils.ChangeBasis(instanceObj.transform, payload);
                        foreach (PrefabGeometry prefabSubMesh in prefabSubMeshes)
                        {
                            payload.modelMeshes.Add(new ExportUtils.ModelMeshPayload(
                                                        payload.groupIdMapping.GetId(widget.Group))
                            {
                                // Copied from "prefab"
                                model              = prefabSubMesh.model,
                                geometry           = prefabSubMesh.pool,
                                exportableMaterial = prefabSubMesh.exportableMaterial,
                                geometryName       = prefabSubMesh.name,
                                // Unique to instance
                                legacyUniqueName = $"{prefabSubMesh.name}_i{objId}",
                                nodeName         = $"{prefabSubMesh.name}_{widgetIndex}",
                                parentXform      = widgetXform,
                                localXform       = localXform,
                                modelId          = widgetIndex,
                                xform            = xform,
                            });
                        }
                    }
                }
            }
        }