1 /* 2 ** Surge Synthesizer is Free and Open Source Software 3 ** 4 ** Surge is made available under the Gnu General Public License, v3.0 5 ** https://www.gnu.org/licenses/gpl-3.0.en.html 6 ** 7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log 8 ** 9 ** All source at: https://github.com/surge-synthesizer/surge.git 10 ** 11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership 12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge 13 ** open source in September 2018. 14 */ 15 16 #include "SkinModel.h" 17 #include "resource.h" 18 19 using Surge::Skin::Connector; 20 using namespace Surge::Skin::Components; 21 22 /* 23 * This file, in conjunction with the SVG assets it references by ID, is a complete 24 * description of the surge default UI layout. The action callbacks bind to it and 25 * the engine to lay it out are the collaboration betweeh this, SkinSupport, and SurgeGUIEditor 26 */ 27 28 namespace Surge 29 { 30 namespace Skin 31 { 32 33 namespace Components 34 { 35 Component None = Component("UNKNOWN"); 36 37 Component HSwitch2 = 38 Component("CHSwitch2") 39 .withProperty(Component::ROWS, {"rows"}, {"Number of rows in the switch"}) 40 .withProperty(Component::COLUMNS, {"cols", "columns"}, {"Number of columns in the switch"}) 41 .withProperty( 42 Component::FRAMES, {"frames"}, 43 {"Number of frames in the graphical asset for the switch (based on rows and columns)"}) 44 .withProperty(Component::FRAME_OFFSET, {"frame_offset"}, 45 {"Used in case when a graphical asset for the switch has multiple variations " 46 "to reach to, valid values are from 0 to 'frames'"}) 47 .withProperty(Component::BACKGROUND, {"image", "bg_resource", "bg_id"}, 48 {"Base image of the switch"}) 49 .withProperty(Component::DRAGGABLE_HSWITCH, {"draggable"}, 50 {"Is the switch draggable as a slider via mouse/touch or not. Valid values: " 51 "true, false"}) 52 .withProperty(Component::HOVER_IMAGE, {"hover_image"}, 53 {"Hover image of the switch - required if you " 54 "set the base image and want feedback on mouse hover"}) 55 .withProperty(Component::HOVER_ON_IMAGE, {"hover_on_image"}, 56 {"Hover image of the switch used when mouse hovers over the currently " 57 "selected value on the switch"}); 58 59 Component Slider = 60 Component("CSurgeSlider") 61 .withProperty(Component::SLIDER_TRAY, {"slider_tray", "handle_tray"}, 62 {"Background image of the slider, contains the slider tray/groove only"}) 63 .withProperty(Component::HANDLE_IMAGE, {"handle_image"}, {"Slider handle image"}) 64 .withProperty( 65 Component::HANDLE_HOVER_IMAGE, {"handle_hover_image"}, 66 {"Hovered slider handle image - required if you want feedback on mouse hover"}) 67 .withProperty(Component::HANDLE_TEMPOSYNC_IMAGE, {"handle_temposync_image"}, 68 {"Slider handle image when parameter is tempo-synced"}) 69 .withProperty(Component::HANDLE_TEMPOSYNC_HOVER_IMAGE, {"handle_temposync_hover_image"}, 70 {"Hovered slider handle image when parameter is tempo-synced - required if " 71 "you want feedback on mouse hover"}) 72 .withProperty(Component::FONT_SIZE, {"font_size"}, {"Font size in points, integer only"}) 73 .withProperty(Component::FONT_STYLE, {"font_style"}, 74 {"Valid values: normal, bold, italic, underline, strikethrough"}) 75 .withProperty(Component::TEXT_ALIGN, {"text_align"}, {"Valid values: left, center, right"}) 76 .withProperty(Component::TEXT_HOFFSET, {"text_hoffset"}, 77 {"Horizontal offset of parameter name label, integer only"}) 78 .withProperty(Component::TEXT_VOFFSET, {"text_voffset"}, 79 {"Vertical offset of parameter name label, integer only"}) 80 .withProperty(Component::HIDE_SLIDER_LABEL, {"hide_slider_label"}, 81 {"Hides the parameter name label"}); 82 83 Component Switch = Component("CSwitchControl") 84 .withProperty(Component::BACKGROUND, {"image", "bg_resource", "bg_id"}, 85 {"Base image of the switch"}); 86 87 Component FilterSelector = 88 Component("FilterSelector") 89 .withProperty(Component::BACKGROUND, {"image"}, 90 {"Base image of the filter type menu itself; it is offset by the glyph if " 91 "glyph is active"}) 92 .withProperty(Component::HOVER_IMAGE, {"hover_image"}, 93 {"Hover image of the filter type menu - required if you " 94 "set the base image and want feedback on mouse hover"}) 95 .withProperty(Component::GLYPH_IMAGE, {"glyph_image"}, 96 {"Resource name of the glyph (filter type icons) image"}) 97 .withProperty( 98 Component::GLYPH_HOVER_IMAGE, {"glyph_hover_image"}, 99 {"Resource name of the glyph (filter type icons) image that shows on mouse hover"}) 100 .withProperty(Component::GLPYH_ACTIVE, {"glyph_active"}, 101 {"Show or hide the filter type icons glyph. Valid values: true, false"}) 102 .withProperty(Component::GLYPH_PLACEMENT, {"glyph_placement"}, 103 {"Valid values: above, below, left, right"}) 104 .withProperty(Component::GLYPH_W, {"glyph_w"}, {"Width of one glyph frame in pixels"}) 105 .withProperty(Component::GLYPH_H, {"glyph_h"}, {"Height of one glyph frame in pixels"}); 106 107 Component LFODisplay = Component("CLFOGui"); 108 109 Component OscMenu = 110 Component("COSCMenu") 111 .withProperty(Component::FONT_SIZE, {"font_size"}, {"Font size in points, integer only"}) 112 .withProperty(Component::FONT_STYLE, {"font_style"}, 113 {"Valid values: normal, bold, italic, underline, strikethrough"}) 114 .withProperty(Component::TEXT_ALIGN, {"text_align"}, {"Valid values: left, center, right"}) 115 .withProperty(Component::TEXT_ALL_CAPS, {"text_allcaps"}, 116 {"Makes the oscillator menu text all caps. Valid values: true, false"}) 117 .withProperty(Component::TEXT_HOFFSET, {"text_hoffset"}, 118 {"Horizontal offset of oscillator menu text label, integer only"}) 119 .withProperty(Component::TEXT_VOFFSET, {"text_voffset"}, 120 {"Vertical offset of oscillator menu text label, integer only"}); 121 122 Component FxMenu = Component("CFXMenu"); 123 124 Component NumberField = 125 Component("CNumberField") 126 .withProperty(Component::BACKGROUND, {"image", "bg_resource", "bg_id"}, 127 {"Base image of the numberfield"}) 128 .withProperty(Component::NUMBERFIELD_CONTROLMODE, {"numberfield_controlmode"}, 129 {"Control mode of the numberfield. Refer to the list of ctrl_mode constants " 130 "in SurgeParamConfig.h"}) 131 .withProperty(Component::TEXT_COLOR, {"text_color"}, 132 {"Valid color formats are #RRGGBB, #RRGGBBAA, and named colors"}) 133 .withProperty(Component::TEXT_HOVER_COLOR, {"text_color.hover"}, 134 {"Valid color formats are #RRGGBB, #RRGGBBAA, and named colors"}); 135 136 Component VuMeter = Component("CVuMeter"); 137 138 Component Custom = Component("--CUSTOM--"); 139 140 Component Group = Component("--GROUP--"); 141 142 /* 143 * We could treat label like everything else but we didn't in S1.7/1.8 and Skin V1 144 * so we are stuck with this slight special casing 145 */ 146 Component Label = 147 Component("Internal Label") 148 .withProperty(Component::TEXT, {"text"}, {"Arbitrary text to be displayed on the label."}) 149 .withProperty(Component::CONTROL_TEXT, {"control_text"}, 150 {"Text tied to a particular Surge parameter. Use skin component connector " 151 "name as a value. Overrules arbitrary text set with 'text' property"}) 152 .withProperty(Component::TEXT_ALIGN, {"text_align"}, {"Valid values: left, center, right"}) 153 .withProperty(Component::FONT_SIZE, {"font_size"}, {"Font size in points, integer only"}) 154 .withProperty(Component::FONT_STYLE, {"font_style"}, 155 {"Valid values: normal, bold, italic, underline, strikethrough"}) 156 .withProperty(Component::TEXT_COLOR, {"color", "text_color"}, 157 {"Valid color formats are #RRGGBB, #RRGGBBAA, and named colors"}) 158 .withProperty(Component::BACKGROUND_COLOR, {"bg_color"}, 159 {"Background color of the label. Valid color formats are #RRGGBB, " 160 "#RRGGBBAA, or named colors"}) 161 .withProperty(Component::FRAME_COLOR, {"frame_color"}, 162 {"Color of the label frame/border. Valid color formats are #RRGGBB, " 163 "#RRGGBBAA, and named colors"}) 164 .withProperty(Component::IMAGE, {"image"}, 165 {"Resource name of the image to be displayed by the label. Overrides " 166 "background and frame/border colors"}); 167 168 } // namespace Components 169 170 namespace Global 171 { 172 Connector active_scene = Connector("global.active_scene", 7, 12, 40, 42, Components::HSwitch2) 173 .withHSwitch2Properties(IDB_SCENE_SELECT, 2, 2, 1); 174 Connector scene_mode = Connector("global.scene_mode", 54, 12, 40, 42, Components::HSwitch2) 175 .withHSwitch2Properties(IDB_SCENE_MODE, 4, 4, 1); 176 Connector fx_disable = Connector("global.fx_disable", 0, 0); 177 Connector fx_bypass = Connector("global.fx_bypass", 607, 12, 135, 27, Components::HSwitch2) 178 .withHSwitch2Properties(IDB_FX_GLOBAL_BYPASS, 4, 1, 4); 179 Connector character = Connector("global.character", 607, 42, 135, 12, Components::HSwitch2) 180 .withHSwitch2Properties(IDB_OSC_CHARACTER, 3, 1, 3); 181 Connector master_volume = Connector("global.volume", 756, 29); 182 183 Connector fx1_return = Connector("global.fx1_return", 759, 141); 184 Connector fx2_return = Connector("global.fx2_return", 759, 162); 185 } // namespace Global 186 187 namespace Scene 188 { 189 Connector polylimit = Connector("scene.polylimit", 100, 41, 43, 14, Components::NumberField) 190 .withBackground(IDB_NUMFIELD_POLY_SPLIT) 191 .withProperty(Component::NUMBERFIELD_CONTROLMODE, cm_polyphony) 192 .withProperty(Component::TEXT_COLOR, "scene.split_poly.text") 193 .withProperty(Component::TEXT_HOVER_COLOR, "scene.split_poly.text.hover"); 194 Connector splitpoint = 195 Connector("scene.splitpoint", 100, 11, 43, 14, Components::NumberField) 196 .withBackground(IDB_NUMFIELD_POLY_SPLIT) 197 .withProperty(Component::TEXT_COLOR, "scene.split_poly.text") 198 .withProperty(Component::TEXT_HOVER_COLOR, "scene.split_poly.text.hover"); 199 // this doesn't have a cm since it is special 200 201 Connector pbrange_dn = Connector("scene.pbrange_dn", 159, 110, 30, 13, Components::NumberField) 202 .withProperty(Component::NUMBERFIELD_CONTROLMODE, cm_pbdepth) 203 .withBackground(IDB_NUMFIELD_PITCHBEND) 204 .withProperty(Component::TEXT_COLOR, "scene.pbrange.text") 205 .withProperty(Component::TEXT_HOVER_COLOR, "scene.pbrange.text.hover"); 206 Connector pbrange_up = Connector("scene.pbrange_up", 187, 110, 30, 13, Components::NumberField) 207 .withProperty(Component::NUMBERFIELD_CONTROLMODE, cm_pbdepth) 208 .withBackground(IDB_NUMFIELD_PITCHBEND) 209 .withProperty(Component::TEXT_COLOR, "scene.pbrange.text") 210 .withProperty(Component::TEXT_HOVER_COLOR, "scene.pbrange.text.hover"); 211 Connector playmode = Connector("scene.playmode", 239, 87, 50, 47, Components::HSwitch2) 212 .withHSwitch2Properties(IDB_PLAY_MODE, 6, 6, 1); 213 Connector drift = Connector("scene.drift", 156, 141).asHorizontal().asWhite(); 214 Connector noise_color = Connector("scene.noise_color", 156, 162).asHorizontal().asWhite(); 215 216 Connector fmrouting = Connector("scene.fmrouting", 309, 83, 134, 52, Components::HSwitch2) 217 .withHSwitch2Properties(IDB_OSC_FM_ROUTING, 4, 1, 4); 218 Connector fmdepth = Connector("scene.fmdepth", 306, 152).asHorizontal().asWhite(); 219 220 Connector octave = Connector("scene.octave", 202, 194, 96, 18, Components::HSwitch2) 221 .withHSwitch2Properties(IDB_SCENE_OCTAVE, 7, 1, 7); 222 Connector pitch = Connector("scene.pitch", 156, 212).asHorizontal(); 223 Connector portatime = Connector("scene.portamento", 156, 234).asHorizontal(); 224 225 Connector keytrack_root = 226 Connector("scene.keytrack_root", 311, 266, 43, 14, Components::NumberField) 227 .withBackground(IDB_NUMFIELD_KEYTRACK_ROOT) 228 .withProperty(Component::NUMBERFIELD_CONTROLMODE, cm_notename) 229 .withProperty(Component::TEXT_COLOR, "scene.keytrackroot.text") 230 .withProperty(Component::TEXT_HOVER_COLOR, "scene.keytrackroot.text.hover"); 231 232 Connector scene_output_panel = Connector("scene.output.panel", 606, 78, Components::Group); 233 Connector volume = 234 Connector("scene.volume", 0, 0).asHorizontal().asWhite().inParent("scene.output.panel"); 235 Connector pan = 236 Connector("scene.pan", 0, 21).asHorizontal().asWhite().inParent("scene.output.panel"); 237 Connector width = 238 Connector("scene.width", 0, 42).asHorizontal().asWhite().inParent("scene.output.panel"); 239 Connector send_fx_1 = 240 Connector("scene.send_fx_1", 0, 63).asHorizontal().asWhite().inParent("scene.output.panel"); 241 Connector send_fx_2 = 242 Connector("scene.send_fx_2", 0, 84).asHorizontal().asWhite().inParent("scene.output.panel"); 243 244 Connector vel_sensitivity = 245 Connector("scene.velocity_sensitivity", 699, 301).asVertical().asWhite(); 246 Connector gain = Connector("scene.gain", 719, 301).asVertical().asWhite(); 247 } // namespace Scene 248 249 namespace Osc 250 { 251 Connector osc_select = 252 Connector("osc.select", 66, 69, 75, 13, Components::HSwitch2, Connector::OSCILLATOR_SELECT) 253 .withHSwitch2Properties(IDB_OSC_SELECT, 3, 1, 3); 254 Connector osc_display = 255 Connector("osc.display", 4, 81, 141, 99, Components::Custom, Connector::OSCILLATOR_DISPLAY); 256 257 Connector keytrack = 258 Connector("osc.keytrack", 4, 180, 45, 9, Components::Switch).withBackground(IDB_OSC_KEYTRACK); 259 Connector retrigger = Connector("osc.retrigger", 51, 180, 45, 9, Components::Switch) 260 .withBackground(IDB_OSC_RETRIGGER); 261 262 Connector octave = Connector("osc.octave", 0, 194, 96, 18, Components::HSwitch2) 263 .withHSwitch2Properties(IDB_OSC_OCTAVE, 7, 1, 7); 264 Connector osc_type = Connector("osc.type", 96, 194, 49, 18, Components::OscMenu) 265 .withProperty(Component::FONT_SIZE, 8) 266 .withProperty(Component::FONT_STYLE, "bold") 267 .withProperty(Component::TEXT_ALL_CAPS, "true") 268 .withProperty(Component::TEXT_ALIGN, "center") 269 .withProperty(Component::TEXT_HOFFSET, -2) 270 .withProperty(Component::TEXT_VOFFSET, -1); 271 272 Connector osc_param_panel = Connector("osc.param.panel", 6, 212, Components::Group); 273 Connector pitch = Connector("osc.pitch", 0, 0).asHorizontal().inParent("osc.param.panel"); 274 Connector param_1 = Connector("osc.param_1", 0, 22).asHorizontal().inParent("osc.param.panel"); 275 Connector param_2 = Connector("osc.param_2", 0, 44).asHorizontal().inParent("osc.param.panel"); 276 Connector param_3 = Connector("osc.param_3", 0, 66).asHorizontal().inParent("osc.param.panel"); 277 Connector param_4 = Connector("osc.param_4", 0, 88).asHorizontal().inParent("osc.param.panel"); 278 Connector param_5 = Connector("osc.param_5", 0, 110).asHorizontal().inParent("osc.param.panel"); 279 Connector param_6 = Connector("osc.param_6", 0, 132).asHorizontal().inParent("osc.param.panel"); 280 Connector param_7 = Connector("osc.param_7", 0, 154).asHorizontal().inParent("osc.param.panel"); 281 } // namespace Osc 282 283 namespace Mixer 284 { 285 Connector mixer_panel = Connector("mixer.panel", 154, 263, Components::Group); 286 Connector mute_o1 = Connector("mixer.mute_o1", 1, 0).asMixerMute().inParent("mixer.panel"); 287 Connector mute_o2 = Connector("mixer.mute_o2", 21, 0).asMixerMute().inParent("mixer.panel"); 288 Connector mute_o3 = Connector("mixer.mute_o3", 41, 0).asMixerMute().inParent("mixer.panel"); 289 Connector mute_ring12 = Connector("mixer.mute_ring12", 61, 0).asMixerMute().inParent("mixer.panel"); 290 Connector mute_ring23 = Connector("mixer.mute_ring23", 81, 0).asMixerMute().inParent("mixer.panel"); 291 Connector mute_noise = Connector("mixer.mute_noise", 101, 0).asMixerMute().inParent("mixer.panel"); 292 293 Connector solo_o1 = Connector("mixer.solo_o1", 1, 11).asMixerSolo().inParent("mixer.panel"); 294 Connector solo_o2 = Connector("mixer.solo_o2", 21, 11).asMixerSolo().inParent("mixer.panel"); 295 Connector solo_o3 = Connector("mixer.solo_o3", 41, 11).asMixerSolo().inParent("mixer.panel"); 296 Connector solo_ring12 = 297 Connector("mixer.solo_ring12", 61, 11).asMixerSolo().inParent("mixer.panel"); 298 Connector solo_ring23 = 299 Connector("mixer.solo_ring23", 81, 11).asMixerSolo().inParent("mixer.panel"); 300 Connector solo_noise = Connector("mixer.solo_noise", 101, 11).asMixerSolo().inParent("mixer.panel"); 301 302 Connector route_o1 = Connector("mixer.route_o1", 1, 22).asMixerRoute().inParent("mixer.panel"); 303 Connector route_o2 = Connector("mixer.route_o2", 21, 22).asMixerRoute().inParent("mixer.panel"); 304 Connector route_o3 = Connector("mixer.route_o3", 41, 22).asMixerRoute().inParent("mixer.panel"); 305 Connector route_ring12 = 306 Connector("mixer.route_ring12", 61, 22).asMixerRoute().inParent("mixer.panel"); 307 Connector route_ring23 = 308 Connector("mixer.route_ring23", 81, 22).asMixerRoute().inParent("mixer.panel"); 309 Connector route_noise = 310 Connector("mixer.route_noise", 101, 22).asMixerRoute().inParent("mixer.panel"); 311 312 Connector level_o1 = 313 Connector("mixer.level_o1", 0, 38).asVertical().asWhite().inParent("mixer.panel"); 314 Connector level_o2 = 315 Connector("mixer.level_o2", 20, 38).asVertical().asWhite().inParent("mixer.panel"); 316 Connector level_o3 = 317 Connector("mixer.level_o3", 40, 38).asVertical().asWhite().inParent("mixer.panel"); 318 Connector level_ring12 = 319 Connector("mixer.level_ring12", 60, 38).asVertical().asWhite().inParent("mixer.panel"); 320 Connector level_ring23 = 321 Connector("mixer.level_ring23", 80, 38).asVertical().asWhite().inParent("mixer.panel"); 322 Connector level_noise = 323 Connector("mixer.level_noise", 100, 38).asVertical().asWhite().inParent("mixer.panel"); 324 325 Connector level_prefiltergain = 326 Connector("mixer.level_prefiltergain", 120, 37).asVertical().asWhite().inParent("mixer.panel"); 327 } // namespace Mixer 328 329 namespace Filter 330 { 331 Connector config = Connector("filter.config", 455, 83, 134, 52, Components::HSwitch2) 332 .withHSwitch2Properties(IDB_FILTER_CONFIG, 8, 1, 8); 333 Connector feedback = Connector("filter.feedback", 457, 152).asHorizontal().asWhite(); 334 335 // FIXME - we should really expose the menu slider fully but for now make a composite FILTERSELECTOR 336 Connector type_1 = Connector("filter.type_1", 305, 191, 124, 21, Components::FilterSelector); 337 Connector subtype_1 = Connector("filter.subtype_1", 432, 194, 12, 18, Components::Switch) 338 .withBackground(IDB_FILTER_SUBTYPE); 339 Connector cutoff_1 = Connector("filter.cutoff_1", 306, 212).asHorizontal(); 340 Connector resonance_1 = Connector("filter.resonance_1", 306, 234).asHorizontal(); 341 342 Connector balance = Connector("filter.balance", 456, 224).asHorizontal(); 343 344 Connector type_2 = Connector("filter.type_2", 605, 191, 124, 21, Components::FilterSelector); 345 Connector subtype_2 = Connector("filter.subtype_2", 732, 194, 12, 18, Components::Switch) 346 .withBackground(IDB_FILTER_SUBTYPE); 347 Connector cutoff_2 = Connector("filter.cutoff_2", 600, 212).asHorizontal(); 348 Connector resonance_2 = Connector("filter.resonance_2", 600, 234).asHorizontal(); 349 350 Connector f2_offset_mode = Connector("filter.f2_offset_mode", 734, 217, 12, 18, Components::Switch) 351 .withBackground(IDB_FILTER2_OFFSET); 352 Connector f2_link_resonance = 353 Connector("filter.f2_link_resonance", 734, 239, 12, 18, Components::Switch) 354 .withBackground(IDB_FILTER2_RESONANCE_LINK); 355 356 Connector keytrack_1 = Connector("filter.keytrack_1", 309, 301).asVertical().asWhite(); 357 Connector keytrack_2 = Connector("filter.keytrack_2", 329, 301).asVertical().asWhite(); 358 359 Connector envmod_1 = Connector("filter.envmod_1", 549, 301).asVertical().asWhite(); 360 Connector envmod_2 = Connector("filter.envmod_2", 569, 301).asVertical().asWhite(); 361 362 Connector waveshaper_drive = Connector("filter.waveshaper_drive", 419, 301).asVertical().asWhite(); 363 Connector waveshaper_type = 364 Connector("filter.waveshaper_type", 388, 311, 28, 51, Components::HSwitch2) 365 .withHSwitch2Properties(IDB_WAVESHAPER_MODE, 6, 6, 1); 366 367 Connector highpass = Connector("filter.highpass", 354, 301).asVertical().asWhite(); 368 } // namespace Filter 369 370 namespace FEG 371 { 372 // If we never refer to it by type we can just construct it and don't need it in extern list 373 Connector feg_panel = Connector("feg.panel", 459, 267, Components::Group); 374 Connector mode = Connector("feg.mode", 93, 0, 34, 18, Components::HSwitch2) 375 .withHSwitch2Properties(IDB_ENV_MODE, 2, 2, 1) 376 .inParent("feg.panel"); 377 378 Connector attack_shape = Connector("feg.attack_shape", 4, 1, 20, 16, Components::HSwitch2) 379 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 380 .inParent("feg.panel"); 381 Connector decay_shape = Connector("feg.decay_shape", 24, 1, 20, 16, Components::HSwitch2) 382 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 383 .withProperty(Component::FRAME_OFFSET, 3) 384 .inParent("feg.panel"); 385 Connector release_shape = Connector("feg.release_shape", 65, 1, 20, 16, Components::HSwitch2) 386 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 387 .withProperty(Component::FRAME_OFFSET, 6) 388 .inParent("feg.panel"); 389 390 Connector attack = Connector("feg.attack", 0, 34).asVertical().asWhite().inParent("feg.panel"); 391 Connector decay = Connector("feg.decay", 20, 34).asVertical().asWhite().inParent("feg.panel"); 392 Connector sustain = Connector("feg.sustain", 40, 34).asVertical().asWhite().inParent("feg.panel"); 393 Connector release = Connector("feg.release", 60, 34).asVertical().asWhite().inParent("feg.panel"); 394 } // namespace FEG 395 396 namespace AEG 397 { 398 Connector aeg_panel = Connector("aeg.panel", 609, 267, Components::Group); 399 Connector mode = Connector("aeg.mode", 93, 0, 34, 18, Components::HSwitch2) 400 .withHSwitch2Properties(IDB_ENV_MODE, 2, 2, 1) 401 .inParent("aeg.panel"); 402 403 Connector attack_shape = Connector("aeg.attack_shape", 4, 1, 20, 16, Components::HSwitch2) 404 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 405 .inParent("aeg.panel"); 406 ; 407 Connector decay_shape = Connector("aeg.decay_shape", 24, 1, 20, 16, Components::HSwitch2) 408 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 409 .withProperty(Component::FRAME_OFFSET, 3) 410 .inParent("aeg.panel"); 411 ; 412 Connector release_shape = Connector("aeg.release_shape", 65, 1, 20, 16, Components::HSwitch2) 413 .withHSwitch2Properties(IDB_ENV_SHAPE, 3, 1, 3) 414 .withProperty(Component::FRAME_OFFSET, 6) 415 .inParent("aeg.panel"); 416 ; 417 418 Connector attack = Connector("aeg.attack", 0, 34).asVertical().asWhite().inParent("aeg.panel"); 419 ; 420 Connector decay = Connector("aeg.decay", 20, 34).asVertical().asWhite().inParent("aeg.panel"); 421 ; 422 Connector sustain = Connector("aeg.sustain", 40, 34).asVertical().asWhite().inParent("aeg.panel"); 423 ; 424 Connector release = Connector("aeg.release", 60, 34).asVertical().asWhite().inParent("aeg.panel"); 425 ; 426 } // namespace AEG 427 428 namespace FX 429 { 430 Connector fx_selector = 431 Connector("fx.selector", 766, 78, 120, 53, Components::Custom, Connector::FX_SELECTOR); 432 Connector fx_type = Connector("fx.type", 761, 194, 133, 18, Components::FxMenu); 433 434 Connector fx_preset = 435 Connector("fx.preset.name", 762, 212, 95, 12, Components::Custom, Connector::FXPRESET_LABEL); 436 Connector fx_jog = Connector("fx.preset.prevnext", 860, 212, Connector::JOG_FX).asJogPlusMinus(); 437 438 Connector fx_param_panel = Connector("fx.param.panel", 759, 224, Components::Group); 439 Connector param_1 = Connector("fx.param_1", 0, 0).inParent("fx.param.panel"); 440 Connector param_2 = Connector("fx.param_2", 0, 20).inParent("fx.param.panel"); 441 Connector param_3 = Connector("fx.param_3", 0, 40).inParent("fx.param.panel"); 442 Connector param_4 = Connector("fx.param_4", 0, 60).inParent("fx.param.panel"); 443 Connector param_5 = Connector("fx.param_5", 0, 80).inParent("fx.param.panel"); 444 Connector param_6 = Connector("fx.param_6", 0, 100).inParent("fx.param.panel"); 445 Connector param_7 = Connector("fx.param_7", 0, 120).inParent("fx.param.panel"); 446 Connector param_8 = Connector("fx.param_8", 0, 140).inParent("fx.param.panel"); 447 Connector param_9 = Connector("fx.param_9", 0, 160).inParent("fx.param.panel"); 448 Connector param_10 = Connector("fx.param_10", 0, 180).inParent("fx.param.panel"); 449 Connector param_11 = Connector("fx.param_11", 0, 200).inParent("fx.param.panel"); 450 Connector param_12 = Connector("fx.param_12", 0, 220).inParent("fx.param.panel"); 451 } // namespace FX 452 453 namespace LFO 454 { 455 // For now these two have component 'CUSTOM' and we hadn't pick a component in the code 456 Connector lfo_title_label = 457 Connector("lfo.title", 6, 489, 11, 83, Components::Custom, Connector::LFO_LABEL); 458 Connector lfo_presets = 459 Connector("lfo.presets", 6, 484, 13, 11, Components::Switch, Connector::LFO_MENU) 460 .withBackground(IDB_LFO_PRESET_MENU); 461 462 Connector lfo_main_panel = Connector("lfo.main.panel", 28, 478, Components::Group); 463 Connector rate = Connector("lfo.rate", 0, 0).asHorizontal().inParent("lfo.main.panel"); 464 Connector phase = Connector("lfo.phase", 0, 21).asHorizontal().inParent("lfo.main.panel"); 465 Connector deform = Connector("lfo.deform", 0, 42).asHorizontal().inParent("lfo.main.panel"); 466 Connector amplitude = Connector("lfo.amplitude", 0, 63).asHorizontal().inParent("lfo.main.panel"); 467 468 Connector trigger_mode = Connector("lfo.trigger_mode", 172, 484, 51, 39, Components::HSwitch2) 469 .withHSwitch2Properties(IDB_LFO_TRIGGER_MODE, 3, 3, 1); 470 Connector unipolar = Connector("lfo.unipolar", 172, 546, 51, 14, Components::Switch) 471 .withBackground(IDB_LFO_UNIPOLAR); 472 473 // combined LFO shape AND LFO display - TODO: split them to individual connectors for 1.9! 474 Connector shape = Connector("lfo.shape", 235, 480, 359, 84, Components::LFODisplay); 475 476 Connector mseg_editor = 477 Connector("lfo.mseg_editor", 597, 484, 11, 11, Components::Switch, Connector::MSEG_EDITOR_OPEN) 478 .withBackground(IDB_LFO_MSEG_EDIT); 479 480 Connector lfo_eg_panel = Connector("lfo.envelope.panel", 616, 493, Components::Group); 481 Connector delay = Connector("lfo.delay", 0, 0).inParent("lfo.envelope.panel"); 482 Connector attack = Connector("lfo.attack", 20, 0).inParent("lfo.envelope.panel"); 483 Connector hold = Connector("lfo.hold", 40, 0).inParent("lfo.envelope.panel"); 484 Connector decay = Connector("lfo.decay", 60, 0).inParent("lfo.envelope.panel"); 485 Connector sustain = Connector("lfo.sustain", 80, 0).inParent("lfo.envelope.panel"); 486 Connector release = Connector("lfo.release", 100, 0).inParent("lfo.envelope.panel"); 487 } // namespace LFO 488 489 /* 490 * We have a collection of controls which don't bind to parameters but which instead 491 * have a non-parameter type. These attach to SurgeGUIEditor by virtue of having the 492 * non-parameter type indicating the action, and the variables are not referenced 493 * except here at construction time and optionally via their names in the skin engine 494 */ 495 namespace OtherControls 496 { 497 Connector surge_menu = 498 Connector("controls.surge_menu", 844, 550, 50, 15, Components::HSwitch2, Connector::SURGE_MENU) 499 .withProperty(Component::BACKGROUND, IDB_MAIN_MENU) 500 .withProperty(Component::DRAGGABLE_HSWITCH, false); 501 502 Connector patch_browser = Connector("controls.patch_browser", 157, 12, 390, 28, Components::Custom, 503 Connector::PATCH_BROWSER); 504 Connector patch_category_jog = 505 Connector("controls.category.prevnext", 157, 42, Connector::JOG_PATCHCATEGORY).asJogPlusMinus(); 506 Connector patch_jog = 507 Connector("controls.patch.prevnext", 246, 42, Connector::JOG_PATCH).asJogPlusMinus(); 508 Connector patch_store = 509 Connector("controls.patch.store", 510, 42, 37, 12, Components::HSwitch2, Connector::STORE_PATCH) 510 .withHSwitch2Properties(IDB_STORE_PATCH, 1, 1, 1) 511 .withProperty(Component::DRAGGABLE_HSWITCH, false); 512 513 Connector status_panel = Connector("controls.status.panel", 562, 12, Components::Group); 514 Connector status_mpe = 515 Connector("controls.status.mpe", 0, 0, 31, 12, Components::Switch, Connector::STATUS_MPE) 516 .withBackground(IDB_MPE_BUTTON) 517 .inParent("controls.status.panel"); 518 Connector status_tune = 519 Connector("controls.status.tune", 0, 15, 31, 12, Components::Switch, Connector::STATUS_TUNE) 520 .withBackground(IDB_TUNE_BUTTON) 521 .inParent("controls.status.panel"); 522 Connector status_zoom = 523 Connector("controls.status.zoom", 0, 30, 31, 12, Components::Switch, Connector::STATUS_ZOOM) 524 .withBackground(IDB_ZOOM_BUTTON) 525 .inParent("controls.status.panel"); 526 527 Connector vu_meter = 528 Connector("controls.vu_meter", 763, 15, 123, 13, Components::VuMeter, Connector::MAIN_VU_METER); 529 530 Connector mseg_editor = Connector("msegeditor.window", 0, 57, 750, 365, Components::Custom, 531 Connector::MSEG_EDITOR_WINDOW); 532 533 Connector store_patch_dialog = Connector("controls.patch.store.window", 157, 57, 390, 143, 534 Components::Custom, Connector::STORE_PATCH_DIALOG); 535 536 // modulation panel is special, so it shows up as 'CUSTOM' with no connector and is special-cased in 537 // SurgeGUIEditor 538 Connector modulation_panel = Connector("controls.modulation.panel", 2, 402, Components::Custom); 539 } // namespace OtherControls 540 } // namespace Skin 541 } // namespace Surge 542