A Quasi-Object-Oriented Module System for Y'all
-
- Lay them out your components.
- Declare the components.
- Compute the vertical centres for the close button. (That's hard-coded for some reason. Its should really be done in my code.)
- Add the skeleton code to create the module (and handle messages).
- Add your submodules. They will automatically be activated/deactivated when the user powers up or down the module.
- Add your code to manage the modules.
This code (included below) creates a module (along with all the data and methods to manage them):
global_modules.push (CreateModule("panel_MODULE_SPACE", TRANSFORMER_Spacial_MODULE_PerformOp, { centre: 52, bottom:91 }));
LAFs are included. I'm using Modern Pictograms as the glyph font.
Please note this is raw code from my plugin; it's not a snippet that can simply be imported. I'm happy to answer questions, though. All code is copiously commented.
Enjoy.
Example Module Code
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // // SPACE ENGINE [UI THREAD] // // // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// STANDARD LIBRARY: GET MODULE POWER STATE FUNCTION /////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function SPACE_GetModulePowerState () { local module = GetModuleFromItsPanelID ("panel_MODULE_SPACE"); return module.ref_activationButton.getValue(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// STANDARD LIBRARY: CORE FUNCTIONS ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function TRANSFORMER_Spacial_MODULE_PerformOp (moduleOperation) { switch (moduleOperation) { case "init": // Show the component. panel_SPACE_SubmodulesInterfaceCover_ART.showControl(true); break; case "ready": // Raise the specialised cover over just the Subections. panel_SPACE_SubmodulesInterfaceCover_ART.fadeComponent(false, SUBMODULE_VISIBILITY_FADE_TIME); break; case "user_poweroff": break; case "user_poweron": break; } if (moduleOperation == "user_poweroff") { TRANSFORM_Space_SUBMOD_OrigAmbience_PerformOp ("user_poweron"); } else { TRANSFORM_Space_SUBMOD_OrigAmbience_PerformOp (moduleOperation); } TRANSFORM_Space_SUBMOD_Anechoic_PerformOp (moduleOperation); TRANSFORM_Space_SUBMOD_3dAudio_PerformOp (moduleOperation); TRANSFORM_Space_SUBMOD_OrigSpace_PerformOp (moduleOperation); TRANSFORM_Space_SUBMOD_NewSpace_PerformOp (moduleOperation); }
Example Submodule Code
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // // SPACE ENGINE: NEW SPACE [UI THREAD] // // // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// COMBOBOX IR SELECTOR FUNCTION //////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Register the Combobox's selection function. combo_SPACE_NEW_SpaceSelector.setControlCallback(onStdConbvolverSpaceSelect); // Define the selection function. inline function onStdConbvolverSpaceSelect(component, value) { if (value == 0) { // ------------- Disable Widgets // Show the image cover. panel_SPACE_NEW_SpaceImageCover_ART.showControl(false); // Hide the images container. image_SPACE_NEW_SpaceImage_ART.fadeComponent.showControl(false); // Disable the knobs. knob_SPACE_NEW_Wet_GUI.set("enabled",false); knob_SPACE_NEW_Dry_GUI.set("enabled",false); knob_SPACE_NEW_Predelay_GUI.set("enabled",false); knob_SPACE_NEW_Damping_GUI.set("enabled",false); knob_SPACE_NEW_HighCut_GUI.set("enabled",false); } else { // ------------- Choose an IR switch (value) { case 1: fx_SPACE_CONVO_NewSpace.fileaccess.setFile("{PROJECT_FOLDER}RoomSmall.aif"); image_SPACE_NEW_SpaceImage_ART.setImageFile("{PROJECT_FOLDER}drum_room-small.png", true); break; case 2: fx_SPACE_CONVO_NewSpace.fileaccess.setFile("{PROJECT_FOLDER}RoomMedium.aif"); image_SPACE_NEW_SpaceImage_ART.setImageFile("{PROJECT_FOLDER}drum_room-medium.png", true); break; case 3: fx_SPACE_CONVO_NewSpace.fileaccess.setFile("{PROJECT_FOLDER}RoomLarge.aif"); image_SPACE_NEW_SpaceImage_ART.setImageFile("{PROJECT_FOLDER}drum_room-large.png", true); break; } // ------------- Enable Widgets // Enable the knobs. knob_SPACE_NEW_Wet_GUI.set("enabled",true); knob_SPACE_NEW_Dry_GUI.set("enabled",true); knob_SPACE_NEW_Predelay_GUI.set("enabled",true); knob_SPACE_NEW_Damping_GUI.set("enabled",true); knob_SPACE_NEW_HighCut_GUI.set("enabled",true); // ------------- IR Room Images // Hide the image cover. panel_SPACE_NEW_SpaceImageCover_ART.fadeComponent(false, IMAGE_VISIBILITY_FADE_TIME); // Show the images container. image_SPACE_NEW_SpaceImage_ART.fadeComponent(true, IMAGE_VISIBILITY_FADE_TIME); // ------------- Reverb Processor UTILITY_SetEffectActivationState (fx_SPACE_CONVO_NewSpace.effect, true); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////// SUBMODULE ACTIVATION BUTTON CALLBACK FUNCTION ///////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Register and define the callback function for when the button is pressed. button_SPACE_UseNewSpace_GUI.setControlCallback(onSpaceChooseNewSpace_Control); inline function onSpaceChooseNewSpace_Control(component, value) { if (value) { TRANSFORM_Space_SUBMOD_NewSpace_PerformOp("user_poweron"); panel_SPACE_NEW_Interface_ART.fadeComponent(true, MODULE_VISIBILITY_FADE_TIME); } else { panel_SPACE_NEW_Interface_ART.fadeComponent(false, MODULE_VISIBILITY_FADE_TIME); TRANSFORM_Space_SUBMOD_NewSpace_PerformOp("user_poweroff"); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////// STANDARD LIBRARY: CORE FUNCTIONS ////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function TRANSFORM_Space_SUBMOD_NewSpace_PerformOp (moduleState) { switch (moduleState) { case "init": // ------------- Data Population // Clear and populate the combobox. combo_SPACE_NEW_SpaceSelector.set("items", ""); combo_SPACE_NEW_SpaceSelector.addItem("Small Room"); combo_SPACE_NEW_SpaceSelector.addItem("Medium Room"); combo_SPACE_NEW_SpaceSelector.addItem("Large Room"); // ------------- Submodule Interface Panel // Hide the submodule's interface. panel_SPACE_NEW_Interface_ART.showControl(false); // ------------- Submodule Radio Activation Button button_SPACE_UseNewSpace_GUI.set("enabled", false); button_SPACE_UseNewSpace_GUI.setValue(false); // ------------- IR Selector Combobox combo_SPACE_NEW_SpaceSelector.setValue(0); combo_SPACE_NEW_SpaceSelector.set ("enabled", false); // ------------- IR Room Images panel_SPACE_NEW_SpaceImageCover_ART.set ("enabled", true); panel_SPACE_NEW_SpaceImageCover_ART.showControl(true); image_SPACE_NEW_SpaceImage_ART.set ("enabled", false); image_SPACE_NEW_SpaceImage_ART.showControl(false); // ------------- Reverb Processor Parameters // Disable the knobs. ????? Set values, or happen autoamtically because they're connected? knob_SPACE_NEW_Wet_GUI.set("enabled",false); knob_SPACE_NEW_Dry_GUI.set("enabled",false); knob_SPACE_NEW_Predelay_GUI.set("enabled",false); knob_SPACE_NEW_Damping_GUI.set("enabled",false); knob_SPACE_NEW_HighCut_GUI.set("enabled",false); // Set the reverb processor to default settings. UTILITY_ConfigureReverb(fx_SPACE_CONVO_NewSpace, "default_new_room"); // Disable the reverb. UTILITY_SetEffectActivationState(fx_SPACE_CONVO_NewSpace.effect, false); break; case "ready": // ------------- Submodule Interface Panel // Hide the submodule's interface. panel_SPACE_NEW_Interface_ART.showControl(false); // ------------- Submodule Radio Activation Button button_SPACE_UseNewSpace_GUI.set("enabled", true); button_SPACE_UseNewSpace_GUI.setValue(false); // ------------- IR Selector Combobox combo_SPACE_NEW_SpaceSelector.setValue(0); combo_SPACE_NEW_SpaceSelector.set ("enabled", true); // ------------- IR Room Images panel_SPACE_NEW_SpaceImageCover_ART.set("enabled", true); panel_SPACE_NEW_SpaceImageCover_ART.showControl(true); image_SPACE_NEW_SpaceImage_ART.set("enabled", true); image_SPACE_NEW_SpaceImage_ART.showControl(false); // ------------- Reverb Processor Parameters // Disable the knobs. knob_SPACE_NEW_Wet_GUI.set("enabled",false); knob_SPACE_NEW_Dry_GUI.set("enabled",false); knob_SPACE_NEW_Predelay_GUI.set("enabled",false); knob_SPACE_NEW_Damping_GUI.set("enabled",false); knob_SPACE_NEW_HighCut_GUI.set("enabled",false); // Set the reverb processor to default settings. UTILITY_ConfigureReverb(fx_SPACE_CONVO_NewSpace, "default_new_room"); // Disable the reverb. UTILITY_SetEffectActivationState(fx_SPACE_CONVO_NewSpace.effect, false); break; case "user_poweroff": // ------------- Submodule Radio Activation Button if (SPACE_GetModulePowerState()) button_SPACE_UseNewSpace_GUI.set("enabled",true); else button_SPACE_UseNewSpace_GUI.set("enabled",false); // ------------- IR Selector Combobox combo_SPACE_NEW_SpaceSelector.set ("enabled", false); // ------------- IR Room Images panel_SPACE_NEW_SpaceImageCover_ART.set ("enabled", false); image_SPACE_NEW_SpaceImage_ART.set ("enabled", false); // ------------- Reverb Processor Parameters knob_SPACE_NEW_Wet_GUI.set("enabled",false); knob_SPACE_NEW_Dry_GUI.set("enabled",false); knob_SPACE_NEW_Predelay_GUI.set("enabled",false); knob_SPACE_NEW_Damping_GUI.set("enabled",false); knob_SPACE_NEW_HighCut_GUI.set("enabled",false); // Deactivate the processor. UTILITY_SetEffectActivationState (fx_SPACE_CONVO_NewSpace.effect, false); break; case "user_poweron": // ------------- Submodule Radio Activation Button // If the module power is on, enable the radio button; if not, disable it. button_SPACE_UseNewSpace_GUI.set("enabled",SPACE_GetModulePowerState()); if ( (button_SPACE_UseNewSpace_GUI.get("enabled")) && (button_SPACE_UseNewSpace_GUI.getValue()) && (SPACE_GetModulePowerState()) ) local subModuleActive = true; else local subModuleActive = false; // ------------- IR Selector Combobox // Disable the IR selector combobox. if (subModuleActive) combo_SPACE_NEW_SpaceSelector.set ("enabled", true); else combo_SPACE_NEW_SpaceSelector.set ("enabled", false); // ------------- IR Room Images if ((subModuleActive) && (combo_SPACE_NEW_SpaceSelector.getValue() > 0) ) { panel_SPACE_NEW_SpaceImageCover_ART.set ("enabled", true); image_SPACE_NEW_SpaceImage_ART.set ("enabled", false); } else { panel_SPACE_NEW_SpaceImageCover_ART.set ("enabled", false); image_SPACE_NEW_SpaceImage_ART.set ("enabled", false); } // ------------- Reverb Processor Parameters if ((subModuleActive) && (combo_SPACE_NEW_SpaceSelector.getValue() > 0) ) { // Enable the knobs. knob_SPACE_NEW_Wet_GUI.set("enabled",true); knob_SPACE_NEW_Dry_GUI.set("enabled",true); knob_SPACE_NEW_Predelay_GUI.set("enabled",true); knob_SPACE_NEW_Damping_GUI.set("enabled",true); knob_SPACE_NEW_HighCut_GUI.set("enabled",true); // Activate the processor. UTILITY_SetEffectActivationState (fx_SPACE_CONVO_NewSpace.effect, true); } else { // Enable the knobs. knob_SPACE_NEW_Wet_GUI.set("enabled",false); knob_SPACE_NEW_Dry_GUI.set("enabled",false); knob_SPACE_NEW_Predelay_GUI.set("enabled",false); knob_SPACE_NEW_Damping_GUI.set("enabled",false); knob_SPACE_NEW_HighCut_GUI.set("enabled",false); // Deactivate the processor. UTILITY_SetEffectActivationState (fx_SPACE_CONVO_NewSpace.effect, false); } break; } }
Example Code for Initialising the Module System
// Configure for Track Selection FOOTER_SetFrameworkState ("ready"); HEADER_SetFrameworkState ("ready"); DOCUMENTATION_SetFrameworkState ("ready"); GLOBAL_SetFrameworkState ("ready"); ENCODER_SetFrameworkState ("ready"); PLAYER_SetFrameworkState ("ready"); TRANSFORMER_SetFrameworkState ("ready"); FUTURE_SetFrameworkState ("ready");
Example code for Setting Ready-States
(Including Broadcaster/Receiver)
The "Ready" message is sent once a SampleMap loads.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////// SAMPLEMAP LOADING CODE //////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ======================================== Declaring and Attaching the Broadcaster const var sampleMapBroadcaster = Engine.createBroadcaster({ id: "sampleMapListener", args: ["samplerId", "eventType", "data"] }); sampleMapBroadcaster.attachToSampleMap("Sampler", "SampleMapChanged", ""); // ============================================= Defining the Listener sampleMapBroadcaster.addListener("SampleMap Name", "sampleMapListener", function(eventType, samplerId, data) { // If we don't check for loading, then this function will execute on initialisation. if ( (global_attemptedLoadingOnce && (g_lastPerformanceLoaded != global_activeSampleSet) ) ) { // ------------- Testing and Recording // Attempt to get an array of every note. global_allHits = mySampler.createSelection(".*"); // Store in an integer global. global_highestNativeNoteNumber = global_allHits.length; // Check for success. if (global_highestNativeNoteNumber > 0) { // ------------- Successful Load of a Samplemap Console.print("• Elements: " + global_highestNativeNoteNumber); // Check if MIDI file was loaded. var successfulMidiLoad = HEADER_LoadMidiFile (); if (!successfulMidiLoad) { Engine.showMessageBox ("Performance Data", dict_ErrorMessages.performance_data_didnt_load, ICON_TYPE_NONE); } // ------------- Configuring for Track Selection // Clear the undo buffer. Engine.clearUndoHistory(); // Configure for Track Selection FOOTER_SetFrameworkState ("ready"); HEADER_SetFrameworkState ("ready"); DOCUMENTATION_SetFrameworkState ("ready"); GLOBAL_SetFrameworkState ("ready"); ENCODER_SetFrameworkState ("ready"); PLAYER_SetFrameworkState ("ready"); TRANSFORMER_SetFrameworkState ("ready"); FUTURE_SetFrameworkState ("ready"); // ------------- Indicating Track Success ExecuteLoadingIndicatorCmd ("colour_indicator_success"); // ------------- Enabling the Player Activation Button button_MIDIPLAYER_PlaybackToggle_GUI.set("enabled",true); } else { // ------------- Failure to Load Engine.showMessageBox ("Session Data File", dict_ErrorMessages.errLoadingSession, ICON_TYPE_NONE); ExecuteLoadingIndicatorCmd ("colour_indicator_failure"); } // ------------- Result Indicator Panel ExecuteLoadingIndicatorCmd ("show_indicator"); g_lastPerformanceLoaded = global_activeSampleSet; // If the Player activation is set to automatic then turn on the Player. if (combo_GLOBAL_ChooseOptions_PrefsTab_Features_MidiplaybackActiv_GUI.getValue() == 1) RemoteControlPlayerAcivation("player",true); Console.print("Samplemap broacaster complete: " + data); // Redraw the performance selector menu(s). panel_HEADER_PerformanceSelector_GUI.repaint(); // Whatever colour the indicator is set to, (re)draw it. ExecuteLoadingIndicatorCmd("repaint"); } });
Backend Code
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // // TRANSFORMATION ENGINE [UI THREAD] [UI THREAD] // // // // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -------------------------------------------------------------------------------------------------------------- // - // Public Access - // - //--------------------------------------------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////// MODULE COMPOSITION AND CONSTRUCTOR /////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function CreateModule (modulePanelID, fun_PerformModuleOp, closeButton) { // Allocate the Module reference. local module = {}; // ==================================== "Private" Instance Variables and Methods // ------------- Master Panel // Assign the Module's panel component. module.panelID = modulePanelID; module.panelComponent = Content.getComponent(modulePanelID); // ------------- Module Keyword reg stringArray = module.panelID.split('_'); local keyword = keyword = stringArray[2]; module.keyword = keyword; // ------------- Composition // Compose cover. module.ref_cover = Content.getComponent("panel_" + keyword + "_ModuleCover_ART"); // Compose bypass shield. module.ref_bypassShield = Content.getComponent("panel_" + keyword + "_BypassShield_ART"); // Compose interface panel. module.ref_interface = Content.getComponent("panel_" + keyword + "_ModuleInterface_ART"); // Compose button cover. module.ref_buttonCover = Content.getComponent("panel_" + keyword + "_ButtonCover_ART"); // Compose open button. module.ref_openButton = Content.getComponent("button_" + keyword + "_OpenModuleInterface_GUI"); module.ref_openButton.setLocalLookAndFeel(LAF_CircleButton); module.ref_openButton.setControlCallback(OpenModule); // Compose close button. module.ref_closeButton = Content.getComponent("button_" + keyword + "_HideModuleInterface_GUI"); module.closeButtonCentre = closeButton.centre; module.closeButtonBottom = closeButton.bottom; module.ref_closeButton.setLocalLookAndFeel(LAF_circleXButton); module.ref_closeButton.setControlCallback(CloseModule); // Compose activation button. module.ref_activationButton = Content.getComponent("button_" + keyword + "_ToggleModuleFunction_GUI"); module.ref_activationButton.setLocalLookAndFeel(LAF_textlessButton); module.ref_activationButton.setControlCallback(SetModuleActivation); // =================================== Public Methods module.fun_PerformModuleOp = fun_PerformModuleOp; // =================================== Initialisation // ------------- Core GUI Operations // Raise the Module's interface shield. module.ref_bypassShield.showControl(true); // Set the Module's hide-interface button's value to false, and hide it. module.ref_closeButton.setValue(false); module.ref_closeButton.showControl(false); // Set the Module's show-interface button's value to false, and show it. module.ref_openButton.setValue (false); module.ref_openButton.showControl(true); // Hide the Module's interface panel. module.ref_interface.showControl(false); // Show the Module's cover. module.ref_cover.showControl(true); // Set the Module's activation button to off, and show it. module.ref_activationButton.setValue(false); module.ref_activationButton.showControl(true); // Show the Module's button-cover. module.ref_buttonCover.showControl(true); // Centre the close button, vertically. module.ref_closeButton.set("y", module.closeButtonCentre); // ------------- Log the ID. Console.print("Created Module: " + module.panelID); // ------------- Adding the Module to the Global List of Modules return module; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////// PRIVATE METHODS ///////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ====================== Getting a Reference to a Module from One of Its Component Components // It's not really a child component, but that title keeps the function name short. inline function GetModuleFromChildComponent (childComponent) { // Get the Master panel's ID local stringArray = childComponent.getId().split('_'); reg modulePanelID = "panel_MODULE_" + stringArray[1]; // Get the Master panel. local masterPanel = Content.getComponent(modulePanelID); // Find the corresponding module. for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { if (global_modules[moduleNumber].panelID == masterPanel.getId()) return global_modules[moduleNumber]; } } // ============================================ Openning a Module inline function OpenModule (component, value) { if (value) { local module = GetModuleFromChildComponent (component); // Execute the method body. module.ref_cover.fadeComponent(false, MODULE_VISIBILITY_FADE_TIME); module.ref_interface.fadeComponent(true, MODULE_VISIBILITY_FADE_TIME); module.ref_closeButton.fadeComponent(true, BUTTON_VISIBILITY_FADE_TIME); } } // =========================================== Closing a Module inline function CloseModule (component, value) { if (value) { local module = GetModuleFromChildComponent (component); module.ref_cover.fadeComponent(true, MODULE_VISIBILITY_FADE_TIME); module.ref_interface.fadeComponent(false, MODULE_VISIBILITY_FADE_TIME); module.ref_closeButton.fadeComponent(false, BUTTON_VISIBILITY_FADE_TIME); } } // =========================================== Activating a Module inline function SetModuleActivation (component, value) { local module = GetModuleFromChildComponent (component); if (value) { // Do core UI functions. module.ref_bypassShield.fadeComponent(false, SHIELD_FADE_TIME); module.ref_bypassShield.set ("enabled", false); // Call the Module's operation function. module.fun_PerformModuleOp ("user_poweron"); } else { // Do core UI functions. module.ref_bypassShield.fadeComponent(true, SHIELD_FADE_TIME); module.ref_bypassShield.set ("enabled", true); // Call the Module's operation function. module.fun_PerformModuleOp ("user_poweroff"); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////// HELPER FUNCTIONS //////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ====================================== Anonymous Function for All Modules // Send in an anonymous function - it will be applied to every Module. inline function ExecuteFunctionForAll (theFunction) { for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { moduleNumber.theFunction(); } } // ============================================ Conversion Functions // Send in whatever child component received a callback – get back the Module's master panel. inline function GetMasterPanelFromChild (childComponent) { local stringArray = childComponent.getId().split('_'); local modulePanelID = "panel_MODULE_" + stringArray[1]; return Content.getComponent(modulePanelID); } // Send in a master module panel - get back the Module's master panel. inline function GetModuleFromItsPanel (modulePanel) { for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { if (global_modules[moduleNumber].panelID == modulePanel.getId()) return global_modules[moduleNumber]; } } // Send in a Module's master panel ID - get back the corresponding module! inline function GetModuleFromItsPanelID (modulePanelID) { for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { if (global_modules[moduleNumber].panelID == modulePanelID) return global_modules[moduleNumber]; } } // ====================================== Getting the Module's Power State inline function MODULE_GetModuleActivationState (module) { return (module.ref_activationButton.getValue()); } // -------------------------------------------------------------------------------------------------------------- // - // Public Access - // - //--------------------------------------------------------------------------------------------------------------- ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////// PUBLIC METHODS ///////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function MODULE_GetModuleActivationStateByID (moduleID) { local module = GetModuleFromItsPanelID(moduleID); return module.ref_activationButton.getValue(); } // ====================================== Hiding the Module's Power Button // Send in an anonymous function - it will be applied to every module! inline function SetInterfaceforReadyState () { for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { global_modules[moduleNumber].ref_buttonCover.fadeComponent(false, BUTTON_VISIBILITY_FADE_TIME); global_modules[moduleNumber].ref_closeButton.set("y", global_modules[moduleNumber].closeButtonBottom); // Ensure power light is out. if (global_modules[moduleNumber].ref_activationButton.getValue()) { global_modules[moduleNumber].ref_activationButton.setValue(false); global_modules[moduleNumber].ref_activationButton.sendRepaintMessage(); } global_modules[moduleNumber].ref_bypassShield.fadeComponent(true, MODULE_VISIBILITY_FADE_TIME); } } // ====================================== Forwarding an Operation to All Modules inline function ForwardOperationToAllModules (operation) { for (moduleNumber = 0; moduleNumber < global_modules.length; moduleNumber++) { global_modules[moduleNumber].fun_PerformModuleOp(operation); } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////// EXTERNAL CORE FRAMEWORK FUNCTION ///////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// inline function TRANSFORMER_SetFrameworkState (operation) { ForwardOperationToAllModules(operation); if (operation == "ready") { SetInterfaceforReadyState(); } }
LAF: Circle X Button
///////////////////////////// CIRCLE-X BUTTON /////////////////////////////// // // ------------- Description // // This button is a drop-in replacement for a HISE button. It presents as an // 'x' within a circle. The 'x' is drawn manually with lines so it can be // perfectly centred. The functinality is momentary, though you can // change it of course within the Properties inspector. // // ------------- Inspector Colour Mapping // // textColour is for the 'x' glyph. // ///////////////////////////////////////////////////////////////////////////// // Create an LAF for the widget. Place it near the module bypass so users are // reminded when they close the cover whether or not the widget is on. const LAF_circleXButton = Content.createLocalLookAndFeel(); // Register and define the drawing function for the button component. LAF_circleXButton.registerFunction("drawToggleButton", function(graphics, widget) { // ------------- Initialisation // Get a more descriptive name for the button's area. var widgetHeight = widget.area[WIDGET_HEIGHT]; var widgetWidth = widget.area[WIDGET_WIDTH]; var widgetStartX = widget.area[WIDGET_STARTX]; var widgetStartY = widget.area[WIDGET_STARTY]; var borderWidth = 1; var xGlyphPadding = 4.5; var xGlyphThickness = 1.5; var hoverBrightnessFactor = 0.1; var widgetOnIndicatorColour = widget.bgColour; var wellTopLeftGradientColour = 0xFF404049; var wellBottomRightGradientColour = 0xFF27272C;; var widgetOffIndicatorColour = 0xFF5A5B5C; // ------------- Border // Create a colour gradient. graphics.setGradientFill([ wellTopLeftGradientColour, widgetStartX, widgetStartY, wellBottomRightGradientColour, widgetWidth, widgetHeight, false]); // Draw the circle. graphics.fillEllipse([ widgetStartX, widgetStartY, widgetWidth, widgetHeight]); // ------------- Surface // Determine which colour to use. if (widget.value == true) { var fillColour = widgetOnIndicatorColour; } else { // Choose the brightness factor based on mouse-over state. var brightnessAdjustment = widget.over ? hoverBrightnessFactor : 0.0; // Set the colour to the widget's indicator colour (specified in this function). var fillColour = WithSignedBrightness(widgetOffIndicatorColour, brightnessAdjustment); } graphics.setColour(fillColour); // Draw the circle. graphics.fillEllipse([ widgetStartX + borderWidth, widgetStartY + borderWidth, widgetWidth - (borderWidth*2), widgetHeight- (borderWidth*2)]); // ------------- X-Glyph // Set the colour. graphics.setColour(widget.textColour); // Draw the first stroke. graphics.drawLine( widgetStartX + xGlyphPadding, widgetWidth - xGlyphPadding, widgetStartY + xGlyphPadding, widgetHeight - xGlyphPadding, xGlyphThickness); // Draw the second stroke. graphics.drawLine( widgetWidth - xGlyphPadding, widgetStartX + xGlyphPadding, widgetStartY + xGlyphPadding, widgetHeight - xGlyphPadding, xGlyphThickness); });
LAF: Power Button
///////////////////////////// TEXTLESS BUTTON /////////////////////////////// // // ------------- Description // // This button is designed to be used for master toggle states. Therefore, // it is not meant to ever be disabled, and has no defined disabled LAF. As // a master toggle, it has no text legend. It features mouse-over styles // for both on and off states. // // ------------- Inspector Colour Mapping // // This LAF maps the same Colours (in the Inspector) as HISE's button. // // bgColour for the border. // itemColour is the top gradient of the button's surface. // itemColour2 bottom gradient of the button's surface. // textColour is unused. // ///////////////////////////////////////////////////////////////////////////// // Create an LAF for the widget. const LAF_textlessButton = Content.createLocalLookAndFeel(); // Define the LAF function. LAF_textlessButton.registerFunction("drawToggleButton", function(graphics, widget) { // ------------- Initialisation // Create descriptive variables name for the widget's properties. var widgetArea = widget.area; var widgetHeight = widget.area[WIDGET_HEIGHT]; var widgetWidth = widget.area[WIDGET_WIDTH]; var widgetStartX = widget.area[WIDGET_STARTX]; var widgetStartY = widget.area[WIDGET_STARTY]; // Set customisable LAF variables. var widgetCornerSize = 2; var widgetBorderWidth = 1; var widgetIndicatorOffset = 6; var widgetWellRadius = 20; var widgetOnIndicatorColour = 0xFAE35BFF; // Create variables we'll use and change. Initialise them to safe values. var fillColour = 0xFFFFFFFF; // ------------- Indicator Colour widgetOnIndicatorColour = widget.textColour; // ------------- Button Surface // Create a colour gradient from itemColour1 to itemColour2. graphics.setGradientFill([ widget.itemColour1, widgetStartX + (widgetWidth/2), widgetStartY, widget.itemColour2, widgetStartX + (widgetWidth/2), widgetHeight]); // Draw the surface. graphics.fillRoundedRectangle(widgetArea, widgetCornerSize); // ------------- Button Border // Set the colour. graphics.setColour(WIDGET_DEFAULT_BORDER_COLOUR); // Draw the border. graphics.drawRoundedRectangle([ widgetStartX, widgetStartY, widgetWidth, widgetHeight], widgetCornerSize, widgetBorderWidth);; // Create the gradient fill. graphics.setGradientFill([ BUTTONWELL_TOPLEFT_GRADIENT_COLOUR, widgetStartX + ((widgetWidth - widgetWellRadius) / 2), widgetStartY + ((widgetHeight - widgetWellRadius) / 2), BUTTONWELL_BOTTOMRIGHT_GRADIENT_COLOUR, widgetStartX + (widgetWidth /2) + (widgetWellRadius/2), widgetStartY + (widgetHeight /2) + (widgetWellRadius/2), false]); // Draw the button well. graphics.fillEllipse([ widgetStartX + ((widgetWidth - widgetWellRadius) / 2), widgetStartY + ((widgetHeight - widgetWellRadius) / 2), widgetWellRadius, widgetWellRadius]); // ------------- Button Value Indicator // Draw the button's indicator circle, with colour dependent on the button's state. if (widget.value) { // Set the colour to the widget's indicator colour (specified in this function). if (widget.enabled) fillColour = Colours.withAlpha (widgetOnIndicatorColour, 1.0); else fillColour = Colours.withAlpha (widgetOnIndicatorColour, 0.3); } else { // Use the default colour for the widget-off state. if (widget.enabled) fillColour = Colours.withAlpha (WIDGETOFF_INDICATOR_COLOUR, 1.0); else fillColour = Colours.withAlpha (WIDGETOFF_INDICATOR_COLOUR, 0.3); } // Set the colour. graphics.setColour(fillColour); // Draw the button value indicator. graphics.fillEllipse([ widgetStartX + ((widgetWidth / 2) - ((widgetWellRadius-widgetIndicatorOffset) / 2)), widgetStartY + ((widgetHeight / 2) - ((widgetWellRadius-widgetIndicatorOffset) / 2)), widgetWellRadius-widgetIndicatorOffset, widgetWellRadius-widgetIndicatorOffset]); });
LAF: Circular Glyph Button
///////////////////////////// CIRCULAR GLYPH BUTTON ///////////////////////// // // ------------- Description // // This button is used for specific functionality in my plugin. You can // easily customise to your own needs. Unlike the other widgets in this // toolkit, the Circular Glyph button is comprised of two different elements: // a HISE button (in the shape of a circle), and a HISE label that is intended // to be a single glyph (inside the circle). // // In the included example, I'm using a numberical glyph. In my plugin, I // use a pictogram font, and that is real intention of this widget: a // circular icon button. To specify the glyph character, type the character // into the Label's value field. // // To set up this button, you must create both widgets (Button and Label). // Type the ID of the Label (i.e., the Label's first field in the Inspector) // into the "text" field of the Button. // // The Circle Button, like the Textless Button in this toolkit, is intended // as a top-level widget; as such, it has no disabled state. It has no // mouse-over states – this is an artistic decision, and you can certainly // implement your own using the approaches for other widgets in this // toolkit. // // ------------- Inspector Colour Mapping // // This LAF maps the same Colours (in the Inspector) as HISE's combobox. // // • bgColour for the border. // • itemColour is the circle's surface colour. // • itemColour2 is unused (because there's no gradient). // • textColour is unused (because the text glyph is created using the label. // • Set the opacity to 0%. // // For the Label, there is no LAF, so whatever you specify in the Inspector for it // will be directly applied. // // • bgColour is unused; set to 0% opacity). // • itemColour is unused; set to 0% opacity). // • itemColour2 is unused; set to 0% opacity). // • textColour is the glyph's colour. // ///////////////////////////////////////////////////////////////////////////// // Create an LAF for the widget. const LAF_CircleButton = Content.createLocalLookAndFeel(); // Register and define the drawing function for the button component. LAF_CircleButton.registerFunction("drawToggleButton", function(graphics, widget) { // ------------- Initialisation // Get a more descriptive name for the button's area. var widgetHeight = widget.area[WIDGET_HEIGHT]; var widgetCircleDiameter; var widgetCircleMargin = 2; // ????? THIS WAS OFF switch (widget.text) { case "label_GLOBAL_SetDirectory_ART": widgetCircleDiameter = widgetHeight; break; case "label_GLOBAL_OpenPrefs_ART": widgetCircleDiameter = widgetHeight; break; case "label_GLOBAL_GetSupport_ART": widgetCircleDiameter = widgetHeight; break; default: widgetCircleDiameter = 40; } // This looks like quite a hack. switch (widgetHeight) { case 40: widgetCircleDiameter = 40; break; default: widgetCircleDiameter = widgetHeight; } // ------------- Button // Set the border's colour. graphics.setColour(WIDGET_DEFAULT_BORDER_COLOUR); // Draw the border. graphics.fillEllipse([0, 0, widgetCircleDiameter,widgetCircleDiameter]); // Set the surface's colour. graphics.setColour(widget.itemColour1); // Draw the surface. graphics.fillEllipse([ widgetCircleMargin, widgetCircleMargin, (widgetCircleDiameter - (2 * widgetCircleMargin)), (widgetCircleDiameter - (2 * widgetCircleMargin))]); // ------------- Glyph var widgetID = widget.id; var glyphIntermediateName = widgetID.replace("OpenModuleInterface_GUI", "ModuleCoverGlyph_ART"); var glyphLabelName = glyphIntermediateName.replace ("button", "label"); var theLabel = Content.getComponent(glyphLabelName); // var theLabelA = Content.getComponent(widgetID); // var theLabelB = theLabelA.get("text"); // var theLabel = Content.getComponent(theLabelB); // Console.print("]]]: " + theLabel); // if (glyphLabelName.contains("MODEL")) Console.print("widgetID: " + widgetID + " glyphIntermediateName: " + glyphIntermediateName + " glyphLabelName: " + glyphLabelName + " OVER"); // Get the Label's text colour. var textColour = theLabel.get("textColour"); if (widget.over) { // Console.print("widgetID: " + widgetID + " glyphIntermediateName: " + glyphIntermediateName + " glyphLabelName: " + glyphLabelName + " OVER"); // If the button is on, use no tranparency for the colour. theLabel.setColour(3, Colours.withAlpha(textColour, 1.0)); } else { // Otherwise, use 40% opacity. This will dim the the glyph. theLabel.setColour(3, Colours.withAlpha(textColour, 0.5)); } });
And the LAF functions…
/**************************************************************************** * * * * * LAF TOOLKIT * * * * * ****************************************************************************/ ///////////////////////////// TOOLKIT CONSTANTS ///////////////////////////// // // ------------- Description // // These constants are used for mulitple widgets in the toolkit. // ///////////////////////////////////////////////////////////////////////////// // ------------- HISE Constants // Define HISE constants. const WIDGET_STARTX = 0; const WIDGET_STARTY = 1; const WIDGET_WIDTH = 2; const WIDGET_HEIGHT = 3; const COMPONENT_BGCLOUOR = 0; const COMPONENT_ITEMCOLOUR1 = 1; const COMPONENT_ITEMCOLOUR2 = 2; const COMPONENT_TEXTCOLOUR = 3; // Define default colours. const BUTTONWELL_TOPLEFT_GRADIENT_COLOUR = 0xFF404049; const BUTTONWELL_BOTTOMRIGHT_GRADIENT_COLOUR = 0xFF27272C; const WIDGETOFF_INDICATOR_COLOUR = 0xFF5A5B5C; const WIDGETOVER_SURFACE_COLOUR = 0xFF41414F; const WIDGET_DEFAULT_BORDER_COLOUR = 0xFF212126; const WIDGET_DEFAULT_TEXT_COLOUR = 0xFAFFFFFF; // Define brightness adjustments. const WIDGET_BRIGHTNESS_ADJUSTMENT_MOUSEOVER = 0.025; const WIDGET_BRIGHTNESS_ADJUSTMENT_TEXTOFF = -0.1; const WIDGET_BRIGHTNESS_ADJUSTMENT_DISABLEDGRAPHIC = -0.06; const WIDGET_BRIGHTNESS_ADJUSTMENT_INDICATOROFF = -0.1; const WIDGET_BRIGHTNESS_ADJUSTMENT_DISABLEDINDICATOR = -0.5; const WIDGET_BRIGHTNESS_ADJUSTMENT_DISABLEDTEXT = -0.7; const WIDGET_TRANSPARENCY_ADJUSTMENT_DISABLEDINDICATOR = 0.4; // ------------- Extra Progress LAF const DISABLED_PROGRESS_BUTTON_TEXT_COLOUR = 0xFF5d5d68; const DISABLED_PROGRESS_BUTTON_BODY_COLOUR = 0xFF404049; const ENABLED_PROGRESS_BUTTON_BODY_COLOUR = 0xFB29292D; /////////////////////////// MESSAGE BOX ICONS ////////////////////////////// /////////////////////////// STANDARD FUNCTIONS ////////////////////////////// // // ------------- Description // // These functions are drop-in replacements for existing HISE functions, // fixing bugs and/or providing additional functionality. // // Unlike the LAF funcitons, these standard functions require error-handling. // They assume proper error-handling and reporting on HISE functions that // are called upon. // ///////////////////////////////////////////////////////////////////////////// /////////////////////// BRIGHTNESS COLOUR ADJUSTMENT //////////////////////// // Brighten or dim a widget using +/- from 0.0 to 0.1. Unlike the HISE // "withBrightness" code, this function can also increase brightness. // The loops are all unrolled in the code here for those who are learning. // (Otherwise, this routine could be done in just a couple lines.) inline function WithSignedBrightness(uint32Colour, brightnessAdjustment) { // Convert the uint32Colour to an array of component floats. local colourArray = Colours.toVec4 (uint32Colour); // Do red. local componentRed = colourArray[0]; componentRed += brightnessAdjustment; if (componentRed < 0.0) componentRed = 0.0; if (componentRed > 1.0) componentRed = 1.0; colourArray[0] = componentRed; // Do blue. local componentBlue = colourArray[1]; componentBlue += brightnessAdjustment; if (componentBlue < 0.0) componentBlue = 0.0; if (componentBlue > 1.0) componentBlue = 1.0; colourArray[1] = componentBlue; // Do green. local componentGreen = colourArray[2]; componentGreen += brightnessAdjustment; if (componentGreen < 0.0) componentGreen = 0.0; if (componentGreen > 1.0) componentGreen = 1.0; colourArray[2] = componentGreen; // Convert the array of floats back into a uint32Colour. local NewColour = Colours.fromVec4(colourArray); // Return our new colour. return NewColour; };
-
@clevername27 Thanks for sharing. I will put the LAF to the HISE LAF Collection asap.
-
@clevername27 Looking good!
-
@orange @Dan-Korneff Thanks guys.