public void MdContentToNone() { var md = "A quick brown **fox** jumped over the lazy dog."; var result = ContentProcessor.MarkdownToContent(md, ContentProcessor.MarkdownConvertType.None); Assert.IsTrue(result == "A quick brown **fox** jumped over the lazy dog."); }
public TemplateProcessor FillContent(Content content) { var processor = new ContentProcessor( new ProcessContext(_wordDocument)) .SetRemoveContentControls(_isNeedToRemoveContentControls); var processResult = processor.FillContent(Document.Root.Element(W.body), content); if (_wordDocument.HasFooters) { foreach (var footer in _wordDocument.FooterParts.Values) { var footerProcessResult = processor.FillContent(footer.Element(W.footer), content); processResult.Merge(footerProcessResult); } } if (_wordDocument.HasHeaders) { foreach (var header in _wordDocument.HeaderParts.Values) { var headerProcessResult = processor.FillContent(header.Element(W.header), content); processResult.Merge(headerProcessResult); } } if (_isNeedToNoticeAboutErrors) { AddErrors(processResult.Errors); } return(this); }
public void RemoveTags() { var html = @"<p>Microsoft</p><p>Rocks!</p><p>Azure <br /><img src=""a.jpg"" /> The best <span>cloud</span>!</p>"; var output = ContentProcessor.RemoveTags(html); Assert.IsTrue(output == "Microsoft Rocks! Azure The best cloud!"); }
public void MdContentToHtml() { var md = "A quick brown **fox** jumped over the lazy dog."; var result = ContentProcessor.MarkdownToContent(md, ContentProcessor.MarkdownConvertType.Html); Assert.IsTrue(result == "<p>A quick brown <strong>fox</strong> jumped over the lazy dog.</p>\n"); }
public void LazyLoadToImgTag_ExistLoading() { const string html = @"<p>Work 996 and have some fu bao!</p><img loading=""lazy"" src=""icu.jpg"" /><video src=""java996.mp4""></video>"; var result = ContentProcessor.AddLazyLoadToImgTag(html); Assert.IsTrue(result == @"<p>Work 996 and have some fu bao!</p><img loading=""lazy"" src=""icu.jpg"" /><video src=""java996.mp4""></video>"); }
public int LogInUser(MyUser myUser) { if (myUser == null) { return(0); } return(ContentProcessor.LogInUser(myUser)); }
public int SaveUser(MyUser myUser) { if (myUser == null) { return(0); } return(ContentProcessor.RegisterNewUser(myUser)); }
public void Clear() { foreach (var child in this) { child.Clear(); } Content = ContentProcessor.GetEmptyContent(); }
public void GetPostAbstract() { var html = @"<p>Microsoft</p> <p>Rocks!</p><p>Azure <br /><img src=""a.jpg"" /> The best <span>cloud</span>!</p>"; var result = ContentProcessor.GetPostAbstract(html, 16); var expected = "Microsoft Rocks!" + "\u00A0\u2026"; Assert.IsTrue(result == expected); }
public static IBuildAction CreateAction(ContentImporter importer, ContentProcessor processor) { return(new ContentCompilerBuildAction() { Importer = importer, Processor = processor }); }
public bool SendNewLetter(MyMessage myMessage) { if (myMessage == null) { return(false); } return(ContentProcessor.SendLetter(myMessage)); }
public void MdContentToException() { var md = "A quick brown **fox** jumped over the lazy dog."; Assert.Throws <ArgumentOutOfRangeException>(() => { var result = ContentProcessor.MarkdownToContent(md, (ContentProcessor.MarkdownConvertType) 4); }); }
public BlogReader(IFileSystem fileSystem, ContentParser parser, ContentConverter converter, ContentProcessor processor) { _fileSystem = fileSystem; _parser = parser; _converter = converter; _processor = processor; }
public string GetMyLetters(int userId) { if (userId == 0) { return(null); } string json = JsonConvert.SerializeObject(ContentProcessor.GetMyLetters(userId)); // List<MyMessage> myMessageJSON = JsonConvert.DeserializeObject<List<MyMessage>>(json); return(json); }
public TemplateProcessor FillContent(Content content) { var processResult = new ContentProcessor( new ProcessContext(Document, NumberingPart, StylesPart)) .SetRemoveContentControls(_isNeedToRemoveContentControls) .FillContent(Document.Root.Element(W.body), content); if (_isNeedToNoticeAboutErrors) { AddErrors(processResult.Errors); } return(this); }
/// <summary> /// Extract vertex maps for all MCS conten, or only selected folders if useSelection == true. /// </summary> public static void ExtractVertexMaps(bool useSelection) { List <GameObject> content = GetContent(useSelection); if (content.Count == 0) { return; } _activeProcess = new ContentProcessor("Extract", content, true); _activeProcess.Process = delegate() { GameObject obj = _activeProcess.GetObject(); if (obj == null) { return; } CoreMesh[] meshes = obj.GetComponentsInChildren <CoreMesh>(); foreach (CoreMesh mesh in meshes) { string collection = GetCollectionName(mesh.runtimeMorphPath); //_activeProcess.status = collection + ":" + mesh.name; SkinnedMeshRenderer smr = mesh.GetComponent <SkinnedMeshRenderer>(); if (smr != null) { string collectionConversionMapPath = _conversionMapPath + ((string.IsNullOrEmpty(collection) ? "" : "/" + collection)); Directory.CreateDirectory(collectionConversionMapPath); VertexMap vertexMap = new VertexMap(smr.sharedMesh.vertices); vertexMap.WriteToDisk(collectionConversionMapPath + "/" + mesh.name + ".json"); } } if (_activeProcess.isLast) { if (EditorUtility.DisplayDialog("Complete!", "Extracted vertex maps were saved in Assets/MCS/ConversionMaps.\nYou can copy the files to your new Unity project.", "Show in Explorer", "Close")) { EditorUtility.RevealInFinder(_conversionMapPath); } } }; }
public async Task <PostEntity> Handle(CreatePostCommand request, CancellationToken cancellationToken) { var abs = ContentProcessor.GetPostAbstract( string.IsNullOrEmpty(request.Payload.Abstract) ? request.Payload.EditorContent : request.Payload.Abstract.Trim(), _blogConfig.ContentSettings.PostAbstractWords, _settings.Editor == EditorChoice.Markdown); var post = new PostEntity { CommentEnabled = request.Payload.EnableComment, Id = Guid.NewGuid(), PostContent = request.Payload.EditorContent, ContentAbstract = abs, CreateTimeUtc = DateTime.UtcNow, LastModifiedUtc = DateTime.UtcNow, // Fix draft orders Slug = request.Payload.Slug.ToLower().Trim(), Author = request.Payload.Author?.Trim(), Title = request.Payload.Title.Trim(), ContentLanguageCode = request.Payload.LanguageCode, IsFeedIncluded = request.Payload.FeedIncluded, PubDateUtc = request.Payload.IsPublished ? DateTime.UtcNow : null, IsDeleted = false, IsPublished = request.Payload.IsPublished, IsFeatured = request.Payload.Featured, IsOriginal = request.Payload.IsOriginal, OriginLink = string.IsNullOrWhiteSpace(request.Payload.OriginLink) ? null : Helper.SterilizeLink(request.Payload.OriginLink), HeroImageUrl = string.IsNullOrWhiteSpace(request.Payload.HeroImageUrl) ? null : Helper.SterilizeLink(request.Payload.HeroImageUrl), InlineCss = request.Payload.InlineCss, PostExtension = new() { Hits = 0, Likes = 0 } }; // check if exist same slug under the same day var todayUtc = DateTime.UtcNow.Date; if (_postRepo.Any(new PostSpec(post.Slug, todayUtc))) { var uid = Guid.NewGuid(); post.Slug += $"-{uid.ToString().ToLower()[..8]}";
public async Task <IActionResult> NewComment(Guid postId, NewCommentModel model, [FromServices] ISessionBasedCaptcha captcha) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } if (!_blogConfig.ContentSettings.EnableComments) { return(Forbid()); } if (!captcha.ValidateCaptchaCode(model.CaptchaCode, HttpContext.Session)) { ModelState.AddModelError(nameof(model.CaptchaCode), "Wrong Captcha Code"); return(Conflict(ModelState)); } var response = await _commentService.CreateAsync(new CommentRequest(postId) { Username = model.Username, Content = model.Content, Email = model.Email, IpAddress = DNT ? "N/A" : HttpContext.Connection.RemoteIpAddress.ToString() }); if (_blogConfig.NotificationSettings.SendEmailOnNewComment && _notificationClient is not null) { _ = Task.Run(async() => { await _notificationClient.NotifyCommentAsync(response, s => ContentProcessor.MarkdownToContent(s, ContentProcessor.MarkdownConvertType.Html)); }); } if (_blogConfig.ContentSettings.RequireCommentReview) { return(Created("moonglade://empty", response)); } return(Ok()); }
public async Task NotifyCommentAsync( string username, string email, string ipAddress, string postTitle, string commentContent, DateTime createTimeUtc) { var payload = new CommentPayload( username, email, ipAddress, postTitle, ContentProcessor.MarkdownToContent(commentContent, ContentProcessor.MarkdownConvertType.Html), createTimeUtc ); try { await SendAsync(new NotificationRequest <CommentPayload>(MailMesageTypes.NewCommentNotification, payload)); } catch (Exception e) { _logger.LogError(e, e.Message); } }
public async Task <CommentReply> AddReply(Guid commentId, string replyContent) { var cmt = await _commentRepo.GetAsync(commentId); if (cmt is null) { throw new InvalidOperationException($"Comment {commentId} is not found."); } var id = Guid.NewGuid(); var model = new CommentReplyEntity { Id = id, ReplyContent = replyContent, CreateTimeUtc = DateTime.UtcNow, CommentId = commentId }; await _commentReplyRepo.AddAsync(model); var reply = new CommentReply { CommentContent = cmt.CommentContent, CommentId = commentId, Email = cmt.Email, Id = model.Id, PostId = cmt.PostId, PubDateUtc = cmt.Post.PubDateUtc.GetValueOrDefault(), ReplyContent = model.ReplyContent, ReplyContentHtml = ContentProcessor.MarkdownToContent(model.ReplyContent, ContentProcessor.MarkdownConvertType.Html), ReplyTimeUtc = model.CreateTimeUtc, Slug = cmt.Post.Slug, Title = cmt.Post.Title }; await _audit.AddAuditEntry(EventType.Content, AuditEventId.CommentReplied, $"Replied comment id '{commentId}'"); return(reply); }
public TopicReader( IFileSystem fileSystem, ContentParser contentParser, ContentConverter contentConverter, ContentProcessor contentProcessor) { if (fileSystem == null) { throw new ArgumentNullException(nameof(fileSystem)); } if (contentParser == null) { throw new ArgumentNullException(nameof(contentParser)); } if (contentConverter == null) { throw new ArgumentNullException(nameof(contentConverter)); } _fileSystem = fileSystem; _contentParser = contentParser; _contentConverter = contentConverter; _contentProcessor = contentProcessor; }
public async Task <CommentReply> Handle(ReplyCommentCommand request, CancellationToken cancellationToken) { var cmt = await _commentRepo.GetAsync(request.CommentId); if (cmt is null) { throw new InvalidOperationException($"Comment {request.CommentId} is not found."); } var id = Guid.NewGuid(); var model = new CommentReplyEntity { Id = id, ReplyContent = request.ReplyContent, CreateTimeUtc = DateTime.UtcNow, CommentId = request.CommentId }; await _commentReplyRepo.AddAsync(model); var reply = new CommentReply { CommentContent = cmt.CommentContent, CommentId = request.CommentId, Email = cmt.Email, Id = model.Id, PostId = cmt.PostId, PubDateUtc = cmt.Post.PubDateUtc.GetValueOrDefault(), ReplyContent = model.ReplyContent, ReplyContentHtml = ContentProcessor.MarkdownToContent(model.ReplyContent, ContentProcessor.MarkdownConvertType.Html), ReplyTimeUtc = model.CreateTimeUtc, Slug = cmt.Post.Slug, Title = cmt.Post.Title }; return(reply); }
public async Task Handle(CommentNotification notification, CancellationToken cancellationToken) { var payload = new CommentPayload( notification.Username, notification.Email, notification.IPAddress, notification.PostTitle, ContentProcessor.MarkdownToContent(notification.CommentContent, ContentProcessor.MarkdownConvertType.Html), notification.CreateTimeUtc ); var response = await _client.SendNotification(MailMesageTypes.NewCommentNotification, payload); var respBody = await response.Content.ReadAsStringAsync(cancellationToken); if (response.IsSuccessStatusCode) { _logger.LogInformation($"Email is sent, server response: '{respBody}'"); } else { throw new($"Email sending failed, response code: '{response.StatusCode}', response body: '{respBody}'"); } }
public virtual async Task <RssChannel> GetChannel(CancellationToken cancellationToken = default(CancellationToken)) { var project = await ProjectService.GetCurrentProjectSettings(); if (project == null) { return(null); } var itemsToGet = project.DefaultFeedItems; var requestedFeedItems = ContextAccessor.HttpContext?.Request.Query["maxItems"].ToString(); if (!string.IsNullOrWhiteSpace(requestedFeedItems)) { int.TryParse(requestedFeedItems, out itemsToGet); if (itemsToGet > project.MaxFeedItems) { itemsToGet = project.MaxFeedItems; } } var posts = await BlogService.GetRecentPosts(itemsToGet); if (posts == null) { return(null); } var channel = new RssChannel { Title = project.Title, Copyright = project.CopyrightNotice, Generator = Name, RemoteFeedUrl = project.RemoteFeedUrl, RemoteFeedProcessorUseAgentFragment = project.RemoteFeedProcessorUseAgentFragment }; if (!string.IsNullOrEmpty(project.Description)) { channel.Description = project.Description; } else { // prevent error, channel desc cannot be empty channel.Description = "Welcome to my blog"; } if (!string.IsNullOrEmpty(project.ChannelCategoriesCsv)) { var channelCats = project.ChannelCategoriesCsv.Split(','); foreach (var cat in channelCats) { channel.Categories.Add(new RssCategory(cat)); } } var urlHelper = UrlHelperFactory.GetUrlHelper(ActionContextAccesor.ActionContext); if (!string.IsNullOrEmpty(project.Image)) { channel.Image.Url = new Uri(urlHelper.Content(project.Image)); } if (!string.IsNullOrEmpty(project.LanguageCode)) { channel.Language = new CultureInfo(project.LanguageCode); } var baseUrl = string.Concat( ContextAccessor.HttpContext.Request.Scheme, "://", ContextAccessor.HttpContext.Request.Host.ToUriComponent() ); // asp.net bug? the comments for this method say it returns an absolute fully qualified url but it returns relative // looking at latest code seems ok so maybe just a bug in rc1 //https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/UrlHelperExtensions.cs //https://github.com/aspnet/Mvc/blob/dev/src/Microsoft.AspNetCore.Mvc.Core/Routing/UrlHelper.cs var indexUrl = urlHelper.RouteUrl(BlogRoutes.BlogIndexRouteName); if (indexUrl == null) { indexUrl = urlHelper.Action("Index", "Blog"); } if (indexUrl.StartsWith("/")) { indexUrl = string.Concat(baseUrl, indexUrl); } channel.Link = new Uri(indexUrl); if (!string.IsNullOrEmpty(project.ManagingEditorEmail)) { channel.ManagingEditor = project.ManagingEditorEmail; } if (!string.IsNullOrEmpty(project.ChannelRating)) { channel.Rating = project.ChannelRating; } var feedUrl = string.Concat( ContextAccessor.HttpContext.Request.Scheme, "://", ContextAccessor.HttpContext.Request.Host.ToUriComponent(), ContextAccessor.HttpContext.Request.PathBase.ToUriComponent(), ContextAccessor.HttpContext.Request.Path.ToUriComponent(), ContextAccessor.HttpContext.Request.QueryString.ToUriComponent()); channel.SelfLink = new Uri(feedUrl); channel.TimeToLive = project.ChannelTimeToLive; if (!string.IsNullOrEmpty(project.WebmasterEmail)) { channel.Webmaster = project.WebmasterEmail; } DateTime mostRecentPubDate = DateTime.MinValue; var items = new List <RssItem>(); foreach (var post in posts) { if (!post.PubDate.HasValue) { continue; } if (post.PubDate.Value > mostRecentPubDate) { mostRecentPubDate = post.PubDate.Value; } var rssItem = new RssItem { Author = post.Author }; if (post.Categories.Count > 0) { foreach (var c in post.Categories) { rssItem.Categories.Add(new RssCategory(c)); } } var postUrl = await BlogUrlResolver.ResolvePostUrl(post, project).ConfigureAwait(false); if (string.IsNullOrEmpty(postUrl)) { //TODO: log continue; } if (postUrl.StartsWith("/")) { //postUrl = urlHelper.Content(postUrl); postUrl = string.Concat( ContextAccessor.HttpContext.Request.Scheme, "://", ContextAccessor.HttpContext.Request.Host.ToUriComponent(), postUrl); } var filteredResult = ContentProcessor.FilterHtmlForRss(post, project, baseUrl); rssItem.Description = filteredResult.FilteredContent; if (!filteredResult.IsFullContent) { //TODO: localize var readMore = " <a href='" + postUrl + "'>...read more</a>"; rssItem.Description += readMore; } //rssItem.Enclosures rssItem.Guid = new RssGuid(postUrl, true); rssItem.Link = new Uri(postUrl); rssItem.PublicationDate = post.PubDate.Value; //rssItem.Source rssItem.Title = post.Title; items.Add(rssItem); } channel.PublicationDate = mostRecentPubDate; channel.Items = items; return(channel); }
protected AgdContentProcessor(ContentProcessor nextProcessor, string contentType, IApplication application) : base(nextProcessor) { _application = application; _contentType = contentType; }
protected ContentProcessor(ContentProcessor nextProcessor) { _nextProcessor = nextProcessor; }
public async Task <PostEntity> Handle(UpdatePostCommand request, CancellationToken cancellationToken) { var post = await _postRepo.GetAsync(request.Id); if (null == post) { throw new InvalidOperationException($"Post {request.Id} is not found."); } post.CommentEnabled = request.Payload.EnableComment; post.PostContent = request.Payload.EditorContent; post.ContentAbstract = ContentProcessor.GetPostAbstract( string.IsNullOrEmpty(request.Payload.Abstract) ? request.Payload.EditorContent : request.Payload.Abstract.Trim(), _blogConfig.ContentSettings.PostAbstractWords, _settings.Editor == EditorChoice.Markdown); // Address #221: Do not allow published posts back to draft status // postModel.IsPublished = request.Request.IsPublished; // Edit draft -> save and publish, ignore false case because #221 bool isNewPublish = false; if (request.Payload.IsPublished && !post.IsPublished) { post.IsPublished = true; post.PubDateUtc = DateTime.UtcNow; isNewPublish = true; } // #325: Allow changing publish date for published posts if (request.Payload.PublishDate is not null && post.PubDateUtc.HasValue) { var tod = post.PubDateUtc.Value.TimeOfDay; var adjustedDate = request.Payload.PublishDate.Value; post.PubDateUtc = adjustedDate.AddTicks(tod.Ticks); } post.Author = request.Payload.Author?.Trim(); post.Slug = request.Payload.Slug.ToLower().Trim(); post.Title = request.Payload.Title.Trim(); post.LastModifiedUtc = DateTime.UtcNow; post.IsFeedIncluded = request.Payload.FeedIncluded; post.ContentLanguageCode = request.Payload.LanguageCode; post.IsFeatured = request.Payload.Featured; post.IsOriginal = request.Payload.IsOriginal; post.OriginLink = string.IsNullOrWhiteSpace(request.Payload.OriginLink) ? null : Helper.SterilizeLink(request.Payload.OriginLink); post.HeroImageUrl = string.IsNullOrWhiteSpace(request.Payload.HeroImageUrl) ? null : Helper.SterilizeLink(request.Payload.HeroImageUrl); post.InlineCss = request.Payload.InlineCss; // compute hash var input = $"{post.Slug}#{post.PubDateUtc.GetValueOrDefault():yyyyMMdd}"; var checkSum = Helper.ComputeCheckSum(input); post.HashCheckSum = checkSum; // 1. Add new tags to tag lib var tags = string.IsNullOrWhiteSpace(request.Payload.Tags) ? Array.Empty <string>() : request.Payload.Tags.Split(',').ToArray(); foreach (var item in tags.Where(item => !_tagRepo.Any(p => p.DisplayName == item))) { await _tagRepo.AddAsync(new() { DisplayName = item, NormalizedName = Tag.NormalizeName(item, _tagNormalizationDictionary) }); } // 2. update tags post.Tags.Clear(); if (tags.Any()) { foreach (var tagName in tags) { if (!Tag.ValidateName(tagName)) { continue; } var tag = await _tagRepo.GetAsync(t => t.DisplayName == tagName); if (tag is not null) { post.Tags.Add(tag); } } } // 3. update categories var catIds = request.Payload.CategoryList.Where(p => p.IsChecked).Select(p => p.Id).ToArray(); post.PostCategory.Clear(); if (catIds is { Length : > 0 })
public void RemoveTags_Empty() { var output = ContentProcessor.RemoveTags(string.Empty); Assert.AreEqual(string.Empty, output); }
/// <summary> /// Removes morphs from selected assets. Useful in cases like hair moving unnaturally with eye blinks. /// </summary> public static void RemoveMorphsFromSelected(List <string> morphNamesToBeRemoved) { List <GameObject> content = GetContent(true); if (content.Count == 0 || morphNamesToBeRemoved == null || morphNamesToBeRemoved.Count == 0) { return; } if (!EditorUtility.DisplayDialog("Warning", "This process is nonreversible.\nAre you sure?", "Yes", "Cancel")) { return; } // Load common conversion tools and data _conversionData = new ConversionData(); _activeProcess = new ContentProcessor("Edit", content, true); _activeProcess.Process = delegate() { GameObject obj = _activeProcess.GetObject(); if (obj == null) { return; } CoreMesh[] meshes = obj.GetComponentsInChildren <CoreMesh>(); foreach (CoreMesh mesh in meshes) { //_activeProcess.status = mesh.name + " : Checking..."; // Check smr SkinnedMeshRenderer smr = mesh.GetComponent <SkinnedMeshRenderer>(); if (smr == null) { continue; } // Create temp directory for generated .morph files string morphPath = Path.Combine(Application.streamingAssetsPath, mesh.runtimeMorphPath); Directory.CreateDirectory(morphPath); try { // Get manifest var manifest = _conversionData.GetManifestForCoreMesh(mesh, _manifestSelectionMethod); // Process morphs List <string> morphNames = new List <string>(manifest.names); morphNames.Add("base"); // Add "base" morph that's not in the manifest but is required for clothing and hair foreach (string morph in morphNames) { MorphData data = _conversionData.GetMorphData(morphPath, morph); if (data != null) { if (morphNamesToBeRemoved.Contains(morph)) { _activeProcess.status = mesh.name + " : Removed Morph " + morph; } else { // Save .morph file for keeping MCS_Utilities.MorphExtraction.MorphExtraction.WriteMorphDataToFile(data, morphPath + "/" + data.name + ".morph", false, false); } } } // Repack morphs into .morph.mr file //_activeProcess.status = mesh.name + " : Rebuilding MR..."; RepackMorphs(morphPath); //_activeProcess.status = mesh.name + " : Success!"; } catch { _activeProcess.status = mesh.name + " : FAILED"; } finally { MCS_Utilities.Paths.TryDirectoryDelete(morphPath); } } }; }
public void LazyLoadToImgTag_Empty() { var result = ContentProcessor.AddLazyLoadToImgTag(string.Empty); Assert.IsTrue(result == string.Empty); }
private string FormatPostContent(string rawContent) { return(_settings.Editor == EditorChoice.Markdown ? ContentProcessor.MarkdownToContent(rawContent, ContentProcessor.MarkdownConvertType.Html, false) : rawContent); }
/// <summary> /// Remaps morph data for all MCS content, or only selected folders if useSelection == true. /// </summary> public static void ConvertMorphData(bool useSelection) { if (!useSelection) { if (!EditorUtility.DisplayDialog("Warning", "This will attempt to convert all MCS morph data in your project. This process is nonreversible.\nAre you sure?", "Yes", "Cancel")) { return; } } List <GameObject> content = GetContent(useSelection); if (content.Count == 0) { return; } // Load common conversion tools and data _conversionData = new ConversionData(); _activeProcess = new ContentProcessor("Convert", content, true); _activeProcess.Process = delegate() { GameObject obj = _activeProcess.GetObject(); if (obj == null) { return; } CoreMesh[] meshes = obj.GetComponentsInChildren <CoreMesh>(); foreach (CoreMesh mesh in meshes) { //_activeProcess.status = mesh.name + " : Checking..."; _conversionData.CreateReport(mesh.name); // Check if already converted if (_conversionData.GetMorphData(mesh.runtimeMorphPath, "_2019compatible") != null) { _conversionData.CloseReport("Skipped (already converted)"); continue; } // Check smr SkinnedMeshRenderer smr = mesh.GetComponent <SkinnedMeshRenderer>(); if (smr == null) { _conversionData.CloseReport("Skipped (no SkinnedMeshRenderer found)"); continue; } // Check for original vertex map string vmPath = ""; foreach (string path in _conversionData.vertexMaps) { if (path.Contains(mesh.name + ".json")) { vmPath = path; break; } } if (vmPath == "") { _conversionData.CloseReport("Skipped (no vertex map found)"); continue; } // Create temp directory for generated .morph files string morphPath = Path.Combine(Application.streamingAssetsPath, mesh.runtimeMorphPath); Directory.CreateDirectory(morphPath); // Run process try { // Read vertex map string mapData = File.ReadAllText(vmPath); VertexMap vertexMap = JsonUtility.FromJson <VertexMap>(mapData); // Generate retarget map //_activeProcess.status = mesh.name + " : Generating Target Map..."; Dictionary <int, int> ttsMap = _conversionData.projectionMeshMap.GenerateTargetToSourceMap(vertexMap.vertices, smr.sharedMesh.vertices); // Get manifest var manifest = _conversionData.GetManifestForCoreMesh(mesh, _manifestSelectionMethod); // Process morphs int n = 0; int total = manifest.names.Length; List <string> morphNames = new List <string>(manifest.names); morphNames.Add("base"); // Add "base" morph that's not in the manifest but is required for clothing and hair foreach (string morph in morphNames) { //_activeProcess.status = string.Format("{0} : Processing Morph {1}/{2}", mesh.name, n, total); n++; MorphData source = _conversionData.GetMorphData(morphPath, morph); // Not all assets will have all morphs if (source != null) { // Retarget morphs MorphData target = RemapMorphData(smr, source, ttsMap); // Save new .morph file MCS_Utilities.MorphExtraction.MorphExtraction.WriteMorphDataToFile(target, morphPath + "/" + target.name + ".morph", false, false); } } // Inject evidence of conversion so we don't accidentally remap again. MorphData note = new MorphData(); note.name = "_2019compatible"; MCS_Utilities.MorphExtraction.MorphExtraction.WriteMorphDataToFile(note, morphPath + "/" + note.name + ".morph", false, false); // Repack morphs into .morph.mr file _activeProcess.status = mesh.name + " : Repacking Morphs..."; RepackMorphs(morphPath); _conversionData.CloseReport("Success"); } catch { _conversionData.CloseReport("Failed"); } finally { MCS_Utilities.Paths.TryDirectoryDelete(morphPath); } } if (_activeProcess.isLast) { _conversionData.PrintSummary(); } }; }