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.paramsplit; 8 import creator.windows; 9 import creator.core; 10 import creator.widgets.dummy; 11 import creator.widgets.label; 12 import creator; 13 import std.string; 14 import creator.utils.link; 15 import inochi2d; 16 import i18n; 17 import std.array : insertInPlace; 18 19 struct ParamMapping { 20 size_t idx; 21 ParameterBinding[] bindings; 22 Node node; 23 bool take; 24 } 25 26 class ParamSplitWindow : Window { 27 private: 28 size_t idx; 29 Parameter param; 30 ParamMapping[uint] mappings; 31 32 void buildMapping() { 33 foreach(i, ref binding; param.bindings) { 34 if (binding.getNodeUUID() !in mappings) { 35 mappings[binding.getNodeUUID()] = ParamMapping( 36 i, 37 [], 38 binding.getNode(), 39 false 40 ); 41 } 42 43 mappings[binding.getNodeUUID()].bindings ~= binding; 44 } 45 } 46 47 void apply() { 48 Parameter newParam = new Parameter(param.name~_(" (Split)"), param.isVec2); 49 foreach(axis; 0..param.axisPoints.length) { 50 newParam.axisPoints[axis] = param.axisPoints[axis].dup; 51 } 52 53 54 // TODO: remap 55 ParameterBinding[] oldParamBindings; 56 ParameterBinding[] newParamBindings; 57 foreach(ref mappingNode; mappings) { 58 if (!mappingNode.take) oldParamBindings ~= mappingNode.bindings; 59 else newParamBindings ~= mappingNode.bindings; 60 } 61 62 if (newParamBindings.length > 0) { 63 param.bindings = oldParamBindings; 64 newParam.bindings = newParamBindings; 65 incActivePuppet().parameters.insertInPlace(idx+1, newParam); 66 } 67 68 this.close(); 69 } 70 71 void oldBindingsList() { 72 73 foreach(k; 0..mappings.keys.length) { 74 auto key = mappings.keys[k]; 75 auto mapping = &mappings[mappings.keys[k]]; 76 77 if (mapping.take) continue; 78 79 igSelectable(mapping.node.name.toStringz); 80 if(igBeginDragDropSource(ImGuiDragDropFlags.SourceAllowNullID)) { 81 igSetDragDropPayload("__OLD_TO_NEW", cast(void*)&key, (&key).sizeof, ImGuiCond.Always); 82 incText(mapping.node.name); 83 igEndDragDropSource(); 84 } 85 } 86 } 87 88 void newBindingsList() { 89 90 foreach(k; 0..mappings.keys.length) { 91 auto key = mappings.keys[k]; 92 auto mapping = &mappings[mappings.keys[k]]; 93 if (!mapping.take) continue; 94 95 igSelectable(mapping.node.name.toStringz); 96 if(igBeginDragDropSource(ImGuiDragDropFlags.SourceAllowNullID)) { 97 igSetDragDropPayload("__NEW_TO_OLD", cast(void*)&key, (&key).sizeof, ImGuiCond.Always); 98 incText(mapping.node.name); 99 igEndDragDropSource(); 100 } 101 } 102 } 103 104 protected: 105 106 override 107 void onBeginUpdate() { 108 igSetNextWindowSizeConstraints(ImVec2(640, 480), ImVec2(float.max, float.max)); 109 super.onBeginUpdate(); 110 } 111 112 override 113 void onUpdate() { 114 ImVec2 space = incAvailableSpace(); 115 float gapspace = 8; 116 float childWidth = (space.x/2); 117 float childHeight = space.y-(24); 118 119 igBeginGroup(); 120 if (igBeginChild("###OldParam", ImVec2(childWidth, childHeight))) { 121 if (igBeginListBox("###ItemListOld", ImVec2(childWidth-gapspace, childHeight))) { 122 oldBindingsList(); 123 igEndListBox(); 124 } 125 126 if(igBeginDragDropTarget()) { 127 const(ImGuiPayload)* payload = igAcceptDragDropPayload("__NEW_TO_OLD"); 128 if (payload !is null) { 129 uint mappingName = *cast(uint*)payload.Data; 130 131 mappings[mappingName].take = false; 132 133 igEndDragDropTarget(); 134 return; 135 } 136 igEndDragDropTarget(); 137 } 138 } 139 igEndChild(); 140 141 igSameLine(0, gapspace); 142 143 if (igBeginChild("###NewParam", ImVec2(childWidth, childHeight))) { 144 if (igBeginListBox("###ItemListNew", ImVec2(childWidth, childHeight))) { 145 newBindingsList(); 146 igEndListBox(); 147 } 148 } 149 igEndChild(); 150 151 if(igBeginDragDropTarget()) { 152 const(ImGuiPayload)* payload = igAcceptDragDropPayload("__OLD_TO_NEW"); 153 if (payload !is null) { 154 uint mappingName = *cast(uint*)payload.Data; 155 156 mappings[mappingName].take = true; 157 158 igEndDragDropTarget(); 159 return; 160 } 161 igEndDragDropTarget(); 162 } 163 igEndGroup(); 164 165 igBeginGroup(); 166 incDummy(ImVec2(-64, 24)); 167 igSameLine(0, 0); 168 if (igButton(__("Apply"), ImVec2(64, 24))) { 169 this.apply(); 170 } 171 igEndGroup(); 172 } 173 174 public: 175 this(size_t idx, Parameter param) { 176 this.idx = idx; 177 this.param = param; 178 this.buildMapping(); 179 super(_("Split Parameter")); 180 } 181 } 182