protected bool IsGRDRBAnim(PropAnim anim) { var gdrbNames = new[] { "_mikedirnt", "_trecool", "_billiejoe" }; // Check if any events are for GDRB specific band members return(anim.DirectorGroups .Select(x => x.PropName) .Any(x => gdrbNames .Any(y => x.EndsWith(y, StringComparison.CurrentCultureIgnoreCase)))); }
protected LyricConfig[] ConvertFromPropAnim(PropAnim lyricConfigProp) { var groupedConfigs = lyricConfigProp .DirectorGroups .SelectMany(x => x.Events .Select(y => (y, x.DirectorName, x.PropName)) .ToList()) .GroupBy(x => (int)x.y.Position) .OrderBy(x => x.Key) // Order by "dc_lyrics_x" .ToList(); var lyricConfigs = new List <LyricConfig>(); foreach (var propConfig in groupedConfigs) { var configName = $"dc_lyrics_{propConfig.Key}"; var lyrics = propConfig .OrderBy(x => x.DirectorName) // Order by "venue_lyric_xx" .GroupBy(x => x.DirectorName) .ToList(); var lyricEvents = new List <LyricEvent>(); foreach (var lyric in lyrics) { // Assume always pos, rot, scale var parts = lyric .OrderBy(x => x.PropName) .Select(x => x.y) .ToList(); var pos = (DirectedEventVector3)parts[0]; var rot = (DirectedEventVector4)parts[1]; var scale = (DirectedEventVector3)parts[2]; lyricEvents.Add(new LyricEvent() { Position = new float[] { pos.Value.X, pos.Value.Y, pos.Value.Z }, Rotation = new float[] { rot.Value.X, rot.Value.Y, rot.Value.Z, rot.Value.W }, Scale = new float[] { scale.Value.X, scale.Value.Y, scale.Value.Z } }); } lyricConfigs.Add(new LyricConfig() { Name = configName, Lyrics = lyricEvents .ToArray() }); } return(lyricConfigs .ToArray()); }
public Anim2Midi(PropAnim anim, string midPath) { Anim = anim; MidiHelper = new MidiHelper(midPath); }
public PropAnim ExportToAnim() { var midTracks = MidiHelper.CreateMidiTracksDictionaryFromBase(); var directedGroups = new Dictionary <string, DirectedEventGroup>(); var trackNames = new[] { "VENUE" } .Concat(TBRBCharacters.Select(x => x.ToUpper())); // Parse venue track foreach (var trackName in trackNames) { // Check if track exists if (!midTracks.TryGetValue(trackName, out var track)) { continue; } // Get midi text events var venueEvents = track .Where(x => (x is TextEvent te) && te.MetaEventType == MetaEventType.TextEvent) .OrderBy(x => x.AbsoluteTime) // Should already be sort (but just in case) .Select(x => (MidiHelper.TickPosToFrames(x.AbsoluteTime), (x as TextEvent).Text)) .ToList(); var isCharTrack = trackName != "VENUE"; var appendName = isCharTrack ? $"_{trackName.ToLower()}" : ""; // Parse text events foreach (var(pos, text) in venueEvents) { // If not formatted as anim event, skip if (!IsPropEvent(text)) { continue; } // Parse event name and values from text var(propEvName, propEvValues) = ParseEventValues(text, isCharTrack, appendName); // Get director group if (!directedGroups.TryGetValue(propEvName, out var dirGroup)) { // Not found, create dir group dirGroup = CreateDirectorGroup(propEvName); directedGroups.Add(propEvName, dirGroup); } // Convert string array of values to anim event var ev = GetDirectedEvent((float)pos, propEvValues, dirGroup.EventType); dirGroup.Events.Add(ev); } } var eventGroups = directedGroups .Select(x => x.Value) .ToList(); var totalTime = eventGroups .SelectMany(x => x.Events) .Select(x => x.Position) .Max(); var anim = new PropAnim() { Name = "song.anim", AnimName = "song_anim", TotalTime = totalTime }; anim.DirectorGroups.AddRange(eventGroups); return(anim); }