internal static void AddPullDownButton(PulldownButton pulldown, LinkedScript script, LinkedScriptAssembly lsa)
 {
     if (pulldown.AddPushButton(NewScriptButton(script, lsa.FilePath)) is PushButton pushButton)
     {
         // do stuff with button?
     }
 }
 internal static void AddPanelButton(RibbonPanel panel, LinkedScript script, LinkedScriptAssembly lsa)
 {
     if (panel.AddItem(NewScriptButton(script, lsa.FilePath)) is PushButton pushButton)
     {
         // do stuff with button?
     }
 }
        internal static PushButtonData NewScriptButton(LinkedScript script, string assmLoc)
        {
            var commandName       = script.ScriptCommandType.Name + (script.Name ?? "");
            var commandButtonName = script.Name.Replace("-", "\n");
            var typeAssmLocation  = assmLoc;
            var typeName          = script.ScriptCommandType.FullName;

            return(new PushButtonData(commandName, commandButtonName, typeAssmLocation, typeName)
            {
                Image = ImageBuilder.LoadRibbonButtonImage($"Ribbon.Grasshopper.{script.ScriptType}.png", true),
                LargeImage = ImageBuilder.LoadRibbonButtonImage($"Ribbon.Grasshopper.{script.ScriptType}.png"),
                ToolTip = "Launch script in Grasshopper player",
                LongDescription = $"Script Path: {script.ScriptPath}",
            });
        }
        public Type MakeScriptCommandType(LinkedScript script)
        {
            var typeBuilder = ModuleBuilder.DefineType(
                $"LinkedScriptCmd-{Guid.NewGuid()}",
                TypeAttributes.Public | TypeAttributes.Class,
                typeof(LinkedScriptCommand)
                );

            // Transaction(TransactionMode.Manual)
            typeBuilder.SetCustomAttribute(
                new CustomAttributeBuilder(
                    typeof(TransactionAttribute).GetConstructor(new Type[] { typeof(TransactionMode) }),
                    new object[] { TransactionMode.Manual }
                    ));

            //  Regeneration(RegenerationOption.Manual)
            typeBuilder.SetCustomAttribute(
                new CustomAttributeBuilder(
                    typeof(RegenerationAttribute).GetConstructor(new Type[] { typeof(RegenerationOption) }),
                    new object[] { RegenerationOption.Manual }
                    ));

            // get GrasshopperScriptCommand(string scriptPath) const
            var ghScriptCmdConst = typeof(LinkedScriptCommand).GetConstructor(new Type[] {
                typeof(int),   // "scriptType"
                typeof(string) // "scriptPath"
            });
            // define a base contructor
            var baseConst = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { });
            var gen       = baseConst.GetILGenerator();

            gen.Emit(OpCodes.Ldarg_0);          // load "this" onto stack
                                                // load "scriptType"
            gen.Emit(OpCodes.Ldc_I4, (int)script.ScriptType);
            // load "scriptPath"
            gen.Emit(OpCodes.Ldstr, script.ScriptPath);

            gen.Emit(OpCodes.Call, ghScriptCmdConst); // call script command constructor with values loaded to stack
            gen.Emit(OpCodes.Nop);                    // add a few NOPs
            gen.Emit(OpCodes.Ret);                    // return

            return(typeBuilder.CreateType());
        }