Skip to content

Commit ac02a08

Browse files
authored
Merge pull request #19 from nasshu2916/feature/dmx-recorder-suport-animation-clip
AnimationClip を EditorWindow から保存できるようにする
2 parents 3361fc5 + 918e1d1 commit ac02a08

File tree

8 files changed

+229
-88
lines changed

8 files changed

+229
-88
lines changed

Assets/ArtNet/Editor/DmxRecorder/DmxRecordWindow.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using UnityEditor;
23
using UnityEngine;
34
using UnityEngine.UIElements;
@@ -54,14 +55,20 @@ private void Initialize(VisualElement root)
5455
senderVisualElement.name = "senderPanel";
5556
tabContent.Add(senderVisualElement);
5657

57-
var config = new RecordConfig
58+
var recordFormatStringType = EditorUserSettings.GetConfigValue(EditorSettingKey("OutputFormat")) ??
59+
RecodeFormat.Binary.ToString();
60+
var format = (RecodeFormat) Enum.Parse(typeof(RecodeFormat), recordFormatStringType);
61+
var binaryRecordConfig = new BinaryRecordConfig
5862
{
5963
Directory = EditorUserSettings.GetConfigValue(EditorSettingKey("OutputDirectory")) ??
6064
Application.dataPath,
6165
FileName = EditorUserSettings.GetConfigValue(EditorSettingKey("OutputFileName")) ??
62-
"dmx-record"
66+
"dmx-record",
6367
};
64-
_recorder.Config = config;
68+
69+
var animationClipRecordConfig = new AnimationClipRecordConfig();
70+
71+
_recorder.RecordConfigs = new RecordConfigs(format, binaryRecordConfig, animationClipRecordConfig);
6572

6673
InitializeHeaderTab(root);
6774
InitializeRecorder(recorderVisualElement);

Assets/ArtNet/Editor/DmxRecorder/RecordConfig.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
3+
namespace ArtNet.Editor.DmxRecorder
4+
{
5+
public enum RecodeFormat
6+
{
7+
Binary = 0,
8+
AnimationClip = 1,
9+
}
10+
11+
public class RecordConfigs
12+
{
13+
public RecodeFormat RecordFormat { get; set; }
14+
15+
public BinaryRecordConfig BinaryConfig { get; }
16+
public AnimationClipRecordConfig AnimationClipConfig { get; }
17+
18+
public RecordConfigs(RecodeFormat format, BinaryRecordConfig binaryConfig, AnimationClipRecordConfig
19+
animationClipConfig)
20+
{
21+
RecordFormat = format;
22+
BinaryConfig = binaryConfig;
23+
AnimationClipConfig = animationClipConfig;
24+
}
25+
26+
private IRecordConfig Config => RecordFormat switch
27+
{
28+
RecodeFormat.Binary => BinaryConfig,
29+
RecodeFormat.AnimationClip => AnimationClipConfig,
30+
_ => throw new System.NotImplementedException()
31+
};
32+
33+
public bool Validate() => ValidateErrors().Count == 0;
34+
public List<string> ValidateErrors() => Config.ValidateErrors();
35+
}
36+
37+
public class BinaryRecordConfig : IRecordConfig
38+
{
39+
private const string Extension = ".dmx";
40+
41+
public string Directory { get; set; }
42+
public string FileName { get; set; }
43+
44+
public string OutputPath => $"{Directory}/{FileName}{Extension}";
45+
46+
public List<string> ValidateErrors()
47+
{
48+
var errors = new List<string>();
49+
if (!ValidateDirectory()) errors.Add("Directory is not set");
50+
if (!ValidateFileName()) errors.Add("FileName is not set");
51+
52+
return errors;
53+
}
54+
55+
private bool ValidateDirectory() => !string.IsNullOrEmpty(Directory);
56+
private bool ValidateFileName() => !string.IsNullOrEmpty(FileName);
57+
}
58+
59+
public class AnimationClipRecordConfig : IRecordConfig
60+
{
61+
public string OutputAnimationClipAssetPath { get; set; } = "Assets/Recording";
62+
63+
public List<string> ValidateErrors()
64+
{
65+
return new List<string>();
66+
}
67+
}
68+
69+
public interface IRecordConfig
70+
{
71+
public List<string> ValidateErrors();
72+
}
73+
}

Assets/ArtNet/Editor/DmxRecorder/Recorder.cs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public Recorder()
2929
_receiver.OnReceivedPacket = OnReceivedPacket;
3030
}
3131
public RecordingStatus Status { get; private set; } = RecordingStatus.None;
32-
public RecordConfig Config { get; set; }
32+
public RecordConfigs RecordConfigs { get; set; }
3333

