public void UpdateMesh()
        {
            if (!this.IsValid)
            {
                return;
            }

            skeleton.SetColor(this.color);
            var smartMesh           = meshBuffers.GetNext();
            var currentInstructions = this.currentInstructions;

            MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, skeleton, null);
            bool updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, smartMesh.instructionUsed);

            meshGenerator.Begin();
            if (currentInstructions.hasActiveClipping)
            {
                meshGenerator.AddSubmesh(currentInstructions.submeshInstructions.Items[0], updateTriangles);
            }
            else
            {
                meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
            }

            if (canvas != null)
            {
                meshGenerator.ScaleVertexData(canvas.referencePixelsPerUnit);
            }
            if (OnPostProcessVertices != null)
            {
                OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
            }

            var mesh = smartMesh.mesh;

            meshGenerator.FillVertexData(mesh);
            if (updateTriangles)
            {
                meshGenerator.FillTriangles(mesh);
            }
            meshGenerator.FillLateVertexData(mesh);

            canvasRenderer.SetMesh(mesh);
            smartMesh.instructionUsed.Set(currentInstructions);

            if (currentInstructions.submeshInstructions.Count > 0)
            {
                var material = currentInstructions.submeshInstructions.Items[0].material;
                if (material != null && baseTexture != material.mainTexture)
                {
                    baseTexture = material.mainTexture;
                    if (overrideTexture == null)
                    {
                        canvasRenderer.SetTexture(this.mainTexture);
                    }
                }
            }

            //this.UpdateMaterial(); // TODO: This allocates memory.
        }
예제 #2
0
        protected void UpdateMeshSingleCanvasRenderer()
        {
            if (canvasRenderers.Count > 0)
            {
                DisableUnusedCanvasRenderers(usedCount: 0);
            }

            var smartMesh = meshBuffers.GetNext();

            MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, skeleton, null);
            bool updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, smartMesh.instructionUsed);

            meshGenerator.Begin();
            if (currentInstructions.hasActiveClipping && currentInstructions.submeshInstructions.Count > 0)
            {
                meshGenerator.AddSubmesh(currentInstructions.submeshInstructions.Items[0], updateTriangles);
            }
            else
            {
                meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
            }

            if (canvas != null)
            {
                meshGenerator.ScaleVertexData(canvas.referencePixelsPerUnit);
            }
            if (OnPostProcessVertices != null)
            {
                OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
            }

            var mesh = smartMesh.mesh;

            meshGenerator.FillVertexData(mesh);
            if (updateTriangles)
            {
                meshGenerator.FillTriangles(mesh);
            }
            meshGenerator.FillLateVertexData(mesh);

            canvasRenderer.SetMesh(mesh);
            smartMesh.instructionUsed.Set(currentInstructions);

            if (currentInstructions.submeshInstructions.Count > 0)
            {
                var material = currentInstructions.submeshInstructions.Items[0].material;
                if (material != null && baseTexture != material.mainTexture)
                {
                    baseTexture = material.mainTexture;
                    if (overrideTexture == null)
                    {
                        canvasRenderer.SetTexture(this.mainTexture);
                    }
                }
            }

            //this.UpdateMaterial(); // note: This would allocate memory.
            usedRenderersCount = 0;
        }
        protected void UpdateMeshMultipleCanvasRenderers(SkeletonRendererInstruction currentInstructions)
        {
            MeshGenerator.GenerateSkeletonRendererInstruction(currentInstructions, skeleton, null,
                                                              enableSeparatorSlots ? separatorSlots : null,
                                                              enableSeparatorSlots ? separatorSlots.Count > 0 : false,
                                                              false);

            int submeshCount = currentInstructions.submeshInstructions.Count;

            EnsureCanvasRendererCount(submeshCount);
            EnsureMeshesCount(submeshCount);
            EnsureSeparatorPartCount();

            var   c     = canvas;
            float scale = (c == null) ? 100 : c.referencePixelsPerUnit;

            // Generate meshes.
            var       meshesItems = meshes.Items;
            bool      useOriginalTextureAndMaterial = (customMaterialOverride.Count == 0 && customTextureOverride.Count == 0);
            int       separatorSlotGroupIndex       = 0;
            Transform parent = this.separatorSlots.Count == 0 ? this.transform : this.separatorParts[0];

            if (updateSeparatorPartLocation)
            {
                for (int p = 0; p < this.separatorParts.Count; ++p)
                {
                    separatorParts[p].position = this.transform.position;
                    separatorParts[p].rotation = this.transform.rotation;
                }
            }

            int targetSiblingIndex = 0;

            for (int i = 0; i < submeshCount; i++)
            {
                var submeshInstructionItem = currentInstructions.submeshInstructions.Items[i];
                meshGenerator.Begin();
                meshGenerator.AddSubmesh(submeshInstructionItem);

                var targetMesh = meshesItems[i];
                meshGenerator.ScaleVertexData(scale);
                if (OnPostProcessVertices != null)
                {
                    OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
                }
                meshGenerator.FillVertexData(targetMesh);
                meshGenerator.FillTriangles(targetMesh);
                meshGenerator.FillLateVertexData(targetMesh);

                var submeshMaterial = submeshInstructionItem.material;
                var canvasRenderer  = canvasRenderers[i];
                canvasRenderer.gameObject.SetActive(true);
                canvasRenderer.SetMesh(targetMesh);
                canvasRenderer.materialCount = 1;

                if (canvasRenderer.transform.parent != parent.transform)
                {
                    canvasRenderer.transform.SetParent(parent.transform, false);
                    canvasRenderer.transform.localPosition = Vector3.zero;
                }
                canvasRenderer.transform.SetSiblingIndex(targetSiblingIndex++);
                if (submeshInstructionItem.forceSeparate)
                {
                    targetSiblingIndex = 0;
                    parent             = separatorParts[++separatorSlotGroupIndex];
                }

                if (useOriginalTextureAndMaterial)
                {
                    canvasRenderer.SetMaterial(this.materialForRendering, submeshMaterial.mainTexture);
                }
                else
                {
                    var      originalTexture = submeshMaterial.mainTexture;
                    Material usedMaterial;
                    Texture  usedTexture;
                    if (!customMaterialOverride.TryGetValue(originalTexture, out usedMaterial))
                    {
                        usedMaterial = material;
                    }
                    if (!customTextureOverride.TryGetValue(originalTexture, out usedTexture))
                    {
                        usedTexture = originalTexture;
                    }
                    canvasRenderer.SetMaterial(usedMaterial, usedTexture);
                }
            }

            DisableUnusedCanvasRenderers(usedCount: submeshCount);
        }
