├── .gitattributes
├── .gitignore
├── CONTRIBUTING.md
├── Ched.Core
├── BarIndexCalculator.cs
├── Ched.Core.csproj
├── Ched.Core.nuspec
├── Constants.cs
├── EventCollection.cs
├── Events
│ ├── BpmChangeEvent.cs
│ ├── EventBase.cs
│ ├── HighSpeedChangeEvent.cs
│ ├── InvalidTimeSignatureException.cs
│ └── TimeSignatureChangeEvent.cs
├── NoteCollection.cs
├── Notes
│ ├── Air.cs
│ ├── AirAction.cs
│ ├── Damage.cs
│ ├── ExTap.cs
│ ├── Flick.cs
│ ├── Hold.cs
│ ├── LongNoteBase.cs
│ ├── Slide.cs
│ ├── Tap.cs
│ └── TappableBase.cs
├── Properties
│ └── AssemblyInfo.cs
├── Score.cs
├── ScoreBook.cs
├── TimeCalculator.cs
├── UI
│ └── SelectionRange.cs
└── packages.config
├── Ched.Drawing
├── Ched.Drawing.csproj
├── Ched.Drawing.nuspec
├── ColorProfile.cs
├── ComponentGraphics.cs
├── DrawingContext.cs
├── GraphicsExtensions.cs
├── NoteGraphics.cs
└── Properties
│ └── AssemblyInfo.cs
├── Ched.Plugins
├── Ched.Plugins.csproj
├── Ched.Plugins.nuspec
├── Diagnostics.cs
├── IPlugin.cs
├── IScoreBookExportPlugin.cs
├── IScoreBookImportPlugin.cs
├── IScorePlugin.cs
├── Properties
│ └── AssemblyInfo.cs
└── UserCancelledException.cs
├── Ched.sln
├── Ched
├── App.config
├── Ched.csproj
├── Components
│ └── Exporter
│ │ └── SusExporter.cs
├── Configuration
│ ├── ApplicationSettings.cs
│ ├── SettingsBase.cs
│ └── SoundSettings.cs
├── Localization
│ ├── ErrorStrings.Designer.cs
│ ├── ErrorStrings.en.resx
│ ├── ErrorStrings.resx
│ ├── FileFilterStrings.Designer.cs
│ ├── FileFilterStrings.en.resx
│ ├── FileFilterStrings.resx
│ ├── MainFormStrings.Designer.cs
│ ├── MainFormStrings.en.Designer.cs
│ ├── MainFormStrings.en.resx
│ ├── MainFormStrings.resx
│ ├── PluginStrings.Designer.cs
│ ├── PluginStrings.en.Designer.cs
│ ├── PluginStrings.en.resx
│ └── PluginStrings.resx
├── Plugins
│ ├── ComboCalculator.cs
│ ├── ExportManager.cs
│ ├── PluginManager.cs
│ ├── ScoreBookExportPluginArgs.cs
│ ├── ScoreBookImportPluginArgs.cs
│ ├── ScorePluginArgs.cs
│ ├── ShiftEvent.cs
│ ├── SlideKnitter.cs
│ ├── SlideMerger.cs
│ ├── SlideReverser.cs
│ ├── SlideSplitter.cs
│ └── SusExportPlugin.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── Resources
│ ├── airaction.png
│ ├── airdown.png
│ ├── airleftdown.png
│ ├── airleftup.png
│ ├── airrightdown.png
│ ├── airrightup.png
│ ├── airup.png
│ ├── arrow-curve-180-left.png
│ ├── arrow-curve.png
│ ├── blue-document-export.png
│ ├── clipboard-paste.png
│ ├── cross-circle.png
│ ├── damage.png
│ ├── disk-black.png
│ ├── document--plus.png
│ ├── document-copy.png
│ ├── eraser.png
│ ├── exclamation.png
│ ├── extap.png
│ ├── flick.png
│ ├── folder-horizontal-open.png
│ ├── guide.mp3
│ ├── hold.png
│ ├── icon.ico
│ ├── information.png
│ ├── magnifier-zoom-in.png
│ ├── magnifier-zoom-out.png
│ ├── pencil.png
│ ├── scissors-blue.png
│ ├── selection.png
│ ├── slide.png
│ ├── slidestep.png
│ └── tap.png
├── UI
│ ├── BpmSelectionForm.Designer.cs
│ ├── BpmSelectionForm.cs
│ ├── BpmSelectionForm.en.resx
│ ├── BpmSelectionForm.resx
│ ├── CheckableToolStripSplitButton.cs
│ ├── ControlExtensions.cs
│ ├── CustomQuantizeSelectionForm.Designer.cs
│ ├── CustomQuantizeSelectionForm.cs
│ ├── CustomQuantizeSelectionForm.en.resx
│ ├── CustomQuantizeSelectionForm.resx
│ ├── GraphicsExtensions.cs
│ ├── Helpers.cs
│ ├── HighSpeedSelectionForm.Designer.cs
│ ├── HighSpeedSelectionForm.cs
│ ├── HighSpeedSelectionForm.en.resx
│ ├── HighSpeedSelectionForm.resx
│ ├── MainForm.Designer.cs
│ ├── MainForm.cs
│ ├── MainForm.resx
│ ├── NoteView.Designer.cs
│ ├── NoteView.cs
│ ├── Operations
│ │ ├── CompositeOperation.cs
│ │ ├── EditNoteOperation.cs
│ │ ├── EventCollectionOperation.cs
│ │ ├── IOperation.cs
│ │ ├── NoteCollectionOperation.cs
│ │ ├── OperationManager.cs
│ │ └── ScoreOperation.cs
│ ├── PlaneExtensions.cs
│ ├── ShiftTimeSelectionForm.Designer.cs
│ ├── ShiftTimeSelectionForm.cs
│ ├── ShiftTimeSelectionForm.resx
│ ├── Shortcuts
│ │ ├── Commands.cs
│ │ ├── KeyExtensions.cs
│ │ ├── ShortcutCommandSource.cs
│ │ ├── ShortcutKeySource.cs
│ │ ├── ShortcutManager.cs
│ │ └── ToolStripItemBuilder.cs
│ ├── SoundManager.cs
│ ├── SoundPreviewManager.cs
│ ├── TimeSignatureSelectionForm.Designer.cs
│ ├── TimeSignatureSelectionForm.cs
│ ├── TimeSignatureSelectionForm.en.resx
│ ├── TimeSignatureSelectionForm.resx
│ ├── VersionInfoForm.Designer.cs
│ ├── VersionInfoForm.cs
│ ├── VersionInfoForm.en.resx
│ ├── VersionInfoForm.resx
│ └── Windows
│ │ ├── Behaviors
│ │ ├── HideWindowCloseButtonBehavior.cs
│ │ ├── InitialFocusBehavior.cs
│ │ ├── OpenFileBehavior.cs
│ │ ├── StyleBehaviorCollection.cs
│ │ └── UpdateOnEnterPressBehaviors.cs
│ │ ├── BindableNumericUpDown.xaml
│ │ ├── BindableNumericUpDown.xaml.cs
│ │ ├── BookPropertiesWindow.xaml
│ │ ├── BookPropertiesWindow.xaml.cs
│ │ ├── CommonStyles.xaml
│ │ ├── Converters
│ │ ├── BitmapImageSourceConverter.cs
│ │ ├── ShortcutKeyTextConverter.cs
│ │ └── VolumeConverter.cs
│ │ ├── DiagnosticsWindow.xaml
│ │ ├── DiagnosticsWindow.xaml.cs
│ │ ├── EnumSourceProvider.cs
│ │ ├── ShortcutSettingsWindow.xaml
│ │ ├── ShortcutSettingsWindow.xaml.cs
│ │ ├── SusExportWindow.xaml
│ │ ├── SusExportWindow.xaml.cs
│ │ ├── ViewModel.cs
│ │ └── WpfExtensions.cs
└── packages.config
├── LICENSE
├── README.md
└── appveyor.yml
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute to Ched
2 |
3 | ## Did you find a bug?
4 |
5 | * Open a new GitHub issue with a clear title, steps to reproduce the bug, executable version, and other environment information.
6 | * Ensure the bug was not already reported by searching existing issues.
7 |
8 | ## Did you write a patch that fixes a bug?
9 |
10 | * Open a new GitHub pull request with the changes.
11 | * Ensure the branch for the pull request is based on the **latest develop branch** at that time.
12 |
--------------------------------------------------------------------------------
/Ched.Core/Ched.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5A5FF947-79DC-4352-94D5-EEC14065F93A}
8 | Library
9 | Properties
10 | Ched.Core
11 | Ched.Core
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 | bin\x86\Debug\
36 | DEBUG;TRACE
37 | full
38 | x86
39 | prompt
40 | MinimumRecommendedRules.ruleset
41 |
42 |
43 | bin\x86\Release\
44 | TRACE
45 | true
46 | pdbonly
47 | x86
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 |
51 |
52 |
53 | ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll
54 | True
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
103 |
--------------------------------------------------------------------------------
/Ched.Core/Ched.Core.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $description$
7 | $author$
8 |
9 | https://github.com/paralleltree/Ched
10 | MIT
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Ched.Core/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core
8 | {
9 | public static class Constants
10 | {
11 | public static int LanesCount = 16;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/Ched.Core/EventCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Events;
8 |
9 | namespace Ched.Core
10 | {
11 | ///
12 | /// イベントを格納するコレクションを表すクラスです。
13 | ///
14 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
15 | public class EventCollection
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private List bpmChangeEvents = new List();
19 | [Newtonsoft.Json.JsonProperty]
20 | private List timeSignatureChangeEvents = new List();
21 | [Newtonsoft.Json.JsonProperty]
22 | private List highSpeedChangeEvents = new List();
23 |
24 | public List BpmChangeEvents
25 | {
26 | get { return bpmChangeEvents; }
27 | set { bpmChangeEvents = value; }
28 | }
29 |
30 | public List TimeSignatureChangeEvents
31 | {
32 | get { return timeSignatureChangeEvents; }
33 | set { timeSignatureChangeEvents = value; }
34 | }
35 |
36 | public List HighSpeedChangeEvents
37 | {
38 | get { return highSpeedChangeEvents; }
39 | set { highSpeedChangeEvents = value; }
40 | }
41 |
42 | public IEnumerable AllEvents =>
43 | BpmChangeEvents.Cast()
44 | .Concat(TimeSignatureChangeEvents)
45 | .Concat(HighSpeedChangeEvents);
46 |
47 | public void UpdateTicksPerBeat(double factor)
48 | {
49 | var events = BpmChangeEvents.Cast()
50 | .Concat(TimeSignatureChangeEvents)
51 | .Concat(HighSpeedChangeEvents);
52 | foreach (var e in events)
53 | e.Tick = (int)(e.Tick * factor);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Ched.Core/Events/BpmChangeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Core.Events
9 | {
10 | ///
11 | /// BPMの変更イベントを表すクラスです。
12 | ///
13 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
14 | [DebuggerDisplay("Tick = {Tick}, Value = {Bpm}")]
15 | public class BpmChangeEvent : EventBase
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private double bpm;
19 |
20 | public double Bpm
21 | {
22 | get { return bpm; }
23 | set { bpm = value; }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Ched.Core/Events/EventBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Core.Events
9 | {
10 | ///
11 | /// 譜面におけるイベントを表すクラスです。
12 | ///
13 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
14 | [DebuggerDisplay("Tick = {Tick}")]
15 | public abstract class EventBase
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private int tick;
19 |
20 | ///
21 | /// このイベントの位置を表すTick値を取得、設定します。
22 | ///
23 | public int Tick
24 | {
25 | get { return tick; }
26 | set
27 | {
28 | if (value < 0) throw new ArgumentOutOfRangeException("value", "Tick must be greater than or equal to 0.");
29 | tick = value;
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Ched.Core/Events/HighSpeedChangeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Core.Events
9 | {
10 | ///
11 | /// ハイスピードの変更を表すクラスです。
12 | ///
13 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
14 | [DebuggerDisplay("Tick = {Tick}, Value = {SpeedRatio}")]
15 | public class HighSpeedChangeEvent : EventBase
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private decimal speedRatio;
19 |
20 | ///
21 | /// 1を基準とする速度比を設定します。
22 | ///
23 | public decimal SpeedRatio
24 | {
25 | get { return speedRatio; }
26 | set { speedRatio = value; }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Ched.Core/Events/InvalidTimeSignatureException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.Serialization;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Core.Events
9 | {
10 | ///
11 | /// 拍子定義が無効な場合にスローされる例外です。
12 | ///
13 | [Serializable]
14 | public class InvalidTimeSignatureException : Exception
15 | {
16 | private static readonly string TickPropertyValue = "tick";
17 |
18 | ///
19 | /// 無効な拍子定義の位置を表すTick値を取得します。
20 | ///
21 | public int Tick { get; }
22 |
23 | public InvalidTimeSignatureException() : base()
24 | {
25 | }
26 |
27 | public InvalidTimeSignatureException(string message) : base(message)
28 | {
29 | }
30 |
31 | public InvalidTimeSignatureException(string message, Exception inner) : base(message, inner)
32 | {
33 | }
34 |
35 | public InvalidTimeSignatureException(string message, int tick) : this(message, tick, null)
36 | {
37 | }
38 |
39 | public InvalidTimeSignatureException(string message, int tick, Exception innerException) : base(message, innerException)
40 | {
41 | Tick = tick;
42 | }
43 |
44 | protected InvalidTimeSignatureException(SerializationInfo info, StreamingContext context) : base(info, context)
45 | {
46 | if (info == null) return;
47 | Tick = info.GetInt32(TickPropertyValue);
48 | }
49 |
50 | public override void GetObjectData(SerializationInfo info, StreamingContext context)
51 | {
52 | base.GetObjectData(info, context);
53 | if (info == null) return;
54 |
55 | info.AddValue(TickPropertyValue, Tick);
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Ched.Core/Events/TimeSignatureChangeEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Core.Events
9 | {
10 | ///
11 | /// 拍子の変更を表します。
12 | ///
13 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
14 | [DebuggerDisplay("Tick = {Tick}, Value = {Numerator} / {Denominator}")]
15 | public class TimeSignatureChangeEvent : EventBase
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private int numerator;
19 | [Newtonsoft.Json.JsonProperty]
20 | private int denominatorExponent;
21 |
22 | ///
23 | /// 拍子の分子を設定します。
24 | ///
25 | public int Numerator
26 | {
27 | get { return numerator; }
28 | set
29 | {
30 | if (value < 1) throw new ArgumentOutOfRangeException("value must be greater than 0.");
31 | numerator = value;
32 | }
33 | }
34 |
35 | ///
36 | /// 拍子の分母を取得します。
37 | ///
38 | public int Denominator
39 | {
40 | get
41 | {
42 | int p = 1;
43 | for (int i = 0; i < DenominatorExponent; i++) p *= 2;
44 | return p;
45 | }
46 | }
47 |
48 | ///
49 | /// 2を底とする拍子の分母の指数を設定します。
50 | ///
51 | public int DenominatorExponent
52 | {
53 | get { return denominatorExponent; }
54 | set
55 | {
56 | if (value < 0) throw new ArgumentOutOfRangeException("value must be positive.");
57 | denominatorExponent = value;
58 | }
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Ched.Core/NoteCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Notes;
8 |
9 | namespace Ched.Core
10 | {
11 | ///
12 | /// ノーツを格納するコレクションを表すクラスです。
13 | ///
14 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
15 | public class NoteCollection
16 | {
17 | [Newtonsoft.Json.JsonProperty]
18 | private List taps;
19 | [Newtonsoft.Json.JsonProperty]
20 | private List exTaps;
21 | [Newtonsoft.Json.JsonProperty]
22 | private List holds;
23 | [Newtonsoft.Json.JsonProperty]
24 | private List slides;
25 | [Newtonsoft.Json.JsonProperty]
26 | private List flicks;
27 | [Newtonsoft.Json.JsonProperty]
28 | private List damages;
29 | [Newtonsoft.Json.JsonProperty]
30 | private List airs;
31 | [Newtonsoft.Json.JsonProperty]
32 | private List airActions;
33 |
34 | public List Taps
35 | {
36 | get { return taps; }
37 | set { taps = value; }
38 | }
39 |
40 | public List ExTaps
41 | {
42 | get { return exTaps; }
43 | set { exTaps = value; }
44 | }
45 |
46 | public List Holds
47 | {
48 | get { return holds; }
49 | set { holds = value; }
50 | }
51 |
52 | public List Slides
53 | {
54 | get { return slides; }
55 | set { slides = value; }
56 | }
57 |
58 | public List Airs
59 | {
60 | get { return airs; }
61 | set { airs = value; }
62 | }
63 |
64 | public List AirActions
65 | {
66 | get { return airActions; }
67 | set { airActions = value; }
68 | }
69 |
70 | public List Flicks
71 | {
72 | get { return flicks; }
73 | set { flicks = value; }
74 | }
75 |
76 | public List Damages
77 | {
78 | get { return damages; }
79 | set { damages = value; }
80 | }
81 |
82 | public NoteCollection()
83 | {
84 | Taps = new List();
85 | ExTaps = new List();
86 | Holds = new List();
87 | Slides = new List();
88 | Airs = new List();
89 | AirActions = new List();
90 | Flicks = new List();
91 | Damages = new List();
92 | }
93 |
94 | public NoteCollection(NoteCollection collection)
95 | {
96 | Taps = collection.Taps.ToList();
97 | ExTaps = collection.ExTaps.ToList();
98 | Holds = collection.Holds.ToList();
99 | Slides = collection.Slides.ToList();
100 | Airs = collection.Airs.ToList();
101 | AirActions = collection.AirActions.ToList();
102 | Flicks = collection.Flicks.ToList();
103 | Damages = collection.Damages.ToList();
104 | }
105 |
106 | public IEnumerable GetShortNotes()
107 | {
108 | return Taps.Cast().Concat(ExTaps).Concat(Flicks).Concat(Damages);
109 | }
110 |
111 | public void UpdateTicksPerBeat(double factor)
112 | {
113 | foreach (var note in GetShortNotes())
114 | note.Tick = (int)(note.Tick * factor);
115 |
116 | foreach (var hold in Holds)
117 | {
118 | hold.StartTick = (int)(hold.StartTick * factor);
119 | hold.Duration = (int)(hold.Duration * factor);
120 | }
121 |
122 | foreach (var slide in Slides)
123 | {
124 | slide.StartTick = (int)(slide.StartTick * factor);
125 | foreach (var step in slide.StepNotes)
126 | step.TickOffset = (int)(step.TickOffset * factor);
127 | }
128 |
129 | foreach (var action in AirActions.SelectMany(p => p.ActionNotes))
130 | action.Offset = (int)(action.Offset * factor);
131 | }
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/Air.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
10 | public class Air
11 | {
12 | [Newtonsoft.Json.JsonProperty]
13 | private IAirable parentNote;
14 | [Newtonsoft.Json.JsonProperty]
15 | private VerticalAirDirection verticalDirection;
16 | [Newtonsoft.Json.JsonProperty]
17 | private HorizontalAirDirection horizontalDirection;
18 |
19 | public IAirable ParentNote { get { return parentNote; } }
20 |
21 | public VerticalAirDirection VerticalDirection
22 | {
23 | get { return verticalDirection; }
24 | set { verticalDirection = value; }
25 | }
26 |
27 | public HorizontalAirDirection HorizontalDirection
28 | {
29 | get { return horizontalDirection; }
30 | set { horizontalDirection = value; }
31 | }
32 |
33 | public int Tick { get { return ParentNote.Tick; } }
34 |
35 | public int LaneIndex { get { return ParentNote.LaneIndex; } }
36 |
37 | public int Width { get { return ParentNote.Width; } }
38 |
39 | public Air(IAirable parent)
40 | {
41 | parentNote = parent;
42 | }
43 |
44 | public void Flip()
45 | {
46 | if (HorizontalDirection == HorizontalAirDirection.Center) return;
47 | HorizontalDirection = HorizontalDirection == HorizontalAirDirection.Left ? HorizontalAirDirection.Right : HorizontalAirDirection.Left;
48 | }
49 | }
50 |
51 | public interface IAirable
52 | {
53 | ///
54 | /// ノートの位置を表すTickを設定します。
55 | ///
56 | int Tick { get; }
57 |
58 | ///
59 | /// ノートの配置されるレーン番号を取得します。。
60 | ///
61 | int LaneIndex { get; }
62 |
63 | ///
64 | /// ノートのレーン幅を取得します。
65 | ///
66 | int Width { get; }
67 | }
68 |
69 | public enum VerticalAirDirection
70 | {
71 | Up,
72 | Down
73 | }
74 |
75 | public enum HorizontalAirDirection
76 | {
77 | Center,
78 | Left,
79 | Right
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/AirAction.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
10 | public class AirAction : ILongNote
11 | {
12 | [Newtonsoft.Json.JsonProperty]
13 | private IAirable parentNote;
14 | [Newtonsoft.Json.JsonProperty]
15 | private List actionNotes = new List();
16 |
17 | public List ActionNotes { get { return actionNotes; } }
18 | public IAirable ParentNote { get { return parentNote; } }
19 | public int StartTick => ParentNote.Tick;
20 |
21 | ///
22 | /// 親オブジェクトを持たないの新しいインスタンスを初期化します。
23 | ///
24 | /// このコンストラクタはシリアライザ用に存在します。
25 | public AirAction()
26 | {
27 | }
28 |
29 | ///
30 | /// 指定のを親とするの新しいインスタンスを初期化します。
31 | ///
32 | /// このの親となるオブジェクト
33 | public AirAction(IAirable parent)
34 | {
35 | parentNote = parent;
36 | }
37 |
38 | public int GetDuration()
39 | {
40 | return ActionNotes.Max(p => p.Offset);
41 | }
42 |
43 |
44 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
45 | public class ActionNote
46 | {
47 | [Newtonsoft.Json.JsonProperty]
48 | private int offset;
49 | [Newtonsoft.Json.JsonProperty]
50 | private AirAction parentNote;
51 |
52 | public AirAction ParentNote { get { return parentNote; } }
53 |
54 | public int Offset
55 | {
56 | get { return offset; }
57 | set
58 | {
59 | if (value <= 0) throw new ArgumentOutOfRangeException("value", "value must be positive.");
60 | offset = value;
61 | }
62 | }
63 |
64 | ///
65 | /// 指定のを親とするの新しいインスタンスを初期化します。
66 | ///
67 | /// このの親となるオブジェクト
68 | public ActionNote(AirAction parent)
69 | {
70 | parentNote = parent;
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/Damage.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | public class Damage : TappableBase
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/ExTap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | public class ExTap : Tap
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/Flick.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | public class Flick : TappableBase
10 | {
11 | }
12 | }
--------------------------------------------------------------------------------
/Ched.Core/Notes/Hold.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
10 | public class Hold : MovableLongNoteBase
11 | {
12 | [Newtonsoft.Json.JsonProperty]
13 | private int laneIndex;
14 | [Newtonsoft.Json.JsonProperty]
15 | private int width = 1;
16 | [Newtonsoft.Json.JsonProperty]
17 | private int duration = 1;
18 |
19 | [Newtonsoft.Json.JsonProperty]
20 | private StartTap startNote;
21 | [Newtonsoft.Json.JsonProperty]
22 | private EndTap endNote;
23 |
24 | ///
25 | /// ノートの配置されるレーン番号を設定します。。
26 | ///
27 | public int LaneIndex
28 | {
29 | get { return laneIndex; }
30 | set
31 | {
32 | CheckPosition(value, Width);
33 | laneIndex = value;
34 | }
35 | }
36 |
37 | ///
38 | /// ノートのレーン幅を設定します。
39 | ///
40 | public int Width
41 | {
42 | get { return width; }
43 | set
44 | {
45 | CheckPosition(LaneIndex, value);
46 | width = value;
47 | }
48 | }
49 |
50 | ///
51 | /// ノートの長さを設定します。
52 | ///
53 | public int Duration
54 | {
55 | get { return duration; }
56 | set
57 | {
58 | if (duration == value) return;
59 | if (duration <= 0) throw new ArgumentOutOfRangeException("value", "value must be positive.");
60 | duration = value;
61 | }
62 | }
63 |
64 | protected void CheckPosition(int laneIndex, int width)
65 | {
66 | if (width < 1 || width > Constants.LanesCount)
67 | throw new ArgumentOutOfRangeException("width", "Invalid width.");
68 | if (laneIndex < 0 || laneIndex + width > Constants.LanesCount)
69 | throw new ArgumentOutOfRangeException("laneIndex", "Invalid lane index.");
70 | }
71 |
72 | public void SetPosition(int laneIndex, int width)
73 | {
74 | CheckPosition(laneIndex, width);
75 | this.laneIndex = laneIndex;
76 | this.width = width;
77 | }
78 |
79 | public StartTap StartNote { get { return startNote; } }
80 | public EndTap EndNote { get { return endNote; } }
81 |
82 | public Hold()
83 | {
84 | startNote = new StartTap(this);
85 | endNote = new EndTap(this);
86 | }
87 |
88 | public override int GetDuration()
89 | {
90 | return Duration;
91 | }
92 |
93 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
94 | public abstract class TapBase : LongNoteTapBase
95 | {
96 | protected Hold parent;
97 |
98 | public override int LaneIndex { get { return parent.LaneIndex; } }
99 |
100 | public override int Width { get { return parent.Width; } }
101 |
102 | public TapBase(Hold parent)
103 | {
104 | this.parent = parent;
105 | }
106 | }
107 |
108 | public class StartTap : TapBase
109 | {
110 | public override int Tick { get { return parent.StartTick; } }
111 |
112 | public override bool IsTap { get { return true; } }
113 |
114 | public StartTap(Hold parent) : base(parent)
115 | {
116 | }
117 | }
118 |
119 | public class EndTap : TapBase
120 | {
121 | public override bool IsTap { get { return false; } }
122 |
123 | public override int Tick { get { return parent.StartTick + parent.Duration; } }
124 |
125 | public EndTap(Hold parent) : base(parent)
126 | {
127 | }
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/LongNoteBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | public interface ILongNote
10 | {
11 | ///
12 | /// ノートの開始位置を表すTickを設定します。
13 | ///
14 | int StartTick { get; }
15 |
16 | ///
17 | /// ノートの長さを表すTickを取得します。
18 | ///
19 | int GetDuration();
20 | }
21 |
22 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
23 | public abstract class MovableLongNoteBase : ILongNote
24 | {
25 | [Newtonsoft.Json.JsonProperty]
26 | private int startTick;
27 |
28 | ///
29 | /// ノートの開始位置を表すTickを設定します。
30 | ///
31 | public int StartTick
32 | {
33 | get { return startTick; }
34 | set
35 | {
36 | if (startTick == value) return;
37 | if (value < 0) throw new ArgumentOutOfRangeException("value", "value must not be negative.");
38 | startTick = value;
39 | }
40 | }
41 |
42 | ///
43 | /// ノートの長さを表すTickを取得します。
44 | ///
45 | public abstract int GetDuration();
46 | }
47 |
48 | public abstract class LongNoteTapBase : IAirable
49 | {
50 | public abstract bool IsTap { get; }
51 | public abstract int LaneIndex { get; }
52 | public abstract int Tick { get; }
53 | public abstract int Width { get; }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/Tap.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | public class Tap : TappableBase
10 | {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/Ched.Core/Notes/TappableBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core.Notes
8 | {
9 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
10 | public abstract class TappableBase : IAirable
11 | {
12 | [Newtonsoft.Json.JsonProperty]
13 | private int tick;
14 | [Newtonsoft.Json.JsonProperty]
15 | private int laneIndex;
16 | [Newtonsoft.Json.JsonProperty]
17 | private int width = 1;
18 |
19 | ///
20 | /// ノートの位置を表すTickを設定します。
21 | ///
22 | public int Tick
23 | {
24 | get { return tick; }
25 | set
26 | {
27 | if (tick == value) return;
28 | if (tick < 0) throw new ArgumentOutOfRangeException("value", "value must not be negative.");
29 | tick = value;
30 | }
31 | }
32 |
33 | ///
34 | /// ノートの配置されるレーン番号を設定します。。
35 | ///
36 | public int LaneIndex
37 | {
38 | get { return laneIndex; }
39 | set
40 | {
41 | CheckPosition(value, Width);
42 | laneIndex = value;
43 | }
44 | }
45 |
46 | ///
47 | /// ノートのレーン幅を設定します。
48 | ///
49 | public int Width
50 | {
51 | get { return width; }
52 | set
53 | {
54 | CheckPosition(LaneIndex, value);
55 | width = value;
56 | }
57 | }
58 |
59 | protected void CheckPosition(int laneIndex, int width)
60 | {
61 | if (width < 1 || width > Constants.LanesCount)
62 | throw new ArgumentOutOfRangeException("width", "Invalid width.");
63 | if (laneIndex < 0 || laneIndex + width > Constants.LanesCount)
64 | throw new ArgumentOutOfRangeException("laneIndex", "Invalid lane index.");
65 | }
66 |
67 | public void SetPosition(int laneIndex, int width)
68 | {
69 | CheckPosition(laneIndex, width);
70 | this.laneIndex = laneIndex;
71 | this.width = width;
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/Ched.Core/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("Ched.Core")]
6 | [assembly: AssemblyDescription("Ched Core Library")]
7 | [assembly: AssemblyCompany("paltee.net")]
8 | [assembly: AssemblyProduct("Ched.Core")]
9 | [assembly: AssemblyCopyright("Copyright (C) 2018 Paralleltree")]
10 |
11 | [assembly: ComVisible(false)]
12 | [assembly: Guid("5a5ff947-79dc-4352-94d5-eec14065f93a")]
13 |
14 | [assembly: AssemblyVersion("3.0.0.0")]
15 |
--------------------------------------------------------------------------------
/Ched.Core/Score.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Core
8 | {
9 | ///
10 | /// 譜面データを表すクラスです。
11 | ///
12 | [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]
13 | public class Score
14 | {
15 | [Newtonsoft.Json.JsonProperty]
16 | private int ticksPerBeat = 480;
17 | [Newtonsoft.Json.JsonProperty]
18 | private NoteCollection notes = new NoteCollection();
19 | [Newtonsoft.Json.JsonProperty]
20 | private EventCollection events = new EventCollection();
21 |
22 | ///
23 | /// 1拍あたりの分解能を設定します。
24 | ///
25 | public int TicksPerBeat
26 | {
27 | get { return ticksPerBeat; }
28 | set { ticksPerBeat = value; }
29 | }
30 |
31 | ///
32 | /// ノーツを格納するコレクションです。
33 | ///
34 | public NoteCollection Notes
35 | {
36 | get { return notes; }
37 | set { notes = value; }
38 | }
39 |
40 | ///
41 | /// イベントを格納するコレクションです。
42 | ///
43 | public EventCollection Events
44 | {
45 | get { return events; }
46 | set { events = value; }
47 | }
48 |
49 | public void UpdateTicksPerBeat(int value)
50 | {
51 | double factor = value / TicksPerBeat;
52 | Notes.UpdateTicksPerBeat(factor);
53 | Events.UpdateTicksPerBeat(factor);
54 | TicksPerBeat = value;
55 | }
56 |
57 | public Score Clone()
58 | {
59 | var score = Newtonsoft.Json.JsonConvert.DeserializeObject(Newtonsoft.Json.JsonConvert.SerializeObject(this, ScoreBook.SerializerSettings));
60 | return score;
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Ched.Core/TimeCalculator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Events;
8 |
9 | namespace Ched.Core
10 | {
11 | ///
12 | /// BPM変更イベントからTick値に対応する時刻を求めるクラスです。
13 | ///
14 | public class TimeCalculator
15 | {
16 | protected int TicksPerBeat { get; }
17 | // 時間順ソート済み
18 | protected List<(int Tick, double Bpm, double Time)> BpmDefinitions { get; } = new List<(int Tick, double Bpm, double Time)>();
19 |
20 | public TimeCalculator(int ticksPerBeat, IEnumerable bpms)
21 | {
22 | TicksPerBeat = ticksPerBeat;
23 | double time = 0;
24 | var ordered = bpms.OrderBy(p => p.Tick).ToList();
25 | if (ordered[0].Tick != 0) throw new ArgumentException("Initial BpmChangeEvent was not found.", "bpms");
26 | BpmDefinitions.Add((0, ordered[0].Bpm, 0));
27 | for (int i = 1; i < ordered.Count; i++)
28 | {
29 | time += GetDuration(ordered[i - 1].Bpm, ordered[i].Tick - ordered[i - 1].Tick);
30 | BpmDefinitions.Add((ordered[i].Tick, ordered[i].Bpm, time));
31 | }
32 | }
33 |
34 | public double GetTimeFromTick(int tick)
35 | {
36 | for (int i = BpmDefinitions.Count - 1; 0 <= i; i--)
37 | {
38 | if (tick < BpmDefinitions[i].Tick) continue;
39 | return BpmDefinitions[i].Time + GetDuration(BpmDefinitions[i].Bpm, tick - BpmDefinitions[i].Tick);
40 | }
41 | // 負の時間は初期BPMで遡る
42 | return GetDuration(BpmDefinitions[0].Bpm, tick);
43 | }
44 |
45 | public int GetTickFromTime(double time)
46 | {
47 | for (int i = BpmDefinitions.Count - 1; 0 <= i; i--)
48 | {
49 | if (time < BpmDefinitions[i].Time) continue;
50 | return BpmDefinitions[i].Tick + GetDurationInTick(BpmDefinitions[i].Bpm, time - BpmDefinitions[i].Time);
51 | }
52 | // 負の時間は初期BPMで遡る
53 | return GetDurationInTick(BpmDefinitions[0].Bpm, time);
54 | }
55 |
56 | // => durationTick * (60 / bpm) / TicksPerBeat;
57 | protected double GetDuration(double bpm, int durationTick) => durationTick * 60 / bpm / TicksPerBeat;
58 |
59 | // => TicksPerBeat * duration * (bpm / 60)
60 | protected int GetDurationInTick(double bpm, double duration) => (int)(TicksPerBeat * duration * bpm / 60);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Ched.Core/UI/SelectionRange.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core;
8 |
9 | namespace Ched.UI
10 | {
11 | ///
12 | /// 選択範囲を表します。
13 | ///
14 | public struct SelectionRange
15 | {
16 | public static SelectionRange Empty = new SelectionRange()
17 | {
18 | StartTick = 0,
19 | Duration = 0,
20 | StartLaneIndex = 0,
21 | SelectedLanesCount = 0
22 | };
23 |
24 | private int startTick;
25 | private int duration;
26 | private int startLaneIndex;
27 | private int selectedLanesCount;
28 |
29 | ///
30 | /// 選択を開始したTickを設定します。
31 | ///
32 | public int StartTick
33 | {
34 | get { return startTick; }
35 | set
36 | {
37 | if (value < 0) throw new ArgumentOutOfRangeException("value must not be negative.");
38 | startTick = value;
39 | }
40 | }
41 |
42 | ///
43 | /// 選択を終了したときのとのオフセットを表すTickを設定します。
44 | /// この値が負であるとき、よりも前の範囲が選択されたことを表します。
45 | ///
46 | public int Duration
47 | {
48 | get { return duration; }
49 | set
50 | {
51 | duration = value;
52 | }
53 | }
54 |
55 | ///
56 | /// 選択されたレーンの左端のインデックスを設定します。
57 | ///
58 | public int StartLaneIndex
59 | {
60 | get { return startLaneIndex; }
61 | set
62 | {
63 | if (value < 0 || value > Constants.LanesCount - 1) throw new ArgumentOutOfRangeException();
64 | startLaneIndex = value;
65 | }
66 | }
67 |
68 | ///
69 | /// 選択されたレーン数を設定します。
70 | ///
71 | public int SelectedLanesCount
72 | {
73 | get { return selectedLanesCount; }
74 | set
75 | {
76 | if (StartLaneIndex + value < 0 || StartLaneIndex + value > Constants.LanesCount) throw new ArgumentOutOfRangeException();
77 | selectedLanesCount = value;
78 | }
79 | }
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Ched.Core/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Ched.Drawing/Ched.Drawing.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {A41EA7D5-9776-421B-A338-DD662287069B}
8 | Library
9 | Properties
10 | Ched.Drawing
11 | Ched.Drawing
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 | bin\x86\Debug\
36 | DEBUG;TRACE
37 | full
38 | x86
39 | prompt
40 | MinimumRecommendedRules.ruleset
41 |
42 |
43 | bin\x86\Release\
44 | TRACE
45 | true
46 | pdbonly
47 | x86
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {5a5ff947-79dc-4352-94d5-eec14065f93a}
68 | Ched.Core
69 |
70 |
71 |
72 |
73 |
74 |
75 |
82 |
--------------------------------------------------------------------------------
/Ched.Drawing/Ched.Drawing.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $description$
7 | $author$
8 |
9 | https://github.com/paralleltree/Ched
10 | MIT
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Ched.Drawing/ColorProfile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Drawing
9 | {
10 | public class GradientColor
11 | {
12 | public Color DarkColor { get; set; }
13 | public Color LightColor { get; set; }
14 |
15 | public GradientColor(Color darkColor, Color lightColor)
16 | {
17 | DarkColor = darkColor;
18 | LightColor = lightColor;
19 | }
20 | }
21 |
22 | public class ColorProfile
23 | {
24 | public GradientColor BorderColor { get; set; }
25 | public GradientColor TapColor { get; set; }
26 | public GradientColor ExTapColor { get; set; }
27 |
28 | ///
29 | /// フリックを描画する際のを指定します.
30 | /// Item1には背景色, Item2には前景色を指定します.
31 | ///
32 | public Tuple FlickColor { get; set; }
33 | public GradientColor DamageColor { get; set; }
34 | public GradientColor HoldBackgroundColor { get; set; }
35 | public GradientColor HoldColor { get; set; }
36 | public GradientColor SlideBackgroundColor { get; set; }
37 | public GradientColor SlideColor { get; set; }
38 | public Color SlideLineColor { get; set; }
39 | public GradientColor AirActionColor { get; set; }
40 | public Color AirUpColor { get; set; }
41 | public Color AirDownColor { get; set; }
42 | public Color AirHoldLineColor { get; set; }
43 | public GradientColor AirStepColor { get; set; }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Ched.Drawing/ComponentGraphics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Drawing2D;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Ched.Drawing
10 | {
11 | internal static class ComponentGraphics
12 | {
13 | public static void DrawTappableNote(this Graphics g, RectangleF rect, GradientColor foregroundColors, GradientColor borderColors)
14 | {
15 | g.DrawNote(rect, foregroundColors, borderColors);
16 | g.DrawTapSymbol(rect);
17 | }
18 |
19 | public static void DrawNote(this Graphics g, RectangleF rect, GradientColor foregroundColors, GradientColor borderColors)
20 | {
21 | DrawNoteBase(g, rect, foregroundColors);
22 | DrawBorder(g, rect, borderColors);
23 | }
24 |
25 | public static void DrawNoteBase(this Graphics g, RectangleF rect, GradientColor colors)
26 | {
27 | using (var path = rect.ToRoundedPath(rect.Height * 0.3f))
28 | {
29 | using (var brush = new LinearGradientBrush(rect, colors.DarkColor, colors.LightColor, LinearGradientMode.Vertical))
30 | {
31 | g.FillPath(brush, path);
32 | }
33 | }
34 | }
35 |
36 | public static void DrawBorder(this Graphics g, RectangleF rect, GradientColor colors)
37 | {
38 | float borderWidth = rect.Height * 0.1f;
39 | using (var brush = new LinearGradientBrush(rect.Expand(borderWidth), colors.DarkColor, colors.LightColor, LinearGradientMode.Vertical))
40 | {
41 | using (var pen = new Pen(brush, borderWidth))
42 | {
43 | using (var path = rect.ToRoundedPath(rect.Height * 0.3f))
44 | {
45 | g.DrawPath(pen, path);
46 | }
47 | }
48 | }
49 | }
50 |
51 | public static void DrawSquarishNote(this Graphics g, RectangleF rect, GradientColor foregroundColors, GradientColor borderColors)
52 | {
53 | float borderWidth = rect.Height * 0.1f;
54 | using (var brush = new LinearGradientBrush(rect, foregroundColors.DarkColor, foregroundColors.LightColor, LinearGradientMode.Vertical))
55 | {
56 | g.FillRectangle(brush, rect);
57 | }
58 |
59 | using (var brush = new LinearGradientBrush(rect.Expand(borderWidth), borderColors.DarkColor, borderColors.LightColor, LinearGradientMode.Vertical))
60 | {
61 | using (var pen = new Pen(brush, borderWidth))
62 | {
63 | g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
64 | }
65 | }
66 | }
67 |
68 | public static void DrawTapSymbol(this Graphics g, RectangleF rect)
69 | {
70 | using (var pen = new Pen(Color.White, rect.Height * 0.1f))
71 | {
72 | g.DrawLine(pen, rect.Left + rect.Width * 0.2f, rect.Top + rect.Height / 2f, rect.Right - rect.Width * 0.2f, rect.Top + rect.Height / 2);
73 | }
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Ched.Drawing/DrawingContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Drawing
9 | {
10 | public class DrawingContext
11 | {
12 | public Graphics Graphics { get; }
13 | public ColorProfile ColorProfile { get; }
14 |
15 | public DrawingContext(Graphics g, ColorProfile colorProfile)
16 | {
17 | Graphics = g;
18 | ColorProfile = colorProfile;
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Ched.Drawing/GraphicsExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Drawing2D;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Ched.Drawing
10 | {
11 | public static class GraphicsExtensions
12 | {
13 | // ref: http://csharphelper.com/blog/2016/01/draw-rounded-rectangles-in-c/
14 | internal static GraphicsPath ToRoundedPath(this RectangleF rect, float radius)
15 | {
16 | if (radius * 2 > Math.Min(rect.Width, rect.Height))
17 | {
18 | radius = Math.Min(rect.Width, rect.Height) / 2;
19 | }
20 |
21 | var path = new GraphicsPath();
22 |
23 | path.AddArc(rect.Left, rect.Top, radius * 2, radius * 2, 180, 90);
24 | path.AddArc(rect.Right - radius * 2, rect.Top, radius * 2, radius * 2, 270, 90);
25 | path.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);
26 | path.AddArc(rect.Left, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90);
27 | path.CloseFigure();
28 | return path;
29 | }
30 |
31 | public static RectangleF Expand(this RectangleF rect, float size)
32 | {
33 | return rect.Expand(size, size);
34 | }
35 |
36 | public static RectangleF Expand(this RectangleF rect, float dx, float dy)
37 | {
38 | return new RectangleF(rect.Left - dx, rect.Top - dy, rect.Width + dx * 2, rect.Height + dy * 2);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Ched.Drawing/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("Ched.Drawing")]
6 | [assembly: AssemblyDescription("Ched Drawing Library")]
7 | [assembly: AssemblyCompany("paltee.net")]
8 | [assembly: AssemblyProduct("Ched.Drawing")]
9 | [assembly: AssemblyCopyright("Copyright (C) 2018 Paralleltree")]
10 |
11 | [assembly: ComVisible(false)]
12 | [assembly: Guid("a41ea7d5-9776-421b-a338-dd662287069b")]
13 |
14 | [assembly: AssemblyVersion("3.0.0.0")]
15 |
--------------------------------------------------------------------------------
/Ched.Plugins/Ched.Plugins.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {BD335AFA-195D-4C2A-986A-167438C81976}
8 | Library
9 | Properties
10 | Ched.Plugins
11 | Ched.Plugins
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 | bin\x86\Debug\
36 | DEBUG;TRACE
37 | full
38 | x86
39 | prompt
40 | MinimumRecommendedRules.ruleset
41 |
42 |
43 | bin\x86\Release\
44 | TRACE
45 | true
46 | pdbonly
47 | x86
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | {5a5ff947-79dc-4352-94d5-eec14065f93a}
68 | Ched.Core
69 |
70 |
71 |
72 |
73 |
74 |
75 |
82 |
--------------------------------------------------------------------------------
/Ched.Plugins/Ched.Plugins.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $id$
5 | $version$
6 | $description$
7 | $author$
8 |
9 | https://github.com/paralleltree/Ched
10 | MIT
11 | false
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Ched.Plugins/Diagnostics.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Plugins
8 | {
9 | public interface IDiagnosable
10 | {
11 | void ReportDiagnostic(Diagnostic diagnostic);
12 | }
13 |
14 | public class Diagnostic
15 | {
16 | public DiagnosticSeverity Severity { get; }
17 | public string Message { get; }
18 |
19 | public Diagnostic(DiagnosticSeverity severity, string message)
20 | {
21 | Severity = severity;
22 | Message = message;
23 | }
24 | }
25 |
26 | public enum DiagnosticSeverity
27 | {
28 | Hidden = 0,
29 | Information = 1,
30 | Warning = 2,
31 | Error = 3
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Ched.Plugins/IPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Plugins
8 | {
9 | ///
10 | /// アプリケーションで利用可能なプラグインを表します。
11 | ///
12 | public interface IPlugin
13 | {
14 | ///
15 | /// プラグインの表示名を取得します。
16 | ///
17 | string DisplayName { get; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Ched.Plugins/IScoreBookExportPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using Ched.Core;
9 |
10 | namespace Ched.Plugins
11 | {
12 | ///
13 | /// 譜面データのエクスポートを行うプラグインを表します。
14 | ///
15 | public interface IScoreBookExportPlugin : IPlugin
16 | {
17 | ///
18 | /// ファイル選択ダイアログで利用するフィルタ文字列を取得します。
19 | ///
20 | string FileFilter { get; }
21 |
22 | ///
23 | /// エクスポート処理を実行します。
24 | ///
25 | /// エクスポート時の情報を取得する
26 | /// メソッドの呼び出し後に処理をキャンセルする場合、をスローします。
27 | void Export(IScoreBookExportPluginArgs args);
28 | }
29 |
30 | ///
31 | /// エクスポート時にプラグインへ渡される情報を表します。
32 | ///
33 | public interface IScoreBookExportPluginArgs : IDiagnosable
34 | {
35 | ///
36 | /// データを書き込むを取得します。
37 | ///
38 | Stream Stream { get; }
39 |
40 | ///
41 | /// 追加情報を入力する必要があるかどうかを示す値を取得します。
42 | /// この値がTrueの場合、追加情報を要求するダイアログを表示する必要はありません。
43 | ///
44 | bool IsQuick { get; }
45 |
46 | ///
47 | /// エクスポートするデータを取得します。
48 | ///
49 | /// エクスポートする譜面データを表す
50 | ScoreBook GetScoreBook();
51 |
52 | ///
53 | /// エクスポートされるデータに関連付けられた追加情報を取得します。
54 | ///
55 | /// 追加情報を表す文字列
56 | string GetCustomData();
57 |
58 | ///
59 | /// エクスポートしたデータに関連付ける追加情報を保存します。
60 | ///
61 | /// 保存する追加情報を表す文字列
62 | void SetCustomData(string data);
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Ched.Plugins/IScoreBookImportPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.IO;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using Ched.Core;
9 |
10 | namespace Ched.Plugins
11 | {
12 | ///
13 | /// 譜面データのインポートを行うプラグインを表します。
14 | ///
15 | public interface IScoreBookImportPlugin : IPlugin
16 | {
17 | ///
18 | /// ファイル選択時に利用するフィルタ文字列を取得します。
19 | ///
20 | string FileFilter { get; }
21 |
22 | ///
23 | /// 譜面データのインポート処理を行います。
24 | ///
25 | /// インポート時に渡される情報を表す
26 | /// インポートされる譜面を表す
27 | ScoreBook Import(IScoreBookImportPluginArgs args);
28 | }
29 |
30 | ///
31 | /// 譜面データのインポート時に渡される情報を表します。
32 | ///
33 | public interface IScoreBookImportPluginArgs : IDiagnosable
34 | {
35 | ///
36 | /// データを読み取るストリームを取得します。
37 | ///
38 | Stream Stream { get; }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ched.Plugins/IScorePlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core;
8 | using Ched.UI;
9 |
10 | namespace Ched.Plugins
11 | {
12 | ///
13 | /// 譜面データを扱うプラグインを表します。
14 | ///
15 | public interface IScorePlugin : IPlugin
16 | {
17 | void Run(IScorePluginArgs args);
18 | }
19 |
20 | ///
21 | /// の実行時に渡される情報を表します。
22 | ///
23 | public interface IScorePluginArgs
24 | {
25 | Score GetCurrentScore();
26 | SelectionRange GetSelectedRange();
27 | void UpdateScore(Score score);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Ched.Plugins/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | [assembly: AssemblyTitle("Ched.Plugins")]
6 | [assembly: AssemblyDescription("Ched Plugin Support Library")]
7 | [assembly: AssemblyCompany("paltee.net")]
8 | [assembly: AssemblyProduct("Ched.Plugins")]
9 | [assembly: AssemblyCopyright("Copyright (C) 2018 Paralleltree")]
10 |
11 | [assembly: ComVisible(false)]
12 | [assembly: Guid("bd335afa-195d-4c2a-986a-167438c81976")]
13 |
14 | [assembly: AssemblyVersion("3.0.0.0")]
15 |
--------------------------------------------------------------------------------
/Ched.Plugins/UserCancelledException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.Plugins
8 | {
9 | [Serializable]
10 | public class UserCancelledException : Exception
11 | {
12 | public UserCancelledException()
13 | {
14 | }
15 |
16 | public UserCancelledException(string message) : base(message)
17 | {
18 | }
19 |
20 | public UserCancelledException(string message, Exception inner) : base(message, inner)
21 | {
22 | }
23 |
24 | protected UserCancelledException(
25 | System.Runtime.Serialization.SerializationInfo info,
26 | System.Runtime.Serialization.StreamingContext context) : base(info, context)
27 | {
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Ched.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ched", "Ched\Ched.csproj", "{4C0C9F98-6FCF-4D2F-B821-37A66362DC75}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ched.Drawing", "Ched.Drawing\Ched.Drawing.csproj", "{A41EA7D5-9776-421B-A338-DD662287069B}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ched.Core", "Ched.Core\Ched.Core.csproj", "{5A5FF947-79DC-4352-94D5-EEC14065F93A}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ched.Plugins", "Ched.Plugins\Ched.Plugins.csproj", "{BD335AFA-195D-4C2A-986A-167438C81976}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|x86 = Debug|x86
17 | Release|x86 = Release|x86
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {4C0C9F98-6FCF-4D2F-B821-37A66362DC75}.Debug|x86.ActiveCfg = Debug|x86
21 | {4C0C9F98-6FCF-4D2F-B821-37A66362DC75}.Debug|x86.Build.0 = Debug|x86
22 | {4C0C9F98-6FCF-4D2F-B821-37A66362DC75}.Release|x86.ActiveCfg = Release|x86
23 | {4C0C9F98-6FCF-4D2F-B821-37A66362DC75}.Release|x86.Build.0 = Release|x86
24 | {A41EA7D5-9776-421B-A338-DD662287069B}.Debug|x86.ActiveCfg = Debug|Any CPU
25 | {A41EA7D5-9776-421B-A338-DD662287069B}.Debug|x86.Build.0 = Debug|Any CPU
26 | {A41EA7D5-9776-421B-A338-DD662287069B}.Release|x86.ActiveCfg = Release|Any CPU
27 | {A41EA7D5-9776-421B-A338-DD662287069B}.Release|x86.Build.0 = Release|Any CPU
28 | {5A5FF947-79DC-4352-94D5-EEC14065F93A}.Debug|x86.ActiveCfg = Debug|Any CPU
29 | {5A5FF947-79DC-4352-94D5-EEC14065F93A}.Debug|x86.Build.0 = Debug|Any CPU
30 | {5A5FF947-79DC-4352-94D5-EEC14065F93A}.Release|x86.ActiveCfg = Release|Any CPU
31 | {5A5FF947-79DC-4352-94D5-EEC14065F93A}.Release|x86.Build.0 = Release|Any CPU
32 | {BD335AFA-195D-4C2A-986A-167438C81976}.Debug|x86.ActiveCfg = Debug|Any CPU
33 | {BD335AFA-195D-4C2A-986A-167438C81976}.Debug|x86.Build.0 = Debug|Any CPU
34 | {BD335AFA-195D-4C2A-986A-167438C81976}.Release|x86.ActiveCfg = Release|Any CPU
35 | {BD335AFA-195D-4C2A-986A-167438C81976}.Release|x86.Build.0 = Release|Any CPU
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/Ched/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | False
29 |
30 |
31 | 120
32 |
33 |
34 | False
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Ched/Configuration/ApplicationSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Configuration;
7 |
8 | namespace Ched.Configuration
9 | {
10 | internal sealed class ApplicationSettings : SettingsBase
11 | {
12 | public static ApplicationSettings Default { get; } = (ApplicationSettings)Synchronized(new ApplicationSettings());
13 |
14 | private ApplicationSettings()
15 | {
16 | }
17 |
18 | [UserScopedSetting]
19 | [DefaultSettingValue("12")]
20 | public int UnitLaneWidth
21 | {
22 | get { return ((int)(this["UnitLaneWidth"])); }
23 | set { this["UnitLaneWidth"] = value; }
24 | }
25 |
26 | [UserScopedSetting]
27 | [DefaultSettingValue("120")]
28 | public int UnitBeatHeight
29 | {
30 | get { return ((int)(this["UnitBeatHeight"])); }
31 | set { this["UnitBeatHeight"] = value; }
32 | }
33 |
34 | [UserScopedSetting]
35 | [DefaultSettingValue("True")]
36 | public bool InsertAirWithAirAction
37 | {
38 | get { return ((bool)(this["InsertAirWithAirAction"])); }
39 | set { this["InsertAirWithAirAction"] = value; }
40 | }
41 |
42 | [UserScopedSetting]
43 | [DefaultSettingValue("False")]
44 | public bool IsPreviewAbortAtLastNote
45 | {
46 | get { return ((bool)(this["IsPreviewAbortAtLastNote"])); }
47 | set { this["IsPreviewAbortAtLastNote"] = value; }
48 | }
49 |
50 | [UserScopedSetting]
51 | [DefaultSettingValue("False")]
52 | public bool IsSlowDownPreviewEnabled
53 | {
54 | get => (bool)this["IsSlowDownPreviewEnabled"];
55 | set => this["IsSlowDownPreviewEnabled"] = value;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/Ched/Configuration/SettingsBase.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Configuration;
7 |
8 | namespace Ched.Configuration
9 | {
10 | internal interface IUpgradable
11 | {
12 | bool HasUpgraded { get; }
13 | }
14 |
15 | internal abstract class SettingsBase : ApplicationSettingsBase, IUpgradable
16 | {
17 | [UserScopedSetting]
18 | [DefaultSettingValue("False")]
19 | public bool HasUpgraded
20 | {
21 | get { return (bool)this["HasUpgraded"]; }
22 | private set { this["HasUpgraded"] = value; }
23 | }
24 |
25 | public override void Upgrade()
26 | {
27 | base.Upgrade();
28 | HasUpgraded = true;
29 | Save();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Ched/Configuration/SoundSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Configuration;
7 |
8 | using Ched.UI;
9 |
10 | namespace Ched.Configuration
11 | {
12 | internal sealed class SoundSettings : SettingsBase
13 | {
14 | public static SoundSettings Default { get; } = (SoundSettings)Synchronized(new SoundSettings());
15 |
16 | private SoundSettings()
17 | {
18 | }
19 |
20 | // ref: https://stackoverflow.com/a/12807699
21 | [UserScopedSetting]
22 | [SettingsSerializeAs(SettingsSerializeAs.Binary)]
23 | [DefaultSettingValue("")] // empty dictionary
24 | public Dictionary ScoreSound
25 | {
26 | get { return (Dictionary)this["ScoreSound"]; }
27 | set { this["ScoreSound"] = value; }
28 | }
29 |
30 | [UserScopedSetting]
31 | public SoundSource GuideSound
32 | {
33 | get => (SoundSource)this["GuideSound"] ?? new SoundSource("guide.mp3", 0.036);
34 | set => this["GuideSound"] = value;
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Ched/Localization/FileFilterStrings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Ched.Localization {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class FileFilterStrings {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal FileFilterStrings() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ched.Localization.FileFilterStrings", typeof(FileFilterStrings).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to 音声ファイル.
65 | ///
66 | public static string AudioFilter {
67 | get {
68 | return ResourceManager.GetString("AudioFilter", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to Ched専用形式.
74 | ///
75 | public static string ChedFilter {
76 | get {
77 | return ResourceManager.GetString("ChedFilter", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to 画像ファイル.
83 | ///
84 | public static string ImageFilter {
85 | get {
86 | return ResourceManager.GetString("ImageFilter", resourceCulture);
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Ched/Localization/MainFormStrings.en.Designer.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Localization/MainFormStrings.en.Designer.cs
--------------------------------------------------------------------------------
/Ched/Localization/PluginStrings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace Ched.Localization {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class PluginStrings {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal PluginStrings() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ched.Localization.PluginStrings", typeof(PluginStrings).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to コンボ計算.
65 | ///
66 | public static string ComboCalculator {
67 | get {
68 | return ResourceManager.GetString("ComboCalculator", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to スライド編み込み.
74 | ///
75 | public static string SlideKnitter {
76 | get {
77 | return ResourceManager.GetString("SlideKnitter", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to スライド結合.
83 | ///
84 | public static string SlideMerger {
85 | get {
86 | return ResourceManager.GetString("SlideMerger", resourceCulture);
87 | }
88 | }
89 |
90 | ///
91 | /// Looks up a localized string similar to スライド時間軸反転.
92 | ///
93 | public static string SlideReverser {
94 | get {
95 | return ResourceManager.GetString("SlideReverser", resourceCulture);
96 | }
97 | }
98 |
99 | ///
100 | /// Looks up a localized string similar to スライド分割.
101 | ///
102 | public static string SlideSplitter {
103 | get {
104 | return ResourceManager.GetString("SlideSplitter", resourceCulture);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/Ched/Localization/PluginStrings.en.Designer.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Localization/PluginStrings.en.Designer.cs
--------------------------------------------------------------------------------
/Ched/Plugins/ExportManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using Ched.Core;
9 |
10 | namespace Ched.Plugins
11 | {
12 | internal class ExportManager
13 | {
14 | private ExportContext LastUsedContext { get; set; }
15 | private Dictionary CustomDataCache { get; set; }
16 |
17 | public bool CanReExport => LastUsedContext != null;
18 |
19 | protected void Initialize()
20 | {
21 | LastUsedContext = null;
22 | CustomDataCache = null;
23 | }
24 |
25 | public void Load(ScoreBook book)
26 | {
27 | Initialize();
28 | CustomDataCache = book.ExportArgs;
29 | }
30 |
31 | public ExportContext PrepareExport(IScoreBookExportPlugin plugin, string dest)
32 | {
33 | return PrepareExport(plugin, dest, false);
34 | }
35 |
36 | public ExportContext PrepareReExport()
37 | {
38 | if (!CanReExport) throw new InvalidOperationException();
39 | return PrepareExport(LastUsedContext.ExportPlugin, LastUsedContext.OutputPath, true);
40 | }
41 |
42 | protected ExportContext PrepareExport(IScoreBookExportPlugin plugin, string dest, bool isQuick)
43 | {
44 | string name = ResolvePluginName(plugin);
45 | return new ExportContext(plugin, dest, isQuick, () => CustomDataCache.ContainsKey(name) ? CustomDataCache[name] : "", data => CustomDataCache[name] = data);
46 | }
47 |
48 | ///
49 | /// エクスポートが正常に完了したことをこのへ通知します。
50 | ///
51 | /// エクスポートを行った
52 | public void CommitExported(ExportContext context) => LastUsedContext = context;
53 |
54 | protected string ResolvePluginName(IScoreBookExportPlugin plugin) => plugin.GetType().FullName;
55 | }
56 |
57 | internal class ExportContext
58 | {
59 | public IScoreBookExportPlugin ExportPlugin { get; }
60 | protected bool IsQuick { get; }
61 | public string OutputPath { get; }
62 | protected readonly Func GetCustomData;
63 | protected readonly Action SetCustomData;
64 | public IReadOnlyCollection Diagnostics { get; private set; }
65 |
66 | public ExportContext(IScoreBookExportPlugin plugin, string dest, bool isQuick, Func getCustomData, Action setCustomData)
67 | {
68 | ExportPlugin = plugin;
69 | IsQuick = isQuick;
70 | OutputPath = dest;
71 | GetCustomData = getCustomData;
72 | SetCustomData = setCustomData;
73 | }
74 |
75 | public void Export(ScoreBook book)
76 | {
77 | using (var ms = new MemoryStream())
78 | {
79 | var args = new ScoreBookExportPluginArgs(book, ms, IsQuick, GetCustomData, SetCustomData);
80 | Diagnostics = args.Diagnostics;
81 | ExportPlugin.Export(args);
82 | using (var fs = new FileStream(OutputPath, FileMode.Create, FileAccess.Write))
83 | {
84 | var res = ms.ToArray();
85 | fs.Write(res, 0, res.Length);
86 | }
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Ched/Plugins/PluginManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.IO;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using System.ComponentModel.Composition;
9 | using System.ComponentModel.Composition.Hosting;
10 | using System.ComponentModel.Composition.Registration;
11 | using System.Reflection;
12 |
13 | namespace Ched.Plugins
14 | {
15 | public class PluginManager
16 | {
17 | internal static string PluginPath => "Plugins";
18 |
19 | [ImportMany]
20 | IEnumerable scorePlugins = Enumerable.Empty();
21 | [ImportMany]
22 | IEnumerable bookImportPlugins = Enumerable.Empty();
23 | [ImportMany]
24 | IEnumerable bookExportPlugins = Enumerable.Empty();
25 |
26 | public IReadOnlyCollection FailedFiles { get; private set; } = new List();
27 | public IReadOnlyCollection InvalidFiles { get; private set; } = new List();
28 |
29 | public IEnumerable ScorePlugins => scorePlugins;
30 | public IEnumerable ScoreBookImportPlugins => bookImportPlugins;
31 | public IEnumerable ScoreBookExportPlugins => bookExportPlugins;
32 |
33 | private PluginManager()
34 | {
35 | }
36 |
37 | public static PluginManager GetInstance()
38 | {
39 | var builder = new RegistrationBuilder();
40 | builder.ForTypesDerivedFrom().ExportInterfaces();
41 | builder.ForType().Export();
42 |
43 | var failedFiles = new List();
44 | var self = new AssemblyCatalog(typeof(PluginManager).Assembly, builder);
45 | var catalog = new AggregateCatalog(self);
46 |
47 | if (Directory.Exists(PluginPath))
48 | {
49 | foreach (string path in new DirectoryInfo(PluginPath).GetFiles().Select(p => p.FullName).Where(p => p.ToLower().EndsWith(".dll")))
50 | {
51 | try
52 | {
53 | var assembly = System.Reflection.Assembly.LoadFile(path);
54 | catalog.Catalogs.Add(new AssemblyCatalog(assembly, builder));
55 | }
56 | catch (Exception ex) when (ex is NotSupportedException || ex is BadImageFormatException)
57 | {
58 | failedFiles.Add(GetRelativePluginPath(path));
59 | }
60 | }
61 | }
62 |
63 | var container = new CompositionContainer(catalog);
64 | PluginManager manager = null;
65 | try
66 | {
67 | manager = container.GetExportedValue();
68 | }
69 | catch (ReflectionTypeLoadException ex) when (ex.LoaderExceptions.Any(p => p is TypeLoadException))
70 | {
71 | return new PluginManager()
72 | {
73 | FailedFiles = failedFiles,
74 | InvalidFiles = ex.Types.Where(p => p != null).Select(p => GetRelativePluginPath(p.Assembly.Location)).Distinct().ToList()
75 | };
76 | }
77 | manager.FailedFiles = failedFiles;
78 | return manager;
79 | }
80 |
81 | private static string GetRelativePluginPath(string path) => Uri.UnescapeDataString(new Uri(Path.GetFullPath(PluginPath)).MakeRelativeUri(new Uri(path)).ToString().Replace('/', Path.DirectorySeparatorChar));
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Ched/Plugins/ScoreBookExportPluginArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | using Ched.Core;
9 |
10 | namespace Ched.Plugins
11 | {
12 | public class ScoreBookExportPluginArgs : IScoreBookExportPluginArgs
13 | {
14 | private readonly List _diagnostics = new List();
15 | private ScoreBook ScoreBook { get; }
16 | private Func getCustomDataFunc { get; }
17 | private Action setCustomDataFunc { get; }
18 |
19 | public IReadOnlyCollection Diagnostics => _diagnostics;
20 | public Stream Stream { get; }
21 | public bool IsQuick { get; }
22 |
23 | public ScoreBookExportPluginArgs(ScoreBook scoreBook, Stream stream, bool isQuick, Func getCustomDataFunc, Action setCustomDataFunc)
24 | {
25 | ScoreBook = scoreBook;
26 | Stream = stream;
27 | IsQuick = isQuick;
28 | this.getCustomDataFunc = getCustomDataFunc;
29 | this.setCustomDataFunc = setCustomDataFunc;
30 | }
31 |
32 | public ScoreBook GetScoreBook() => ScoreBook.Clone();
33 |
34 | public string GetCustomData() => getCustomDataFunc();
35 |
36 | public void SetCustomData(string data) => setCustomDataFunc(data);
37 |
38 | public void ReportDiagnostic(Diagnostic diagnostic)
39 | {
40 | _diagnostics.Add(diagnostic);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Ched/Plugins/ScoreBookImportPluginArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace Ched.Plugins
9 | {
10 | public class ScoreBookImportPluginArgs : IScoreBookImportPluginArgs
11 | {
12 | private readonly List _diagnostics = new List();
13 | public IReadOnlyCollection Diagnostics => _diagnostics;
14 | public Stream Stream { get; }
15 |
16 | public ScoreBookImportPluginArgs(Stream stream)
17 | {
18 | Stream = stream;
19 | }
20 |
21 | public void ReportDiagnostic(Diagnostic diagnostic)
22 | {
23 | _diagnostics.Add(diagnostic);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Ched/Plugins/ScorePluginArgs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core;
8 | using Ched.Core.Events;
9 | using Ched.UI;
10 |
11 | namespace Ched.Plugins
12 | {
13 | public class ScorePluginArgs : IScorePluginArgs
14 | {
15 | private Func getScoreFunc;
16 | private SelectionRange selectedRange;
17 | private Action updateScoreAction;
18 |
19 | public ScorePluginArgs(Func getScoreFunc, SelectionRange selectedRange, Action updateScoreAction)
20 | {
21 | this.getScoreFunc = getScoreFunc;
22 | this.selectedRange = selectedRange;
23 | this.updateScoreAction = updateScoreAction;
24 | }
25 |
26 | public Score GetCurrentScore() => getScoreFunc();
27 |
28 | public SelectionRange GetSelectedRange() => selectedRange;
29 |
30 | public void UpdateScore(Score score)
31 | {
32 | CheckEventDuplicate(score.Events.BpmChangeEvents);
33 | CheckEventDuplicate(score.Events.TimeSignatureChangeEvents);
34 | CheckEventDuplicate(score.Events.HighSpeedChangeEvents);
35 | updateScoreAction(score);
36 | }
37 |
38 | private void CheckEventDuplicate(IList src) where T : EventBase
39 | {
40 | var set = new HashSet();
41 | if (src.All(p => set.Add(p.Tick))) return;
42 | throw new ArgumentException("There are some events in same ticks.");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Ched/Plugins/ShiftEvent.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | using Ched.Core;
9 | using Ched.Core.Events;
10 | using Ched.Localization;
11 | using Ched.UI;
12 |
13 | namespace Ched.Plugins
14 | {
15 | public class ShiftEvent : IScorePlugin
16 | {
17 | public string DisplayName => "イベント移動";
18 |
19 | public void Run(IScorePluginArgs args)
20 | {
21 | var form = new ShiftTimeSelectionForm();
22 | if (form.ShowDialog() != DialogResult.OK) return;
23 | if (form.CountValue == 0) return;
24 |
25 | var score = args.GetCurrentScore();
26 | int origin = args.GetSelectedRange().StartTick;
27 | BarIndexCalculator barIndexCalculator;
28 | try
29 | {
30 | barIndexCalculator = new BarIndexCalculator(score.TicksPerBeat, score.Events.TimeSignatureChangeEvents);
31 | }
32 | catch (InvalidTimeSignatureException ex)
33 | {
34 | int beatAt = ex.Tick / score.TicksPerBeat + 1;
35 | MessageBox.Show(string.Format(ErrorStrings.InvalidTimeSignature, beatAt), DisplayName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
36 | return;
37 | }
38 | var barIndex = barIndexCalculator.GetBarPositionFromTick(origin).BarIndex;
39 | var sig = barIndexCalculator.GetTimeSignatureFromBarIndex(barIndex);
40 | int offset = 4 * score.TicksPerBeat * form.CountValue * (form.DurationType == DurationType.Bar ? sig.Numerator : 1) / sig.Denominator;
41 |
42 | var (heading, targets) = Partition(score.Events.AllEvents.Where(p => p.Tick > 0), p => p.Tick <= origin);
43 | if (targets.Count == 0) return;
44 | int firstEventTick = targets.Min(p => p.Tick);
45 | int lowerLimitTick = heading.Count == 0 ? 0 : heading.Max(p => p.Tick);
46 |
47 | if (offset < 0 && firstEventTick + offset <= lowerLimitTick)
48 | {
49 | MessageBox.Show("移動対象のイベントが先行するイベントを追い越すため、移動は実行されません。", DisplayName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
50 | return;
51 | }
52 |
53 | foreach (var item in targets) item.Tick += offset;
54 |
55 | args.UpdateScore(score);
56 | }
57 |
58 | protected (IList, IList) Partition(IEnumerable collection, Func predicate)
59 | {
60 | var trueList = new List();
61 | var falseList = new List();
62 | foreach (var item in collection) (predicate(item) ? trueList : falseList).Add(item);
63 | return (trueList, falseList);
64 | }
65 |
66 | public enum DurationType
67 | {
68 | Bar,
69 | Beat
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/Ched/Plugins/SlideKnitter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Localization;
8 |
9 | namespace Ched.Plugins
10 | {
11 | public class SlideKnitter : IScorePlugin
12 | {
13 | public string DisplayName => PluginStrings.SlideKnitter;
14 |
15 | public void Run(IScorePluginArgs args)
16 | {
17 | var score = args.GetCurrentScore();
18 | var range = args.GetSelectedRange();
19 | var slides = score.Notes.Slides
20 | .Where(p => p.StartTick <= range.StartTick && p.StepNotes.OrderByDescending(q => q.Tick).First().Tick >= range.StartTick);
21 |
22 | foreach (var slide in slides.Where(p => p.StepNotes.Count == 3))
23 | {
24 | var steps = slide.StepNotes.OrderBy(p => p.TickOffset).ToList();
25 | // 始点と2つ目の中継点間の時間が等しいものが対象
26 | int initInterval = steps[0].TickOffset;
27 | if (initInterval * 2 != steps[1].TickOffset) continue;
28 |
29 | bool stepVisible = steps[0].IsVisible;
30 | int duration = steps[steps.Count - 1].TickOffset;
31 | int stepsCount = duration / initInterval;
32 | for (int i = 0; i < stepsCount - 2; i++)
33 | {
34 | int pos = initInterval * (i + 3);
35 | if (pos >= duration) break;
36 | var step = new Core.Notes.Slide.StepTap(slide)
37 | {
38 | TickOffset = pos,
39 | IsVisible = stepVisible
40 | };
41 | step.SetPosition(steps[i % 2].LaneIndexOffset, steps[i % 2].WidthChange);
42 | slide.StepNotes.Add(step);
43 | }
44 | }
45 |
46 | args.UpdateScore(score);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Ched/Plugins/SlideReverser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Notes;
8 | using Ched.Localization;
9 |
10 | namespace Ched.Plugins
11 | {
12 | public class SlideReverser : IScorePlugin
13 | {
14 | public string DisplayName => PluginStrings.SlideReverser;
15 |
16 | public void Run(IScorePluginArgs args)
17 | {
18 | var score = args.GetCurrentScore();
19 | var range = args.GetSelectedRange();
20 | int startTick = range.Duration < 0 ? range.StartTick + range.Duration : range.StartTick;
21 | int endTick = range.Duration < 0 ? range.StartTick : range.StartTick + range.Duration;
22 | var endStepDic = score.Notes.Slides.ToDictionary(p => p, p => p.StepNotes.OrderByDescending(q => q.TickOffset).First());
23 | var airStepDic = score.Notes.Airs
24 | .Where(p => endStepDic.Values.Contains(p.ParentNote))
25 | .ToDictionary(p => p.ParentNote as Slide.StepTap, p => p);
26 | var airActionStepDic = score.Notes.AirActions
27 | .Where(p => endStepDic.Values.Contains(p.ParentNote))
28 | .ToDictionary(p => p.ParentNote as Slide.StepTap, p => p);
29 |
30 | var targets = score.Notes.Slides
31 | .Where(p => p.StartTick >= startTick && p.StartTick + p.GetDuration() <= endTick)
32 | .Where(p => p.StartLaneIndex >= range.StartLaneIndex && p.StartLaneIndex + p.StartWidth <= range.StartLaneIndex + range.SelectedLanesCount)
33 | .Where(p => p.StepNotes.All(q => q.LaneIndex >= range.StartLaneIndex && q.LaneIndex + q.Width <= range.StartLaneIndex + range.SelectedLanesCount))
34 | .Where(p => !airStepDic.ContainsKey(endStepDic[p]) && !airActionStepDic.ContainsKey(endStepDic[p]))
35 | .ToList();
36 | if (targets.Count == 0) return;
37 | var results = targets.Select(p =>
38 | {
39 | var ordered = p.StepNotes.OrderByDescending(q => q.TickOffset).ToList();
40 | var res = new Slide() { StartTick = startTick + (endTick - ordered[0].Tick) };
41 | res.SetPosition(ordered[0].LaneIndex, ordered[0].Width);
42 | var trailing = new Slide.StepTap(res) { IsVisible = true, TickOffset = startTick + (endTick - p.StartTick) - res.StartTick };
43 | trailing.SetPosition(p.StartLaneIndex - res.StartLaneIndex, p.StartWidth - res.StartWidth);
44 | var steps = ordered.Skip(1).Select(q =>
45 | {
46 | var step = new Slide.StepTap(res) { IsVisible = q.IsVisible, TickOffset = startTick + (endTick - q.Tick) - res.StartTick };
47 | step.SetPosition(q.LaneIndex - res.StartLaneIndex, q.Width - res.StartWidth);
48 | return step;
49 | })
50 | .Concat(new[] { trailing });
51 | res.StepNotes.AddRange(steps);
52 | return res;
53 | });
54 |
55 | foreach (var slide in targets) score.Notes.Slides.Remove(slide);
56 | score.Notes.Slides.AddRange(results);
57 | args.UpdateScore(score);
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Ched/Plugins/SlideSplitter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Notes;
8 | using Ched.Localization;
9 |
10 | namespace Ched.Plugins
11 | {
12 | public class SlideSplitter : IScorePlugin
13 | {
14 | public string DisplayName => PluginStrings.SlideSplitter;
15 |
16 | public void Run(IScorePluginArgs args)
17 | {
18 | var score = args.GetCurrentScore();
19 | var range = args.GetSelectedRange();
20 | bool modified = false;
21 | var targets = score.Notes.Slides.Where(p => p.StartTick < range.StartTick && p.StepNotes.OrderByDescending(q => q.TickOffset).First().Tick > range.StartTick);
22 | var endStepDic = score.Notes.Slides.ToDictionary(p => p, p => p.StepNotes.OrderByDescending(q => q.TickOffset).First());
23 | var airStepDic = score.Notes.Airs
24 | .Where(p => endStepDic.Values.Contains(p.ParentNote))
25 | .ToDictionary(p => p.ParentNote as Slide.StepTap, p => p);
26 | var airActionStepDic = score.Notes.AirActions
27 | .Where(p => endStepDic.Values.Contains(p.ParentNote))
28 | .ToDictionary(p => p.ParentNote as Slide.StepTap, p => p);
29 |
30 | foreach (var slide in targets.ToList())
31 | {
32 | // カーソル位置に中継点が存在しなければ処理しない
33 | int offset = range.StartTick - slide.StartTick;
34 | if (slide.StepNotes.All(p => p.TickOffset != offset)) continue;
35 |
36 | var first = new Slide() { StartTick = slide.StartTick };
37 | first.SetPosition(slide.StartLaneIndex, slide.StartWidth);
38 | first.StepNotes.AddRange(slide.StepNotes.OrderBy(p => p.TickOffset).TakeWhile(p => p.TickOffset <= offset).Select(p =>
39 | {
40 | var step = new Slide.StepTap(first) { TickOffset = p.TickOffset, IsVisible = p.IsVisible };
41 | step.SetPosition(p.LaneIndexOffset, p.WidthChange);
42 | return step;
43 | }));
44 | first.StepNotes[first.StepNotes.Count - 1].IsVisible = true;
45 |
46 | var second = new Slide() { StartTick = range.StartTick };
47 | var trailing = slide.StepNotes.OrderBy(p => p.TickOffset).SkipWhile(p => p.TickOffset < offset).ToList();
48 | second.SetPosition(trailing[0].LaneIndex, trailing[0].Width);
49 | second.StepNotes.AddRange(trailing.Skip(1).Select(p =>
50 | {
51 | var step = new Slide.StepTap(second) { TickOffset = p.TickOffset - offset, IsVisible = p.IsVisible };
52 | step.SetPosition(p.LaneIndex - second.StartLaneIndex, p.Width - second.StartWidth);
53 | return step;
54 | }));
55 |
56 | // 終点AIRをsecondに挿入
57 | if (airStepDic.ContainsKey(endStepDic[slide]))
58 | {
59 | var origAir = airStepDic[endStepDic[slide]];
60 | var air = new Air(second.StepNotes[second.StepNotes.Count - 1])
61 | {
62 | VerticalDirection = origAir.VerticalDirection,
63 | HorizontalDirection = origAir.HorizontalDirection
64 | };
65 | score.Notes.Airs.Remove(origAir);
66 | score.Notes.Airs.Add(air);
67 | }
68 | if (airActionStepDic.ContainsKey(endStepDic[slide]))
69 | {
70 | var origAirAction = airActionStepDic[endStepDic[slide]];
71 | var airAction = new AirAction(second.StepNotes[second.StepNotes.Count - 1]);
72 | airAction.ActionNotes.AddRange(origAirAction.ActionNotes.Select(p => new AirAction.ActionNote(airAction) { Offset = p.Offset }));
73 | score.Notes.AirActions.Remove(origAirAction);
74 | score.Notes.AirActions.Add(airAction);
75 | }
76 |
77 | score.Notes.Slides.Add(first);
78 | score.Notes.Slides.Add(second);
79 | score.Notes.Slides.Remove(slide);
80 | modified = true;
81 | }
82 | if (modified) args.UpdateScore(score);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/Ched/Plugins/SusExportPlugin.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | using Newtonsoft.Json;
9 | using Ched.Components.Exporter;
10 | using Ched.UI.Windows;
11 |
12 | namespace Ched.Plugins
13 | {
14 | public class SusExportPlugin : IScoreBookExportPlugin
15 | {
16 | public string DisplayName => "Sliding Universal Score (*.sus)";
17 |
18 | public string FileFilter => "Sliding Universal Score (*.sus)|*.sus";
19 |
20 | public void Export(IScoreBookExportPluginArgs args)
21 | {
22 | var book = args.GetScoreBook();
23 | SusArgs susArgs = JsonConvert.DeserializeObject(args.GetCustomData() ?? "") ?? new SusArgs();
24 | if (!args.IsQuick)
25 | {
26 | var vm = new SusExportWindowViewModel(book, susArgs);
27 | var window = new SusExportWindow() { DataContext = vm };
28 | var result = window.ShowDialog();
29 | if (!result.HasValue || !result.Value) throw new UserCancelledException();
30 | args.SetCustomData(JsonConvert.SerializeObject(susArgs));
31 | }
32 |
33 | var exporter = new SusExporter(book, susArgs);
34 | exporter.Export(args.Stream);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Ched/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.IO;
5 | using System.Reflection;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 |
9 | using Ched.Configuration;
10 |
11 | namespace Ched
12 | {
13 | static class Program
14 | {
15 | internal static readonly string ApplicationName = System.Reflection.Assembly.GetEntryAssembly().GetName().Name;
16 |
17 | ///
18 | /// The main entry point for the application.
19 | ///
20 | [STAThread]
21 | static void Main(string[] args)
22 | {
23 | Directory.SetCurrentDirectory(Path.GetDirectoryName(Application.ExecutablePath));
24 |
25 | #if !DEBUG
26 | Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
27 | AppDomain.CurrentDomain.UnhandledException += (s, e) => DumpException((Exception)e.ExceptionObject, true);
28 | #endif
29 |
30 | AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
31 | {
32 | string path = Path.Combine(Plugins.PluginManager.PluginPath, new AssemblyName(e.Name).Name + ".dll");
33 | return File.Exists(path) ? Assembly.LoadFrom(path) : null;
34 | };
35 |
36 | UpgradeConfiguration(ApplicationSettings.Default);
37 | UpgradeConfiguration(SoundSettings.Default);
38 |
39 | Application.EnableVisualStyles();
40 | Application.SetCompatibleTextRenderingDefault(false);
41 | Application.Run(args.Length == 0 ? new UI.MainForm() : new UI.MainForm(args[0]));
42 | }
43 |
44 | public static void DumpExceptionTo(Exception ex, string filename)
45 | {
46 | try
47 | {
48 | File.WriteAllText(filename, Newtonsoft.Json.JsonConvert.SerializeObject(ex));
49 | }
50 | catch (UnauthorizedAccessException)
51 | {
52 | }
53 | }
54 |
55 | public static void DumpException(Exception ex)
56 | {
57 | DumpException(ex, false);
58 | }
59 |
60 | public static void DumpException(Exception ex, bool forceClose)
61 | {
62 | DumpExceptionTo(ex, "exception.json");
63 | if (!forceClose) return;
64 | try
65 | {
66 | MessageBox.Show("エラーが発生しました。\nアプリケーションを終了します。", ApplicationName, MessageBoxButtons.OK, MessageBoxIcon.Error);
67 | }
68 | finally
69 | {
70 | Environment.Exit(1);
71 | }
72 | }
73 |
74 | private static bool UpgradeConfiguration(SettingsBase setting)
75 | {
76 | try
77 | {
78 | if (!setting.HasUpgraded) setting.Upgrade();
79 | }
80 | catch (Exception ex)
81 | {
82 | DumpExceptionTo(ex, "configuration_exeption.json");
83 | setting.Reset();
84 | return false;
85 | }
86 | return true;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Ched/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 | using System.Windows.Media;
5 |
6 | [assembly: AssemblyTitle("Ched")]
7 | [assembly: AssemblyDescription("Yet Another Chart Editor")]
8 | [assembly: AssemblyCompany("paltee.net")]
9 | [assembly: AssemblyProduct("Ched")]
10 | [assembly: AssemblyCopyright("Copyright (C) 2017 Paralleltree")]
11 |
12 | [assembly: ComVisible(false)]
13 | [assembly: Guid("4c0c9f98-6fcf-4d2f-b821-37a66362dc75")]
14 |
15 | [assembly: AssemblyVersion("3.2.0.0")]
16 |
17 | [assembly: DisableDpiAwareness]
18 |
--------------------------------------------------------------------------------
/Ched/Resources/airaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airaction.png
--------------------------------------------------------------------------------
/Ched/Resources/airdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airdown.png
--------------------------------------------------------------------------------
/Ched/Resources/airleftdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airleftdown.png
--------------------------------------------------------------------------------
/Ched/Resources/airleftup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airleftup.png
--------------------------------------------------------------------------------
/Ched/Resources/airrightdown.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airrightdown.png
--------------------------------------------------------------------------------
/Ched/Resources/airrightup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airrightup.png
--------------------------------------------------------------------------------
/Ched/Resources/airup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/airup.png
--------------------------------------------------------------------------------
/Ched/Resources/arrow-curve-180-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/arrow-curve-180-left.png
--------------------------------------------------------------------------------
/Ched/Resources/arrow-curve.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/arrow-curve.png
--------------------------------------------------------------------------------
/Ched/Resources/blue-document-export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/blue-document-export.png
--------------------------------------------------------------------------------
/Ched/Resources/clipboard-paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/clipboard-paste.png
--------------------------------------------------------------------------------
/Ched/Resources/cross-circle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/cross-circle.png
--------------------------------------------------------------------------------
/Ched/Resources/damage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/damage.png
--------------------------------------------------------------------------------
/Ched/Resources/disk-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/disk-black.png
--------------------------------------------------------------------------------
/Ched/Resources/document--plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/document--plus.png
--------------------------------------------------------------------------------
/Ched/Resources/document-copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/document-copy.png
--------------------------------------------------------------------------------
/Ched/Resources/eraser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/eraser.png
--------------------------------------------------------------------------------
/Ched/Resources/exclamation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/exclamation.png
--------------------------------------------------------------------------------
/Ched/Resources/extap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/extap.png
--------------------------------------------------------------------------------
/Ched/Resources/flick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/flick.png
--------------------------------------------------------------------------------
/Ched/Resources/folder-horizontal-open.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/folder-horizontal-open.png
--------------------------------------------------------------------------------
/Ched/Resources/guide.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/guide.mp3
--------------------------------------------------------------------------------
/Ched/Resources/hold.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/hold.png
--------------------------------------------------------------------------------
/Ched/Resources/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/icon.ico
--------------------------------------------------------------------------------
/Ched/Resources/information.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/information.png
--------------------------------------------------------------------------------
/Ched/Resources/magnifier-zoom-in.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/magnifier-zoom-in.png
--------------------------------------------------------------------------------
/Ched/Resources/magnifier-zoom-out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/magnifier-zoom-out.png
--------------------------------------------------------------------------------
/Ched/Resources/pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/pencil.png
--------------------------------------------------------------------------------
/Ched/Resources/scissors-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/scissors-blue.png
--------------------------------------------------------------------------------
/Ched/Resources/selection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/selection.png
--------------------------------------------------------------------------------
/Ched/Resources/slide.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/slide.png
--------------------------------------------------------------------------------
/Ched/Resources/slidestep.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/slidestep.png
--------------------------------------------------------------------------------
/Ched/Resources/tap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paralleltree/Ched/fa880077e9e82fa87e03f20f398daf2303f29a81/Ched/Resources/tap.png
--------------------------------------------------------------------------------
/Ched/UI/BpmSelectionForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class BpmSelectionForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(BpmSelectionForm));
32 | this.buttonOK = new System.Windows.Forms.Button();
33 | this.buttonCancel = new System.Windows.Forms.Button();
34 | this.bpmBox = new System.Windows.Forms.NumericUpDown();
35 | this.label1 = new System.Windows.Forms.Label();
36 | ((System.ComponentModel.ISupportInitialize)(this.bpmBox)).BeginInit();
37 | this.SuspendLayout();
38 | //
39 | // buttonOK
40 | //
41 | resources.ApplyResources(this.buttonOK, "buttonOK");
42 | this.buttonOK.Name = "buttonOK";
43 | this.buttonOK.UseVisualStyleBackColor = true;
44 | //
45 | // buttonCancel
46 | //
47 | resources.ApplyResources(this.buttonCancel, "buttonCancel");
48 | this.buttonCancel.Name = "buttonCancel";
49 | this.buttonCancel.UseVisualStyleBackColor = true;
50 | //
51 | // bpmBox
52 | //
53 | resources.ApplyResources(this.bpmBox, "bpmBox");
54 | this.bpmBox.Name = "bpmBox";
55 | //
56 | // label1
57 | //
58 | resources.ApplyResources(this.label1, "label1");
59 | this.label1.Name = "label1";
60 | //
61 | // BpmSelectionForm
62 | //
63 | resources.ApplyResources(this, "$this");
64 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
65 | this.Controls.Add(this.label1);
66 | this.Controls.Add(this.bpmBox);
67 | this.Controls.Add(this.buttonCancel);
68 | this.Controls.Add(this.buttonOK);
69 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
70 | this.MaximizeBox = false;
71 | this.MinimizeBox = false;
72 | this.Name = "BpmSelectionForm";
73 | ((System.ComponentModel.ISupportInitialize)(this.bpmBox)).EndInit();
74 | this.ResumeLayout(false);
75 | this.PerformLayout();
76 |
77 | }
78 |
79 | #endregion
80 |
81 | private System.Windows.Forms.Button buttonOK;
82 | private System.Windows.Forms.Button buttonCancel;
83 | private System.Windows.Forms.NumericUpDown bpmBox;
84 | private System.Windows.Forms.Label label1;
85 | }
86 | }
--------------------------------------------------------------------------------
/Ched/UI/BpmSelectionForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Ched.UI
12 | {
13 | public partial class BpmSelectionForm : Form
14 | {
15 | public double Bpm
16 | {
17 | get => (double)bpmBox.Value;
18 | set
19 | {
20 | bpmBox.Value = (decimal)value;
21 | bpmBox.SelectAll();
22 | }
23 | }
24 |
25 | public BpmSelectionForm()
26 | {
27 | InitializeComponent();
28 | AcceptButton = buttonOK;
29 | CancelButton = buttonCancel;
30 | buttonOK.DialogResult = DialogResult.OK;
31 | buttonCancel.DialogResult = DialogResult.Cancel;
32 |
33 | bpmBox.DecimalPlaces = 0;
34 | bpmBox.Increment = 1;
35 | bpmBox.Maximum = 10000;
36 | bpmBox.Minimum = 10;
37 | bpmBox.Value = 120;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ched/UI/CheckableToolStripSplitButton.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using System.Windows.Forms.VisualStyles;
8 |
9 | namespace Ched.UI
10 | {
11 | // https://arstechnica.com/civis/viewtopic.php?f=20&t=311656
12 | public class CheckableToolStripSplitButton : ToolStripSplitButton
13 | {
14 | private bool _Checked = false;
15 | private VisualStyleRenderer renderer = null;
16 | private readonly VisualStyleElement element = VisualStyleElement.ToolBar.Button.Checked;
17 |
18 | public CheckableToolStripSplitButton()
19 | {
20 | if (Application.RenderWithVisualStyles && VisualStyleRenderer.IsElementDefined(element))
21 | {
22 | renderer = new VisualStyleRenderer(element);
23 | }
24 | }
25 |
26 | public bool Checked
27 | {
28 | get
29 | {
30 | return _Checked;
31 | }
32 | set
33 | {
34 | _Checked = value;
35 | this.Invalidate();
36 | }
37 | }
38 |
39 | protected override void OnPaint(PaintEventArgs e)
40 | {
41 | if (_Checked)
42 | {
43 | if (renderer != null)
44 | {
45 | System.Drawing.Rectangle cr = base.ContentRectangle;
46 | System.Drawing.Image img = this.Image;
47 |
48 | // Compute the center of the item's ContentRectangle.
49 | int centerY = (cr.Height - img.Height) / 2;
50 | System.Drawing.Rectangle fullRect = new System.Drawing.Rectangle(0, 0, this.Width, this.Height);
51 |
52 | System.Drawing.Rectangle imageRect = new System.Drawing.Rectangle(
53 | base.ContentRectangle.Left,
54 | centerY,
55 | base.Image.Width,
56 | base.Image.Height);
57 |
58 | System.Drawing.Rectangle textRect = new System.Drawing.Rectangle(
59 | imageRect.Width,
60 | base.ContentRectangle.Top,
61 | base.ContentRectangle.Width - (imageRect.Width + 10),
62 | base.ContentRectangle.Height);
63 |
64 | renderer.DrawBackground(e.Graphics, fullRect);
65 | //renderer.DrawText(e.Graphics, textRect, this.Text);
66 | //renderer.DrawImage(e.Graphics, imageRect, this.Image);
67 | base.OnPaint(e);
68 | }
69 | else
70 | {
71 | e.Graphics.FillRectangle(System.Drawing.SystemBrushes.Control, 0, 0, this.Width, this.Height);
72 | e.Graphics.DrawRectangle(new System.Drawing.Pen(System.Drawing.SystemColors.Highlight), 0, 0, this.Width - 1, this.Height - 1);
73 | base.OnPaint(e);
74 | }
75 | }
76 | else
77 | {
78 | base.OnPaint(e);
79 | }
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/Ched/UI/ControlExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using System.Reactive.Linq;
8 |
9 | namespace Ched.UI
10 | {
11 | internal static class ControlExtensions
12 | {
13 | public static LayoutManager WorkWithLayout(this Control control)
14 | {
15 | return new LayoutManager(control);
16 | }
17 |
18 | public static void InvokeIfRequired(this Control control, Action action)
19 | {
20 | if (control.InvokeRequired) control.Invoke((MethodInvoker)(() => action()));
21 | else action();
22 | }
23 |
24 | public static IObservable MouseDownAsObservable(this Control control)
25 | {
26 | return Observable.FromEvent(
27 | h => (o, e) => h(e),
28 | h => control.MouseDown += h,
29 | h => control.MouseDown -= h);
30 | }
31 |
32 | public static IObservable MouseMoveAsObservable(this Control control)
33 | {
34 | return Observable.FromEvent(
35 | h => (o, e) => h(e),
36 | h => control.MouseMove += h,
37 | h => control.MouseMove -= h);
38 | }
39 |
40 | public static IObservable MouseUpAsObservable(this Control control)
41 | {
42 | return Observable.FromEvent(
43 | h => (o, e) => h(e),
44 | h => control.MouseUp += h,
45 | h => control.MouseUp -= h);
46 | }
47 |
48 | public static int GetMaximumValue(this ScrollBar scrollbar)
49 | {
50 | return scrollbar.Maximum - scrollbar.LargeChange + 1;
51 | }
52 |
53 | public static void SelectAll(this NumericUpDown control)
54 | {
55 | control.Select(0, control.Text.Length);
56 | }
57 | }
58 |
59 | internal class LayoutManager : IDisposable
60 | {
61 | protected Control _control;
62 |
63 | public LayoutManager(Control control)
64 | {
65 | control.SuspendLayout();
66 | _control = control;
67 | }
68 |
69 | public void Dispose()
70 | {
71 | _control.ResumeLayout(false);
72 | _control.PerformLayout();
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/Ched/UI/CustomQuantizeSelectionForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class CustomQuantizeSelectionForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CustomQuantizeSelectionForm));
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.label2 = new System.Windows.Forms.Label();
34 | this.noteLengthBox = new System.Windows.Forms.ComboBox();
35 | this.noteDivisionBox = new System.Windows.Forms.NumericUpDown();
36 | this.buttonOK = new System.Windows.Forms.Button();
37 | this.buttonCancel = new System.Windows.Forms.Button();
38 | ((System.ComponentModel.ISupportInitialize)(this.noteDivisionBox)).BeginInit();
39 | this.SuspendLayout();
40 | //
41 | // label1
42 | //
43 | resources.ApplyResources(this.label1, "label1");
44 | this.label1.Name = "label1";
45 | //
46 | // label2
47 | //
48 | resources.ApplyResources(this.label2, "label2");
49 | this.label2.Name = "label2";
50 | //
51 | // noteLengthBox
52 | //
53 | this.noteLengthBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
54 | this.noteLengthBox.FormattingEnabled = true;
55 | resources.ApplyResources(this.noteLengthBox, "noteLengthBox");
56 | this.noteLengthBox.Name = "noteLengthBox";
57 | //
58 | // noteDivisionBox
59 | //
60 | resources.ApplyResources(this.noteDivisionBox, "noteDivisionBox");
61 | this.noteDivisionBox.Name = "noteDivisionBox";
62 | //
63 | // buttonOK
64 | //
65 | resources.ApplyResources(this.buttonOK, "buttonOK");
66 | this.buttonOK.Name = "buttonOK";
67 | this.buttonOK.UseVisualStyleBackColor = true;
68 | //
69 | // buttonCancel
70 | //
71 | resources.ApplyResources(this.buttonCancel, "buttonCancel");
72 | this.buttonCancel.Name = "buttonCancel";
73 | this.buttonCancel.UseVisualStyleBackColor = true;
74 | //
75 | // CustomQuantizeSelectionForm
76 | //
77 | resources.ApplyResources(this, "$this");
78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
79 | this.Controls.Add(this.buttonCancel);
80 | this.Controls.Add(this.buttonOK);
81 | this.Controls.Add(this.noteDivisionBox);
82 | this.Controls.Add(this.noteLengthBox);
83 | this.Controls.Add(this.label2);
84 | this.Controls.Add(this.label1);
85 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
86 | this.MaximizeBox = false;
87 | this.MinimizeBox = false;
88 | this.Name = "CustomQuantizeSelectionForm";
89 | ((System.ComponentModel.ISupportInitialize)(this.noteDivisionBox)).EndInit();
90 | this.ResumeLayout(false);
91 | this.PerformLayout();
92 |
93 | }
94 |
95 | #endregion
96 |
97 | private System.Windows.Forms.Label label1;
98 | private System.Windows.Forms.Label label2;
99 | private System.Windows.Forms.ComboBox noteLengthBox;
100 | private System.Windows.Forms.NumericUpDown noteDivisionBox;
101 | private System.Windows.Forms.Button buttonOK;
102 | private System.Windows.Forms.Button buttonCancel;
103 | }
104 | }
--------------------------------------------------------------------------------
/Ched/UI/CustomQuantizeSelectionForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Ched.UI
12 | {
13 | public partial class CustomQuantizeSelectionForm : Form
14 | {
15 | private int BarTick { get; }
16 |
17 | public double QuantizeTick
18 | {
19 | get
20 | {
21 | return Math.Max(BarTick / Math.Pow(2, noteLengthBox.SelectedIndex) / (int)noteDivisionBox.Value, 1);
22 | }
23 | }
24 |
25 | public CustomQuantizeSelectionForm(int barTick)
26 | {
27 | InitializeComponent();
28 | AcceptButton = buttonOK;
29 | CancelButton = buttonCancel;
30 | buttonOK.DialogResult = DialogResult.OK;
31 | buttonCancel.DialogResult = DialogResult.Cancel;
32 |
33 | BarTick = barTick;
34 |
35 | noteLengthBox.Items.AddRange(Enumerable.Range(0, 7).Select(p => ((int)Math.Pow(2, p)).ToString()).ToArray());
36 | noteLengthBox.SelectedIndex = 2;
37 |
38 | noteDivisionBox.Minimum = 1;
39 | noteDivisionBox.Maximum = 30;
40 | noteDivisionBox.Value = 1;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Ched/UI/GraphicsExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Drawing;
7 | using System.Runtime.InteropServices;
8 |
9 | namespace Ched.UI
10 | {
11 | internal static class GraphicsExtensions
12 | {
13 | [DllImport("gdi32.dll")]
14 | private static extern int SetROP2(IntPtr hdc, int enDrawMode);
15 |
16 | [DllImport("gdi32.dll")]
17 | private static extern IntPtr CreatePen(PenStyles enPenStyle, int nWidth, int crColor);
18 |
19 | [DllImport("gdi32.dll")]
20 | private static extern bool DeleteObject(IntPtr hObject);
21 |
22 | [DllImport("gdi32.dll")]
23 | private static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);
24 |
25 | [DllImport("gdi32.dll")]
26 | private static extern bool Rectangle(IntPtr hdc, int x1, int y1, int x2, int y2);
27 |
28 | [DllImport("gdi32.dll")]
29 | private static extern IntPtr GetStockObject(int brStyle);
30 |
31 | private const int NULL_BRUSH = 5;
32 | private const int BLACK_PEN = 0;
33 | private const int R2_XORPEN = 7;
34 |
35 | // ref: https://www.codeproject.com/Articles/4958/Combining-GDI-and-GDI-to-Draw-Rubber-Band-Rectangl
36 | public static void DrawXorRectangle(this Graphics g, PenStyles style, int x1, int y1, int x2, int y2)
37 | {
38 | IntPtr hdc = g.GetHdc();
39 | IntPtr pen = CreatePen(style, 1, BLACK_PEN);
40 |
41 | SetROP2(hdc, R2_XORPEN);
42 |
43 | IntPtr oldPen = SelectObject(hdc, pen);
44 | IntPtr oldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
45 |
46 | Rectangle(hdc, x1, y1, x2, y2);
47 |
48 | SelectObject(hdc, oldBrush);
49 | SelectObject(hdc, oldPen);
50 | DeleteObject(pen);
51 |
52 | g.ReleaseHdc(hdc);
53 | }
54 |
55 | public static void DrawXorRectangle(this Graphics g, PenStyles style, Point start, Point end)
56 | {
57 | g.DrawXorRectangle(style, start.X, start.Y, end.X, end.Y);
58 | }
59 | }
60 |
61 | internal enum PenStyles
62 | {
63 | Solid = 0,
64 | Dash = 1,
65 | Dot = 2,
66 | DashDot = 3,
67 | DashDotDot = 4
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Ched/UI/Helpers.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.UI
8 | {
9 | public static class Helpers
10 | {
11 | public static string GetFilterString(string kind, IEnumerable extensions)
12 | {
13 | var wildcards = extensions.Select(p => "*" + p);
14 | return kind + string.Format("({0})|{1}", string.Join(", ", wildcards), string.Join(";", wildcards));
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Ched/UI/HighSpeedSelectionForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class HighSpeedSelectionForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(HighSpeedSelectionForm));
32 | this.label1 = new System.Windows.Forms.Label();
33 | this.speedRatioBox = new System.Windows.Forms.NumericUpDown();
34 | this.buttonOK = new System.Windows.Forms.Button();
35 | this.buttonCancel = new System.Windows.Forms.Button();
36 | ((System.ComponentModel.ISupportInitialize)(this.speedRatioBox)).BeginInit();
37 | this.SuspendLayout();
38 | //
39 | // label1
40 | //
41 | resources.ApplyResources(this.label1, "label1");
42 | this.label1.Name = "label1";
43 | //
44 | // speedRatioBox
45 | //
46 | resources.ApplyResources(this.speedRatioBox, "speedRatioBox");
47 | this.speedRatioBox.Name = "speedRatioBox";
48 | //
49 | // buttonOK
50 | //
51 | resources.ApplyResources(this.buttonOK, "buttonOK");
52 | this.buttonOK.Name = "buttonOK";
53 | this.buttonOK.UseVisualStyleBackColor = true;
54 | //
55 | // buttonCancel
56 | //
57 | resources.ApplyResources(this.buttonCancel, "buttonCancel");
58 | this.buttonCancel.Name = "buttonCancel";
59 | this.buttonCancel.UseVisualStyleBackColor = true;
60 | //
61 | // HighSpeedSelectionForm
62 | //
63 | resources.ApplyResources(this, "$this");
64 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
65 | this.Controls.Add(this.buttonCancel);
66 | this.Controls.Add(this.buttonOK);
67 | this.Controls.Add(this.speedRatioBox);
68 | this.Controls.Add(this.label1);
69 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
70 | this.MaximizeBox = false;
71 | this.MinimizeBox = false;
72 | this.Name = "HighSpeedSelectionForm";
73 | ((System.ComponentModel.ISupportInitialize)(this.speedRatioBox)).EndInit();
74 | this.ResumeLayout(false);
75 | this.PerformLayout();
76 |
77 | }
78 |
79 | #endregion
80 |
81 | private System.Windows.Forms.Label label1;
82 | private System.Windows.Forms.NumericUpDown speedRatioBox;
83 | private System.Windows.Forms.Button buttonOK;
84 | private System.Windows.Forms.Button buttonCancel;
85 | }
86 | }
--------------------------------------------------------------------------------
/Ched/UI/HighSpeedSelectionForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Ched.UI
12 | {
13 | public partial class HighSpeedSelectionForm : Form
14 | {
15 | public decimal SpeedRatio
16 | {
17 | get { return speedRatioBox.Value; }
18 | set
19 | {
20 | speedRatioBox.Value = value;
21 | speedRatioBox.SelectAll();
22 | }
23 | }
24 |
25 | public HighSpeedSelectionForm()
26 | {
27 | InitializeComponent();
28 | AcceptButton = buttonOK;
29 | CancelButton = buttonCancel;
30 | buttonOK.DialogResult = DialogResult.OK;
31 | buttonCancel.DialogResult = DialogResult.Cancel;
32 |
33 | speedRatioBox.Minimum = -10000m;
34 | speedRatioBox.Maximum = 10000m;
35 | speedRatioBox.Increment = 0.01m;
36 | speedRatioBox.DecimalPlaces = 2;
37 | speedRatioBox.Value = 1;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Ched/UI/MainForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class MainForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing)
17 | {
18 | if (components != null) components.Dispose();
19 |
20 | PreviewManager.Dispose();
21 | base.Dispose(disposing);
22 | }
23 | }
24 |
25 | #region Windows Form Designer generated code
26 |
27 | ///
28 | /// Required method for Designer support - do not modify
29 | /// the contents of this method with the code editor.
30 | ///
31 | private void InitializeComponent()
32 | {
33 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
34 | this.SuspendLayout();
35 | //
36 | // MainForm
37 | //
38 | resources.ApplyResources(this, "$this");
39 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
40 | this.Name = "MainForm";
41 | this.ResumeLayout(false);
42 |
43 | }
44 |
45 | #endregion
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/Ched/UI/NoteView.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class NoteView
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing)
17 | {
18 | if (components != null)
19 | {
20 | components.Dispose();
21 | }
22 |
23 | Subscriptions.Dispose();
24 | }
25 | base.Dispose(disposing);
26 | }
27 |
28 | #region Component Designer generated code
29 |
30 | ///
31 | /// Required method for Designer support - do not modify
32 | /// the contents of this method with the code editor.
33 | ///
34 | private void InitializeComponent()
35 | {
36 | components = new System.ComponentModel.Container();
37 | }
38 |
39 | #endregion
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Ched/UI/Operations/CompositeOperation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.UI.Operations
8 | {
9 | ///
10 | /// 複数のからなる1つの操作を表します。
11 | ///
12 | public class CompositeOperation : IOperation
13 | {
14 | public string Description { get; }
15 |
16 | protected IEnumerable Operations { get; }
17 |
18 | ///
19 | /// 操作の説明とからこのを初期化します。
20 | ///
21 | /// この操作の説明
22 | /// 操作順にソートされた
23 | public CompositeOperation(string description, IEnumerable operations)
24 | {
25 | Description = description;
26 | Operations = operations;
27 | }
28 |
29 | public void Redo()
30 | {
31 | foreach (var op in Operations) op.Redo();
32 | }
33 |
34 | public void Undo()
35 | {
36 | foreach (var op in Operations.Reverse()) op.Undo();
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Ched/UI/Operations/EventCollectionOperation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core.Events;
8 |
9 | namespace Ched.UI.Operations
10 | {
11 | public abstract class EventCollectionOperation : IOperation where T : EventBase
12 | {
13 | protected T Event { get; }
14 | protected List Collection { get; }
15 | public abstract string Description { get; }
16 |
17 | public EventCollectionOperation(List collection, T item)
18 | {
19 | Collection = collection;
20 | Event = item;
21 | }
22 |
23 | public abstract void Redo();
24 | public abstract void Undo();
25 | }
26 |
27 | public class InsertEventOperation : EventCollectionOperation where T : EventBase
28 | {
29 | public override string Description { get { return "イベントの挿入"; } }
30 |
31 | public InsertEventOperation(List collection, T item) : base(collection, item)
32 | {
33 | }
34 |
35 | public override void Redo()
36 | {
37 | Collection.Add(Event);
38 | }
39 |
40 | public override void Undo()
41 | {
42 | Collection.Remove(Event);
43 | }
44 | }
45 |
46 | public class RemoveEventOperation : EventCollectionOperation where T : EventBase
47 | {
48 | public override string Description { get { return "イベントの削除"; } }
49 |
50 | public RemoveEventOperation(List collection, T item) : base(collection, item)
51 | {
52 | }
53 |
54 | public override void Redo()
55 | {
56 | Collection.Remove(Event);
57 | }
58 |
59 | public override void Undo()
60 | {
61 | Collection.Add(Event);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Ched/UI/Operations/IOperation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.UI.Operations
8 | {
9 | ///
10 | /// ユーザーの操作を表すインタフェースです。
11 | ///
12 | public interface IOperation
13 | {
14 | ///
15 | /// この操作の説明を取得します。
16 | ///
17 | string Description { get; }
18 |
19 | ///
20 | /// 操作を元に戻します。
21 | ///
22 | void Undo();
23 |
24 | ///
25 | /// 操作をやり直します。
26 | ///
27 | void Redo();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Ched/UI/Operations/OperationManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.UI.Operations
8 | {
9 | ///
10 | /// 操作を管理するクラスです。
11 | ///
12 | public class OperationManager
13 | {
14 | public event EventHandler OperationHistoryChanged;
15 | public event EventHandler ChangesCommitted;
16 |
17 | protected Stack UndoStack { get; } = new Stack();
18 | protected Stack RedoStack { get; } = new Stack();
19 |
20 | private IOperation LastCommittedOperation { get; set; } = null;
21 |
22 | ///
23 | /// 元に戻す操作の概要のコレクションを取得します。
24 | ///
25 | public IEnumerable UndoOperationsDescription
26 | {
27 | get { return UndoStack.Select(p => p.Description); }
28 | }
29 |
30 | ///
31 | /// やり直す操作の概要のコレクションを取得します。
32 | ///
33 | public IEnumerable RedoOperationsDescription
34 | {
35 | get { return RedoStack.Select(p => p.Description); }
36 | }
37 |
38 | ///
39 | /// 操作を元に戻せるかどうかを取得します。
40 | ///
41 | public bool CanUndo { get { return UndoStack.Count > 0; } }
42 |
43 | ///
44 | /// 操作をやり直せるかどうかを取得します。
45 | ///
46 | public bool CanRedo { get { return RedoStack.Count > 0; } }
47 |
48 | ///
49 | /// 前回のの呼び出しから変更が加えられているかどうかを取得します。
50 | ///
51 | public bool IsChanged { get { return LastCommittedOperation != (UndoStack.Count > 0 ? UndoStack.Peek() : null); } }
52 |
53 | ///
54 | /// 新たな操作を記録します。
55 | ///
56 | /// 記録する操作
57 | public void Push(IOperation op)
58 | {
59 | UndoStack.Push(op);
60 | RedoStack.Clear();
61 | OperationHistoryChanged?.Invoke(this, EventArgs.Empty);
62 | }
63 |
64 | ///
65 | /// 操作を実行し、記録します。
66 | ///
67 | /// 実行・記録する操作
68 | public void InvokeAndPush(IOperation op)
69 | {
70 | op.Redo();
71 | Push(op);
72 | }
73 |
74 | ///
75 | /// 直前の操作を元に戻します。
76 | ///
77 | public void Undo()
78 | {
79 | IOperation op = UndoStack.Pop();
80 | op.Undo();
81 | RedoStack.Push(op);
82 | OperationHistoryChanged?.Invoke(this, EventArgs.Empty);
83 | }
84 |
85 | ///
86 | /// 直後の操作をやり直します。
87 | ///
88 | public void Redo()
89 | {
90 | IOperation op = RedoStack.Pop();
91 | op.Redo();
92 | UndoStack.Push(op);
93 | OperationHistoryChanged?.Invoke(this, EventArgs.Empty);
94 | }
95 |
96 | ///
97 | /// 記録されている操作をクリアします。
98 | ///
99 | public void Clear()
100 | {
101 | UndoStack.Clear();
102 | RedoStack.Clear();
103 | LastCommittedOperation = null;
104 | OperationHistoryChanged?.Invoke(this, EventArgs.Empty);
105 | }
106 |
107 | ///
108 | /// 現在のの状態に対して、保存処理が行われたことを通知します。
109 | ///
110 | public void CommitChanges()
111 | {
112 | LastCommittedOperation = UndoStack.Count > 0 ? UndoStack.Peek() : null;
113 | ChangesCommitted?.Invoke(this, EventArgs.Empty);
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/Ched/UI/Operations/ScoreOperation.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | using Ched.Core;
8 |
9 | namespace Ched.UI.Operations
10 | {
11 | public class UpdateScoreOperation : IOperation
12 | {
13 | public string Description { get { return "譜面の更新"; } }
14 |
15 | protected Action setScoreAction;
16 | protected Score BeforeScore { get; }
17 | protected Score AfterScore { get; }
18 |
19 | public UpdateScoreOperation(Score beforeScore, Score afterScore, Action setScoreAction)
20 | {
21 | BeforeScore = beforeScore;
22 | AfterScore = afterScore;
23 | this.setScoreAction = setScoreAction;
24 | }
25 |
26 | public void Undo()
27 | {
28 | setScoreAction(BeforeScore);
29 | }
30 |
31 | public void Redo()
32 | {
33 | setScoreAction(AfterScore);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Ched/UI/PlaneExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Drawing.Drawing2D;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace Ched.UI
10 | {
11 | public static class PlaneExtensions
12 | {
13 | public static RectangleF GetLeftThumb(this RectangleF rect, float widthRate, float minimumWidth)
14 | {
15 | return new RectangleF(rect.X, rect.Y, Math.Max(rect.Width * widthRate, minimumWidth), rect.Height);
16 | }
17 |
18 | public static RectangleF GetRightThumb(this RectangleF rect, float widthRate, float minimumWidth)
19 | {
20 | float width = Math.Max(rect.Width * widthRate, minimumWidth);
21 | return new RectangleF(rect.Right - width, rect.Y, width, rect.Height);
22 | }
23 |
24 | public static Matrix GetInvertedMatrix(this Matrix src)
25 | {
26 | var dest = src.Clone();
27 | dest.Invert();
28 | return dest;
29 | }
30 |
31 | public static Point TransformPoint(this Matrix matrix, Point point)
32 | {
33 | var arr = new Point[] { point };
34 | matrix.TransformPoints(arr);
35 | return arr.Single();
36 | }
37 |
38 | public static PointF TransformPoint(this Matrix matrix, PointF point)
39 | {
40 | var arr = new PointF[] { point };
41 | matrix.TransformPoints(arr);
42 | return arr.Single();
43 | }
44 |
45 | ///
46 | /// 凸状のポリゴン内に点が含まれているかどうか判定します。
47 | ///
48 | /// 頂点を格納した配列
49 | /// 判定する座標
50 | /// 座標がポリゴン内に含まれていればtrue
51 | /// ref: http://blackpawn.com/texts/pointinpoly/default.html
52 | public static bool ContainsPoint(this PointF[] vertexes, PointF point)
53 | {
54 | bool hitTriangle(PointF a, PointF b, PointF c, PointF p)
55 | {
56 | var ab = b.Subtract(a);
57 | var ac = c.Subtract(a);
58 | var ap = p.Subtract(a);
59 |
60 | float abab = ab.Dot(ab);
61 | float acac = ac.Dot(ac);
62 | float acap = ac.Dot(ap);
63 | float abac = ab.Dot(ac);
64 | float abap = ab.Dot(ap);
65 |
66 | float denom = acac * abab - abac * abac;
67 |
68 | float u = (acac * abap - abac * acap) / denom;
69 | float v = (abab * acap - abac * abap) / denom;
70 |
71 | return u >= 0 && v >= 0 && u + v < 1;
72 | }
73 |
74 | for (int i = 1; i <= vertexes.Length - 2; i++)
75 | {
76 | if (hitTriangle(vertexes[0], vertexes[i], vertexes[i + 1], point)) return true;
77 | }
78 |
79 | return false;
80 | }
81 |
82 | public static PointF Subtract(this PointF point, PointF offset)
83 | {
84 | return new PointF(point.X - offset.X, point.Y - offset.Y);
85 | }
86 |
87 | public static float Dot(this PointF point, PointF other)
88 | {
89 | return point.X * other.X + point.Y * other.Y;
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Ched/UI/ShiftTimeSelectionForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | using Ched.Plugins;
12 |
13 | namespace Ched.UI
14 | {
15 | public partial class ShiftTimeSelectionForm : Form
16 | {
17 | private static readonly IReadOnlyList<(ShiftEvent.DurationType Type, string Text)> DurationTypes = new List<(ShiftEvent.DurationType, string)>()
18 | {
19 | (ShiftEvent.DurationType.Bar, "小節"),
20 | (ShiftEvent.DurationType.Beat, "拍")
21 | };
22 |
23 | public int CountValue => (int)countBox.Value;
24 |
25 | public ShiftEvent.DurationType DurationType => DurationTypes[durationTypeBox.SelectedIndex].Type;
26 |
27 | public ShiftTimeSelectionForm()
28 | {
29 | InitializeComponent();
30 | AcceptButton = buttonOK;
31 | CancelButton = buttonCancel;
32 | buttonOK.DialogResult = DialogResult.OK;
33 | buttonCancel.DialogResult = DialogResult.Cancel;
34 |
35 | countBox.Minimum = -10000;
36 | countBox.Maximum = 10000;
37 | countBox.Value = 1;
38 | durationTypeBox.DropDownStyle = ComboBoxStyle.DropDownList;
39 | durationTypeBox.Items.AddRange(DurationTypes.Select(p => p.Text).ToArray());
40 | durationTypeBox.SelectedIndex = 0;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Ched/UI/Shortcuts/Commands.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace Ched.UI.Shortcuts
8 | {
9 | public static class Commands
10 | {
11 | // MenuStrip
12 | public static string NewFile => "files.new";
13 | public static string OpenFile => "files.open";
14 | public static string Save => "files.save";
15 | public static string SaveAs => "files.saveAs";
16 | public static string ReExport => "files.reExport";
17 | public static string ShowScoreBookProperties => "editor.action.showScoreBookProperties";
18 | public static string ShowShortcutSettings => "application.showShortcutSettings";
19 |
20 | public static string Undo => "editor.action.undo";
21 | public static string Redo => "editor.action.redo";
22 |
23 | public static string Cut => "editor.action.clipboardCut";
24 | public static string Copy => "editor.action.clipboardCopy";
25 | public static string Paste => "editor.action.clipboardPaste";
26 | public static string PasteFlip => "editor.action.clipboardPasteFlip";
27 |
28 | public static string SelectAll => "editor.action.selectAll";
29 | public static string SelectToBegin => "editor.action.selectToBegin";
30 | public static string SelectToEnd => "editor.action.selectToEnd";
31 |
32 | public static string FlipSelectedNotes => "editor.action.flipSelectedNotes";
33 | public static string RemoveSelectedNotes => "editor.action.removeSelectedNotes";
34 | public static string RemoveSelectedEvents => "editor.action.removeSelectedEvents";
35 |
36 | public static string SwitchScorePreviewMode => "editor.view.switchScorePreviewMode";
37 |
38 | public static string WidenLaneWidth => "editor.view.widenLaneWidth";
39 | public static string NarrowLaneWidth => "editor.view.narrowLaneWidth";
40 |
41 | public static string InsertBpmChange => "editor.action.insertBpmChange";
42 | public static string InsertTimeSignatureChange => "editor.action.insertTimeSignatureChange";
43 | public static string InsertHighSpeedChange => "editor.action.insertHighSpeedChange";
44 |
45 | public static string PlayPreview => "editor.view.playPreview";
46 |
47 | public static string ShowHelp => "application.showHelp";
48 |
49 | // ToolStrip
50 | public static string SelectPen => "editor.selectPen";
51 | public static string SelectSelection => "editor.selectSelection";
52 | public static string SelectEraser => "editor.selectEraser";
53 |
54 | public static string ZoomIn => "editor.view.zoomIn";
55 | public static string ZoomOut => "editor.view.zoomOut";
56 |
57 | public static string SelectTap => "editor.selectTap";
58 | public static string SelectExTap => "editor.selectExTap";
59 | public static string SelectHold => "editor.selectHold";
60 | public static string SelectSlide => "editor.selectSlide";
61 | public static string SelectSlideStep => "editor.selectSlideStep";
62 | public static string SelectAir => "editor.selectAir";
63 | public static string SelectAirUp => "editor.selectAirUp";
64 | public static string SelectAirDown => "editor.selectAirDown";
65 | public static string SelectAirAction => "editor.selectAirAction";
66 | public static string SelectFlick => "editor.selectFlick";
67 | public static string SelectDamage => "editor.selectDamage";
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Ched/UI/Shortcuts/KeyExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 |
9 | namespace Ched.UI.Shortcuts
10 | {
11 | public static class ShortcutExtensions
12 | {
13 | public static string ToShortcutChar(this Keys key) => key.ToShortcutString(key.IsMapRequired());
14 | public static string ToShortcutKey(this Keys key) => key.ToShortcutString(false);
15 |
16 | private static string ToShortcutString(this Keys key, bool toChar)
17 | {
18 | IEnumerable Build()
19 | {
20 | if (key.HasFlag(Keys.Control)) yield return "Ctrl";
21 | if (key.HasFlag(Keys.Shift)) yield return "Shift";
22 | if (key.HasFlag(Keys.Alt)) yield return "Alt";
23 |
24 | var keyCode = key & Keys.KeyCode;
25 | switch (keyCode)
26 | {
27 | case Keys.None:
28 | case Keys.ControlKey:
29 | case Keys.ShiftKey:
30 | yield break;
31 | }
32 |
33 | yield return toChar ? keyCode.ToChar().ToString() : keyCode.ToString();
34 | }
35 |
36 | return string.Join("+", Build());
37 | }
38 |
39 | private static bool IsMapRequired(this Keys key)
40 | {
41 | var keyCode = key & Keys.KeyCode;
42 |
43 | if (keyCode >= Keys.D0 && keyCode <= Keys.D9) return true;
44 | if ((int)keyCode >= 0xba && (int)keyCode <= 0xe2) return true; // Oem key
45 |
46 | return false;
47 | }
48 | }
49 |
50 | // https://stackoverflow.com/questions/318777/c-sharp-how-to-translate-virtual-keycode-to-char
51 | internal static class NativeMethods
52 | {
53 | [DllImport("user32.dll")]
54 | private static extern int MapVirtualKey(uint uCode, uint uMapType);
55 |
56 | public static char ToChar(this Keys key)
57 | {
58 | // Convert with MAPVK_VK_TO_CHAR
59 | return Convert.ToChar(MapVirtualKey((uint)key, 2));
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/Ched/UI/Shortcuts/ShortcutCommandSource.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | namespace Ched.UI.Shortcuts
9 | {
10 | public interface IShortcutCommandSource
11 | {
12 | IEnumerable Commands { get; }
13 |
14 | ///
15 | /// 指定のコマンドを実行します。
16 | ///
17 | /// 実行するコマンド
18 | /// コマンドが実行された場合はTrue
19 | bool ExecuteCommand(string command);
20 |
21 | bool ResolveCommandName(string command, out string name);
22 | }
23 |
24 | public class NullShortcutCommandSource : IShortcutCommandSource
25 | {
26 | public IEnumerable Commands => Enumerable.Empty();
27 |
28 | // Do nothing
29 | public bool ExecuteCommand(string command) => false;
30 |
31 | public bool ResolveCommandName(string command, out string name)
32 | {
33 | name = null;
34 | return false;
35 | }
36 | }
37 |
38 | public class ShortcutCommandSource : IShortcutCommandSource
39 | {
40 | private Dictionary commands { get; } = new Dictionary();
41 |
42 | public IEnumerable Commands => commands.Keys;
43 |
44 | public void RegisterCommand(string command, string name, Action action)
45 | {
46 | if (commands.ContainsKey(command)) throw new InvalidOperationException("The command is already registered.");
47 | commands.Add(command, (name, action));
48 | }
49 |
50 | public bool ExecuteCommand(string command)
51 | {
52 | if (!commands.ContainsKey(command)) return false;
53 | commands[command].Action();
54 | return true;
55 | }
56 |
57 | public bool ResolveCommandName(string command, out string name)
58 | {
59 | name = null;
60 | if (!commands.ContainsKey(command)) return false;
61 | name = commands[command].Name;
62 | return true;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/Ched/UI/Shortcuts/ShortcutManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 |
8 | namespace Ched.UI.Shortcuts
9 | {
10 | public class ShortcutManager
11 | {
12 | public event EventHandler ShortcutUpdated;
13 |
14 | public IShortcutCommandSource CommandSource { get; set; } = new NullShortcutCommandSource();
15 | public IShortcutKeySource DefaultKeySource { get; set; } = new NullShortcutKeySource();
16 | public IShortcutKeySource UserKeySource { get; set; } = new NullShortcutKeySource();
17 |
18 | public bool ExecuteCommand(Keys key)
19 | {
20 | bool Resolve(IShortcutKeySource source)
21 | {
22 | if (source.ResolveCommand(key, out string command))
23 | {
24 | return CommandSource.ExecuteCommand(command);
25 | }
26 | return false;
27 | }
28 |
29 | // User, Defaultの順にトラバースしてひっかける
30 | return Resolve(UserKeySource) || Resolve(DefaultKeySource);
31 | }
32 |
33 | public bool ResolveShortcutKey(string command, out Keys key)
34 | {
35 | return UserKeySource.ResolveShortcutKey(command, out key) || DefaultKeySource.ResolveShortcutKey(command, out key);
36 | }
37 |
38 | public void NotifyUpdateShortcut() => ShortcutUpdated?.Invoke(this, EventArgs.Empty);
39 | }
40 |
41 | public class ShortcutManagerHost
42 | {
43 | private ShortcutManager shortcutManager;
44 | private UserShortcutKeySource userShortcutKeySource;
45 |
46 | public ShortcutManager ShortcutManager => shortcutManager;
47 |
48 | public UserShortcutKeySource UserShortcutKeySource
49 | {
50 | get => userShortcutKeySource;
51 | set
52 | {
53 | userShortcutKeySource = value;
54 | ShortcutManager.UserKeySource = value;
55 | ShortcutManager.NotifyUpdateShortcut();
56 | }
57 | }
58 |
59 | public ShortcutManagerHost(ShortcutManager shortcutManager)
60 | {
61 | this.shortcutManager = shortcutManager;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/Ched/UI/Shortcuts/ToolStripItemBuilder.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows.Forms;
8 |
9 | namespace Ched.UI.Shortcuts
10 | {
11 | internal abstract class ToolStripItemBuilder
12 | {
13 | private Dictionary items = new Dictionary();
14 | protected ShortcutManager ShortcutManager { get; }
15 |
16 | public ToolStripItemBuilder(ShortcutManager shortcutManager)
17 | {
18 | ShortcutManager = shortcutManager;
19 | ShortcutManager.ShortcutUpdated += OnShortcutUpdated;
20 | }
21 |
22 | private void OnShortcutUpdated(object sender, EventArgs e)
23 | {
24 | var shortcutManager = (ShortcutManager)sender;
25 | foreach (var item in items)
26 | {
27 | if (shortcutManager.ResolveShortcutKey(item.Key, out Keys key))
28 | {
29 | UpdateShortcutKey(item.Value, key.ToShortcutChar());
30 | continue;
31 | }
32 | UpdateShortcutKey(item.Value, "");
33 | }
34 | }
35 |
36 | public T BuildItem(string command, string commandName) => BuildItem(command, commandName, null);
37 |
38 | public T BuildItem(string command, string commandName, Image image)
39 | {
40 | var item = BuildItemInstance(command, commandName, image);
41 | items.Add(command, item);
42 | return item;
43 | }
44 |
45 | protected abstract T BuildItemInstance(string command, string commandName, Image image);
46 | protected abstract void UpdateShortcutKey(T item, string keyText);
47 | }
48 |
49 | internal class ToolStripMenuItemBuilder : ToolStripItemBuilder
50 | {
51 | public ToolStripMenuItemBuilder(ShortcutManager shortcutManager) : base(shortcutManager)
52 | {
53 | }
54 |
55 | protected override ToolStripMenuItem BuildItemInstance(string command, string commandName, Image image)
56 | {
57 | return new ToolStripMenuItem(commandName, null, (s, e) => ShortcutManager.CommandSource.ExecuteCommand(command));
58 | }
59 |
60 | protected override void UpdateShortcutKey(ToolStripMenuItem item, string keyText)
61 | {
62 | item.ShortcutKeyDisplayString = keyText;
63 | }
64 | }
65 |
66 | internal class ToolStripButtonBuilder : ToolStripItemBuilder
67 | {
68 | private Dictionary commandNameMap = new Dictionary();
69 |
70 | public ToolStripButtonBuilder(ShortcutManager shortcutManager) : base(shortcutManager)
71 | {
72 | }
73 |
74 | protected override ToolStripButton BuildItemInstance(string command, string commandName, Image image)
75 | {
76 | var button = new ToolStripButton(commandName, image, (s, e) => ShortcutManager.CommandSource.ExecuteCommand(command))
77 | {
78 | DisplayStyle = ToolStripItemDisplayStyle.Image
79 | };
80 | commandNameMap.Add(button, commandName);
81 | return button;
82 | }
83 |
84 | protected override void UpdateShortcutKey(ToolStripButton item, string keyText)
85 | {
86 | string commandName = commandNameMap[item];
87 | item.Text = string.IsNullOrEmpty(keyText) ? commandName : $"{commandName} ({keyText})";
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Ched/UI/TimeSignatureSelectionForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class TimeSignatureSelectionForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TimeSignatureSelectionForm));
32 | this.numeratorBox = new System.Windows.Forms.ComboBox();
33 | this.denominatorBox = new System.Windows.Forms.ComboBox();
34 | this.buttonOK = new System.Windows.Forms.Button();
35 | this.buttonCancel = new System.Windows.Forms.Button();
36 | this.label1 = new System.Windows.Forms.Label();
37 | this.SuspendLayout();
38 | //
39 | // numeratorBox
40 | //
41 | this.numeratorBox.FormattingEnabled = true;
42 | resources.ApplyResources(this.numeratorBox, "numeratorBox");
43 | this.numeratorBox.Name = "numeratorBox";
44 | //
45 | // denominatorBox
46 | //
47 | this.denominatorBox.FormattingEnabled = true;
48 | resources.ApplyResources(this.denominatorBox, "denominatorBox");
49 | this.denominatorBox.Name = "denominatorBox";
50 | //
51 | // buttonOK
52 | //
53 | resources.ApplyResources(this.buttonOK, "buttonOK");
54 | this.buttonOK.Name = "buttonOK";
55 | this.buttonOK.UseVisualStyleBackColor = true;
56 | //
57 | // buttonCancel
58 | //
59 | resources.ApplyResources(this.buttonCancel, "buttonCancel");
60 | this.buttonCancel.Name = "buttonCancel";
61 | this.buttonCancel.UseVisualStyleBackColor = true;
62 | //
63 | // label1
64 | //
65 | resources.ApplyResources(this.label1, "label1");
66 | this.label1.Name = "label1";
67 | //
68 | // TimeSignatureSelectionForm
69 | //
70 | resources.ApplyResources(this, "$this");
71 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
72 | this.Controls.Add(this.label1);
73 | this.Controls.Add(this.buttonCancel);
74 | this.Controls.Add(this.buttonOK);
75 | this.Controls.Add(this.denominatorBox);
76 | this.Controls.Add(this.numeratorBox);
77 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
78 | this.MaximizeBox = false;
79 | this.MinimizeBox = false;
80 | this.Name = "TimeSignatureSelectionForm";
81 | this.ResumeLayout(false);
82 | this.PerformLayout();
83 |
84 | }
85 |
86 | #endregion
87 |
88 | private System.Windows.Forms.ComboBox numeratorBox;
89 | private System.Windows.Forms.ComboBox denominatorBox;
90 | private System.Windows.Forms.Button buttonOK;
91 | private System.Windows.Forms.Button buttonCancel;
92 | private System.Windows.Forms.Label label1;
93 | }
94 | }
--------------------------------------------------------------------------------
/Ched/UI/TimeSignatureSelectionForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace Ched.UI
12 | {
13 | public partial class TimeSignatureSelectionForm : Form
14 | {
15 | public int Numerator
16 | {
17 | get { return numeratorBox.SelectedIndex + 1; }
18 | }
19 |
20 | public int DenominatorExponent
21 | {
22 | get { return denominatorBox.SelectedIndex + 1; }
23 | }
24 |
25 | public TimeSignatureSelectionForm()
26 | {
27 | InitializeComponent();
28 | AcceptButton = buttonOK;
29 | CancelButton = buttonCancel;
30 | buttonOK.DialogResult = DialogResult.OK;
31 | buttonCancel.DialogResult = DialogResult.Cancel;
32 |
33 | numeratorBox.DropDownStyle = ComboBoxStyle.DropDownList;
34 | denominatorBox.DropDownStyle = ComboBoxStyle.DropDownList;
35 | numeratorBox.Items.AddRange(Enumerable.Range(1, 32).Select(p => p.ToString()).ToArray());
36 | denominatorBox.Items.AddRange(Enumerable.Range(1, 6).Select(p => Math.Pow(2, p).ToString()).ToArray());
37 | numeratorBox.SelectedIndex = 4 - 1;
38 | denominatorBox.SelectedIndex = 2 - 1;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Ched/UI/VersionInfoForm.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace Ched.UI
2 | {
3 | partial class VersionInfoForm
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VersionInfoForm));
32 | this.pictureBox1 = new System.Windows.Forms.PictureBox();
33 | this.labelTitle = new System.Windows.Forms.Label();
34 | this.labelVersion = new System.Windows.Forms.Label();
35 | this.labelProduct = new System.Windows.Forms.Label();
36 | this.buttonClose = new System.Windows.Forms.Button();
37 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
38 | this.SuspendLayout();
39 | //
40 | // pictureBox1
41 | //
42 | resources.ApplyResources(this.pictureBox1, "pictureBox1");
43 | this.pictureBox1.Name = "pictureBox1";
44 | this.pictureBox1.TabStop = false;
45 | //
46 | // labelTitle
47 | //
48 | resources.ApplyResources(this.labelTitle, "labelTitle");
49 | this.labelTitle.Name = "labelTitle";
50 | //
51 | // labelVersion
52 | //
53 | resources.ApplyResources(this.labelVersion, "labelVersion");
54 | this.labelVersion.Name = "labelVersion";
55 | //
56 | // labelProduct
57 | //
58 | resources.ApplyResources(this.labelProduct, "labelProduct");
59 | this.labelProduct.Name = "labelProduct";
60 | //
61 | // buttonClose
62 | //
63 | resources.ApplyResources(this.buttonClose, "buttonClose");
64 | this.buttonClose.Name = "buttonClose";
65 | this.buttonClose.UseVisualStyleBackColor = true;
66 | //
67 | // VersionInfoForm
68 | //
69 | resources.ApplyResources(this, "$this");
70 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
71 | this.Controls.Add(this.buttonClose);
72 | this.Controls.Add(this.labelProduct);
73 | this.Controls.Add(this.labelVersion);
74 | this.Controls.Add(this.labelTitle);
75 | this.Controls.Add(this.pictureBox1);
76 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
77 | this.MaximizeBox = false;
78 | this.MinimizeBox = false;
79 | this.Name = "VersionInfoForm";
80 | ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
81 | this.ResumeLayout(false);
82 | this.PerformLayout();
83 |
84 | }
85 |
86 | #endregion
87 |
88 | private System.Windows.Forms.PictureBox pictureBox1;
89 | private System.Windows.Forms.Label labelTitle;
90 | private System.Windows.Forms.Label labelVersion;
91 | private System.Windows.Forms.Label labelProduct;
92 | private System.Windows.Forms.Button buttonClose;
93 | }
94 | }
--------------------------------------------------------------------------------
/Ched/UI/VersionInfoForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 | using System.Reflection;
11 | using Ched.Properties;
12 |
13 | namespace Ched.UI
14 | {
15 | public partial class VersionInfoForm : Form
16 | {
17 | public VersionInfoForm()
18 | {
19 | InitializeComponent();
20 |
21 | var asm = Assembly.GetEntryAssembly();
22 |
23 | labelTitle.Text = string.Format("{0} - {1}", asm.GetCustomAttribute().Title, asm.GetCustomAttribute().Description);
24 | labelVersion.Text = string.Format("Version {0}", asm.GetName().Version.ToString());
25 | labelProduct.Text = asm.GetCustomAttribute().Copyright;
26 |
27 | pictureBox1.Image = Bitmap.FromHicon(Resources.MainIcon.Handle);
28 |
29 | buttonClose.Click += (s, e) => Close();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Ched/UI/Windows/Behaviors/HideWindowCloseButtonBehavior.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Runtime.InteropServices;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 | using System.Windows.Interop;
9 | using Microsoft.Xaml.Behaviors;
10 |
11 | namespace Ched.UI.Windows.Behaviors
12 | {
13 | public class HideWindowCloseButtonBehavior : Behavior
14 | {
15 | #region NativeMethods
16 | private const int GWL_STYLE = -16;
17 | private const int WS_SYSMENU = 0x80000;
18 |
19 | [DllImport("user32.dll", SetLastError = true)]
20 | private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
21 |
22 | [DllImport("user32.dll")]
23 | private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
24 | #endregion
25 |
26 | protected override void OnAttached()
27 | {
28 | base.OnAttached();
29 | AssociatedObject.Loaded += OnLoaded;
30 | }
31 |
32 | protected override void OnDetaching()
33 | {
34 | AssociatedObject.Loaded -= OnLoaded;
35 | base.OnDetaching();
36 | }
37 |
38 | private void OnLoaded(object sender, RoutedEventArgs e)
39 | {
40 | var hwnd = new WindowInteropHelper(AssociatedObject).Handle;
41 | SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) & ~WS_SYSMENU);
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Ched/UI/Windows/Behaviors/InitialFocusBehavior.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Input;
8 | using Microsoft.Xaml.Behaviors;
9 |
10 | namespace Ched.UI.Windows.Behaviors
11 | {
12 | public class InitialFocusBehavior : Behavior
13 | {
14 | protected override void OnAttached()
15 | {
16 | base.OnAttached();
17 | AssociatedObject.Loaded += OnLoaded;
18 | }
19 |
20 | protected override void OnDetaching()
21 | {
22 | base.OnDetaching();
23 | AssociatedObject.Loaded -= OnLoaded;
24 | }
25 |
26 | private void OnLoaded(object sender, RoutedEventArgs e)
27 | {
28 | ((Window)sender).MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Ched/UI/Windows/Behaviors/OpenFileBehavior.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Input;
9 | using Microsoft.Xaml.Behaviors;
10 |
11 | namespace Ched.UI.Windows.Behaviors
12 | {
13 | public class OpenFileBehavior : Behavior