3434
public int GetRecordedCount() => _recordedDmx.Count;
3535

@@ -124,18 +124,42 @@ private void StoreDmxPacket()
124124
return;
125125
}
126126

127-
var storeData = RecordData.Serialize(_recordedDmx);
127+
switch (RecordConfigs.RecordFormat)
128+
{
129+
case RecodeFormat.Binary:
130+
StoreBinary();
131+
break;
132+
case RecodeFormat.AnimationClip:
133+
StoreAnimationClip();
134+
break;
135+
default:
136+
throw new ArgumentOutOfRangeException();
137+
}
138+
}
139+
140+
private void StoreBinary()
141+
{
142+
var binaryConfig = RecordConfigs.BinaryConfig;
128143

129-
if (!Directory.Exists(Config.Directory))
144+
if (!Directory.Exists(binaryConfig.Directory))
130145
{
131-
Directory.CreateDirectory(Config.Directory);
146+
Directory.CreateDirectory(binaryConfig.Directory);
132147
}
133148

134-
var path = Config.OutputPath;
149+
var binary = RecordData.Serialize(_recordedDmx);
150+
151+
var path = binaryConfig.OutputPath;
135152
var exists = File.Exists(path);
136-
File.WriteAllBytes(path, storeData);
153+
File.WriteAllBytes(path, binary);
137154
var message = exists ? "Data updated" : "Data stored";
138155
Debug.Log($"ArtNet Recorder: {message} at {path}");
139156
}
157+
158+
private void StoreAnimationClip()
159+
{
160+
var animationClipConfig = RecordConfigs.AnimationClipConfig;
161+
var timelineConverter = new TimelineConverter(_recordedDmx);
162+
timelineConverter.SaveDmxTimelineClips(animationClipConfig.OutputAnimationClipAssetPath);
163+
}
140164
}
141165
}

Assets/ArtNet/Editor/DmxRecorder/RecorderWindow.cs

Lines changed: 59 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ partial class DmxRecordWindow
1414
private readonly Recorder _recorder = new();
1515

1616
private Label _errorMessageLabel;
17+
18+
private VisualElement _outputBinaryConfig, _outputAnimationClipConfig;
19+
private TextField _outputAssetDirectoryField;
1720
private TextField _outputFileNameField, _outputDirectoryField;
1821

