355 lines
15 KiB
C#
355 lines
15 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using JD.Core;
|
|
using JD.Serialization;
|
|
using TeaBox.Macros;
|
|
using FrameConverter = JD.Serialization.FrameConverter;
|
|
|
|
namespace JDSongConverter.Tasks
|
|
{
|
|
internal enum LayerTypes
|
|
{
|
|
Events_0 = 12,
|
|
Moves = 13,
|
|
KinectMoves = 14,
|
|
Lyrics = 15,
|
|
Pictos = 16,
|
|
KaraokeScoring = 17,
|
|
};
|
|
|
|
public class ConvertDtapeToTimelineTask : Task
|
|
{
|
|
public string TimelineFile { get; set; }
|
|
public string DanceTapeFile { get; set; }
|
|
public string OutputDirectoryPath { get; set; }
|
|
|
|
public void Init(string timelineFile, string danceTapeFile)
|
|
{
|
|
TimelineFile = timelineFile;
|
|
DanceTapeFile = danceTapeFile;
|
|
}
|
|
|
|
public override string Name
|
|
{
|
|
get { return "Convert dance tape to timeline"; }
|
|
set { }
|
|
}
|
|
|
|
public override string ProgressText
|
|
{
|
|
get { return "Converting dance tape to timeline"; }
|
|
}
|
|
|
|
public override TaskResult Process(IExecutionContext executionContext)
|
|
{
|
|
OutputDirectoryPath = Context.OutputMap.Folder;
|
|
|
|
var tape = Tape.CreateTape(DanceTapeFile);
|
|
CreateReadableTimelineTemplateFile();
|
|
Convert(tape, TimelineFile);
|
|
return TaskResult.Ok;
|
|
}
|
|
|
|
private void CreateReadableTimelineTemplateFile()
|
|
{
|
|
var outputTimelineDirectory = System.IO.Path.Combine(OutputDirectoryPath, "Timeline");
|
|
|
|
if (!System.IO.Directory.Exists(outputTimelineDirectory))
|
|
{
|
|
System.IO.Directory.CreateDirectory(outputTimelineDirectory);
|
|
}
|
|
|
|
var timelineTemplateDirectory = GetTimelineTemplateDirectory(OutputDirectoryPath);
|
|
var timelineTemplateFilePath = System.IO.Path.Combine(timelineTemplateDirectory, "timeline.tpl");
|
|
|
|
System.IO.File.Copy(timelineTemplateFilePath, TimelineFile, true);
|
|
System.IO.FileInfo fileInfo = new System.IO.FileInfo(timelineTemplateFilePath);
|
|
fileInfo.IsReadOnly = false;
|
|
}
|
|
|
|
private string GetTimelineTemplateDirectory(string outputDir)
|
|
{
|
|
string temp = outputDir;
|
|
return Regex.Replace(temp, @"data.*", @"data\EngineData\Level_Structure\MapTemplateALT\Timeline");
|
|
}
|
|
|
|
private void Convert(Tape tape, string timeLinefileName)
|
|
{
|
|
var serializer = new LuaSerializer();
|
|
UAFDictionary<string, int> layerNameId = new UAFDictionary<string, int>();
|
|
|
|
JD_Timeline_Template timeline;
|
|
var actorTemplate = ReadTimelineTemplateFile(timeLinefileName, serializer, out timeline);
|
|
|
|
ClearExistingTimelineData(timeline);
|
|
CreateTimelineLayers(tape, timeline, layerNameId);
|
|
|
|
foreach (var clip in tape.Clips)
|
|
{
|
|
ConvertClipToTimeline(clip, layerNameId, timeline);
|
|
}
|
|
|
|
actorTemplate.Save(timeLinefileName);
|
|
}
|
|
|
|
private void ClearExistingTimelineData(JD_Timeline_Template timeline)
|
|
{
|
|
timeline.Song = Context.Song.Name;
|
|
timeline.Layers = new UAFList<TimelineLayer>();
|
|
timeline.Pictos = new UAFList<PictoClip>();
|
|
timeline.Moves = new UAFList<MoveClip>();
|
|
timeline.MovesKinect = new UAFList<MoveClip>();
|
|
timeline.MoveModels = new UAFList<TimelineModelMove>();
|
|
timeline.Block = new UAFList<TimelineBlock>();
|
|
timeline.BlockModel = new UAFList<TimelineModelBlock>();
|
|
timeline.PictoModel = new UAFList<TimelineModelPicto>();
|
|
timeline.KinectModelMoves = new UAFList<TimelineKinectModelMove>();
|
|
timeline.SongGeneralData = new TimelineGeneralData();
|
|
}
|
|
|
|
private static Actor_Template ReadTimelineTemplateFile(string timeLinefileName, LuaSerializer serializer, out JD_Timeline_Template timeline)
|
|
{
|
|
var actorTemplate = (Actor_Template)serializer.LoadObjectFromFile(timeLinefileName);
|
|
if (actorTemplate == null)
|
|
{
|
|
throw new Exception(string.Format("No timeline file {0} not found at the target directory", timeLinefileName));
|
|
}
|
|
|
|
timeline = actorTemplate.COMPONENTS.OfType<JD_Timeline_Template>().FirstOrDefault();
|
|
if (timeline == null)
|
|
{
|
|
throw new Exception(string.Format("The timeline file {0} format is wrong", timeLinefileName));
|
|
}
|
|
return actorTemplate;
|
|
}
|
|
|
|
private void ConvertClipToTimeline(Clip clip, UAFDictionary<string, int> layerNameId, JD_Timeline_Template timeline)
|
|
{
|
|
// Create Pictos and PictoModels in the timeline file
|
|
if (clip.Type == typeof(PictogramClip))
|
|
{
|
|
WritePictoClip(clip, layerNameId, timeline);
|
|
}
|
|
|
|
// Create moves and moveModels
|
|
else if (clip.Type == typeof(MotionClip))
|
|
{
|
|
string moveName;
|
|
var motionClip = ExtractClipName(clip, out moveName);
|
|
|
|
if (motionClip.MoveType == MotionClip.MoveType_Enum.MoveType_HandOnly)
|
|
{
|
|
WriteControllerMoveClip(layerNameId, timeline, moveName, motionClip);
|
|
}
|
|
|
|
else // Create movesKinect and kinectMoveModels
|
|
{
|
|
WriteKinectMotionClip(layerNameId, timeline, moveName, motionClip);
|
|
}
|
|
}
|
|
|
|
else if (clip.Type == typeof(GoldEffectClip))
|
|
{
|
|
WriteBlockModelWithGoldMoveClip(clip, timeline);
|
|
WriteBlockWithGoldMove(clip, timeline);
|
|
}
|
|
}
|
|
|
|
private void WriteBlockWithGoldMove(Clip clip, JD_Timeline_Template timeline)
|
|
{
|
|
GoldEffectClip goldClip = clip as GoldEffectClip;
|
|
TimelineBlock timelineBlock = new TimelineBlock();
|
|
|
|
timelineBlock.StartPosition = goldClip.StartBeat;
|
|
timelineBlock.StopPosition = goldClip.StopBeat;
|
|
timelineBlock.LayerID = timeline.Layers.FirstOrDefault(x => x.LayerName == "Events_0").LayerID;
|
|
timelineBlock.ModelName = "goldmove";
|
|
|
|
timelineBlock.Parameters = new UAFList<BlockParameter>();
|
|
BlockParameterString blockParameterString = new BlockParameterString();
|
|
blockParameterString.Value = "GoldMove";
|
|
timelineBlock.Parameters.Add(blockParameterString);
|
|
|
|
timeline.Block.Add(timelineBlock);
|
|
}
|
|
|
|
private MotionClip ExtractClipName(Clip clip, out string name)
|
|
{
|
|
MotionClip motionClip = clip as MotionClip;
|
|
name = motionClip.ClassifierPath.getRelativePath();
|
|
Regex rgx = new Regex(@"\w*\.");
|
|
Match m = rgx.Match(name.ToLower());
|
|
name = m.Value.Substring(Context.Song.Name.Length + 1, m.Value.Length - (Context.Song.Name.Length + 1) - 1);
|
|
return motionClip;
|
|
}
|
|
|
|
private static void WriteBlockModelWithGoldMoveClip(Clip clip, JD_Timeline_Template timeline)
|
|
{
|
|
GoldEffectClip goldClip = clip as GoldEffectClip;
|
|
TimelineModelBlock blockModel = new TimelineModelBlock();
|
|
|
|
if (goldClip.EffectType == GoldEffectClip.EffectType_Enum.GoldEffect_Auto)
|
|
{
|
|
blockModel.Name = "goldmove";
|
|
}
|
|
else if (goldClip.EffectType == GoldEffectClip.EffectType_Enum.GoldEffect_Cascade)
|
|
{
|
|
blockModel.Name = "goldmovecascade";
|
|
}
|
|
else if (goldClip.EffectType == GoldEffectClip.EffectType_Enum.GoldEffect_Classic)
|
|
{
|
|
blockModel.Name = "goldmoveclassic";
|
|
}
|
|
timeline.BlockModel.Add(blockModel);
|
|
}
|
|
|
|
private static void WriteKinectMotionClip(UAFDictionary<string, int> layerNameId, JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
WriteTilmelineKinectMove(layerNameId, timeline, moveName, motionClip);
|
|
|
|
WriteTimelineKinectModelMove(timeline, moveName, motionClip);
|
|
}
|
|
|
|
private static void WriteTimelineKinectModelMove(JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
TimelineKinectModelMove kinectMoveModel = new TimelineKinectModelMove();
|
|
kinectMoveModel.Name = moveName;
|
|
kinectMoveModel.Color =
|
|
(uint) Color.FromArgb(0, motionClip.Color.R, motionClip.Color.G, motionClip.Color.B).ToArgb();
|
|
kinectMoveModel.ScoreSmoothing = motionClip.MotionPlatformSpecifics[Platform.X360].ScoreSmoothing;
|
|
kinectMoveModel.ScoreScale = motionClip.MotionPlatformSpecifics[Platform.X360].ScoreScale;
|
|
//TODO
|
|
//kinectMoveModel.ScoringMode = motionClip.MotionPlatformSpecifics[Platform.X360].ScoringMode;
|
|
|
|
//kinectMoveModel.ScoreSmoothingDurango = motionClip.MotionPlatformSpecifics[Platform.DURANGO].ScoreSmoothing;
|
|
//kinectMoveModel.ScoreScaleDurango = motionClip.MotionPlatformSpecifics[Platform.DURANGO].ScoreScale;
|
|
//kinectMoveModel.ScoringModeDurango = motionClip.MotionPlatformSpecifics[Platform.DURANGO].ScoringMode;
|
|
|
|
// Add code for writing the Length in Subdivisions and subdivision in beats
|
|
if (timeline.KinectModelMoves.FirstOrDefault(item => item.Name == moveName) == null)
|
|
{
|
|
timeline.KinectModelMoves.Add(kinectMoveModel);
|
|
}
|
|
}
|
|
|
|
private static void WriteTilmelineKinectMove(UAFDictionary<string, int> layerNameId, JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
MoveClip kinectMove = new MoveClip();
|
|
kinectMove.MoveName = moveName;
|
|
kinectMove.LayerID = layerNameId["KinectMoves" + (int) (motionClip.CoachId + 1)];
|
|
kinectMove.StartPosition = FrameConverter.TimeFromFrame(motionClip.StartFrame);
|
|
kinectMove.StopPosition = FrameConverter.TimeFromFrame(motionClip.StopFrame);
|
|
kinectMove.ClassifierPath = motionClip.ClassifierPath;
|
|
kinectMove.GoldMove = motionClip.GoldMove;
|
|
timeline.MovesKinect.Add(kinectMove);
|
|
}
|
|
|
|
private static void WriteControllerMoveClip(UAFDictionary<string, int> layerNameId, JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
WriteTimelineMove(layerNameId, timeline, moveName, motionClip);
|
|
|
|
WriteTimelineMoveModel(timeline, moveName, motionClip);
|
|
}
|
|
|
|
private static void WriteTimelineMoveModel(JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
TimelineModelMove moveModel = new TimelineModelMove();
|
|
moveModel.Name = moveName;
|
|
|
|
// Add code for writing the Length in Subdivisions and subdivision in beats
|
|
|
|
moveModel.Color = (uint) Color.FromArgb(0, motionClip.Color.R, motionClip.Color.G, motionClip.Color.B).ToArgb();
|
|
moveModel.GoldenMove = motionClip.GoldMove;
|
|
|
|
moveModel.SubdivisionsInBeat = 2;
|
|
var startPosition = FrameConverter.TimeFromFrame(motionClip.StartFrame);
|
|
var stopPosition = FrameConverter.TimeFromFrame(motionClip.StopFrame);
|
|
moveModel.LengthInSubdivisions = (uint)((stopPosition - startPosition) * (float)moveModel.SubdivisionsInBeat);
|
|
|
|
if (!timeline.MoveModels.Any(item => (item.Name == moveName && item.LengthInSubdivisions == moveModel.LengthInSubdivisions)))
|
|
{
|
|
timeline.MoveModels.Add(moveModel);
|
|
}
|
|
}
|
|
|
|
private static void WriteTimelineMove(UAFDictionary<string, int> layerNameId, JD_Timeline_Template timeline, string moveName, MotionClip motionClip)
|
|
{
|
|
MoveClip move = new MoveClip();
|
|
move.MoveName = moveName;
|
|
move.LayerID = layerNameId["Moves" + (int) (motionClip.CoachId + 1)];
|
|
move.StartPosition = FrameConverter.TimeFromFrame(motionClip.StartFrame);
|
|
move.StopPosition = FrameConverter.TimeFromFrame(motionClip.StopFrame);
|
|
move.ClassifierPath = motionClip.ClassifierPath;
|
|
move.GoldMove = motionClip.GoldMove;
|
|
timeline.Moves.Add(move);
|
|
}
|
|
|
|
private static void WritePictoClip(Clip clip, UAFDictionary<string, int> LayerNameId, JD_Timeline_Template timeline)
|
|
{
|
|
PictogramClip pictoClip = clip as PictogramClip;
|
|
PictoClip picto = new PictoClip();
|
|
TimelineModelPicto pictoModel = new TimelineModelPicto();
|
|
string name = pictoClip.PictoPath.getRelativePath();
|
|
Regex rgx = new Regex(@"\w*\.");
|
|
Match m = rgx.Match(name.ToLower());
|
|
name = m.Value.Substring(0, m.Value.Length - 1);
|
|
|
|
picto.Position = FrameConverter.TimeFromFrame(pictoClip.StartFrame);
|
|
picto.Pictoname = name;
|
|
picto.LayerID = LayerNameId["Pictos"];
|
|
picto.TexturePath = pictoClip.PictoPath;
|
|
|
|
pictoModel.Pictoname = name;
|
|
|
|
timeline.PictoModel.Add(pictoModel);
|
|
timeline.Pictos.Add(picto);
|
|
}
|
|
|
|
private static void CreateTimelineLayers(Tape tape, JD_Timeline_Template timeline, UAFDictionary<string, int> layerNameId)
|
|
{
|
|
int layerCount = 0;
|
|
|
|
foreach (var track in tape.Tracks)
|
|
{
|
|
if (track.Name != "GoldMoveEffects")
|
|
{
|
|
TimelineLayer layer = new TimelineLayer();
|
|
layer.LayerID = layerCount++;
|
|
layer.LayerPosition = layer.LayerID;
|
|
|
|
if (track.Name.Contains("CameraMoves"))
|
|
{
|
|
layer.LayerName = "KinectMoves" + track.Name.ElementAt(track.Name.Length - 1);
|
|
layer.LayerType = (uint)LayerTypes.KinectMoves;
|
|
}
|
|
else if (track.Name == "Pictos")
|
|
{
|
|
layer.LayerType = (uint)LayerTypes.Pictos;
|
|
layer.LayerName = track.Name;
|
|
}
|
|
else if (track.Name.Contains("Moves"))
|
|
{
|
|
layer.LayerType = (uint)LayerTypes.Moves;
|
|
layer.LayerName = track.Name;
|
|
}
|
|
timeline.Layers.Add(layer);
|
|
layerNameId.Add(layer.LayerName, layer.LayerID);
|
|
}
|
|
}
|
|
AddTimelineEventsLayer(layerCount, timeline);
|
|
}
|
|
|
|
private static void AddTimelineEventsLayer(int layerCount, JD_Timeline_Template timeline)
|
|
{
|
|
//Add the Events_0 Layer
|
|
TimelineLayer eLayer = new TimelineLayer();
|
|
eLayer.LayerID = ++layerCount;
|
|
eLayer.LayerPosition = eLayer.LayerID;
|
|
eLayer.LayerName = "Events_0";
|
|
eLayer.LayerType = (uint)LayerTypes.Events_0;
|
|
timeline.Layers.Add(eLayer);
|
|
}
|
|
}
|
|
}
|