Just wanted to wish everyone a happy, productive and prosperous new year!
Just wanted to wish everyone a happy, productive and prosperous new year!
Until you spend hours debugging an inaudible filter node because Claude set the smoothing to 20 seconds instead of 20ms! 
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.
@David-Healey In a conversation with ChatGPT today, it said to me
Your mockup surprised meβI expected to dislike it. I don't.
AI is getting cheekier! 
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.
@Christoph-Hart said in Saving MIDI CC assignments in user presets?:
If you want to distinguish between the two, you need this method:
https://docs.hise.audio/scripting/scripting-api/userpresethandler/index.html#isinternalpresetload
Personally, I don't need to distinguish between a DAW session reload and a preset load. I just want no MIDI CC data saved to, or loaded from, user presets.
@Christoph-Hart I don't really want lies in my user preset data. Might be confusing to anyone who read/edits the XML
@ustk From what Claude says, this is minimally useful for my situation.
Although you can preprocess the preset data before loading it, you still have to set all the values to something, meaning you can't just say "don't overwrite the existing CC assignments". I suppose you could read the current assignments, then preprocess to replace the preset assignments with the current ones. Phew!
But as I replied to David earlier, that leads to there being lies on disk.
@Christoph-Hart said in Saving MIDI CC assignments in user presets?:
the Midi CC settings are part of the data model of a user preset that is saved in the DAW project
Are you referring here to the saved DAW session, or the saved user preset? Or both?
Saving as part of the DAW session is cool, I just don't want them saved in the user presets.
@ustk Yes, 'active' is too ambiguous a word to have used in the first place. My bad.
@ustk A DAW will only route incoming live controller messages to the active or record-armed track(s), surely?
So if I have 3 different synths all set to respond to mod wheel > filter, then only the active one will respond when I turn the mod wheel, right?
Regardless of whether the synth UI is visible or hidden. It's based on active tracks, right?
The other 2 'unselected', 'inactive', 'not record-armed' synths won't respond to live controller data
Otherwise there would be chaos! Unless that's what you wanted, and armed ALL tracks for record! 
@ustk said in Saving MIDI CC assignments in user presets?:
I'd prefer not in my case, because if you load multiple instances of the plugin, they'll all react to the same CC...
That's a very interesting point!
EDIT: actually, maybe it's fine. The DAW will only send MIDI CC to the active plugin, right?
@ustk Not sure. To be honest, I just want all the 'CC data in presets' code out of my fork.
Might just drop the preprocessor and remove it all directly.
I can't see a situation where I would ever want CC data in the presets. So a preprocessor is only useful for backwards compatibility, which I don't have any of 
@David-Healey Apparently not.
There are 3 HISE restore points that run after onInit, so it still needs handling.
From Claude:
Fresh instance in a DAW:
FrontendProcessor::restorePluginrunscompileAllScripts()(your onInit applies the file) and then restores the
MidiAutomation node from the embedded project state (FrontEndProcessor.cpp:458). The export always writes that node β even when empty,exportAsValueTreeadds it unconditionally β so a fresh instance immediately clears the mappings you just loaded. Your file-load is defeated before the user ever touches the plugin.Reopening a session: the host calls
setStateInformationat some point after instantiation (host-dependent timing), andFrontEndProcessor.cpp:576restores the session's stale mapping copy over whatever onInit applied.In the editor: every project load stashes the project XML's
<MidiAutomation/>and applies it after script compilation (MainController.cpp:562/577)
β same wipe while you're developing.