@@ -31,9 +31,9 @@ namespace DistrhoArtworkNekobi | |||
const unsigned int claw2Height = 32; | |||
extern const char* knobData; | |||
const unsigned int knobDataSize = 390000; | |||
const unsigned int knobDataSize = 10000; | |||
const unsigned int knobWidth = 50; | |||
const unsigned int knobHeight = 1950; | |||
const unsigned int knobHeight = 50; | |||
extern const char* run1Data; | |||
const unsigned int run1DataSize = 4096; | |||
@@ -41,10 +41,11 @@ DistrhoUINekobi::DistrhoUINekobi() | |||
Image sliderImage(DistrhoArtworkNekobi::sliderData, DistrhoArtworkNekobi::sliderWidth, DistrhoArtworkNekobi::sliderHeight); | |||
fSliderWaveform = new ImageSlider(this, sliderImage); | |||
fSliderWaveform->setStartPos(133, 38); | |||
fSliderWaveform->setEndPos(133, 64); | |||
fSliderWaveform->setStartPos(133, 40); | |||
fSliderWaveform->setEndPos(133, 60); | |||
fSliderWaveform->setRange(0.0f, 1.0f); | |||
fSliderWaveform->setValue(0.0f); | |||
fSliderWaveform->setIsSwitch(true); | |||
fSliderWaveform->setCallback(this); | |||
// knobs | |||
@@ -52,51 +53,58 @@ DistrhoUINekobi::DistrhoUINekobi() | |||
// knob Tuning | |||
fKnobTuning = new ImageKnob(this, knobImage); | |||
fKnobTuning->setPos(42, 45); | |||
fKnobTuning->setPos(41, 43); | |||
fKnobTuning->setRange(-12.0f, 12.0f); | |||
fKnobTuning->setValue(0.0f); | |||
fKnobTuning->setRotationAngle(270); | |||
fKnobTuning->setCallback(this); | |||
// knob Cutoff | |||
fKnobCutoff = new ImageKnob(this, knobImage); | |||
fKnobCutoff->setPos(185, 45); | |||
fKnobCutoff->setPos(185, 43); | |||
fKnobCutoff->setRange(0.0f, 100.0f); | |||
fKnobCutoff->setValue(25.0f); | |||
fKnobCutoff->setRotationAngle(270); | |||
fKnobCutoff->setCallback(this); | |||
// knob Resonance | |||
fKnobResonance = new ImageKnob(this, knobImage); | |||
fKnobResonance->setPos(258, 45); | |||
fKnobResonance->setPos(257, 43); | |||
fKnobResonance->setRange(0.0f, 95.0f); | |||
fKnobResonance->setValue(25.0f); | |||
fKnobResonance->setRotationAngle(270); | |||
fKnobResonance->setCallback(this); | |||
// knob Env Mod | |||
fKnobEnvMod = new ImageKnob(this, knobImage); | |||
fKnobEnvMod->setPos(330, 45); | |||
fKnobEnvMod->setPos(329, 43); | |||
fKnobEnvMod->setRange(0.0f, 100.0f); | |||
fKnobEnvMod->setValue(50.0f); | |||
fKnobEnvMod->setRotationAngle(270); | |||
fKnobEnvMod->setCallback(this); | |||
// knob Decay | |||
fKnobDecay = new ImageKnob(this, knobImage); | |||
fKnobDecay->setPos(402, 45); | |||
fKnobDecay->setPos(400, 43); | |||
fKnobDecay->setRange(0.0f, 100.0f); | |||
fKnobDecay->setValue(75.0f); | |||
fKnobDecay->setRotationAngle(270); | |||
fKnobDecay->setCallback(this); | |||
// knob Accent | |||
fKnobAccent = new ImageKnob(this, knobImage); | |||
fKnobAccent->setPos(474, 45); | |||
fKnobAccent->setPos(473, 43); | |||
fKnobAccent->setRange(0.0f, 100.0f); | |||
fKnobAccent->setValue(25.0f); | |||
fKnobAccent->setRotationAngle(270); | |||
fKnobAccent->setCallback(this); | |||
// knob Volume | |||
fKnobVolume = new ImageKnob(this, knobImage); | |||
fKnobVolume->setPos(546, 45); | |||
fKnobVolume->setPos(545, 43); | |||
fKnobVolume->setRange(0.0f, 100.0f); | |||
fKnobVolume->setValue(75.0f); | |||
fKnobVolume->setRotationAngle(270); | |||
fKnobVolume->setCallback(this); | |||
// about button | |||
@@ -50,6 +50,7 @@ public: | |||
void setOrientation(Orientation orientation); | |||
void setRange(float min, float max); | |||
void setValue(float value, bool sendCallback = false); | |||
void setRotationAngle(int angle); | |||
void setCallback(Callback* callback); | |||
@@ -57,6 +58,8 @@ protected: | |||
void onDisplay() override; | |||
bool onMouse(int button, bool press, int x, int y) override; | |||
bool onMotion(int x, int y) override; | |||
void onReshape(int width, int height) override; | |||
void onClose() override; | |||
private: | |||
Image fImage; | |||
@@ -65,6 +68,7 @@ private: | |||
float fValue; | |||
Orientation fOrientation; | |||
int fRotationAngle; | |||
bool fDragging; | |||
int fLastX; | |||
int fLastY; | |||
@@ -75,6 +79,7 @@ private: | |||
int fImgLayerSize; | |||
int fImgLayerCount; | |||
Rectangle<int> fKnobArea; | |||
GLuint fTextureId; | |||
}; | |||
// ------------------------------------------------- | |||
@@ -49,6 +49,7 @@ public: | |||
void setRange(float min, float max); | |||
void setValue(float value, bool sendCallback = false); | |||
void setIsSwitch(bool yesNo); | |||
void setCallback(Callback* callback); | |||
@@ -63,6 +64,7 @@ private: | |||
float fMaximum; | |||
float fValue; | |||
bool fIsSwitch; | |||
bool fDragging; | |||
int fStartedX; | |||
int fStartedY; | |||
@@ -16,6 +16,9 @@ | |||
#include "../ImageKnob.hpp" | |||
#include <cassert> | |||
#include <cstdio> | |||
START_NAMESPACE_DGL | |||
// ------------------------------------------------- | |||
@@ -27,6 +30,7 @@ ImageKnob::ImageKnob(Window* parent, const Image& image, Orientation orientation | |||
fMaximum(1.0f), | |||
fValue(0.5f), | |||
fOrientation(orientation), | |||
fRotationAngle(0), | |||
fDragging(false), | |||
fLastX(0), | |||
fLastY(0), | |||
@@ -34,7 +38,8 @@ ImageKnob::ImageKnob(Window* parent, const Image& image, Orientation orientation | |||
fIsImgVertical(image.getHeight() > image.getWidth()), | |||
fImgLayerSize(fIsImgVertical ? image.getWidth() : image.getHeight()), | |||
fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize), | |||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize) | |||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), | |||
fTextureId(0) | |||
{ | |||
setSize(fImgLayerSize, fImgLayerSize); | |||
} | |||
@@ -46,6 +51,7 @@ ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation | |||
fMaximum(1.0f), | |||
fValue(0.5f), | |||
fOrientation(orientation), | |||
fRotationAngle(0), | |||
fDragging(false), | |||
fLastX(0), | |||
fLastY(0), | |||
@@ -53,7 +59,8 @@ ImageKnob::ImageKnob(Widget* widget, const Image& image, Orientation orientation | |||
fIsImgVertical(image.getHeight() > image.getWidth()), | |||
fImgLayerSize(fIsImgVertical ? image.getWidth() : image.getHeight()), | |||
fImgLayerCount(fIsImgVertical ? image.getHeight()/fImgLayerSize : image.getWidth()/fImgLayerSize), | |||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize) | |||
fKnobArea(0, 0, fImgLayerSize, fImgLayerSize), | |||
fTextureId(0) | |||
{ | |||
setSize(fImgLayerSize, fImgLayerSize); | |||
} | |||
@@ -65,6 +72,7 @@ ImageKnob::ImageKnob(const ImageKnob& imageKnob) | |||
fMaximum(imageKnob.fMaximum), | |||
fValue(imageKnob.fValue), | |||
fOrientation(imageKnob.fOrientation), | |||
fRotationAngle(imageKnob.fRotationAngle), | |||
fDragging(false), | |||
fLastX(0), | |||
fLastY(0), | |||
@@ -72,9 +80,17 @@ ImageKnob::ImageKnob(const ImageKnob& imageKnob) | |||
fIsImgVertical(imageKnob.fIsImgVertical), | |||
fImgLayerSize(imageKnob.fImgLayerSize), | |||
fImgLayerCount(imageKnob.fImgLayerCount), | |||
fKnobArea(imageKnob.fKnobArea) | |||
fKnobArea(imageKnob.fKnobArea), | |||
fTextureId(0) | |||
{ | |||
setSize(fImgLayerSize, fImgLayerSize); | |||
if (fRotationAngle != 0) | |||
{ | |||
// force new texture creation | |||
fRotationAngle = 0; | |||
setRotationAngle(imageKnob.fRotationAngle); | |||
} | |||
} | |||
float ImageKnob::getValue() const | |||
@@ -125,6 +141,38 @@ void ImageKnob::setValue(float value, bool sendCallback) | |||
fCallback->imageKnobValueChanged(this, fValue); | |||
} | |||
void ImageKnob::setRotationAngle(int angle) | |||
{ | |||
if (fRotationAngle == angle) | |||
return; | |||
if (fRotationAngle != 0) | |||
{ | |||
// delete old texture | |||
glDeleteTextures(1, &fTextureId); | |||
fTextureId = 0; | |||
} | |||
fRotationAngle = angle; | |||
if (angle != 0) | |||
{ | |||
glEnable(GL_TEXTURE_2D); | |||
glGenTextures(1, &fTextureId); | |||
glBindTexture(GL_TEXTURE_2D, fTextureId); | |||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWidth(), getHeight(), 0, fImage.getFormat(), fImage.getType(), fImage.getRawData()); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
glBindTexture(GL_TEXTURE_2D, 0); | |||
glDisable(GL_TEXTURE_2D); | |||
} | |||
} | |||
void ImageKnob::setCallback(Callback* callback) | |||
{ | |||
fCallback = callback; | |||
@@ -132,17 +180,58 @@ void ImageKnob::setCallback(Callback* callback) | |||
void ImageKnob::onDisplay() | |||
{ | |||
float normValue = (fValue - fMinimum) / (fMaximum - fMinimum); | |||
const float normValue = (fValue - fMinimum) / (fMaximum - fMinimum); | |||
if (fRotationAngle != 0 || true) | |||
{ | |||
glEnable(GL_TEXTURE_2D); | |||
glBindTexture(GL_TEXTURE_2D, fTextureId); | |||
// FIXME: assuming GL_BGRA data (* 4) | |||
int layerDataSize = fImgLayerSize * fImgLayerSize * 4; | |||
int imageDataSize = layerDataSize * fImgLayerCount; | |||
int imageDataOffset = imageDataSize - layerDataSize - (layerDataSize * int(normValue * float(fImgLayerCount-1))); | |||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWidth(), getHeight(), 0, fImage.getFormat(), fImage.getType(), fImage.getRawData()); | |||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
glRasterPos2i(getX(), getY()+getHeight()); | |||
glDrawPixels(fImgLayerSize, fImgLayerSize, fImage.getFormat(), fImage.getType(), fImage.getRawData() + imageDataOffset); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
glPushMatrix(); | |||
const GLint w2 = getWidth()/2; | |||
const GLint h2 = getHeight()/2; | |||
glTranslatef(getX()+w2, getY()+h2, 0.f); | |||
glRotatef(normValue*fRotationAngle, 0.0f, 0.0f, 1.0f); | |||
glBegin(GL_QUADS); | |||
glTexCoord2f(0.0f, 1.0f); | |||
glVertex2i(-w2, -h2); | |||
glTexCoord2f(1.0f, 1.0f); | |||
glVertex2i(getWidth()-w2, -h2); | |||
glTexCoord2f(1.0f, 0.0f); | |||
glVertex2i(getWidth()-w2, getHeight()-h2); | |||
glTexCoord2f(0.0f, 0.0f); | |||
glVertex2i(-w2, getHeight()-h2); | |||
glEnd(); | |||
glPopMatrix(); | |||
glBindTexture(GL_TEXTURE_2D, 0); | |||
glDisable(GL_TEXTURE_2D); | |||
} | |||
else | |||
{ | |||
const int layerDataSize = fImgLayerSize * fImgLayerSize * (fImage.getFormat() == GL_BGRA || fImage.getFormat() == GL_RGBA ? 4 : 3); | |||
const int imageDataSize = layerDataSize * fImgLayerCount; | |||
const int imageDataOffset = imageDataSize - layerDataSize - (layerDataSize * int(normValue * float(fImgLayerCount-1))); | |||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
glRasterPos2i(getX(), getY()+getHeight()); | |||
glDrawPixels(fImgLayerSize, fImgLayerSize, fImage.getFormat(), fImage.getType(), fImage.getRawData() + imageDataOffset); | |||
} | |||
} | |||
bool ImageKnob::onMouse(int button, bool press, int x, int y) | |||
@@ -222,6 +311,20 @@ bool ImageKnob::onMotion(int x, int y) | |||
return true; | |||
} | |||
void ImageKnob::onReshape(int width, int height) | |||
{ | |||
// if (fRotationAngle != 0) | |||
// glEnable(GL_TEXTURE_2D); | |||
Widget::onReshape(width, height); | |||
} | |||
void ImageKnob::onClose() | |||
{ | |||
// delete old texture | |||
setRotationAngle(0); | |||
} | |||
// ------------------------------------------------- | |||
END_NAMESPACE_DGL |
@@ -26,6 +26,7 @@ ImageSlider::ImageSlider(Window* parent, const Image& image) | |||
fMinimum(0.0f), | |||
fMaximum(1.0f), | |||
fValue(0.5f), | |||
fIsSwitch(false), | |||
fDragging(false), | |||
fStartedX(0), | |||
fStartedY(0), | |||
@@ -40,6 +41,7 @@ ImageSlider::ImageSlider(Widget* widget, const Image& image) | |||
fMinimum(0.0f), | |||
fMaximum(1.0f), | |||
fValue(0.5f), | |||
fIsSwitch(false), | |||
fDragging(false), | |||
fStartedX(0), | |||
fStartedY(0), | |||
@@ -54,6 +56,7 @@ ImageSlider::ImageSlider(const ImageSlider& imageSlider) | |||
fMinimum(imageSlider.fMinimum), | |||
fMaximum(imageSlider.fMaximum), | |||
fValue(imageSlider.fValue), | |||
fIsSwitch(imageSlider.fIsSwitch), | |||
fDragging(false), | |||
fStartedX(0), | |||
fStartedY(0), | |||
@@ -127,6 +130,15 @@ void ImageSlider::setValue(float value, bool sendCallback) | |||
fCallback->imageSliderValueChanged(this, fValue); | |||
} | |||
void ImageSlider::setIsSwitch(bool yesNo) | |||
{ | |||
if (fIsSwitch == yesNo) | |||
return; | |||
fIsSwitch = yesNo; | |||
repaint(); | |||
} | |||
void ImageSlider::setCallback(Callback* callback) | |||
{ | |||
fCallback = callback; | |||
@@ -184,12 +196,24 @@ bool ImageSlider::onMouse(int button, bool press, int x, int y) | |||
else | |||
return false; | |||
float value = fMaximum - vper * (fMaximum - fMinimum); | |||
float value; | |||
if (fIsSwitch) | |||
{ | |||
if (vper < 0.5f) | |||
value = fMaximum; | |||
else | |||
value = fMinimum; | |||
} | |||
else | |||
{ | |||
value = fMaximum - vper * (fMaximum - fMinimum); | |||
if (value < fMinimum) | |||
value = fMinimum; | |||
else if (value > fMaximum) | |||
value = fMaximum; | |||
if (value < fMinimum) | |||
value = fMinimum; | |||
else if (value > fMaximum) | |||
value = fMaximum; | |||
} | |||
fDragging = true; | |||
fStartedX = x; | |||
@@ -236,12 +260,24 @@ bool ImageSlider::onMotion(int x, int y) | |||
vper = float(y - fSliderArea.getY()) / float(fSliderArea.getHeight()); | |||
} | |||
float value = fMaximum - vper * (fMaximum - fMinimum); | |||
float value; | |||
if (value < fMinimum) | |||
value = fMinimum; | |||
else if (value > fMaximum) | |||
value = fMaximum; | |||
if (fIsSwitch) | |||
{ | |||
if (vper < 0.5f) | |||
value = fMaximum; | |||
else | |||
value = fMinimum; | |||
} | |||
else | |||
{ | |||
value = fMaximum - vper * (fMaximum - fMinimum); | |||
if (value < fMinimum) | |||
value = fMinimum; | |||
else if (value > fMaximum) | |||
value = fMaximum; | |||
} | |||
setValue(value, true); | |||
} | |||