@@ -129,36 +129,6 @@ private: | |||
struct PrivateData; | |||
PrivateData* const pData; | |||
/* | |||
Image fImage; | |||
float fMinimum; | |||
float fMaximum; | |||
float fStep; | |||
float fValue; | |||
float fValueDef; | |||
float fValueTmp; | |||
bool fUsingDefault; | |||
bool fUsingLog; | |||
Orientation fOrientation; | |||
int fRotationAngle; | |||
bool fDragging; | |||
int fLastX; | |||
int fLastY; | |||
Callback* fCallback; | |||
bool fIsImgVertical; | |||
uint fImgLayerWidth; | |||
uint fImgLayerHeight; | |||
uint fImgLayerCount; | |||
bool fIsReady; | |||
GLuint fTextureId; | |||
float _logscale(float value) const; | |||
float _invlogscale(float value) const; | |||
*/ | |||
DISTRHO_LEAK_DETECTOR(ImageBaseKnob) | |||
}; | |||
@@ -180,6 +150,7 @@ public: | |||
}; | |||
explicit ImageBaseSlider(Widget* parentWidget, const ImageType& image) noexcept; | |||
~ImageBaseSlider() override; | |||
float getValue() const noexcept; | |||
void setValue(float value, bool sendCallback = false) noexcept; | |||
@@ -205,31 +176,6 @@ private: | |||
struct PrivateData; | |||
PrivateData* const pData; | |||
/* | |||
Image fImage; | |||
float fMinimum; | |||
float fMaximum; | |||
float fStep; | |||
float fValue; | |||
float fValueDef; | |||
float fValueTmp; | |||
bool fUsingDefault; | |||
bool fDragging; | |||
bool fInverted; | |||
bool fValueIsSet; | |||
int fStartedX; | |||
int fStartedY; | |||
Callback* fCallback; | |||
Point<int> fStartPos; | |||
Point<int> fEndPos; | |||
Rectangle<double> fSliderArea; | |||
void _recheckArea() noexcept; | |||
*/ | |||
// these should not be used | |||
void setAbsoluteX(int) const noexcept {} | |||
void setAbsoluteY(int) const noexcept {} | |||
@@ -18,6 +18,7 @@ | |||
#include "../Color.hpp" | |||
#include "../ImageBaseWidgets.hpp" | |||
#include "Common.hpp" | |||
#include "SubWidgetPrivateData.hpp" | |||
#include "TopLevelWidgetPrivateData.hpp" | |||
#include "WidgetPrivateData.hpp" | |||
@@ -216,7 +217,6 @@ template class Triangle<uint>; | |||
template class Triangle<short>; | |||
template class Triangle<ushort>; | |||
// ----------------------------------------------------------------------- | |||
// Rectangle | |||
@@ -461,16 +461,56 @@ CairoBaseWidget<StandaloneWindow>::CairoBaseWidget(Application& app, Window& par | |||
template class CairoBaseWidget<StandaloneWindow>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseAboutWindow | |||
#if 0 | |||
template <> | |||
void ImageBaseAboutWindow<CairoImage>::onDisplay() | |||
{ | |||
img.draw(getGraphicsContext()); | |||
} | |||
#endif | |||
template class ImageBaseAboutWindow<CairoImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseButton | |||
template class ImageBaseButton<CairoImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseKnob | |||
template <> | |||
void ImageBaseKnob<CairoImage>::PrivateData::init() | |||
{ | |||
notImplemented("ImageBaseKnob::PrivateData::init"); | |||
} | |||
template <> | |||
void ImageBaseKnob<CairoImage>::PrivateData::cleanup() | |||
{ | |||
notImplemented("ImageBaseKnob::PrivateData::cleanup"); | |||
} | |||
template <> | |||
void ImageBaseKnob<CairoImage>::onDisplay() | |||
{ | |||
notImplemented("ImageBaseKnob::onDisplay"); | |||
} | |||
template class ImageBaseKnob<CairoImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseSlider | |||
template class ImageBaseSlider<CairoImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseSwitch | |||
template class ImageBaseSwitch<CairoImage>; | |||
// ----------------------------------------------------------------------- | |||
void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) | |||
@@ -120,6 +120,64 @@ struct ButtonImpl { | |||
// ----------------------------------------------------------------------- | |||
template <class ImageType> | |||
struct ImageBaseKnob<ImageType>::PrivateData { | |||
ImageType image; | |||
float minimum; | |||
float maximum; | |||
float step; | |||
float value; | |||
float valueDef; | |||
float valueTmp; | |||
bool usingDefault; | |||
bool usingLog; | |||
Orientation orientation; | |||
int rotationAngle; | |||
bool dragging; | |||
int lastX; | |||
int lastY; | |||
Callback* callback; | |||
bool isImgVertical; | |||
uint imgLayerWidth; | |||
uint imgLayerHeight; | |||
uint imgLayerCount; | |||
bool isReady; | |||
/*GL*/uint textureId; | |||
explicit PrivateData(const ImageType& img, const Orientation o); | |||
explicit PrivateData(PrivateData* const other); | |||
void assignFrom(PrivateData* const other); | |||
~PrivateData() | |||
{ | |||
cleanup(); | |||
} | |||
void init(); | |||
void cleanup(); | |||
inline float logscale(float value) const | |||
{ | |||
const float b = std::log(maximum/minimum)/(maximum-minimum); | |||
const float a = maximum/std::exp(maximum*b); | |||
return a * std::exp(b*value); | |||
} | |||
inline float invlogscale(float value) const | |||
{ | |||
const float b = std::log(maximum/minimum)/(maximum-minimum); | |||
const float a = maximum/std::exp(maximum*b); | |||
return std::log(value/a)/b; | |||
} | |||
DISTRHO_DECLARE_NON_COPY_STRUCT(PrivateData) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
END_NAMESPACE_DGL | |||
#endif // DGL_APP_PRIVATE_DATA_HPP_INCLUDED |
@@ -18,6 +18,7 @@ | |||
#include "../Color.hpp" | |||
#include "../ImageWidgets.hpp" | |||
#include "Common.hpp" | |||
#include "SubWidgetPrivateData.hpp" | |||
#include "TopLevelWidgetPrivateData.hpp" | |||
#include "WidgetPrivateData.hpp" | |||
@@ -435,17 +436,125 @@ void OpenGLImage::drawAt(const Point<int>& pos) | |||
} | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseAboutWindow | |||
#if 0 | |||
template <> | |||
void ImageBaseAboutWindow<OpenGLImage>::onDisplay() | |||
{ | |||
const GraphicsContext& context(getGraphicsContext()); | |||
img.draw(context); | |||
} | |||
#endif | |||
template class ImageBaseAboutWindow<OpenGLImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseButton | |||
template class ImageBaseButton<OpenGLImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseKnob | |||
template <> | |||
void ImageBaseKnob<OpenGLImage>::PrivateData::init() | |||
{ | |||
glGenTextures(1, &textureId); | |||
} | |||
template <> | |||
void ImageBaseKnob<OpenGLImage>::PrivateData::cleanup() | |||
{ | |||
if (textureId != 0) | |||
{ | |||
glDeleteTextures(1, &textureId); | |||
textureId = 0; | |||
} | |||
} | |||
template <> | |||
void ImageBaseKnob<OpenGLImage>::onDisplay() | |||
{ | |||
const GraphicsContext& context(getGraphicsContext()); | |||
const float normValue = ((pData->usingLog ? pData->invlogscale(pData->value) : pData->value) - pData->minimum) / (pData->maximum - pData->minimum); | |||
glEnable(GL_TEXTURE_2D); | |||
glBindTexture(GL_TEXTURE_2D, pData->textureId); | |||
if (! pData->isReady) | |||
{ | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); | |||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); | |||
static const float trans[] = { 0.0f, 0.0f, 0.0f, 0.0f }; | |||
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, trans); | |||
glPixelStorei(GL_PACK_ALIGNMENT, 1); | |||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | |||
uint imageDataOffset = 0; | |||
if (pData->rotationAngle == 0) | |||
{ | |||
DISTRHO_SAFE_ASSERT_RETURN(pData->imgLayerCount > 0,); | |||
DISTRHO_SAFE_ASSERT_RETURN(normValue >= 0.0f,); | |||
const uint& v1(pData->isImgVertical ? pData->imgLayerWidth : pData->imgLayerHeight); | |||
const uint& v2(pData->isImgVertical ? pData->imgLayerHeight : pData->imgLayerWidth); | |||
const uint layerDataSize = v1 * v2 * ((pData->image.getFormat() == kImageFormatBGRA || | |||
pData->image.getFormat() == kImageFormatRGBA) ? 4 : 3); | |||
/* */ imageDataOffset = layerDataSize * uint(normValue * float(pData->imgLayerCount-1)); | |||
} | |||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, | |||
static_cast<GLsizei>(getWidth()), static_cast<GLsizei>(getHeight()), 0, | |||
asOpenGLImageFormat(pData->image.getFormat()), GL_UNSIGNED_BYTE, pData->image.getRawData() + imageDataOffset); | |||
pData->isReady = true; | |||
} | |||
const int w = static_cast<int>(getWidth()); | |||
const int h = static_cast<int>(getHeight()); | |||
if (pData->rotationAngle != 0) | |||
{ | |||
glPushMatrix(); | |||
const int w2 = w/2; | |||
const int h2 = h/2; | |||
glTranslatef(static_cast<float>(w2), static_cast<float>(h2), 0.0f); | |||
glRotatef(normValue*static_cast<float>(pData->rotationAngle), 0.0f, 0.0f, 1.0f); | |||
Rectangle<int>(-w2, -h2, w, h).draw(context); | |||
glPopMatrix(); | |||
} | |||
else | |||
{ | |||
Rectangle<int>(0, 0, w, h).draw(context); | |||
} | |||
glBindTexture(GL_TEXTURE_2D, 0); | |||
glDisable(GL_TEXTURE_2D); | |||
} | |||
template class ImageBaseKnob<OpenGLImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseSlider | |||
template class ImageBaseSlider<OpenGLImage>; | |||
// ----------------------------------------------------------------------- | |||
// ImageBaseSwitch | |||
template class ImageBaseSwitch<OpenGLImage>; | |||
// ----------------------------------------------------------------------- | |||
void SubWidget::PrivateData::display(const uint width, const uint height, const double autoScaleFactor) | |||