1 /*
2     Copyright © 2020, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module creator.windows.trkbind;
8 import creator.viewport.test;
9 import creator.windows;
10 import creator.widgets;
11 import creator.core;
12 import creator;
13 import std.string;
14 import creator.utils.link;
15 import i18n;
16 import inochi2d;
17 
18 class TrackingBindingWindow : Window {
19 private:
20     TrackingBinding binding;
21     const(char)* paramComboName = "";
22     const(char)* trackingComboName = "";
23     const(char)* bindingBoneInputName = "";
24     const(char)* bindingAxisName = "";
25     TrackingBindingMode[string] currBindable;
26 
27     void boneElementSelectable(const(char)* name, TrackingBindingMode mode) {
28 
29         if (igSelectable(name, binding.mode == mode)) {
30             binding.mode = mode;
31             bindingBoneInputName = name;
32         }
33     }
34 
35 protected:
36     override
37     void onBeginUpdate() {
38         flags |= ImGuiWindowFlags.NoResize;
39         igSetNextWindowSize(ImVec2(384, 192), ImGuiCond.Appearing);
40         igSetNextWindowSizeConstraints(ImVec2(384, 192), ImVec2(float.max, float.max));
41         super.onBeginUpdate();
42     }
43 
44     override
45     void onUpdate() {
46         if (igBeginChild("###MainSettings", ImVec2(0, -28))) {
47             if (igBeginCombo(__("Parameter"), paramComboName)) {
48                 foreach(i, param; incActivePuppet().parameters) {
49                     igPushID(cast(int)i);
50                         bool isSelected = binding.param == param;
51                         if (igSelectable(param.name.toStringz, isSelected)) {
52                             binding.param = param;
53                             paramComboName = param.name.toStringz;
54                         }
55                     igPopID();
56                 }
57                 igEndCombo();
58             }
59 
60             if (binding.param) {
61                 if (igBeginCombo(__("Bind To"), trackingComboName)) {
62                     foreach(name, mode; currBindable) {
63                         igPushID(name.ptr);
64                             bool isSelected = binding.key == name;
65                             if (igSelectable(name.toStringz, isSelected)) {
66                                 binding.key = name;
67                                 trackingComboName = name.toStringz;
68 
69                                 if (mode == TrackingBindingMode.Blendshape) {
70                                     binding.mode = mode;
71                                 } else {
72                                     binding.mode = TrackingBindingMode.Bone;
73                                 }
74                             }
75                         igPopID();
76                     }
77                     igEndCombo();
78                 }
79 
80                 if (binding.key in currBindable && currBindable[binding.key] == TrackingBindingMode.Bone) {
81                     
82                     if (igBeginCombo(__("Bone Input"), bindingBoneInputName)) {
83                         boneElementSelectable(__("Position (X)"), TrackingBindingMode.BonePosX);
84                         boneElementSelectable(__("Position (Y)"), TrackingBindingMode.BonePosY);
85                         boneElementSelectable(__("Position (Z)"), TrackingBindingMode.BonePosZ);
86                         boneElementSelectable(__("Rotation (X)"), TrackingBindingMode.BoneRotX);
87                         boneElementSelectable(__("Rotation (Y)"), TrackingBindingMode.BoneRotY);
88                         boneElementSelectable(__("Rotation (Z)"), TrackingBindingMode.BoneRotZ);
89                         igEndCombo();
90                     }
91                 }
92 
93                 if (binding.param.isVec2) {
94                     if (igBeginCombo(__("Binding Axis"), bindingAxisName)) {
95                         if (igSelectable("X", binding.axis == 0)) {
96                             binding.axis = 0;
97                             bindingAxisName = "X";
98                         }
99 
100                         if (igSelectable("Y", binding.axis == 1)) {
101                             binding.axis = 1;
102                             bindingAxisName = "Y";
103                         }
104                         igEndCombo();
105                     }
106                 } else {
107                     binding.axis = 0;
108                 }
109 
110                 igCheckbox(__("Invert"), &binding.inverse);
111             }
112             igEndChild();
113 
114             if (igBeginChild("###SettingsBtns", ImVec2(0, 0))) {
115                 if (igButton(__("Refresh Bindable"), ImVec2(0, 24))) {
116                     this.currBindable = incViewportTestGetCurrBindable();
117                 }
118 
119                 igSameLine(0, 0);
120                 incDummy(ImVec2(-64, 0));
121                 igSameLine(0, 0);
122 
123                 bool canSave = binding.key.length > 0 && binding.mode != TrackingBindingMode.Bone;
124 
125                 if (!canSave) igBeginDisabled();
126                     // Settings are autosaved, but in case the user
127                     // feels more safe with a save button then we have
128                     // it here.
129                     if (igButton(__("Save"), ImVec2(64, 24))) {
130                         incTestAddTrackingBinding(binding);
131                         this.close();
132                     }
133                 if (!canSave) igEndDisabled();
134             }
135         }
136         igEndChild();
137     }
138 
139 public:
140     this(TrackingBindingMode[string] bindable) {
141         this.currBindable = bindable;
142 
143         // Title for the parameter properties window.
144         super(_("Bind Tracking to Parameter"));
145     }
146 }