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 = TrackingBindingMode.BonePosX;
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.BoneRotX);
88                     boneElementSelectable(__("Rotation (Z)"), TrackingBindingMode.BoneRotX);
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             if (igBeginChild("###SettingsBtns", ImVec2(0, 0))) {
114                 if (igButton(__("Refresh Bindable"), ImVec2(0, 24))) {
115                     this.currBindable = incViewportTestGetCurrBindable();
116                 }
117 
118                 igSameLine(0, 0);
119                 incDummy(ImVec2(-64, 0));
120                 igSameLine(0, 0);
121 
122                 bool canSave = binding.key.length > 0 && binding.mode != TrackingBindingMode.Bone;
123 
124                 if (!canSave) igBeginDisabled();
125                     // Settings are autosaved, but in case the user
126                     // feels more safe with a save button then we have
127                     // it here.
128                     if (igButton(__("Save"), ImVec2(64, 24))) {
129                         incTestAddTrackingBinding(binding);
130                         this.close();
131                     }
132                 if (!canSave) igEndDisabled();
133             }
134             igEndChild();
135         }
136     }
137 
138 public:
139     this(TrackingBindingMode[string] bindable) {
140         this.currBindable = bindable;
141 
142         // Title for the parameter properties window.
143         super(_("Bind Tracking to Parameter"));
144     }
145 }