/// <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(); } 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); }
public static bool GeometryNotEqual(SkeletonRendererInstruction a, SkeletonRendererInstruction b) { #if SPINE_TRIANGLECHECK #if UNITY_EDITOR if (!Application.isPlaying) { return(true); } #endif if (a.hasActiveClipping || b.hasActiveClipping) { return(true); // Triangles are unpredictable when clipping is active. } // Everything below assumes the raw vertex and triangle counts were used. (ie, no clipping was done) if (a.rawVertexCount != b.rawVertexCount) { return(true); } if (a.immutableTriangles != b.immutableTriangles) { return(true); } int attachmentCountB = b.attachments.Count; if (a.attachments.Count != attachmentCountB) { return(true); // Bounds check for the looped storedAttachments count below. } // Submesh count changed int submeshCountA = a.submeshInstructions.Count; int submeshCountB = b.submeshInstructions.Count; if (submeshCountA != submeshCountB) { return(true); } // Submesh Instruction mismatch var submeshInstructionsItemsA = a.submeshInstructions.Items; var submeshInstructionsItemsB = b.submeshInstructions.Items; var attachmentsA = a.attachments.Items; var attachmentsB = b.attachments.Items; for (int i = 0; i < attachmentCountB; i++) { if (!System.Object.ReferenceEquals(attachmentsA[i], attachmentsB[i])) { return(true); } } for (int i = 0; i < submeshCountB; i++) { var submeshA = submeshInstructionsItemsA[i]; var submeshB = submeshInstructionsItemsB[i]; if (!( submeshA.rawVertexCount == submeshB.rawVertexCount && submeshA.startSlot == submeshB.startSlot && submeshA.endSlot == submeshB.endSlot && submeshA.rawTriangleCount == submeshB.rawTriangleCount && submeshA.rawFirstVertexIndex == submeshB.rawFirstVertexIndex )) { return(true); } } return(false); #else // In normal immutable triangle use, immutableTriangles will be initially false, forcing the smartmesh to update the first time but never again after that, unless there was an immutableTriangles flag mismatch.. if (a.immutableTriangles || b.immutableTriangles) { return(a.immutableTriangles != b.immutableTriangles); } return(true); #endif }
/// <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.IsPartOfPrefabInstance(this) && (prefabType == UnityEditor.PrefabAssetType.Regular || prefabType == UnityEditor.PrefabAssetType.Variant)) { return; } #endif #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 }
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; } } 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]; if (i >= usedRenderersCount) { canvasRenderer.gameObject.SetActive(true); rawImages[i].Rebuild(CanvasUpdate.PreRender); } 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); usedRenderersCount = submeshCount; }
void HandleRender(SkeletonRendererInstruction instruction) { int rendererCount = partsRenderers.Count; if (rendererCount <= 0) { return; } if (copyPropertyBlock) { mainMeshRenderer.GetPropertyBlock(copiedBlock); } var settings = new MeshGenerator.Settings { addNormals = skeletonRenderer.addNormals, calculateTangents = skeletonRenderer.calculateTangents, immutableTriangles = false, // parts cannot do immutable triangles. pmaVertexColors = skeletonRenderer.pmaVertexColors, tintBlack = skeletonRenderer.tintBlack, useClipping = true, zSpacing = skeletonRenderer.zSpacing }; var submeshInstructions = instruction.submeshInstructions; var submeshInstructionsItems = submeshInstructions.Items; int lastSubmeshInstruction = submeshInstructions.Count - 1; int rendererIndex = 0; var currentRenderer = partsRenderers[rendererIndex]; for (int si = 0, start = 0; si <= lastSubmeshInstruction; si++) { if (submeshInstructionsItems[si].forceSeparate || si == lastSubmeshInstruction) { // Apply properties var meshGenerator = currentRenderer.MeshGenerator; meshGenerator.settings = settings; if (copyPropertyBlock) { currentRenderer.SetPropertyBlock(copiedBlock); } // Render currentRenderer.RenderParts(instruction.submeshInstructions, start, si + 1); start = si + 1; rendererIndex++; if (rendererIndex < rendererCount) { currentRenderer = partsRenderers[rendererIndex]; } else { // Not enough renderers. Skip the rest of the instructions. break; } } } // Clear extra renderers if they exist. for (; rendererIndex < rendererCount; rendererIndex++) { partsRenderers[rendererIndex].ClearMesh(); } }
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 && 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(); // TODO: This allocates memory. if (OnMeshAndMaterialsUpdated != null) { OnMeshAndMaterialsUpdated(this); } }
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; }
public virtual void LateUpdate() { if (this.valid) { bool generateMeshOverride = this.generateMeshOverride != null; if (this.meshRenderer.enabled || generateMeshOverride) { bool flag2; SkeletonRendererInstruction currentInstructions = this.currentInstructions; ExposedList <SubmeshInstruction> submeshInstructions = currentInstructions.submeshInstructions; MeshRendererBuffers.SmartMesh nextMesh = this.rendererBuffers.GetNextMesh(); if (this.singleSubmesh) { MeshGenerator.GenerateSingleSubmeshInstruction(currentInstructions, this.skeleton, this.skeletonDataAsset.atlasAssets[0].materials[0]); if (this.customMaterialOverride.Count > 0) { MeshGenerator.TryReplaceMaterials(submeshInstructions, this.customMaterialOverride); } MeshGenerator.Settings settings = new MeshGenerator.Settings { pmaVertexColors = this.pmaVertexColors, zSpacing = this.zSpacing, useClipping = this.useClipping, tintBlack = this.tintBlack, calculateTangents = this.calculateTangents, addNormals = this.addNormals }; this.meshGenerator.settings = settings; this.meshGenerator.Begin(); flag2 = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, nextMesh.instructionUsed); if (currentInstructions.hasActiveClipping) { this.meshGenerator.AddSubmesh(submeshInstructions.Items[0], flag2); } else { this.meshGenerator.BuildMeshWithArrays(currentInstructions, flag2); } } else { MeshGenerator.GenerateSkeletonRendererInstruction(currentInstructions, this.skeleton, this.customSlotMaterials, this.separatorSlots, generateMeshOverride, this.immutableTriangles); if (this.customMaterialOverride.Count > 0) { MeshGenerator.TryReplaceMaterials(submeshInstructions, this.customMaterialOverride); } if (generateMeshOverride) { this.generateMeshOverride(currentInstructions); if (this.disableRenderingOnOverride) { return; } } flag2 = SkeletonRendererInstruction.GeometryNotEqual(currentInstructions, nextMesh.instructionUsed); MeshGenerator.Settings settings2 = new MeshGenerator.Settings { pmaVertexColors = this.pmaVertexColors, zSpacing = this.zSpacing, useClipping = this.useClipping, tintBlack = this.tintBlack, calculateTangents = this.calculateTangents, addNormals = this.addNormals }; this.meshGenerator.settings = settings2; this.meshGenerator.Begin(); if (currentInstructions.hasActiveClipping) { this.meshGenerator.BuildMesh(currentInstructions, flag2); } else { this.meshGenerator.BuildMeshWithArrays(currentInstructions, flag2); } } if (this.OnPostProcessVertices != null) { this.OnPostProcessVertices(this.meshGenerator.Buffers); } Mesh mesh = nextMesh.mesh; this.meshGenerator.FillVertexData(mesh); this.rendererBuffers.UpdateSharedMaterials(submeshInstructions); if (flag2) { this.meshGenerator.FillTriangles(mesh); this.meshRenderer.sharedMaterials = this.rendererBuffers.GetUpdatedSharedMaterialsArray(); } else if (this.rendererBuffers.MaterialsChangedInLastUpdate()) { this.meshRenderer.sharedMaterials = this.rendererBuffers.GetUpdatedSharedMaterialsArray(); } this.meshGenerator.FillLateVertexData(mesh); this.meshFilter.sharedMesh = mesh; nextMesh.instructionUsed.Set(currentInstructions); } } }
public void BuildMeshWithArrays(SkeletonRendererInstruction instruction, bool updateTriangles) { Settings settings = this.settings; int rawVertexCount = instruction.rawVertexCount; if (rawVertexCount > vertexBuffer.Items.Length) { Array.Resize(ref vertexBuffer.Items, rawVertexCount); Array.Resize(ref uvBuffer.Items, rawVertexCount); Array.Resize(ref colorBuffer.Items, rawVertexCount); } vertexBuffer.Count = (uvBuffer.Count = (colorBuffer.Count = rawVertexCount)); Color32 color = default(Color32); int num = 0; float[] array = tempVerts; Vector3 v = meshBoundsMin; Vector3 v2 = meshBoundsMax; Vector3[] items = vertexBuffer.Items; Vector2[] items2 = uvBuffer.Items; Color32[] items3 = colorBuffer.Items; int num2 = 0; int i = 0; Vector2 vector = default(Vector2); Vector2 vector2 = default(Vector2); for (int count = instruction.submeshInstructions.Count; i < count; i++) { SubmeshInstruction submeshInstruction = instruction.submeshInstructions.Items[i]; Skeleton skeleton = submeshInstruction.skeleton; Slot[] items4 = skeleton.drawOrder.Items; float num3 = skeleton.a * 255f; float r = skeleton.r; float g = skeleton.g; float b = skeleton.b; int endSlot = submeshInstruction.endSlot; int startSlot = submeshInstruction.startSlot; num2 = endSlot; if (settings.tintBlack) { int num4 = num; vector.y = 1f; if (uv2 == null) { uv2 = new ExposedList <Vector2>(); uv3 = new ExposedList <Vector2>(); } if (rawVertexCount > uv2.Items.Length) { Array.Resize(ref uv2.Items, rawVertexCount); Array.Resize(ref uv3.Items, rawVertexCount); } uv2.Count = (uv3.Count = rawVertexCount); Vector2[] items5 = uv2.Items; Vector2[] items6 = uv3.Items; for (int j = startSlot; j < endSlot; j++) { Slot slot = items4[j]; Attachment attachment = slot.attachment; vector2.x = slot.r2; vector2.y = slot.g2; vector.x = slot.b2; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { items5[num4] = vector2; items5[num4 + 1] = vector2; items5[num4 + 2] = vector2; items5[num4 + 3] = vector2; items6[num4] = vector; items6[num4 + 1] = vector; items6[num4 + 2] = vector; items6[num4 + 3] = vector; num4 += 4; continue; } MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { int worldVerticesLength = meshAttachment.worldVerticesLength; for (int k = 0; k < worldVerticesLength; k += 2) { items5[num4] = vector2; items6[num4] = vector; num4++; } } } } for (int l = startSlot; l < endSlot; l++) { Slot slot2 = items4[l]; Attachment attachment2 = slot2.attachment; float z = (float)l * settings.zSpacing; RegionAttachment regionAttachment2 = attachment2 as RegionAttachment; if (regionAttachment2 != null) { regionAttachment2.ComputeWorldVertices(slot2.bone, array, 0); float num5 = array[0]; float num6 = array[1]; float num7 = array[2]; float num8 = array[3]; float num9 = array[4]; float num10 = array[5]; float num11 = array[6]; float num12 = array[7]; items[num].x = num5; items[num].y = num6; items[num].z = z; items[num + 1].x = num11; items[num + 1].y = num12; items[num + 1].z = z; items[num + 2].x = num7; items[num + 2].y = num8; items[num + 2].z = z; items[num + 3].x = num9; items[num + 3].y = num10; items[num + 3].z = z; if (settings.pmaVertexColors) { color.a = (byte)(num3 * slot2.a * regionAttachment2.a); color.r = (byte)(r * slot2.r * regionAttachment2.r * (float)(int)color.a); color.g = (byte)(g * slot2.g * regionAttachment2.g * (float)(int)color.a); color.b = (byte)(b * slot2.b * regionAttachment2.b * (float)(int)color.a); if (slot2.data.blendMode == BlendMode.Additive) { color.a = 0; } } else { color.a = (byte)(num3 * slot2.a * regionAttachment2.a); color.r = (byte)(r * slot2.r * regionAttachment2.r * 255f); color.g = (byte)(g * slot2.g * regionAttachment2.g * 255f); color.b = (byte)(b * slot2.b * regionAttachment2.b * 255f); } items3[num] = color; items3[num + 1] = color; items3[num + 2] = color; items3[num + 3] = color; float[] uvs = regionAttachment2.uvs; items2[num].x = uvs[0]; items2[num].y = uvs[1]; items2[num + 1].x = uvs[6]; items2[num + 1].y = uvs[7]; items2[num + 2].x = uvs[2]; items2[num + 2].y = uvs[3]; items2[num + 3].x = uvs[4]; items2[num + 3].y = uvs[5]; if (num5 < v.x) { v.x = num5; } if (num5 > v2.x) { v2.x = num5; } if (num7 < v.x) { v.x = num7; } else if (num7 > v2.x) { v2.x = num7; } if (num9 < v.x) { v.x = num9; } else if (num9 > v2.x) { v2.x = num9; } if (num11 < v.x) { v.x = num11; } else if (num11 > v2.x) { v2.x = num11; } if (num6 < v.y) { v.y = num6; } if (num6 > v2.y) { v2.y = num6; } if (num8 < v.y) { v.y = num8; } else if (num8 > v2.y) { v2.y = num8; } if (num10 < v.y) { v.y = num10; } else if (num10 > v2.y) { v2.y = num10; } if (num12 < v.y) { v.y = num12; } else if (num12 > v2.y) { v2.y = num12; } num += 4; continue; } MeshAttachment meshAttachment2 = attachment2 as MeshAttachment; if (meshAttachment2 == null) { continue; } int worldVerticesLength2 = meshAttachment2.worldVerticesLength; if (array.Length < worldVerticesLength2) { array = (tempVerts = new float[worldVerticesLength2]); } meshAttachment2.ComputeWorldVertices(slot2, array); if (settings.pmaVertexColors) { color.a = (byte)(num3 * slot2.a * meshAttachment2.a); color.r = (byte)(r * slot2.r * meshAttachment2.r * (float)(int)color.a); color.g = (byte)(g * slot2.g * meshAttachment2.g * (float)(int)color.a); color.b = (byte)(b * slot2.b * meshAttachment2.b * (float)(int)color.a); if (slot2.data.blendMode == BlendMode.Additive) { color.a = 0; } } else { color.a = (byte)(num3 * slot2.a * meshAttachment2.a); color.r = (byte)(r * slot2.r * meshAttachment2.r * 255f); color.g = (byte)(g * slot2.g * meshAttachment2.g * 255f); color.b = (byte)(b * slot2.b * meshAttachment2.b * 255f); } float[] uvs2 = meshAttachment2.uvs; if (num == 0) { float num13 = array[0]; float num14 = array[1]; if (num13 < v.x) { v.x = num13; } if (num13 > v2.x) { v2.x = num13; } if (num14 < v.y) { v.y = num14; } if (num14 > v2.y) { v2.y = num14; } } for (int m = 0; m < worldVerticesLength2; m += 2) { float num15 = array[m]; float num16 = array[m + 1]; items[num].x = num15; items[num].y = num16; items[num].z = z; items3[num] = color; items2[num].x = uvs2[m]; items2[num].y = uvs2[m + 1]; if (num15 < v.x) { v.x = num15; } else if (num15 > v2.x) { v2.x = num15; } if (num16 < v.y) { v.y = num16; } else if (num16 > v2.y) { v2.y = num16; } num++; } } } meshBoundsMin = v; meshBoundsMax = v2; meshBoundsThickness = (float)num2 * settings.zSpacing; if (!updateTriangles) { return; } int count2 = instruction.submeshInstructions.Count; if (submeshes.Count < count2) { submeshes.Resize(count2); int n = 0; for (int num17 = count2; n < num17; n++) { ExposedList <int> exposedList = submeshes.Items[n]; if (exposedList == null) { submeshes.Items[n] = new ExposedList <int>(); } else { exposedList.Clear(clearArray: false); } } } SubmeshInstruction[] items7 = instruction.submeshInstructions.Items; int num18 = 0; for (int num19 = 0; num19 < count2; num19++) { SubmeshInstruction submeshInstruction2 = items7[num19]; ExposedList <int> exposedList2 = submeshes.Items[num19]; int rawTriangleCount = submeshInstruction2.rawTriangleCount; if (rawTriangleCount > exposedList2.Items.Length) { Array.Resize(ref exposedList2.Items, rawTriangleCount); } else if (rawTriangleCount < exposedList2.Items.Length) { int[] items8 = exposedList2.Items; int num20 = rawTriangleCount; for (int num21 = items8.Length; num20 < num21; num20++) { items8[num20] = 0; } } exposedList2.Count = rawTriangleCount; int[] items9 = exposedList2.Items; int num22 = 0; Skeleton skeleton2 = submeshInstruction2.skeleton; Slot[] items10 = skeleton2.drawOrder.Items; int num23 = submeshInstruction2.startSlot; for (int endSlot2 = submeshInstruction2.endSlot; num23 < endSlot2; num23++) { Attachment attachment3 = items10[num23].attachment; if (attachment3 is RegionAttachment) { items9[num22] = num18; items9[num22 + 1] = num18 + 2; items9[num22 + 2] = num18 + 1; items9[num22 + 3] = num18 + 2; items9[num22 + 4] = num18 + 3; items9[num22 + 5] = num18 + 1; num22 += 6; num18 += 4; continue; } MeshAttachment meshAttachment3 = attachment3 as MeshAttachment; if (meshAttachment3 != null) { int[] triangles = meshAttachment3.triangles; int num24 = 0; int num25 = triangles.Length; while (num24 < num25) { items9[num22] = num18 + triangles[num24]; num24++; num22++; } num18 += meshAttachment3.worldVerticesLength >> 1; } } } }
public static void GenerateSkeletonRendererInstruction(SkeletonRendererInstruction instructionOutput, Skeleton skeleton, Dictionary <Slot, Material> customSlotMaterials, List <Slot> separatorSlots, bool generateMeshOverride, bool immutableTriangles = false) { ExposedList <Slot> drawOrder = skeleton.drawOrder; int count = drawOrder.Count; instructionOutput.Clear(); ExposedList <SubmeshInstruction> submeshInstructions = instructionOutput.submeshInstructions; instructionOutput.attachments.Resize(count); Attachment[] items = instructionOutput.attachments.Items; int num = 0; bool hasActiveClipping = false; SubmeshInstruction submeshInstruction = default(SubmeshInstruction); submeshInstruction.skeleton = skeleton; submeshInstruction.preActiveClippingSlotSource = -1; SubmeshInstruction submeshInstruction2 = submeshInstruction; bool flag = customSlotMaterials != null && customSlotMaterials.Count > 0; int num2 = (separatorSlots != null) ? separatorSlots.Count : 0; bool flag2 = num2 > 0; int num3 = -1; int preActiveClippingSlotSource = -1; SlotData slotData = null; int num4 = 0; Slot[] items2 = drawOrder.Items; for (int i = 0; i < count; i++) { Slot slot = items2[i]; Attachment attachment = items[i] = slot.attachment; int num5 = 0; int num6 = 0; object obj = null; bool flag3 = false; RegionAttachment regionAttachment = attachment as RegionAttachment; if (regionAttachment != null) { obj = regionAttachment.RendererObject; num5 = 4; num6 = 6; } else { MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { obj = meshAttachment.RendererObject; num5 = meshAttachment.worldVerticesLength >> 1; num6 = meshAttachment.triangles.Length; } else { ClippingAttachment clippingAttachment = attachment as ClippingAttachment; if (clippingAttachment != null) { slotData = clippingAttachment.endSlot; num3 = i; submeshInstruction2.hasClipping = true; hasActiveClipping = true; } flag3 = true; } } if (slotData != null && slot.data == slotData) { slotData = null; num3 = -1; } if (flag2) { submeshInstruction2.forceSeparate = false; for (int j = 0; j < num2; j++) { if (object.ReferenceEquals(slot, separatorSlots[j])) { submeshInstruction2.forceSeparate = true; break; } } } if (flag3) { if (submeshInstruction2.forceSeparate && generateMeshOverride) { submeshInstruction2.endSlot = i; submeshInstruction2.preActiveClippingSlotSource = preActiveClippingSlotSource; submeshInstructions.Resize(num4 + 1); submeshInstructions.Items[num4] = submeshInstruction2; num4++; submeshInstruction2.startSlot = i; preActiveClippingSlotSource = num3; submeshInstruction2.rawTriangleCount = 0; submeshInstruction2.rawVertexCount = 0; submeshInstruction2.rawFirstVertexIndex = num; submeshInstruction2.hasClipping = (num3 >= 0); } continue; } Material value; if (flag) { if (!customSlotMaterials.TryGetValue(slot, out value)) { value = (Material)((AtlasRegion)obj).page.rendererObject; } } else { value = (Material)((AtlasRegion)obj).page.rendererObject; } if (submeshInstruction2.forceSeparate || (submeshInstruction2.rawVertexCount > 0 && !object.ReferenceEquals(submeshInstruction2.material, value))) { submeshInstruction2.endSlot = i; submeshInstruction2.preActiveClippingSlotSource = preActiveClippingSlotSource; submeshInstructions.Resize(num4 + 1); submeshInstructions.Items[num4] = submeshInstruction2; num4++; submeshInstruction2.startSlot = i; preActiveClippingSlotSource = num3; submeshInstruction2.rawTriangleCount = 0; submeshInstruction2.rawVertexCount = 0; submeshInstruction2.rawFirstVertexIndex = num; submeshInstruction2.hasClipping = (num3 >= 0); } submeshInstruction2.material = value; submeshInstruction2.rawTriangleCount += num6; submeshInstruction2.rawVertexCount += num5; submeshInstruction2.rawFirstVertexIndex = num; num += num5; } if (submeshInstruction2.rawVertexCount > 0) { submeshInstruction2.endSlot = count; submeshInstruction2.preActiveClippingSlotSource = preActiveClippingSlotSource; submeshInstruction2.forceSeparate = false; submeshInstructions.Resize(num4 + 1); submeshInstructions.Items[num4] = submeshInstruction2; } instructionOutput.hasActiveClipping = hasActiveClipping; instructionOutput.rawVertexCount = num; instructionOutput.immutableTriangles = immutableTriangles; }
public static void GenerateSingleSubmeshInstruction(SkeletonRendererInstruction instructionOutput, Skeleton skeleton, Material material) { ExposedList <Slot> drawOrder = skeleton.drawOrder; int count = drawOrder.Count; instructionOutput.Clear(); ExposedList <SubmeshInstruction> submeshInstructions = instructionOutput.submeshInstructions; submeshInstructions.Resize(1); instructionOutput.attachments.Resize(count); Attachment[] items = instructionOutput.attachments.Items; int num = 0; SubmeshInstruction submeshInstruction = default(SubmeshInstruction); submeshInstruction.skeleton = skeleton; submeshInstruction.preActiveClippingSlotSource = -1; submeshInstruction.startSlot = 0; submeshInstruction.rawFirstVertexIndex = 0; submeshInstruction.material = material; submeshInstruction.forceSeparate = false; submeshInstruction.endSlot = count; SubmeshInstruction submeshInstruction2 = submeshInstruction; bool hasActiveClipping = false; Slot[] items2 = drawOrder.Items; for (int i = 0; i < count; i++) { Slot slot = items2[i]; Attachment attachment = items[i] = slot.attachment; RegionAttachment regionAttachment = attachment as RegionAttachment; int num2; int num3; if (regionAttachment != null) { num2 = 4; num3 = 6; } else { MeshAttachment meshAttachment = attachment as MeshAttachment; if (meshAttachment != null) { num2 = meshAttachment.worldVerticesLength >> 1; num3 = meshAttachment.triangles.Length; } else { ClippingAttachment clippingAttachment = attachment as ClippingAttachment; if (clippingAttachment != null) { submeshInstruction2.hasClipping = true; hasActiveClipping = true; } num2 = 0; num3 = 0; } } submeshInstruction2.rawTriangleCount += num3; submeshInstruction2.rawVertexCount += num2; num += num2; } instructionOutput.hasActiveClipping = hasActiveClipping; instructionOutput.rawVertexCount = num; submeshInstructions.Items[0] = submeshInstruction2; }
public virtual void LateUpdate() { if (!valid) { return; } bool flag = this.generateMeshOverride != null; if (!meshRenderer.enabled && !flag) { return; } SkeletonRendererInstruction skeletonRendererInstruction = currentInstructions; ExposedList <SubmeshInstruction> submeshInstructions = skeletonRendererInstruction.submeshInstructions; MeshRendererBuffers.SmartMesh nextMesh = rendererBuffers.GetNextMesh(); bool flag2; if (singleSubmesh) { MeshGenerator.GenerateSingleSubmeshInstruction(skeletonRendererInstruction, skeleton, skeletonDataAsset.atlasAssets[0].materials[0]); if (customMaterialOverride.Count > 0) { MeshGenerator.TryReplaceMaterials(submeshInstructions, customMaterialOverride); } meshGenerator.settings = new MeshGenerator.Settings { pmaVertexColors = pmaVertexColors, zSpacing = zSpacing, useClipping = useClipping, tintBlack = tintBlack, calculateTangents = calculateTangents, addNormals = addNormals }; meshGenerator.Begin(); flag2 = SkeletonRendererInstruction.GeometryNotEqual(skeletonRendererInstruction, nextMesh.instructionUsed); if (skeletonRendererInstruction.hasActiveClipping) { meshGenerator.AddSubmesh(submeshInstructions.Items[0], flag2); } else { meshGenerator.BuildMeshWithArrays(skeletonRendererInstruction, flag2); } } else { MeshGenerator.GenerateSkeletonRendererInstruction(skeletonRendererInstruction, skeleton, customSlotMaterials, separatorSlots, flag, immutableTriangles); if (customMaterialOverride.Count > 0) { MeshGenerator.TryReplaceMaterials(submeshInstructions, customMaterialOverride); } if (flag) { this.generateMeshOverride(skeletonRendererInstruction); if (disableRenderingOnOverride) { return; } } flag2 = SkeletonRendererInstruction.GeometryNotEqual(skeletonRendererInstruction, nextMesh.instructionUsed); meshGenerator.settings = new MeshGenerator.Settings { pmaVertexColors = pmaVertexColors, zSpacing = zSpacing, useClipping = useClipping, tintBlack = tintBlack, calculateTangents = calculateTangents, addNormals = addNormals }; meshGenerator.Begin(); if (skeletonRendererInstruction.hasActiveClipping) { meshGenerator.BuildMesh(skeletonRendererInstruction, flag2); } else { meshGenerator.BuildMeshWithArrays(skeletonRendererInstruction, flag2); } } if (this.OnPostProcessVertices != null) { this.OnPostProcessVertices(meshGenerator.Buffers); } Mesh mesh = nextMesh.mesh; meshGenerator.FillVertexData(mesh); rendererBuffers.UpdateSharedMaterials(submeshInstructions); if (flag2) { meshGenerator.FillTriangles(mesh); meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedShaderdMaterialsArray(); } else if (rendererBuffers.MaterialsChangedInLastUpdate()) { meshRenderer.sharedMaterials = rendererBuffers.GetUpdatedShaderdMaterialsArray(); } meshFilter.sharedMesh = mesh; nextMesh.instructionUsed.Set(skeletonRendererInstruction); }