using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; using System.Web.Http.Results; using System.IO; using MongoDB.Bson; using MongoDB.Driver; using Newtonsoft.Json.Linq; using ShadowEditor.Server.Base; using ShadowEditor.Server.Helpers; using System.Text; namespace ShadowEditor.Server.Controllers.Export { /// /// 导出场景控制器 /// public class ExportSceneController : ApiBase { /// /// 执行 /// /// /// /// [HttpPost] public JsonResult Run(string ID, int version = -1) { var mongo = new MongoHelper(); var filter = Builders.Filter.Eq("ID", BsonObjectId.Create(ID)); var doc = mongo.FindOne(Constant.SceneCollectionName, filter); if (doc == null) { return Json(new { Code = 300, Msg = "The scene is not existed!" }); } // 获取场景数据 var collectionName = doc["CollectionName"].AsString; List docs; if (version == -1) // 最新版本 { docs = mongo.FindAll(collectionName).ToList(); } else // 特定版本 { filter = Builders.Filter.Eq(Constant.VersionField, BsonInt32.Create(version)); docs = mongo.FindMany($"{collectionName}{Constant.HistorySuffix}", filter).ToList(); } // 创建临时目录 var now = DateTime.Now; var path = HttpContext.Current.Server.MapPath($"~/temp/{now.ToString("yyyyMMddHHmmss")}"); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } // 拷贝静态资源 var viewPath = HttpContext.Current.Server.MapPath("~/view.html"); var viewFileData = File.ReadAllText(viewPath, Encoding.UTF8); viewFileData = viewFileData.Replace("location.origin", "'.'"); // 替换server地址,以便部署到Git Pages上 File.WriteAllText($"{path}/view.html", viewFileData, Encoding.UTF8); var faviconPath = HttpContext.Current.Server.MapPath("~/favicon.ico"); File.Copy(faviconPath, $"{path}/favicon.ico", true); var assetsPath = HttpContext.Current.Server.MapPath($"~/assets"); DirectoryHelper.Copy(assetsPath, $"{path}/assets"); var buildPath = HttpContext.Current.Server.MapPath($"~/build"); DirectoryHelper.Copy(buildPath, $"{path}/build"); // 分析场景,拷贝使用的资源 var data = new JArray(); var urls = new List(); foreach (var i in docs) { i["_id"] = i["_id"].ToString(); // ObjectId var generator = i["metadata"]["generator"].ToString(); if (generator == "ServerObject") // 服务端模型 { urls.Add(i["userData"]["Url"].ToString()); // 模型文件 if (i["userData"].AsBsonDocument.Contains("Animation")) // MMD模型动画 { urls.Add(i["userData"]["Animation"]["Url"].ToString()); } if (i["userData"].AsBsonDocument.Contains("CameraAnimation")) // MMD相机动画 { urls.Add(i["userData"]["CameraAnimation"]["Url"].ToString()); } if (i["userData"].AsBsonDocument.Contains("Audio")) // MMD音频 { urls.Add(i["userData"]["Audio"]["Url"].ToString()); } } else if (generator == "SceneSerializer") // 场景 { if (i["background"].IsBsonDocument) // 贴图或立方体纹理 { if (i["background"]["metadata"]["generator"].ToString() == "CubeTextureSerializer") // 立方体纹理 { var array = i["background"]["image"].AsBsonArray; foreach (var j in array) { urls.Add(j["src"].ToString()); } } else // 普通纹理 { urls.Add(i["background"]["image"]["src"].ToString()); } } } else if (generator == "MeshSerializer" || generator == "SpriteSerializer") // 模型 { if (i["material"]["alphaMap"].IsBsonDocument) { urls.Add(i["material"]["alphaMap"]["image"]["src"].ToString()); } else if (i["material"]["aoMap"].IsBsonDocument) { urls.Add(i["material"]["aoMap"]["image"]["src"].ToString()); } else if (i["material"]["bumpMap"].IsBsonDocument) { urls.Add(i["material"]["bumpMap"]["image"]["src"].ToString()); } else if (i["material"]["displacementMap"].IsBsonDocument) { urls.Add(i["material"]["displacementMap"]["image"]["src"].ToString()); } else if (i["material"]["emissiveMap"].IsBsonDocument) { urls.Add(i["material"]["emissiveMap"]["image"]["src"].ToString()); } else if (i["material"]["envMap"].IsBsonDocument) { urls.Add(i["material"]["envMap"]["image"]["src"].ToString()); } else if (i["material"]["lightMap"].IsBsonDocument) { urls.Add(i["material"]["lightMap"]["image"]["src"].ToString()); } else if (i["material"]["map"].IsBsonDocument) { urls.Add(i["material"]["map"]["image"]["src"].ToString()); } else if (i["material"]["metalnessMap"].IsBsonDocument) { urls.Add(i["material"]["metalnessMap"]["image"]["src"].ToString()); } else if (i["material"]["normalMap"].IsBsonDocument) { urls.Add(i["material"]["normalMap"]["image"]["src"].ToString()); } else if (i["material"]["roughnessMap"].IsBsonDocument) { urls.Add(i["material"]["roughnessMap"]["image"]["src"].ToString()); } } data.Add(JsonHelper.ToObject(i.ToJson())); } // 将场景写入文件 if (!Directory.Exists($"{path}/Scene")) { Directory.CreateDirectory($"{path}/Scene"); } // 复制资源 var file = new FileStream($"{path}/Scene/{ID}.txt", FileMode.Create, FileAccess.Write); var writer = new StreamWriter(file); writer.Write(JsonHelper.ToJson(data)); writer.Close(); file.Close(); foreach (var url in urls) { if (!url.StartsWith("/")) // 可能是base64地址 { continue; } // LOL模型存在多个url,两个url之间用分号分隔 var _urls = url.Split(';'); foreach (var _url in _urls) { if (string.IsNullOrEmpty(_url)) { continue; } var sourceDirName = Path.GetDirectoryName(HttpContext.Current.Server.MapPath($"~{_url}")); var targetDirName = Path.GetDirectoryName($"{path}{_url}"); DirectoryHelper.Copy(sourceDirName, targetDirName); } } return Json(new { Code = 200, Msg = "Export successfully!", Url = $"/temp/{now.ToString("yyyyMMddHHmmss")}/view.html?sceneFile={ID}" }); } } }