Hey folks, I’ve been playing around with Juce dsp for a few months now and I’m attempting to build my first UI (beyond some basic tutorials).
I apologize if this is an obvious or dumb problem (I hope it is so I can get past it), but I’m getting strange behavior with an XY controller I’m building and I haven’t been able to figure it out.
The dragging and updating parameters all works fine, however, I’m getting a phantom extra node(s) in the top left corner. If I explicitly call paint on the nodes from the parent, they draw correctly along with the phantom one. If I don’t call paint or call repaint(), only the phantom ones draw, and only appear if you drag the component into the top left corner. I’ve added white boxes around the component bounds and that all seems good. Images, links to video of the behavior, and the relevant code are below.
Any help would be appreciated, even if the mistake is just me being a dumb noob.
video:
https://drive.google.com/file/d/1A94n5BhfyhvMDWkc6BodXkGaNkdo3Tal/view?usp=sharing
Parent code:
// in the constructor creating nodes...
for (auto i = 0; i < mNumNodes; ++i) {
std::unique_ptr<XYNode> node = std::make_unique<XYNode>(i, nodeColors.at(i));
addAndMakeVisible(node.get());
node->setSize(XY_NODE_SIZE, XY_NODE_SIZE);
node->addMouseListener(this, true);
node->setWantsKeyboardFocus(true);
mNodes.push_back(std::move(node));
}
void drawNodes(Graphics& g)
{
mPlotValues = getPlotValues();
for (auto i = 0; i < mNodes.size(); ++i)
{
float xValue = mPlotValues[i][xOptions.at(mXControlIndex)];
float yValue = mPlotValues[i][yOptions.at(mYControlIndex)];
float sampleValue = mPlotValues[i]["sample"];
drawNode(g, xValue, yValue, sampleValue, i);
}
}
void drawNode(Graphics& g, float xValue, float yValue, float sampleValue, int index) {
float x;
float y;
// if they are dragging, prevent them from being dragged outside parent
if (!mNodes[index]->getDragging()) {
x = jmap<float>(xValue, 0.0, 1.0, mOffset , getWidth() - mOffset );
y = getHeight() - jmap<float>(yValue, 0.0, 1.0, mOffset, getHeight() - mOffset);
} else {
Position pos = mNodes[index]->getPosition();
x = pos.x;
y = pos.y;
}
mNodes[index]->setCentrePosition(x, y);
// mNodes[index]->paint(g);
}
class XYNode: public Component {
public:
XYNode(unsigned int index, juce::Colour color): nodeIndex(index), mColor(color) {}
~XYNode()=default;
void setColor(juce::Colour color) {
mColor = color;
}
void setPosition(float x, float y) {
mPosition.x = x;
mPosition.y = y;
}
Position getPosition() {
return mPosition;
}
void paint(Graphics& g) override
{
g.setColour(juce::Colours::white);
g.drawRect(getLocalBounds());
g.setColour(mColor);
int x = getX();
int y = getY();
g.fillEllipse(x, y, mSize.height , mSize.width);
g.fillEllipse(x + ((getWidth() / 2) - ((mSize.width * 0.667) / 2)), y + ((getHeight() / 2) - ((mSize.height * 0.667) / 2)), mSize.height * 0.667f , mSize.width * 0.667);
g.fillEllipse(x + ((getWidth() / 2) - ((mSize.width / 3) / 2)), y + ((getHeight() / 2) - ((mSize.height / 3) / 2)), mSize.width / 3, mSize.height / 3);
}
unsigned int nodeIndex;
private:
float mValue;
Size mSize{XY_NODE_SIZE, XY_NODE_SIZE};
Position mPosition;
juce::Colour mColor;
std::string mLabel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XYNode);
};