Just wanted to wish everyone a happy, productive and prosperous new year!
Just wanted to wish everyone a happy, productive and prosperous new year!
Anyone care to share their overall plans and goals for the coming year? 
My main goal is to start releasing HISE plugins. I've been learning HISE for a while and it's time to start exporting my efforts!
A series of 4 free synth plugins, first one Sublime posted here for design feedback, and another 3, each based around one simple preset concept. Sublime is all about bass.
Then I have 2 collaborations I want to work on, both with UK house music producers. One is a multi-output drum plugin based on a series of expansions, the other is a chord synth with some interesting features.
I also have a lot of vintage reverb impulses recorded and processed, which I'd like to turn into a suite of free reverbs.
My user base is mostly house music producers & related genres - rave, techno, classic house, etc. I've built a decent brand and I think my customers will love the move from Maize-based ROMpler plugins to way more fully-featured HISE-based plugins.
What are your goals?
I like using overlay images to ensure my Figma design is translated properly to HISE. Currently, the only way I know to toggle the image visibility is to select/unselect the image, or quickly slide the alpha slider, which is difficult because of the 'invert' half of the slider.
This PR adds a toggle button between the image dropdown and the alpha slider. It uses an existing image icon for the button and respects the alpha slider value.
This allows me to toggle the image without taking my eyes off the interface, making it easier to spot changes.
PR here: https://github.com/christophhart/HISE/pull/825

@David-Healey I just had a go at fixing this. Is that what you mean?

HiseSnippet 1112.3ocsVs2aaaCDmJIJKwacqEne.H7e4roYH+pIcACMO8pwxCi4rhMDDTPKcxhKRjFRTMwXneH12z8MH6ndXKO6klZfI.av6Eue2wi2w9QRGHNVFQLpb0jw.w3qLGLQn7O1mwEjdmPL9ZyyYwJHhlw5nIiYwwfKwvX8eRyvX6MHoe+8aNhEvDNvLVDx6jbG3LdHWMia+C9YdPPWlKbEOrj1sOnmiTbrLPlf3YcSaxXlysrQvELsZqYRdKK1mX7sl1scX60zqSqVu9061wcH330.FtqCytCyqCC41l0tSi1DiMO0kqjQCTLEDia5QR2IC7k2Ixbv63w7gAflnAY.54L1ji84At8KRNwDhwF8mkpVOKU8Ryy4t7o7mkxddp.5LKJmzLV6wfTiOCHYTBRajAoWXNvIhOVMShFOeoYOAdB5wvylxPISWxZ+05lGKQMDp5gragtQHwTKp0z11hh+sy9UpfmOwJZ.yi9izBSbh.LRNS5vBNSJu8PgaW.BpoUGUrdDLhqqe5lHbTbonVU2H1c8kiSFeNHRNBOhGEISDtUsndE5LxhJG9G6T4OqPwuQ0iAUVcQsp12am+UEcQlXOrd5W.GUsqssrsz.F+cCJ9iOQTzSAg+29+CrHJCiXjUcFFs3dVvdLy8PjCJ7Z1012P+NZSKJ65FSW07F52SaqW0Jc0M6uPHo2Vd7a4i7CveJvk9FZln35ih.PP+gozCCRf4CacpCb0QOSLJ.pkiHK5d6TBmJ3dUAPy0HCt6YUDCHnmsNE1Md0LFstYIHu.U24yUyfEJuKVaTq5IfGKIPgI1FsqaOUtNyeHFpBv8JDVowuFeVSQoEsZ.3opVbBlU1crLbn7H48MJU7MRikvwRAnc3TMzVNkPCnEJOwhhc1u37lJEWHUvkhZ5i7sq7wJz+sHOukJSiiHYP.DsTw5FbQOlg0DIgCgHK7PRexVnHdgd9tDa9z5R3jkVJonTzSvUWNFxo6JCb0290qWrmBIOup6tjiPTUUZukmm2aoHuR3t5VKSSyjzPnbyexu16DlhUrY39h9ZLDo35Px3D3C3vgrFWaadBDeqRNF6yO8.kXrUlqeVQaMl.BR86VloqaPturCmTl.KICKFlr8lDxCOLO2lkYeG2U4OyZ9A9f9tXYNjR35KdhoDDclFMyPlowKwEgrTdqunO+8CzXCSLei4kBnxU2IqbkOd8GGXtPedbBizMIfoleridfbt.rJatd8594hXtZR4A1eFyhrezYQOUH9By9bki+xw3ZKAiXsy+GXLeB9yLO0yC6bNCfaX182V0w0eB2icpUbwnyYpHttF3hjvAXYnCfdWf0xw55h0z2Ayns0z5Lv.P3lR7.9kKrgl1HWXiBgX0kSj78NY2b0uQXqTNHlDougZa7wbHMcIWVCwmr7dGm42pELr4pZXqU0v1qpgcVUCe0pZ3tqpg68oMT+hxCSTxvrqMDx48OMs4pgwoBFVAlVsR9GztgJYG
Content.makeFrontInterface(200, 200);
const laf = Content.createLocalLookAndFeel();
laf.registerFunction("drawPopupMenuBackground", function(g, obj)
{
g.setColour("0x00000000"); // any transparent colour
g.fillRect([0,0,200,200]);
});
laf.registerFunction("drawPopupMenuItem", function(g, obj)
{
var a = obj.area;
var padArea = [a[0] + 2, a[1] + 2, a[2] - 4, a[3] - 4];
g.setColour(obj.isHighlighted ? Colours.green : Colours.blue);
g.fillRoundedRectangle(padArea, 8);
var textArea = [padArea[0] + 8, padArea[1], padArea[2] - 16, padArea[3]];
g.setColour(Colours.white);
g.setFont("Default", 14.0);
g.drawAlignedText(obj.text, textArea, "left");
});
const ComboBox1 = Content.getComponent("ComboBox1");
ComboBox1.setLocalLookAndFeel(laf);
The drawPopupMenuBackground object should probably include an area, and the popup menu items still have a subtle drop shadow. But they're both fixes for another day.
PR here, if it's useful: https://github.com/christophhart/HISE/pull/805
@bendurso Today I learned that right-clicking a module in edit mode shows a different context menu to right-clicking not in edit mode. 
Posting this in case it helps anyone else. I just banged my head against a brick wall for too long before I realised how simple this was! 
When using a Floating Tile with content type Waveform (to display the waveform of Sine Wave Generator or Waveform Generator, for example) the default waveform path is a filled shape.
You can override this with LAF function drawAnalyserPath and draw a line path instead of a filled path:
laf.registerFunction("drawAnalyserPath", function(g, obj)
{
g.setColour(Colours.white);
g.drawPath(obj.path, obj.area, 5);
});
However, this means that the path is clipped at the bounds of the floating tile, especially at wider line thicknesses:

To prevent the clipping, I fudged around with it for longer than I want to admit before I realised the answer is to simply reduce the area that the path is drawn in, by half the thickness of the path:
laf.registerFunction("drawAnalyserPath", function(g, obj)
{
g.setColour(Colours.white);
g.drawPath(obj.path, obj.area.reduced(2.5), 5);
});
Voila! No more clipped paths!
Top row is using obj.area, bottom row is using area reduced by half line thickness:

You might want the left/right of the path to bleed out of bounds, in which case change the reduction from all-round to y-only:
obj.area.reduced(5) 👈 all-round
obj.area.reduced(0, 5) 👈 y-only
Note: you might need to compile with HISE_USE_SCRIPT_RECTANGLE_OBJECT=1 for the reduced and other Rectangle helper functions, as per the docs: https://docs.hise.dev/scripting/scripting-api/rectangle/index.html. Not sure if it's still the same, or if it's built-in to all new builds.
Until you spend hours debugging an inaudible filter node because Claude set the smoothing to 20 seconds instead of 20ms! 
Don't know if this has been posted before, but it's a good read from Moonbase:
State of the Independent Audio Plugin Companies PDF
https://moonbase.sh/reports/state-of-audio-plugin-companies-2025/
Not too many shocking conclusions in there. Mostly what you'd expect, but good as sanity check.
@Lindon Fixing regression issues seems like it should be high(est?) priority.
PR that adds StartPhase1 and StartPhase2 to Waveform Generator.
Coded for my own needs but someone else might find it useful.
Works great for setting a random phase offset on MIDI note-on.
Works independently for Osc1 and Osc2.
https://github.com/christophhart/HISE/pull/792
EDIT: from this conversation https://forum.hise.audio/topic/13720/free-running-or-randomised-phase-for-waveform-generator-oscillators/9
Until you spend hours debugging an inaudible filter node because Claude set the smoothing to 20 seconds instead of 20ms! 
@Chazrox But also, as David said, I thought masks were still buggy so keep that in mind as well.
@Chazrox I gave your post to Claude, here's the response. Might be helpful, I don't know! 
The issue is almost certainly the layer mode you opened before the mask, not the mask call itself.
g.applyMask() only works inside a layer (g.beginLayer(...)), and the boolean you pass to beginLayer is what makes or breaks this:
- g.beginLayer(false) draws your shape onto a fresh transparent layer. The mask then cuts that shape, and anything outside the ellipse becomes transparent. This is what you want.
- g.beginLayer(true) makes the layer draw on top of the parent backdrop. Now the mask multiplies the whole composite (your grip plus the background under it) down toward black. Where the ellipse does not cover, everything gets darkened instead of cut, so the grip goes dark and almost disappears. That matches your screenshots exactly.
Under the hood applyMask multiplies all four channels (R, G, B and alpha) by the mask coverage. On a transparent layer that gives a clean cut (masked pixels go fully transparent). On a draw-on-parent layer it just darkens.
So the fix is to wrap it like this:
g.beginLayer(false); // fresh transparent layer, not drawOnParent
// ... draw your pointer grip here ...
var pgMaskPath = Content.createPath();
pgMaskPath.addEllipse([0, 0, 1, 1]);
g.applyMask(pgMaskPath, [cx - pgMaskR, cy - pgMaskR, pgMaskR * 2, pgMaskR * 2], false);
g.endLayer();
Two other things worth a quick check:
- Make sure pgMaskR is in pixels in the same coordinate space as the grip. If it ends up as a small fraction, the ellipse is tiny and masks almost everything to zero, which also reads as "dark".
- Your invert flag is false, so the mask keeps what is inside the ellipse. Flip it to true if you actually meant to keep the outside.
Try beginLayer(false) first - that is the usual culprit for the darkening.
@Oli-Ullmann The --force flag overwrites any existing signature.
@Chazrox Never used them, sorry.
@David-Healey @Chazrox Simplest answer is probably to add conical/angular gradients to HISE.
They're common in Photoshop and other tools. Claude will know how! 
@David-Healey Then you hit 'full colour' way too early and mess up the end gradient. See how it starts to go back to green at the very end of the travel.

You can only truly get "thermometer style gradient" with either a real angled/conical gradient, which HISE doesn't have, or the simulated stepped version.
Linear is a poor version of that. And linear falls down completely with more than 2 colours.
Stepped can handle as many intermediary colours as you need.
@David-Healey Simulated angled/conical gradient looks way better to me.
With a simple linear gradient you get almost all solid colour on each side and a small transition band at the top in the middle.
@Chazrox I just edited the above code to be even simpler. Claude missed HISE's built-in colour interpolation method, which removed a helper function.