public bool CombineMeshes(ObjectSelectionState objectSelectionState, out ErrorList errorMessages)
        {
            ModelCombiner modelValidator = new ModelCombiner();
            var           objs           = objectSelectionState.SelectedObjects().Where(x => x is Rmv2MeshNode).Select(x => x as Rmv2MeshNode);

            if (!modelValidator.CanCombine(objs.ToList(), out errorMessages))
            {
                return(false);
            }

            var command = new CombineMeshCommand(objectSelectionState.SelectedObjects());

            _commandManager.ExecuteCommand(command);

            return(true);
        }
        /// <summary>
        /// Gets Unity Mesh from previously combined model data.
        /// </summary>
        /// <param name="dfUnity">DaggerfallUnity singleon for loading content.</param>
        /// <param name="combiner">ModelCombiner to build from.</param>
        /// <param name="cachedMaterialsOut">Array of cached materials in order of submesh.</param>
        /// <param name="textureKeysOut">Array of original texture keys in order of submesh.</param>
        /// <param name="hasAnimationsOut">True if one or more materials have animations.</param>
        /// <param name="solveTangents">Solve tangents for this mesh.</param>
        /// <param name="lightmapUVs">Add secondary lightmap UVs to this mesh.</param>
        /// <returns>Mesh object or null.</returns>
        public Mesh GetCombinedMesh(
            DaggerfallUnity dfUnity,
            ModelCombiner combiner,
            out CachedMaterial[] cachedMaterialsOut,
            out int[] textureKeysOut,
            out bool hasAnimationsOut,
            bool solveTangents = false,
            bool lightmapUVs   = false)
        {
            cachedMaterialsOut = null;
            hasAnimationsOut   = false;
            textureKeysOut     = null;

            // Ready check
            if (!IsReady)
            {
                return(null);
            }

            // Get combined model
            ModelCombiner.CombinedModel combinedModel;
            if (!combiner.GetCombinedModel(out combinedModel))
            {
                return(null);
            }

            // Load materials
            cachedMaterialsOut = new CachedMaterial[combinedModel.SubMeshes.Length];
            textureKeysOut     = new int[combinedModel.SubMeshes.Length];
            for (int i = 0; i < combinedModel.SubMeshes.Length; i++)
            {
                int archive = combinedModel.SubMeshes[i].TextureArchive;
                int record  = combinedModel.SubMeshes[i].TextureRecord;
                textureKeysOut[i] = MaterialReader.MakeTextureKey((short)archive, (byte)record, (byte)0);

                // Add material to array
                CachedMaterial cachedMaterial;
                dfUnity.MaterialReader.GetCachedMaterial(archive, record, 0, out cachedMaterial);
                cachedMaterialsOut[i] = cachedMaterial;

                // Set animation flag
                if (cachedMaterial.singleFrameCount > 1 && !hasAnimationsOut)
                {
                    hasAnimationsOut = true;
                }
            }

            // Create mesh
            Mesh mesh = new Mesh();

            mesh.name         = "CombinedMesh";
            mesh.vertices     = combinedModel.Vertices;
            mesh.normals      = combinedModel.Normals;
            mesh.uv           = combinedModel.UVs;
            mesh.subMeshCount = combinedModel.SubMeshes.Length;

            // Set submesh triangles
            for (int s = 0; s < mesh.subMeshCount; s++)
            {
                var   sub       = combinedModel.SubMeshes[s];
                int[] triangles = new int[sub.PrimitiveCount * 3];
                for (int t = 0; t < sub.PrimitiveCount * 3; t++)
                {
                    triangles[t] = combinedModel.Indices[sub.StartIndex + t];
                }
                mesh.SetTriangles(triangles, s);
            }

            // Finalise mesh
            if (solveTangents)
            {
                TangentSolver(mesh);
            }
            if (lightmapUVs)
            {
                AddLightmapUVs(mesh);
            }
            mesh.RecalculateBounds();

            return(mesh);
        }