예제 #4
0
        /// <summary>
        /// Generates a new UnityEngine.Mesh from the internal Skeleton.</summary>
        public virtual void LateUpdate()
        {
            if (!valid)
            {
                return;
            }

                        #if UNITY_EDITOR && NEW_PREFAB_SYSTEM
            // Don't store mesh or material at the prefab, otherwise it will permanently reload
            var prefabType = UnityEditor.PrefabUtility.GetPrefabAssetType(this);
            if (UnityEditor.PrefabUtility.IsPartOfPrefabAsset(this) &&
                (prefabType == UnityEditor.PrefabAssetType.Regular || prefabType == UnityEditor.PrefabAssetType.Variant))
            {
                return;
            }
                        #endif

            if (updateMode != UpdateMode.FullUpdate)
            {
                return;
            }

                        #if SPINE_OPTIONAL_RENDEROVERRIDE
            bool doMeshOverride = generateMeshOverride != null;
            if ((!meshRenderer.enabled) && !doMeshOverride)
            {
                return;
            }
                        #else
            const bool doMeshOverride = false;
            if (!meshRenderer.enabled)
            {
                return;
            }
                        #endif
            var currentInstructions        = this.currentInstructions;
            var workingSubmeshInstructions = currentInstructions.submeshInstructions;
            var currentSmartMesh           = rendererBuffers.GetNextMesh();   // Double-buffer for performance.

            bool updateTriangles;

            if (this.singleSubmesh)
            {
                // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. =============================================
                MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, skeleton, skeletonDataAsset.atlasAssets[0].PrimaryMaterial);

                // STEP 1.9. Post-process workingInstructions. ==================================================================================
                                #if SPINE_OPTIONAL_MATERIALOVERRIDE
                if (customMaterialOverride.Count > 0)                 // isCustomMaterialOverridePopulated
                {
                    MeshGenerator.TryReplaceMaterials(workingSubmeshInstructions, customMaterialOverride);
                }
                                #endif

                // STEP 2. Update vertex buffer based on verts from the attachments. ===========================================================
                meshGenerator.settings = new MeshGenerator.Settings {
                    pmaVertexColors   = this.pmaVertexColors,
                    zSpacing          = this.zSpacing,
                    useClipping       = this.useClipping,
                    tintBlack         = this.tintBlack,
                    calculateTangents = this.calculateTangents,
                    addNormals        = this.addNormals
                };
                meshGenerator.Begin();
                updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, currentSmartMesh.instructionUsed);
                if (currentInstructions.hasActiveClipping)
                {
                    meshGenerator.AddSubmesh(workingSubmeshInstructions.Items[0], updateTriangles);
                }
                else
                {
                    meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
                }
            }
            else
            {
                // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. =============================================
                MeshGenerator.GenerateSkeletonRendererInstruction(currentInstructions, skeleton, customSlotMaterials, separatorSlots, doMeshOverride, this.immutableTriangles);

                // STEP 1.9. Post-process workingInstructions. ==================================================================================
#if SPINE_OPTIONAL_MATERIALOVERRIDE
                if (customMaterialOverride.Count > 0)                 // isCustomMaterialOverridePopulated
                {
                    MeshGenerator.TryReplaceMaterials(workingSubmeshInstructions, customMaterialOverride);
                }
#endif

#if SPINE_OPTIONAL_RENDEROVERRIDE
                if (doMeshOverride)
                {
                    this.generateMeshOverride(currentInstructions);
                    if (disableRenderingOnOverride)
                    {
                        return;
                    }
                }
#endif

                updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, currentSmartMesh.instructionUsed);

                // STEP 2. Update vertex buffer based on verts from the attachments. ===========================================================
                meshGenerator.settings = new MeshGenerator.Settings {
                    pmaVertexColors   = this.pmaVertexColors,
                    zSpacing          = this.zSpacing,
                    useClipping       = this.useClipping,
                    tintBlack         = this.tintBlack,
                    calculateTangents = this.calculateTangents,
                    addNormals        = this.addNormals
                };
                meshGenerator.Begin();
                if (currentInstructions.hasActiveClipping)
                {
                    meshGenerator.BuildMesh(currentInstructions, updateTriangles);
                }
                else
                {
                    meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
                }
            }

            if (OnPostProcessVertices != null)
            {
                OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
            }

            // STEP 3. Move the mesh data into a UnityEngine.Mesh ===========================================================================
            var currentMesh = currentSmartMesh.mesh;
            meshGenerator.FillVertexData(currentMesh);

            rendererBuffers.UpdateSharedMaterials(workingSubmeshInstructions);

            bool materialsChanged = rendererBuffers.MaterialsChangedInLastUpdate();
            if (updateTriangles)               // Check if the triangles should also be updated.
            {
                meshGenerator.FillTriangles(currentMesh);
                meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
            }
            else if (materialsChanged)
            {
                meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
            }
            if (materialsChanged && (this.maskMaterials.AnyMaterialCreated))
            {
                this.maskMaterials = new SpriteMaskInteractionMaterials();
            }

            meshGenerator.FillLateVertexData(currentMesh);

            // STEP 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. ===========
            meshFilter.sharedMesh = currentMesh;
            currentSmartMesh.instructionUsed.Set(currentInstructions);

                        #if BUILT_IN_SPRITE_MASK_COMPONENT
            if (meshRenderer != null)
            {
                AssignSpriteMaskMaterials();
            }
                        #endif

                        #if PER_MATERIAL_PROPERTY_BLOCKS
            if (fixDrawOrder && meshRenderer.sharedMaterials.Length > 2)
            {
                SetMaterialSettingsToFixDrawOrder();
            }
                        #endif

            if (OnMeshAndMaterialsUpdated != null)
            {
                OnMeshAndMaterialsUpdated(this);
            }
        }
        /// <summary>
        /// Generates a new UnityEngine.Mesh from the internal Skeleton.</summary>
        public virtual void LateUpdate()
        {
            if (!valid)
            {
                return;
            }

                        #if SPINE_OPTIONAL_RENDEROVERRIDE
            bool doMeshOverride = generateMeshOverride != null;
            if ((!meshRenderer.enabled) && !doMeshOverride)
            {
                return;
            }
                        #else
            const bool doMeshOverride = false;
            if (!meshRenderer.enabled)
            {
                return;
            }
                        #endif
            var currentInstructions        = this.currentInstructions;
            var workingSubmeshInstructions = currentInstructions.submeshInstructions;
            var currentSmartMesh           = rendererBuffers.GetNextMesh();   // Double-buffer for performance.

            bool updateTriangles;

            if (this.singleSubmesh)
            {
                // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. =============================================
                MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, skeleton, skeletonDataAsset.atlasAssets[0].materials[0]);

                // STEP 1.9. Post-process workingInstructions. ==================================================================================
                                #if SPINE_OPTIONAL_MATERIALOVERRIDE
                if (customMaterialOverride.Count > 0)                 // isCustomMaterialOverridePopulated
                {
                    MeshGenerator.TryReplaceMaterials(workingSubmeshInstructions, customMaterialOverride);
                }
                                #endif

                // STEP 2. Update vertex buffer based on verts from the attachments.  ===========================================================
                meshGenerator.settings = new MeshGenerator.Settings {
                    pmaVertexColors   = this.pmaVertexColors,
                    zSpacing          = this.zSpacing,
                    useClipping       = this.useClipping,
                    tintBlack         = this.tintBlack,
                    calculateTangents = this.calculateTangents,
                    addNormals        = this.addNormals
                };
                meshGenerator.Begin();
                updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, currentSmartMesh.instructionUsed);
                if (currentInstructions.hasActiveClipping)
                {
                    meshGenerator.AddSubmesh(workingSubmeshInstructions.Items[0], updateTriangles);
                }
                else
                {
                    meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
                }
            }
            else
            {
                // STEP 1. Determine a SmartMesh.Instruction. Split up instructions into submeshes. =============================================
                MeshGenerator.GenerateSkeletonRendererInstruction(currentInstructions, skeleton, customSlotMaterials, separatorSlots, doMeshOverride, this.immutableTriangles);

                // STEP 1.9. Post-process workingInstructions. ==================================================================================
                                #if SPINE_OPTIONAL_MATERIALOVERRIDE
                if (customMaterialOverride.Count > 0)                 // isCustomMaterialOverridePopulated
                {
                    MeshGenerator.TryReplaceMaterials(workingSubmeshInstructions, customMaterialOverride);
                }
                                #endif

                                #if SPINE_OPTIONAL_RENDEROVERRIDE
                if (doMeshOverride)
                {
                    this.generateMeshOverride(currentInstructions);
                    if (disableRenderingOnOverride)
                    {
                        return;
                    }
                }
                                #endif

                updateTriangles = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, currentSmartMesh.instructionUsed);

                // STEP 2. Update vertex buffer based on verts from the attachments.  ===========================================================
                meshGenerator.settings = new MeshGenerator.Settings {
                    pmaVertexColors   = this.pmaVertexColors,
                    zSpacing          = this.zSpacing,
                    useClipping       = this.useClipping,
                    tintBlack         = this.tintBlack,
                    calculateTangents = this.calculateTangents,
                    addNormals        = this.addNormals
                };
                meshGenerator.Begin();
                if (currentInstructions.hasActiveClipping)
                {
                    meshGenerator.BuildMesh(currentInstructions, updateTriangles);
                }
                else
                {
                    meshGenerator.BuildMeshWithArrays(currentInstructions, updateTriangles);
                }
            }

            if (OnPostProcessVertices != null)
            {
                OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
            }

            // STEP 3. Move the mesh data into a UnityEngine.Mesh ===========================================================================
            var currentMesh = currentSmartMesh.mesh;
            meshGenerator.FillVertexData(currentMesh);
            rendererBuffers.UpdateSharedMaterials(workingSubmeshInstructions);
            if (updateTriangles)               // Check if the triangles should also be updated.
            {
                meshGenerator.FillTriangles(currentMesh);
                meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
            }
            else if (rendererBuffers.MaterialsChangedInLastUpdate())
            {
                meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedSharedMaterialsArray();
            }


            // STEP 4. The UnityEngine.Mesh is ready. Set it as the MeshFilter's mesh. Store the instructions used for that mesh. ===========
            meshFilter.sharedMesh = currentMesh;
            currentSmartMesh.instructionUsed.Set(currentInstructions);
        }
