21#include <CustomLookAndFeel.h>
38 g.setColour(getLookAndFeel().findColour(JUCEAppBasics::CustomLookAndFeel::ColourIds::MeteringRmsColourId));
41 auto font = juce::Font(juce::FontOptions(knobSize, juce::Font::plain));
44 for (
auto const sourceScreenPositionKV : m_sourceScreenPositions)
46 auto& sourceId = sourceScreenPositionKV.first;
47 if (!m_sourceIdFilter.empty() && m_sourceIdFilter.count(sourceId) == 0)
49 auto sourceScreenPos = sourceScreenPositionKV.second.toFloat();
52 g.drawEllipse(juce::Rectangle<float>(sourceScreenPos.getX() - (knobSize / 2.0f), sourceScreenPos.getY() - (knobSize / 2.0f), knobSize, knobSize), knobThickness);
55 juce::String textLabel = juce::String(sourceId);
56 auto fontDependantWidth = float(juce::GlyphArrangement::getStringWidthInt(font, textLabel));
57 g.drawText(textLabel, juce::Rectangle<float>(sourceScreenPos.getX() - (0.5f * fontDependantWidth), sourceScreenPos.getY() + 3, fontDependantWidth, knobSize * 2.0f), Justification::centred,
true);
61 if (m_draggedSourceId != -1 && m_sourceScreenPositions.count(m_draggedSourceId))
63 auto dragPos = m_sourceScreenPositions.at(m_draggedSourceId).toFloat();
64 g.drawLine(0.0f, dragPos.getY(),
float(getWidth()), dragPos.getY(), 1.0f);
65 g.drawLine(dragPos.getX(), 0.0f, dragPos.getX(),
float(getHeight()), 1.0f);
71 PrerenderSourcesInBounds();
76 if (sourcePositions.empty())
78 m_sourcePositions.clear();
79 m_sourceScreenPositions.clear();
83 m_sourcePositions = sourcePositions;
85 PrerenderSourcesInBounds();
94 auto point = juce::Point<int>(x, y);
95 for (
auto const& kv : m_sourceScreenPositions)
97 if (!m_sourceIdFilter.empty() && m_sourceIdFilter.count(kv.first) == 0)
99 if (point.getDistanceFrom(kv.second) <= hitRadius)
107 m_sourceIdFilter = allowedIds;
113 m_sourcePositions[sourceId] = position;
114 m_sourceScreenPositions[sourceId] =
GetPointForRealCoordinate({ position.at(0), position.at(1), position.at(2) }).toInt();
123 auto clickPos = e.getPosition();
125 m_draggedSourceId = -1;
126 for (
auto const& kv : m_sourceScreenPositions)
128 if (!m_sourceIdFilter.empty() && m_sourceIdFilter.count(kv.first) == 0)
130 if (clickPos.getDistanceFrom(kv.second) <= hitRadius)
132 m_draggedSourceId = kv.first;
142 if (m_draggedSourceId == -1)
145 auto dragPos = e.getPosition().toFloat();
146 dragPos.setX(juce::jlimit(0.0f,
float(getWidth()), dragPos.getX()));
147 dragPos.setY(juce::jlimit(0.0f,
float(getHeight()), dragPos.getY()));
149 m_sourceScreenPositions[m_draggedSourceId] = dragPos.toInt();
152 m_sourcePositions[m_draggedSourceId] = realCoord;
164 if (m_draggedSourceId != -1)
166 m_draggedSourceId = -1;
171void UmsciSoundobjectsPaintComponent::onZoomChanged()
173 PrerenderSourcesInBounds();
177void UmsciSoundobjectsPaintComponent::PrerenderSourcesInBounds()
180 for (
auto const sourcePositionKV : m_sourcePositions)
182 auto& sourceId = sourcePositionKV.first;
183 auto& spourcePos = sourcePositionKV.second;
184 auto& x = spourcePos.at(0);
185 auto& y = spourcePos.at(1);
186 auto& z = spourcePos.at(2);
Abstract base class for all three overlaid visualisation layers in UmsciControlComponent.
bool processPinchGesture(const juce::MouseEvent &e, bool isDown, bool isUp)
JUCE-level two-touch pinch-zoom fallback for platforms where neither mouseMagnify nor a native gestur...
std::array< float, 3 > GetRealCoordinateForPoint(const juce::Point< float > &screenPoint)
Inverse of GetPointForRealCoordinate — converts a screen pixel point back to a 3D real-world coordina...
juce::Point< float > GetPointForRealCoordinate(const std::array< float, 3 > &realCoordinate)
Converts a 3D real-world coordinate to a 2D screen pixel point.
float getControlsSizeMultiplier() const
Returns a multiplier (e.g. 0.5 / 1.0 / 1.5) for S/M/L icon sizes.
void setSourcePosition(std::int16_t sourceId, const std::array< std::float_t, 3 > &position)
Updates a single source position.
UmsciSoundobjectsPaintComponent()
void paint(Graphics &) override
void setSourcePositions(const std::map< std::int16_t, std::array< std::float_t, 3 > > &sourcePositions)
Replaces all source positions at once (e.g. on reconnect or initial query).
~UmsciSoundobjectsPaintComponent() override
void setSourceIdFilter(const std::set< std::int16_t > &allowedIds)
Restricts rendering and interaction to the given set of source IDs. An empty set means no sources are...
void mouseDrag(const juce::MouseEvent &e) override
Converts the drag position to world coordinates and fires onSourcePositionChanged.
std::function< void(std::int16_t, std::array< std::float_t, 3 >)> onSourcePositionChanged
Fired during a drag with the new world position. UmsciControlComponent receives this and calls Device...
void mouseDown(const juce::MouseEvent &e) override
Identifies which source is under the cursor and begins a drag.
void mouseUp(const juce::MouseEvent &e) override
Clears the active drag state.
bool hitTest(int x, int y) override
Returns true only when the point falls within a rendered source circle.