Repository: baconpaul/sapphire-plugins (language: cpp)

Issue:
Knobs do not align with text labels
In my panel SVG generator [make_sapphire_svg.py](https://github.com/cosinekitty/sapphire/blob/main/util/make_sapphire_svg.py), I have a development command line option "preview". When present, the export panels get generated with a thin black outline circle where I think each knob should be.

When I use this option, then build sapphire-plugins, then run Bitwig, I can see the knobs are not where I want them. The text labels appear to be exactly where I want them. The result is visual misalignment. The knobs should be horizontally centered directly beneath the center of their respective labels. Here is a screenshot that shows real knobs + my fake circles showing where they should be.

![Image](https://github.com/user-attachments/assets/105d58d7-7078-43d0-837c-549145b91666)

Here is a screenshot of the raw preview svg by itself, with no knobs rendered on top:

![Image](https://github.com/user-attachments/assets/64e4a4ab-d818-4059-93d0-47a7a87e8c7b)


Discussion / hints:
Here is how to generate the preview panel for yourself. After cloning the repo, change into that directory, then

```
cd libs/sapphire/util
./make_panels preview
```

This will update libs/sapphire/export/tubeunit.svg to be:

![Image](https://github.com/user-attachments/assets/84ff10dd-3e43-4820-9ea7-2f8892a93bd3)

Rebuild sapphire-plugins as usual to include the reference circles.
Thanks I almost guarantee this is the int vs float stuff surgo tried to fix gone off. 

How do I generate the panel with the rings? 

https://github.com/baconpaul/sapphire-plugins/blob/74fa91d033e4b7dd6bc40e4863b584c7ff63757e/src/shared/editor_interactions.h#L290

I wonder if those values are lingering from before the restructure for instance
> How do I generate the panel with the rings?

Our posts crossed paths, ha ha. I just posted instructions.
Oh, I wonder if this is related to the window size anomaly mentioned [here](https://github.com/baconpaul/sapphire-plugins/blob/74fa91d033e4b7dd6bc40e4863b584c7ff63757e/src/shared/graphics_resources.h#L40).


So not quite

In tube unit if you set that 1.5 I lined to 0 it lines up
but then elastika is off

if I set that 1.5 to zero basically I get this

![Image](https://github.com/user-attachments/assets/77bf16c1-7d6a-4352-a264-8cf84104c43d)
And if I set it to dx=1.5, dy=0.5 I get this

![Image](https://github.com/user-attachments/assets/f773a3ed-0e36-43d3-89cf-b9e4eeda3cbe)
Right so : tube unit needs dx / dy 0.5 and the rest need 1.5/0.5

we could figure out why but for now i can just toss in an option to makeLargeKnob and set it in TU. Stay tuned
![Image](https://github.com/user-attachments/assets/ae9baad7-e26f-442f-88ed-b4d1a51a9d43)

And voila. merging now.

Fix patch:
diff --git a/src/shared/editor_interactions.h b/src/shared/editor_interactions.h
index ee26d0e..8667d96 100644
--- a/src/shared/editor_interactions.h
+++ b/src/shared/editor_interactions.h
@@ -281,14 +281,15 @@ inline void set_control_position(juce::Component &control, float cx, float cy, f
 }
 template <typename Editor>
 std::unique_ptr<juce::Slider> makeLargeKnob(Editor *editor, const std::string &prefix,
-                                            const std::string pos)
+                                            const std::string pos,
+                                            float extraDx = 0.f) // see #33
 {
     auto r = Sapphire::FindComponent(prefix, pos);
     auto cx = r.cx;
     auto cy = r.cy;
 
-    static constexpr float dx = 1.5;
-    static constexpr float dy = 0.0;
+    float dx = 1.5 - extraDx;
+    float dy = 0.5;
     auto kn = std::make_unique<juce::Slider>();
     kn->setSliderStyle(juce::Slider::RotaryHorizontalVerticalDrag);
     kn->setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
diff --git a/src/tube_unit/editor.cpp b/src/tube_unit/editor.cpp
index 9c6226f..9c4ffd5 100644
--- a/src/tube_unit/editor.cpp
+++ b/src/tube_unit/editor.cpp
@@ -50,31 +50,32 @@ TubeUnitEditor::TubeUnitEditor(shared::audioToUIQueue_t &atou, shared::uiToAudio
 
     const std::string modcode("tubeunit_export");
 
-    airflow = shared::makeLargeKnob(this, modcode, "airflow_knob");
+    // see #33 for this 1.0
+    airflow = shared::makeLargeKnob(this, modcode, "airflow_knob", 1.0);
     shared::bindSlider(this, airflow, patchCopy.airflow);
 
-    vortex = shared::makeLargeKnob(this, modcode, "vortex_knob");
+    vortex = shared::makeLargeKnob(this, modcode, "vortex_knob", 1.0);
     shared::bindSlider(this, vortex, patchCopy.vortex);
 
-    width = shared::makeLargeKnob(this, modcode, "width_knob");
+    width = shared::makeLargeKnob(this, modcode, "width_knob", 1.0);
     shared::bindSlider(this, width, patchCopy.width);
 
-    center = shared::makeLargeKnob(this, modcode, "center_knob");
+    center = shared::makeLargeKnob(this, modcode, "center_knob", 1.0);
     shared::bindSlider(this, center, patchCopy.center);
 
-    decay = shared::makeLargeKnob(this, modcode, "decay_knob");
+    decay = shared::makeLargeKnob(this, modcode, "decay_knob", 1.0);
     shared::bindSlider(this, decay, patchCopy.decay);
 
-    angle = shared::makeLargeKnob(this, modcode, "angle_knob");
+    angle = shared::makeLargeKnob(this, modcode, "angle_knob", 1.0);
     shared::bindSlider(this, angle, patchCopy.angle);
 
-    root = shared::makeLargeKnob(this, modcode, "root_knob");
+    root = shared::makeLargeKnob(this, modcode, "root_knob", 1.0);
     shared::bindSlider(this, root, patchCopy.root);
 
-    spring = shared::makeLargeKnob(this, modcode, "spring_knob");
+    spring = shared::makeLargeKnob(this, modcode, "spring_knob", 1.0);
     shared::bindSlider(this, spring, patchCopy.spring);
 
-    mix = shared::makeLargeKnob(this, modcode, "mix_knob");
+    mix = shared::makeLargeKnob(this, modcode, "mix_knob", 1.0);
     shared::bindSlider(this, mix, patchCopy.mix);
 
     auto dim = shared::getPanelDimensions(modcode, 2);


Test patch: