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 #pragma once 17 #include "vstcontrols.h" 18 #include "SurgeStorage.h" 19 #include "CDIBitmap.h" 20 #include "DspUtilities.h" 21 #include "SkinSupport.h" 22 #include "CursorControlGuard.h" 23 24 #define OSC_MOD_ANIMATION 0 25 26 class COscillatorDisplay : public VSTGUI::CControl, 27 public Surge::UI::SkinConsumingComponent, 28 public Surge::UI::CursorControlAdapter<COscillatorDisplay> 29 { 30 public: COscillatorDisplay(const VSTGUI::CRect & size,VSTGUI::IControlListener * l,OscillatorStorage * oscdata,SurgeStorage * storage)31 COscillatorDisplay(const VSTGUI::CRect &size, VSTGUI::IControlListener *l, 32 OscillatorStorage *oscdata, SurgeStorage *storage) 33 : VSTGUI::CControl(size, l, 0, 0), Surge::UI::CursorControlAdapter<COscillatorDisplay>( 34 storage) 35 { 36 this->oscdata = oscdata; 37 this->storage = storage; 38 controlstate = 0; 39 40 this->scene = oscdata->type.scene - 1; 41 this->osc_in_scene = oscdata->type.ctrlgroup_entry; 42 43 if (storage->getPatch() 44 .dawExtraState.editor.oscExtraEditState[scene][osc_in_scene] 45 .hasCustomEditor) 46 { 47 openCustomEditor(); 48 } 49 } ~COscillatorDisplay()50 virtual ~COscillatorDisplay() {} 51 52 /* 53 * Custom Editor Support where I can change this UI based on a type to allow edits 54 * Currently only used by alias oscillator 55 */ 56 struct CustomEditor 57 { CustomEditorCustomEditor58 CustomEditor(COscillatorDisplay *d) : disp(d) {} 59 virtual ~CustomEditor() = default; 60 virtual void draw(VSTGUI::CDrawContext *dc) = 0; 61 onMouseDownCustomEditor62 virtual VSTGUI::CMouseEventResult onMouseDown(VSTGUI::CPoint &where, 63 const VSTGUI::CButtonState &buttons) 64 { 65 return VSTGUI::kMouseEventNotHandled; 66 }; onMouseUpCustomEditor67 virtual VSTGUI::CMouseEventResult onMouseUp(VSTGUI::CPoint &where, 68 const VSTGUI::CButtonState &buttons) 69 { 70 return VSTGUI::kMouseEventNotHandled; 71 }; onMouseMovedCustomEditor72 virtual VSTGUI::CMouseEventResult onMouseMoved(VSTGUI::CPoint &where, 73 const VSTGUI::CButtonState &buttons) 74 { 75 return VSTGUI::kMouseEventNotHandled; 76 }; onMouseExitedCustomEditor77 virtual VSTGUI::CMouseEventResult onMouseExited(VSTGUI::CPoint &where, 78 const VSTGUI::CButtonState &buttons) 79 { 80 return VSTGUI::kMouseEventNotHandled; 81 }; onMouseEnteredCustomEditor82 virtual VSTGUI::CMouseEventResult onMouseEntered(VSTGUI::CPoint &where, 83 const VSTGUI::CButtonState &buttons) 84 { 85 return VSTGUI::kMouseEventNotHandled; 86 }; 87 onWheelCustomEditor88 virtual bool onWheel(const VSTGUI::CPoint &where, const float &distance, 89 const VSTGUI::CButtonState &buttons) 90 { 91 return false; 92 } 93 94 // Entered and Exited too 95 COscillatorDisplay *disp; 96 }; 97 bool canHaveCustomEditor(); 98 void openCustomEditor(); 99 void closeCustomEditor(); 100 std::shared_ptr<CustomEditor> customEditor; // I really want unique but that 101 // clashes with the VSTGUI copy semantics 102 bool customEditorActive = false, editButtonHover = false; 103 VSTGUI::CRect customEditButtonRect; 104 105 virtual void draw(VSTGUI::CDrawContext *dc) override; 106 107 void drawExtraEditButton(VSTGUI::CDrawContext *dc, const std::string &label); 108 109 void loadWavetable(int id); 110 void loadWavetableFromFile(); 111 112 // virtual void mouse (CDrawContext *pContext, VSTGUI::CPoint &where, long button = -1); 113 virtual VSTGUI::CMouseEventResult onMouseDown(VSTGUI::CPoint &where, 114 const VSTGUI::CButtonState &buttons) override; 115 virtual VSTGUI::CMouseEventResult onMouseUp(VSTGUI::CPoint &where, 116 const VSTGUI::CButtonState &buttons) override; 117 virtual VSTGUI::CMouseEventResult onMouseMoved(VSTGUI::CPoint &where, 118 const VSTGUI::CButtonState &buttons) override; 119 VSTGUI::CMouseEventResult onMouseExited(VSTGUI::CPoint &where, 120 const VSTGUI::CButtonState &buttons) override; 121 VSTGUI::CMouseEventResult onMouseEntered(VSTGUI::CPoint &where, 122 const VSTGUI::CButtonState &buttons) override; 123 bool onWheel(const VSTGUI::CPoint &where, const float &distance, 124 const VSTGUI::CButtonState &buttons) override; 125 126 void invalidateIfIdIsInRange(int id); 127 128 #if OSC_MOD_ANIMATION setIsMod(bool b)129 void setIsMod(bool b) 130 { 131 is_mod = b; 132 mod_time = 0; 133 } setModSource(modsources m)134 void setModSource(modsources m) { modsource = m; } tickModTime()135 void tickModTime() { mod_time += 1.0 / 30.0; } 136 #endif 137 138 protected: 139 void populateMenu(VSTGUI::COptionMenu *m, int selectedItem); 140 bool populateMenuForCategory(VSTGUI::COptionMenu *parent, int categoryId, int selectedItem); 141 142 OscillatorStorage *oscdata; 143 SurgeStorage *storage; 144 unsigned int controlstate; 145 146 int scene, osc_in_scene; 147 148 bool doingDrag = false; 149 enum 150 { 151 NONE, 152 PREV, 153 MENU, 154 NEXT 155 } isWTHover = NONE; 156 157 static constexpr float scaleDownBy = 0.235; 158 159 #if OSC_MOD_ANIMATION 160 bool is_mod = false; 161 modsources modsource = ms_original; 162 float mod_time = 0; 163 #endif 164 VSTGUI::CRect rnext, rprev, rmenu; 165 VSTGUI::CPoint lastpos; 166 CLASS_METHODS(COscillatorDisplay, VSTGUI::CControl) 167 }; 168