@@ -4,29 +4,29 @@ This file describes the available features for each plugin format. | |||
The limitations could be due to the plugin format itself or within DPF. | |||
If the limitation is within DPF, a link is provided to a description below on the reason for it. | |||
| Feature | JACK/Standalone | LADSPA | DSSI | LV2 | VST2 | VST3 | Feature | | |||
|---------------------|---------------------------------------|-------------------------|---------------------|-------------------------------|--------------------------------|----------------------------------|---------------------| | |||
| Audio port groups | [Yes*](#jack-audio-port-groups) | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Audio port groups | | |||
| Audio port as CV | Yes | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Audio port as CV | | |||
| Audio sidechan | Yes | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | Audio sidechan | | |||
| Bypass control | No | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | Bypass control | | |||
| MIDI input | Yes | No | Yes | Yes | Yes | Yes | MIDI input | | |||
| MIDI output | Yes | No | No | Yes | Yes | Yes | MIDI output | | |||
| Parameter changes | Yes | No | No | [No*](#lv2-parameter-changes) | Yes | Yes | Parameter changes | | |||
| Parameter groups | No | No | No | Yes | Yes | [No*](#vst3-is-work-in-progress) | Parameter groups | | |||
| Parameter outputs | No | No | No | Yes | No | [No*](#vst3-is-work-in-progress) | Parameter outputs | | |||
| Parameter triggers | Yes | No | No | Yes | [No*](#parameter-triggers) | [No*](#parameter-triggers) | Parameter triggers | | |||
| Programs | [Yes*](#jack-parameters-and-programs) | [No*](#ladspa-programs) | [Yes*](#dssi-state) | Yes | [No*](#vst2-programs) | Yes | Programs | | |||
| States | Yes | No | [Yes*](#dssi-state) | Yes | Yes | Yes | States | | |||
| Full/internal state | Yes | No | No | Yes | Yes | Yes | Full/internal state | | |||
| Time position | Yes | No | No | Yes | Yes | Yes | Time position | | |||
| UI | [Yes*](#jack-custom-ui-only) | No | External only | Yes | Embed only | Embed only | UI | | |||
| UI bg/fg colors | No | No | No | Yes | No | No? | UI bg/fg colors | | |||
| UI direct access | Yes | No | No | Yes | Yes | Yes | UI direct access | | |||
| UI host-filebrowser | No | No | No | Yes | [No*](#vst2-potential-support) | [No*](#vst3-is-work-in-progress) | UI host-filebrowser | | |||
| UI host-resize | Yes | No | Yes | Yes | No | [No*](#vst3-is-work-in-progress) | UI host-resize | | |||
| UI remote control | No | No | Yes | Yes | No | Yes | UI remote control | | |||
| UI send midi note | Yes | No | Yes | Yes | Yes | Yes | UI send midi note | | |||
| Feature | JACK/Standalone | LADSPA | DSSI | LV2 | VST2 | VST3 | CLAP | Feature | | |||
|---------------------|---------------------------------------|--------------------|---------------------|-------------------------------|----------------------------|----------------------------|-------------------------------|---------------------| | |||
| Audio port groups | [Yes*](#jack-audio-port-groups) | No | No | Yes | No | Yes | Yes | Audio port groups | | |||
| Audio port as CV | Yes | No | No | Yes | No | [Yes*](#vst3-cv) | [No*](#work-in-progress) | Audio port as CV | | |||
| Audio sidechan | Yes | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Audio sidechan | | |||
| Bypass control | No | No | No | Yes | [No*](#vst2-deprecated) | Yes | Yes | Bypass control | | |||
| MIDI input | Yes | No | Yes | Yes | Yes | Yes | Yes | MIDI input | | |||
| MIDI output | Yes | No | No | Yes | Yes | Yes | Yes | MIDI output | | |||
| Parameter changes | Yes | No | No | [No*](#lv2-parameter-changes) | Yes | Yes | Yes | Parameter changes | | |||
| Parameter groups | No | No | No | Yes | Yes | [No*](#work-in-progress) | Yes | Parameter groups | | |||
| Parameter outputs | No | No | No | Yes | No | Yes | Yes | Parameter outputs | | |||
| Parameter triggers | Yes | No | No | Yes | [No*](#parameter-triggers) | [No*](#parameter-triggers) | [No*](#parameter-triggers) | Parameter triggers | | |||
| Programs | [Yes*](#jack-parameters-and-programs) | [No*](#ladspa-rdf) | [Yes*](#dssi-state) | Yes | [No*](#vst2-programs) | Yes | No | Programs | | |||
| States | Yes | No | [Yes*](#dssi-state) | Yes | Yes | Yes | Yes | States | | |||
| Full/internal state | Yes | No | No | Yes | Yes | Yes | Yes | Full/internal state | | |||
| Time position | Yes | No | No | Yes | Yes | Yes | Yes | Time position | | |||
| UI | [Yes*](#jack-custom-ui-only) | No | External only | Yes | Embed only | Embed only | Yes | UI | | |||
| UI bg/fg colors | No | No | No | Yes | No | No? | No | UI bg/fg colors | | |||
| UI direct access | Yes | No | No | Yes | Yes | Yes | Yes | UI direct access | | |||
| UI host-filebrowser | No | No | No | Yes | [No*](#vst2-deprecated) | [No*](#work-in-progress) | [No*](#work-in-progress) | UI host-filebrowser | | |||
| UI host-resize | Yes | No | Yes | Yes | No | Yes | Yes | UI host-resize | | |||
| UI remote control | No | No | Yes | Yes | No | Yes | No | UI remote control | | |||
| UI send midi note | Yes | No | Yes | Yes | Yes | Yes | Yes | UI send midi note | | |||
For things that could be unclear: | |||
@@ -59,7 +59,7 @@ MIDI CCs are used for parameter changes (matching the `midiCC` value you set on | |||
There is no generic plugin editor view. | |||
If your plugin has no custom UI, the standalone executable will run but not show any window. | |||
## LADSPA programs | |||
## LADSPA RDF | |||
Programs for LADSPA could be done via LRDF but this is not supported in DPF. | |||
@@ -78,7 +78,7 @@ But if we involve programs, they would need to pass through the UI in order to w | |||
Although this is already implemented in DPF (through a custom extension), this is not implemented on most hosts. | |||
So for now you can pretty much treat it as if not supported. | |||
## VST2 potential support | |||
## VST2 deprecated | |||
Not supported in DPF at the moment. | |||
It could eventually be, but likely not due to VST2 being phased out by Steinberg. | |||
@@ -88,6 +88,11 @@ Contact DPF authors if you require such a feature. | |||
VST2 program support requires saving state of all programs in memory, which is very expensive and thus not done in DPF. | |||
## VST3 is work in progress | |||
## VST3 CV | |||
Although VST3 officially supports CV (Control Voltage) tagged audio ports, | |||
at the moment no host supports such feature and thus it is not possible to validate it. | |||
## Work in progress | |||
Feature is possible, just not implemented yet in DPF. |
@@ -3,21 +3,21 @@ | |||
[](https://github.com/DISTRHO/DPF/actions/workflows/cmake.yml) | |||
[](https://github.com/DISTRHO/DPF/actions/workflows/example-plugins.yml) | |||
DPF is designed to make development of new plugins an easy and enjoyable task.<br/> | |||
It allows developers to create plugins with custom UIs using a simple C++ API.<br/> | |||
The framework facilitates exporting various different plugin formats from the same code-base.<br/> | |||
DPF is designed to make development of new plugins an easy and enjoyable task. | |||
It allows developers to create plugins with custom UIs using a simple C++ API. | |||
The framework facilitates exporting various different plugin formats from the same code-base. | |||
DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats.<br/> | |||
All current plugin format implementations are complete.<br/> | |||
A JACK/Standalone mode is also available, allowing you to quickly test plugins.<br/> | |||
DPF can build for LADSPA, DSSI, LV2, VST2, VST3 and CLAP formats. | |||
A JACK/Standalone mode is also available, allowing you to quickly test plugins. | |||
Plugin DSP and UI communication is done via key-value string pairs.<br/> | |||
You send messages from the UI to the DSP side, which is automatically saved in the host when required.<br/> | |||
(You can also store state internally if needed, but this breaks DSSI compatibility).<br/> | |||
Plugin DSP and UI communication is done via key-value string pairs. | |||
You send messages from the UI to the DSP side, which is automatically saved in the host when required. | |||
(You can also store state internally if needed, but this breaks DSSI compatibility). | |||
Getting time information from the host is possible.<br/> | |||
It uses the same format as the JACK Transport API, making porting some code easier.<br/> | |||
Getting time information from the host is possible. | |||
It uses the same format as the JACK Transport API, making porting some code easier. | |||
Provided features and implementation status for specific plugin formats can be seen in [FEATURES.md](FEATURES.md). | |||
## Licensing | |||
@@ -31,43 +31,11 @@ Bug reports happen on the [DPF github project](https://github.com/DISTRHO/DPF/is | |||
Online documentation is available at [https://distrho.github.io/DPF/](https://distrho.github.io/DPF/). | |||
Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/). | |||
Online help and discussion about DPF happens in the [kx.studio chat, DPF room](https://chat.kx.studio/channel/dpf). | |||
## List of plugins made with DPF: | |||
- [DISTRHO glBars](https://github.com/DISTRHO/glBars) | |||
- [DISTRHO Kars](https://github.com/DISTRHO/Kars) | |||
- [DISTRHO Mini-Series](https://github.com/DISTRHO/Mini-Series) | |||
- [DISTRHO MVerb](https://github.com/DISTRHO/MVerb) | |||
- [DISTRHO ndc Plugs](https://github.com/DISTRHO/ndc-Plugs) | |||
- [DISTRHO Nekobi](https://github.com/DISTRHO/Nekobi) | |||
- [DISTRHO ProM](https://github.com/DISTRHO/ProM) | |||
- [Dragonfly Reverb](https://michaelwillis.github.io/dragonfly-reverb) | |||
- [Fogpad-port](https://github.com/linuxmao-org/fogpad-port) | |||
- [master_me](https://github.com/trummerschlunk/master_me) | |||
- [Ninjas2](https://github.com/rghvdberg/ninjas2) | |||
- [osamc-lv2-workshop](https://github.com/osamc-lv2-workshop/lv2-workshop) (simple plugins code examples) | |||
- [QuadraFuzz](https://github.com/jpcima/quadrafuzz) | |||
- [Regrader-Port](https://github.com/linuxmao-org/regrader-port) | |||
- [Rezonateur](https://github.com/jpcima/rezonateur) | |||
- [Spectacle-analyzer](https://github.com/jpcima/spectacle/) | |||
- [Stone Phaser](https://github.com/jpcima/stone-phaser) | |||
- [String-machine](https://github.com/jpcima/string-machine) | |||
- [Uhhyou Plugins](https://github.com/ryukau/LV2Plugins) | |||
- [VL1-emulator](https://github.com/linuxmao-org/VL1-emulator) | |||
- [Wolf Shaper](https://github.com/pdesaulniers/wolf-shaper) | |||
- [Wolf Spectrum](https://github.com/pdesaulniers/wolf-spectrum) | |||
- [YK Chorus](https://github.com/SpotlightKid/ykchorus) | |||
- [ZamAudio Suite](https://github.com/zamaudio/zam-plugins) | |||
## Work in progress | |||
- [CV-LFO-blender-LV2](https://github.com/BramGiesen/cv-lfo-blender-lv2) | |||
- [fverb](https://github.com/jpcima/fverb) | |||
- [Juice Plugins](https://github.com/DISTRHO/JuicePlugins) | |||
- [gunshot](https://github.com/soerenbnoergaard/gunshot) | |||
- [midiomatic](https://github.com/SpotlightKid/midiomatic) | |||
- [Shiro Plugins](https://github.com/ninodewit/SHIRO-Plugins/) | |||
- [Shiru Plugins](https://github.com/linuxmao-org/shiru-plugins) | |||
Checking the [github "DPF" tag](https://github.com/topics/dpf) can potentially bring up other DPF-made plugins. | |||
Plugin examples are available in the `example/` folder inside this repo. | |||
See [this wiki page](https://github.com/DISTRHO/DPF/wiki/Plugins-made-with-DPF) for a list of plugins made with DPF. | |||
Plugin examples are also available in the `example/` folder inside this repo. |
@@ -28,6 +28,17 @@ TopLevelWidget::PrivateData::PrivateData(TopLevelWidget* const s, Window& w) | |||
selfw(s), | |||
window(w) | |||
{ | |||
/* if window already has a top-level-widget, make the new one match the first one in size | |||
* this is needed because window creation and resize is a synchronous operation in some systems. | |||
* as such, there's a chance the non-1st top-level-widgets would never get a valid size. | |||
*/ | |||
if (!window.pData->topLevelWidgets.empty()) | |||
{ | |||
TopLevelWidget* const first = window.pData->topLevelWidgets.front(); | |||
selfw->pData->size = first->getSize(); | |||
} | |||
window.pData->topLevelWidgets.push_back(self); | |||
} | |||
@@ -35,6 +35,16 @@ | |||
#define PUGL_LOCAL_CLIENT_MSG (WM_USER + 52) | |||
#define PUGL_USER_TIMER_MIN 9470 | |||
#ifdef __cplusplus | |||
# define PUGL_INIT_STRUCT \ | |||
{} | |||
#else | |||
# define PUGL_INIT_STRUCT \ | |||
{ \ | |||
0 \ | |||
} | |||
#endif | |||
typedef BOOL(WINAPI* PFN_SetProcessDPIAware)(void); | |||
typedef HRESULT(WINAPI* PFN_GetProcessDpiAwareness)(HANDLE, DWORD*); | |||
typedef HRESULT(WINAPI* PFN_GetScaleFactorForMonitor)(HMONITOR, DWORD*); | |||
@@ -80,7 +90,7 @@ puglRegisterWindowClass(const char* name) | |||
module = GetModuleHandle(NULL); | |||
} | |||
WNDCLASSEX wc = {0}; | |||
WNDCLASSEX wc = PUGL_INIT_STRUCT; | |||
if (GetClassInfoEx(module, name, &wc)) { | |||
return true; // Already registered | |||
} | |||
@@ -472,8 +482,8 @@ initKeyEvent(PuglKeyEvent* event, | |||
} | |||
} else if (!dead) { | |||
// Translate unshifted key | |||
BYTE keyboardState[256] = {0}; | |||
wchar_t buf[5] = {0}; | |||
BYTE keyboardState[256] = PUGL_INIT_STRUCT; | |||
wchar_t buf[5] = PUGL_INIT_STRUCT; | |||
event->key = puglDecodeUTF16( | |||
buf, ToUnicode(vkey, vcode, keyboardState, buf, 4, 1 << 2)); | |||
@@ -689,7 +699,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) | |||
pt.y = GET_Y_LPARAM(lParam); | |||
if (!view->impl->mouseTracked) { | |||
TRACKMOUSEEVENT tme = {0}; | |||
TRACKMOUSEEVENT tme = PUGL_INIT_STRUCT; | |||
tme.cbSize = sizeof(tme); | |||
tme.dwFlags = TME_LEAVE; | |||
@@ -72,6 +72,12 @@ static const uint32_t kCVPortHasPositiveUnipolarRange = 0x40; | |||
*/ | |||
static const uint32_t kCVPortHasScaledRange = 0x80; | |||
/** | |||
CV port is optional, allowing hosts that do no CV ports to load the plugin. | |||
When loaded in hosts that don't support CV, the float* buffer for this port will be null. | |||
*/ | |||
static const uint32_t kCVPortIsOptional = 0x100; | |||
/** @} */ | |||
/* ------------------------------------------------------------------------------------------------------------ | |||
@@ -14,6 +14,14 @@ | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | |||
/* TODO items: | |||
* CV: write a specification | |||
* INFO: define url, manual url, support url and string version | |||
* PARAMETERS: test parameter triggers | |||
* States: skip DSP/UI only states as appropriate | |||
* UI: expose external-only UIs | |||
*/ | |||
#include "DistrhoPluginInternal.hpp" | |||
#include "extra/ScopedPointer.hpp" | |||
@@ -1070,8 +1078,7 @@ public: | |||
fPlugin.run(audioInputs, audioOutputs, frames); | |||
#endif | |||
// TODO set last frame | |||
flushParameters(nullptr, process->out_events); | |||
flushParameters(nullptr, process->out_events, frames - 1); | |||
fOutputEvents = nullptr; | |||
} | |||
@@ -1210,7 +1217,9 @@ public: | |||
return true; | |||
} | |||
void flushParameters(const clap_input_events_t* const in, const clap_output_events_t* const out) | |||
void flushParameters(const clap_input_events_t* const in, | |||
const clap_output_events_t* const out, | |||
const uint32_t frameOffset) | |||
{ | |||
if (const uint32_t len = in != nullptr ? in->size(in) : 0) | |||
{ | |||
@@ -1231,7 +1240,7 @@ public: | |||
if (out != nullptr) | |||
{ | |||
clap_event_param_value_t clapEvent = { | |||
{ sizeof(clap_event_param_value_t), 0, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE }, | |||
{ sizeof(clap_event_param_value_t), frameOffset, 0, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_IS_LIVE }, | |||
0, nullptr, 0, 0, 0, 0, 0.0 | |||
}; | |||
@@ -2336,7 +2345,7 @@ static CLAP_ABI bool clap_plugin_params_text_to_value(const clap_plugin_t* plugi | |||
static CLAP_ABI void clap_plugin_params_flush(const clap_plugin_t* plugin, const clap_input_events_t* in, const clap_output_events_t* out) | |||
{ | |||
PluginCLAP* const instance = static_cast<PluginCLAP*>(plugin->plugin_data); | |||
return instance->flushParameters(in, out); | |||
return instance->flushParameters(in, out, 0); | |||
} | |||
static const clap_plugin_params_t clap_plugin_params = { | |||
@@ -532,6 +532,9 @@ void lv2_generate_ttl(const char* const basename) | |||
} | |||
} | |||
if ((port.hints & (kAudioPortIsCV|kCVPortIsOptional)) == (kAudioPortIsCV|kCVPortIsOptional)) | |||
pluginString += " lv2:portProperty lv2:connectionOptional;\n"; | |||
if (i+1 == DISTRHO_PLUGIN_NUM_INPUTS) | |||
pluginString += " ] ;\n"; | |||
else | |||
@@ -817,11 +820,10 @@ void lv2_generate_ttl(const char* const basename) | |||
// MIDI CC binding | |||
if (const uint8_t midiCC = plugin.getParameterMidiCC(i)) | |||
{ | |||
char midiCCBuf[7]; | |||
snprintf(midiCCBuf, sizeof(midiCCBuf), "B0%02x00", midiCC); | |||
pluginString += " midi:binding \""; | |||
pluginString += midiCCBuf; | |||
pluginString += "\"^^midi:MidiEvent ;\n"; | |||
pluginString += " midi:binding [\n"; | |||
pluginString += " a midi:Controller ;\n"; | |||
pluginString += " midi:controllerNumber " + String(midiCC) + " ;\n"; | |||
pluginString += " ] ;\n"; | |||
} | |||
// unit | |||
@@ -14,28 +14,6 @@ | |||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||
*/ | |||
#include "DistrhoPluginInternal.hpp" | |||
#include "../DistrhoPluginUtils.hpp" | |||
#include "../extra/ScopedPointer.hpp" | |||
#define DPF_VST3_MAX_BUFFER_SIZE 32768 | |||
#define DPF_VST3_MAX_SAMPLE_RATE 384000 | |||
#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
# include "../extra/RingBuffer.hpp" | |||
#endif | |||
#include "travesty/audio_processor.h" | |||
#include "travesty/component.h" | |||
#include "travesty/edit_controller.h" | |||
#include "travesty/factory.h" | |||
#include "travesty/host.h" | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
/* TODO items: | |||
* == parameters | |||
* - test parameter triggers | |||
@@ -43,7 +21,6 @@ | |||
* - parameter groups via unit ids | |||
* - test parameter changes from DSP (aka requestParameterValueChange) | |||
* - implement getParameterNormalized/setParameterNormalized for MIDI CC params ? | |||
* - fully implemented parameter stuff and verify | |||
* - float to int safe casting | |||
* - verify that latency changes works (with and without DPF_VST3_USES_SEPARATE_CONTROLLER) | |||
* == MIDI | |||
@@ -60,6 +37,28 @@ | |||
* - do something with set_io_mode? | |||
*/ | |||
#include "DistrhoPluginInternal.hpp" | |||
#include "../DistrhoPluginUtils.hpp" | |||
#include "../extra/ScopedPointer.hpp" | |||
#define DPF_VST3_MAX_BUFFER_SIZE 32768 | |||
#define DPF_VST3_MAX_SAMPLE_RATE 384000 | |||
#define DPF_VST3_MAX_LATENCY DPF_VST3_MAX_SAMPLE_RATE * 10 | |||
#if DISTRHO_PLUGIN_HAS_UI | |||
# include "../extra/RingBuffer.hpp" | |||
#endif | |||
#include "travesty/audio_processor.h" | |||
#include "travesty/component.h" | |||
#include "travesty/edit_controller.h" | |||
#include "travesty/factory.h" | |||
#include "travesty/host.h" | |||
#include <map> | |||
#include <string> | |||
#include <vector> | |||
START_NAMESPACE_DISTRHO | |||
// -------------------------------------------------------------------------------------------------------------------- | |||
@@ -2733,7 +2732,7 @@ private: | |||
} | |||
if (busId < busInfo.groups) | |||
return portCountToSpeaker(fPlugin.getAudioPortCountWithGroupId(isInput, busId)); | |||
return portCountToSpeaker(fPlugin.getAudioPortCountWithGroupId(isInput, portGroupId)); | |||
if (busInfo.audio != 0 && busId == busInfo.groups) | |||
return portCountToSpeaker(busInfo.audioPorts); | |||
@@ -27,7 +27,7 @@ | |||
START_NAMESPACE_DISTRHO | |||
#if ! DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||
static const sendNoteFunc sendNoteCallback = nullptr; | |||
static constexpr const sendNoteFunc sendNoteCallback = nullptr; | |||
#endif | |||
// ----------------------------------------------------------------------- | |||
@@ -373,13 +373,12 @@ void DistrhoPluginNekobi::run(const float**, float** outputs, uint32_t frames, c | |||
fSynth.nugget_remains = XSYNTH_NUGGET_SIZE; | |||
/* process any ready events */ | |||
while (curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame) | |||
for (; curEventIndex < midiEventCount && framesDone == midiEvents[curEventIndex].frame; ++curEventIndex) | |||
{ | |||
if (midiEvents[curEventIndex].size > MidiEvent::kDataSize) | |||
continue; | |||
nekobee_handle_raw_event(&fSynth, midiEvents[curEventIndex].size, midiEvents[curEventIndex].data); | |||
curEventIndex++; | |||
} | |||
/* calculate the sample count (burstSize) for the next nekobee_voice_render() call to be the smallest of: | |||
@@ -376,7 +376,7 @@ nekobee_voice_render(nekobee_synth_t *synth, nekobee_voice_t *voice, | |||
osc_index += sample_count; | |||
if (do_control_update) { | |||
if (do_control_update || osc_index > MINBLEP_BUFFER_LENGTH - (XSYNTH_NUGGET_SIZE + LONGEST_DD_PULSE_LENGTH)) { | |||
/* do those things should be done only once per control-calculation | |||
* interval ("nugget"), such as voice check-for-dead, pitch envelope | |||
* calculations, volume envelope phase transition checks, etc. */ | |||
@@ -25,16 +25,6 @@ START_NAMESPACE_DGL | |||
class ResizeHandle : public TopLevelWidget | |||
{ | |||
public: | |||
/** Constructor for placing this handle on top of a window. */ | |||
explicit ResizeHandle(Window& window) | |||
: TopLevelWidget(window), | |||
handleSize(16), | |||
hasCursor(false), | |||
isResizing(false) | |||
{ | |||
resetArea(); | |||
} | |||
/** Overloaded constructor, will fetch the window from an existing top-level widget. */ | |||
explicit ResizeHandle(TopLevelWidget* const tlw) | |||
: TopLevelWidget(tlw->getWindow()), | |||
@@ -56,31 +46,27 @@ public: | |||
protected: | |||
void onDisplay() override | |||
{ | |||
// TODO implement gl3 stuff in DPF | |||
#ifndef DGL_USE_OPENGL3 | |||
const GraphicsContext& context(getGraphicsContext()); | |||
const double lineWidth = 1.0 * getScaleFactor(); | |||
#if defined(DGL_OPENGL) && !defined(DGL_USE_OPENGL3) | |||
glMatrixMode(GL_MODELVIEW); | |||
#endif | |||
glLineWidth(lineWidth); | |||
// draw white lines, 1px wide | |||
Color(1.0f, 1.0f, 1.0f).setFor(context); | |||
l1.draw(context, lineWidth); | |||
l2.draw(context, lineWidth); | |||
l3.draw(context, lineWidth); | |||
glColor3f(1.0f, 1.0f, 1.0f); | |||
drawLine(l1); | |||
drawLine(l2); | |||
drawLine(l3); | |||
// draw black lines, offset by 1px and 1px wide | |||
Color(0.0f, 0.0f, 0.0f).setFor(context); | |||
glColor3f(0.0f, 0.0f, 0.0f); | |||
Line<double> l1b(l1), l2b(l2), l3b(l3); | |||
l1b.moveBy(lineWidth, lineWidth); | |||
l2b.moveBy(lineWidth, lineWidth); | |||
l3b.moveBy(lineWidth, lineWidth); | |||
l1b.draw(context, lineWidth); | |||
l2b.draw(context, lineWidth); | |||
l3b.draw(context, lineWidth); | |||
#endif | |||
drawLine(l1b); | |||
drawLine(l2b); | |||
drawLine(l3b); | |||
} | |||
bool onMouse(const MouseEvent& ev) override | |||
@@ -201,6 +187,25 @@ private: | |||
l3.setEndPos(x + offset, y + linesize + offset); | |||
} | |||
void drawLine(const Line<double>& line) | |||
{ | |||
drawLine(line.getStartPos(), line.getEndPos()); | |||
} | |||
void drawLine(const Point<double>& posStart, const Point<double>& posEnd) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(posStart != posEnd,); | |||
glBegin(GL_LINES); | |||
{ | |||
glVertex2d(posStart.getX(), posStart.getY()); | |||
glVertex2d(posEnd.getX(), posEnd.getY()); | |||
} | |||
glEnd(); | |||
} | |||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ResizeHandle) | |||
}; | |||