1922
private Label _outputFilePathLabel, _footerStatusLabel;
@@ -68,7 +71,7 @@ private void InitializeControlPanel(VisualElement root)
6871
playButton.Add(stopButtonImage);
6972
playButton.clicked += () =>
7073
{
71-
if (!_recorder.Config.Validate()) return;
74+
if (!_recorder.RecordConfigs.Validate()) return;
7275
if (_recorder.Status == RecordingStatus.None)
7376
{
7477
SetEnabledTextField(false);
@@ -121,27 +124,44 @@ private void InitializeControlPanel(VisualElement root)
121124

122125
private void InitializeRecordingConfig(VisualElement root)
123126
{
127+
_outputBinaryConfig = root.Q<VisualElement>("binaryOutputConfig");
128+
_outputAnimationClipConfig = root.Q<VisualElement>("animationClipOutputConfig");
129+
130+
// 出力ファイルのフォーマット選択
131+
var outputFormatGroup = root.Q<RadioButtonGroup>("outputFormatGroup");
132+
outputFormatGroup.choices = new[] { "Binary", "AnimationClip" };
133+
outputFormatGroup.value = (int) _recorder.RecordConfigs.RecordFormat;
134+
ChangeOutputFormat(_recorder.RecordConfigs.RecordFormat);
135+
136+
outputFormatGroup.RegisterValueChangedCallback(evt =>
137+
{
138+
var format = (RecodeFormat) evt.newValue;
139+
ChangeOutputFormat(format);
140+
EditorUserSettings.SetConfigValue(EditorSettingKey("RecodeFormat"), format.ToString());
141+
UpdateErrorMessage();
142+
});
143+
124144
_outputFilePathLabel = root.Q<Label>("outputFileName");
125145
_outputWarningIcon = root.Q<Image>("outputWarningIcon");
126146

127147
// 出力ファイル名の設定
128148
_outputFileNameField = root.Q<TextField>("outputFileNameField");
129-
_outputFileNameField.value = _recorder.Config.FileName;
149+
_outputFileNameField.value = _recorder.RecordConfigs.BinaryConfig.FileName;
130150
_outputFileNameField.RegisterValueChangedCallback(evt =>
131151
{
132152
var fileName = evt.newValue;
133-
_recorder.Config.FileName = fileName;
153+
_recorder.RecordConfigs.BinaryConfig.FileName = fileName;
134154
UpdateOutputFilePath();
135155
EditorUserSettings.SetConfigValue(EditorSettingKey("OutputFileName"), fileName);
136156
});
137157

138158
// 出力ディレクトリの設定
139159
_outputDirectoryField = root.Q<TextField>("outputDirectoryField");
140-
_outputDirectoryField.value = _recorder.Config.Directory;
160+
_outputDirectoryField.value = _recorder.RecordConfigs.BinaryConfig.Directory;
141161
_outputDirectoryField.RegisterValueChangedCallback(evt =>
142162
{
143163
var directory = evt.newValue;
144-
_recorder.Config.Directory = directory;
164+
_recorder.RecordConfigs.BinaryConfig.Directory = directory;
145165
UpdateOutputFilePath();
146166
EditorUserSettings.SetConfigValue(EditorSettingKey("OutputDirectory"), directory);
147167
});
@@ -155,17 +175,27 @@ private void InitializeRecordingConfig(VisualElement root)
155175
{
156176
var selectedDirectory =
157177
EditorUtility.OpenFolderPanel(title: "Output Folder",
158-
folder: _recorder.Config.Directory,
178+
folder: _recorder.RecordConfigs.BinaryConfig.Directory,
159179
defaultName: "");
160180

161181
if (string.IsNullOrEmpty(selectedDirectory)) return;
162182

163-
_recorder.Config.Directory = selectedDirectory;
183+
_recorder.RecordConfigs.BinaryConfig.Directory = selectedDirectory;
164184
_outputDirectoryField.value = selectedDirectory;
165185
UpdateOutputFilePath();
166186
EditorUserSettings.SetConfigValue(EditorSettingKey("OutputDirectory"), selectedDirectory);
167187
};
168188

189+
// Animation Config
190+
var outputAssetDirectoryField = root.Q<TextField>("outputAssetDirectoryField");
191+
outputAssetDirectoryField.value = _recorder.RecordConfigs.AnimationClipConfig.OutputAnimationClipAssetPath;
192+
outputAssetDirectoryField.RegisterValueChangedCallback(evt =>
193+
{
194+
var directory = evt.newValue;
195+
_recorder.RecordConfigs.AnimationClipConfig.OutputAnimationClipAssetPath = directory;
196+
EditorUserSettings.SetConfigValue(EditorSettingKey("OutputAssetDirectory"), directory);
197+
});
198+
169199

170200
var outputWarningIcon = root.Q<Image>("outputWarningIcon");
171201
outputWarningIcon.image = EditorGUIUtility.IconContent("Warning@2x").image;
@@ -177,7 +207,7 @@ private void InitializeRecordingConfig(VisualElement root)
177207
);
178208
openOutputFolderButton.clicked += () =>
179209
{
180-
Process.Start(_recorder.Config.Directory);
210+
Process.Start(_recorder.RecordConfigs.BinaryConfig.Directory);
181211
};
182212

183213
_errorMessageArea = root.Q<VisualElement>("errorMessageArea");
@@ -192,17 +222,36 @@ private void InitializeRecordingConfig(VisualElement root)
192222
UpdateOutputFilePath();
193223
}
194224

225+
private void ChangeOutputFormat(RecodeFormat format)
226+
{
227+
_outputBinaryConfig.style.display = DisplayStyle.None;
228+
_outputAnimationClipConfig.style.display = DisplayStyle.None;
229+
switch (format)
230+
{
231+
case RecodeFormat.Binary:
232+
_outputBinaryConfig.style.display = DisplayStyle.Flex;
233+
break;
234+
case RecodeFormat.AnimationClip:
235+
_outputAnimationClipConfig.style.display = DisplayStyle.Flex;
236+
break;
237+
default:
238+
throw new ArgumentOutOfRangeException(nameof(format), format, null);
239+
}
240+
241+
_recorder.RecordConfigs.RecordFormat = format;
242+
}
243+
195244
private void UpdateOutputFilePath()
196245
{
197-
var path = _recorder.Config.OutputPath;
246+
var path = _recorder.RecordConfigs.BinaryConfig.OutputPath;
198247
_outputFilePathLabel.text = path;
199248
_outputWarningIcon.style.display = System.IO.File.Exists(path) ? DisplayStyle.Flex : DisplayStyle.None;
200249
UpdateErrorMessage();
201250
}
202251

203252
private void UpdateErrorMessage()
204253
{
205-
var errors = _recorder.Config.ValidateErrors();
254+
var errors = _recorder.RecordConfigs.ValidateErrors();
206255
if (errors.Count > 0)
207256
{
208257
_errorMessageLabel.text = string.Join("\n", errors);

0 commit comments

Comments
 (0)