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.panels.tracking;
8 import creator.core;
9 import creator.viewport.test;
10 import creator.panels;
11 import creator.windows;
12 import creator.widgets;
13 import creator;
14 import bindbc.imgui;
15 import inochi2d;
16 import std.conv;
17 import i18n;
18 import std.string;
19 
20 /**
21     The textures frame
22 */
23 class TrackingPanel : Panel {
24 private:
25     string[string] optionValues;
26 
27     bool trackingModeCheckbox(string receiverName, string tooltip, TrackingMode mode) {
28         bool track = incTestGetTrackingMode() == mode;
29 
30         // Appended to the name of a face tracking receiver
31         // in the Tracking settings panel
32         const(char)* recvName = (receiverName~_(" Receiver")).toStringz;
33 
34         if (igCheckbox(recvName, &track)) {
35             incTestSetTrackingMode(track ? mode : TrackingMode.None);
36             incTestRestartTracker();
37         }
38         incTooltip(tooltip);
39         return track;
40     }
41 
42     bool canParseAddr(string addr) {
43         import std.socket : parseAddress;
44         try {
45             parseAddress(addr);
46             return true;
47         } catch (Exception ex) {
48             return false;
49         }
50     }
51 
52 protected:
53     override
54     void onUpdate() {
55 
56         if (incEditMode == EditMode.ModelTest) {
57             ImVec2 avail = incAvailableSpace();
58 
59             if (trackingModeCheckbox("VMC", _("A reciever which uses your phone and associated app to track your body"), TrackingMode.VMC)) {
60                 auto adaptorOptions = incTestGetAdaptorOptions();
61 
62                 string bindingIP = incSettingsGet("vmc_bind_ip", "0.0.0.0");
63                 if (incInputText(__("Bind Address"), avail.x/2, bindingIP, ImGuiInputTextFlags.None)) {
64                     incSettingsSet("vmc_bind_ip", bindingIP);
65 
66                     if (this.canParseAddr(bindingIP)) {
67                         incSettingsSave();
68                         adaptorOptions["address"] = bindingIP;
69                         incTestRestartTracker();
70                     }
71                 }
72                 incTooltip(_("The IP address that the VMC binding server should listen on, default 0.0.0.0"));
73 
74                 int bindingPort = incSettingsGet("vmc_bind_port", 39540);
75                 if (igInputInt(__("Port"), &bindingPort)) {
76                     incSettingsSet("vmc_bind_port", bindingPort);
77 
78                     if (bindingPort > 1 && bindingPort < ushort.max) {
79                         incSettingsSave();
80                         optionValues["port"] = bindingPort.text;
81                         incTestRestartTracker();
82                     }
83                 }
84                 incTooltip(_("The port that the VMC binding server should listen on, default 39540"));
85             }
86 
87             if (trackingModeCheckbox("VTube Studio", _("A reciever which uses the VTubeStudio iOS app"), TrackingMode.VTS)) {
88                 
89                 string bindingIP = incSettingsGet!string("vts_phone_ip");
90                 if (incInputText(__("iPhone IP"), avail.x/2, bindingIP, ImGuiInputTextFlags.None)) {
91                     incSettingsSet("vts_phone_ip", bindingIP);
92 
93                     if (this.canParseAddr(bindingIP)) {
94                         incSettingsSave();
95                         optionValues["phoneIP"] = bindingIP;
96                         incTestRestartTracker();
97                     }
98                 }
99                 incTooltip(_("The IP Address of your iPhone,\nYou can find it in the VSeeFace Config panel in VTube Studio"));
100             }
101 
102             if (igCollapsingHeader(__("Tracking Bindings"), ImGuiTreeNodeFlags.DefaultOpen)) {
103                 if (igBeginListBox("")) {
104                     foreach(i, binding; incTestGetTrackingBindings()) {
105                         igPushID(cast(int)i);
106 
107                             const(char)* nm = _("%s bound to %s").format(binding.key, binding.param.name).toStringz;
108                             if (igSelectable(nm)) {
109                                 incTestRemoveTrackingBinding(binding);
110                             }
111 
112                         igPopID();
113                     }
114                     igEndListBox();
115                 }
116 
117                 if (igButton("", ImVec2(0, 32))) {
118                     incPushWindowList(new TrackingBindingWindow(incViewportTestGetCurrBindable()));
119                 }
120             }
121         } else {
122             igText(__("Not in Test Mode..."));
123         }
124     }
125 
126 public:
127     this() {
128         super("Tracking", _("Tracking"), false);
129     }
130 }
131 
132 /**
133     Generate tracking panel frame
134 */
135 mixin incPanel!TrackingPanel;
136 
137