예제 #6
0
        protected void UpdateMeshMultipleCanvasRenderers(SkeletonRendererInstruction currentInstructions, bool keepRendererCount)
        {
            MeshGenerator.GenerateSkeletonRendererInstruction(currentInstructions, skeleton, null,
                                                              enableSeparatorSlots ? separatorSlots : null,
                                                              enableSeparatorSlots ? separatorSlots.Count > 0 : false,
                                                              false);

            int submeshCount = currentInstructions.submeshInstructions.Count;

            if (keepRendererCount && submeshCount != usedRenderersCount)
            {
                return;
            }
            EnsureCanvasRendererCount(submeshCount);
            EnsureMeshesCount(submeshCount);
            EnsureSeparatorPartCount();

            var   c     = canvas;
            float scale = (c == null) ? 100 : c.referencePixelsPerUnit;

            // Generate meshes.
            var       meshesItems = meshes.Items;
            bool      useOriginalTextureAndMaterial = (customMaterialOverride.Count == 0 && customTextureOverride.Count == 0);
            int       separatorSlotGroupIndex       = 0;
            Transform parent = this.separatorSlots.Count == 0 ? this.transform : this.separatorParts[0];

            if (updateSeparatorPartLocation)
            {
                for (int p = 0; p < this.separatorParts.Count; ++p)
                {
                    separatorParts[p].position = this.transform.position;
                    separatorParts[p].rotation = this.transform.rotation;
                }
            }

            BlendModeMaterials blendModeMaterials = skeletonDataAsset.blendModeMaterials;
            bool hasBlendModeMaterials            = blendModeMaterials.RequiresBlendModeMaterials;

#if HAS_CULL_TRANSPARENT_MESH
            bool mainCullTransparentMesh = this.canvasRenderer.cullTransparentMesh;
#endif
            bool pmaVertexColors    = meshGenerator.settings.pmaVertexColors;
            int  targetSiblingIndex = 0;
            for (int i = 0; i < submeshCount; i++)
            {
                var submeshInstructionItem = currentInstructions.submeshInstructions.Items[i];
                meshGenerator.Begin();
                meshGenerator.AddSubmesh(submeshInstructionItem);

                Mesh targetMesh = meshesItems[i];
                meshGenerator.ScaleVertexData(scale);
                if (OnPostProcessVertices != null)
                {
                    OnPostProcessVertices.Invoke(this.meshGenerator.Buffers);
                }
                meshGenerator.FillVertexData(targetMesh);
                meshGenerator.FillTriangles(targetMesh);
                meshGenerator.FillLateVertexData(targetMesh);

                var submeshMaterial = submeshInstructionItem.material;
                var canvasRenderer  = canvasRenderers[i];
                if (i >= usedRenderersCount)
                {
                    canvasRenderer.gameObject.SetActive(true);
                }
                canvasRenderer.SetMesh(targetMesh);
                canvasRenderer.materialCount = 1;

                if (canvasRenderer.transform.parent != parent.transform)
                {
                    canvasRenderer.transform.SetParent(parent.transform, false);
                    canvasRenderer.transform.localPosition = Vector3.zero;
                }
                canvasRenderer.transform.SetSiblingIndex(targetSiblingIndex++);
                if (submeshInstructionItem.forceSeparate)
                {
                    targetSiblingIndex = 0;
                    parent             = separatorParts[++separatorSlotGroupIndex];
                }

                SkeletonSubmeshGraphic submeshGraphic = submeshGraphics[i];
                if (useOriginalTextureAndMaterial)
                {
                    Texture usedTexture = submeshMaterial.mainTexture;
                    if (!hasBlendModeMaterials)
                    {
                        canvasRenderer.SetMaterial(this.materialForRendering, usedTexture);
                    }
                    else
                    {
                        bool      allowCullTransparentMesh = true;
                        BlendMode blendMode    = blendModeMaterials.BlendModeForMaterial(submeshMaterial);
                        Material  usedMaterial = this.materialForRendering;
                        if (blendMode == BlendMode.Normal)
                        {
                            if (submeshInstructionItem.hasPMAAdditiveSlot)
                            {
                                allowCullTransparentMesh = false;
                            }
                        }
                        else if (blendMode == BlendMode.Additive)
                        {
                            if (pmaVertexColors)
                            {
                                allowCullTransparentMesh = false;
                            }
                            else if (additiveMaterial)
                            {
                                usedMaterial = additiveMaterial;
                            }
                        }
                        else if (blendMode == BlendMode.Multiply && multiplyMaterial)
                        {
                            usedMaterial = multiplyMaterial;
                        }
                        else if (blendMode == BlendMode.Screen && screenMaterial)
                        {
                            usedMaterial = screenMaterial;
                        }

                        usedMaterial = submeshGraphic.GetModifiedMaterial(usedMaterial);
                        canvasRenderer.SetMaterial(usedMaterial, usedTexture);
#if HAS_CULL_TRANSPARENT_MESH
                        canvasRenderer.cullTransparentMesh = allowCullTransparentMesh ?
                                                             mainCullTransparentMesh : false;
#endif
                    }
                }
                else
                {
                    var      originalTexture = submeshMaterial.mainTexture;
                    Material usedMaterial;
                    Texture  usedTexture;
                    if (!customMaterialOverride.TryGetValue(originalTexture, out usedMaterial))
                    {
                        usedMaterial = material;
                    }
                    if (!customTextureOverride.TryGetValue(originalTexture, out usedTexture))
                    {
                        usedTexture = originalTexture;
                    }

                    usedMaterial = submeshGraphic.GetModifiedMaterial(usedMaterial);
                    canvasRenderer.SetMaterial(usedMaterial, usedTexture);
                }
            }

            DisableUnusedCanvasRenderers(usedCount: submeshCount);
            usedRenderersCount = submeshCount;
        }