C# component icon

Did you check out Junichiro’s tutorial ?
Is this what you mean ?

The act of adding a resource might be simple (although not in my personal experience), but the deluge of files and bouncing references around that goes on behind the scene is intimidating.

Its a slightly different way but basicly the same. You can add a resource item the same way you add a new class file etc. Then you can just reference it from the code.

Victory !

Icons

As a side note, the indications in the template file are incomplete :


It should read :
return “project name”.Properties.Resources.IconForThisComponent

:tada:
And in six weeks you will say to yourself: “How easy it was” :slight_smile:

Just to muddy the waters, I’ve never been a big fan of the automatic resources system and instead directly create a bitmap from an embedded resource

3 Likes

Yeah, but now @stevebaer , we’re gonna lose @osuire .
Me too. I rarely use automatic resources.

2 Likes

@stevebaer Thanks for this, I had a similar issue using Rider. I was following @LongNguyen recorded workshop. This is what ended up working for me:

  1. Make sure the 24x24 icon is an ‘Embedded Resource’

  2. Use a stream, but with the EndsWith recommendation found on this Stack Overflow: c# - Determining the name of a .NET embedded resource? - Stack Overflow

Here is the code that finally worked from the .cs file:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Runtime.Versioning;
using Grasshopper;
using Grasshopper.Kernel;
using Rhino.Geometry;

namespace Plugin_1_Day_3
{
  public class Averages : GH_Component
  {
    /// <summary>
    /// Each implementation of GH_Component must provide a public 
    /// constructor without any arguments.
    /// Category represents the Tab in which the component will appear, 
    /// Subcategory the panel. If you use non-existing tab or panel names, 
    /// new tabs/panels will automatically be created.
    /// </summary>
    public Averages()
      : base("Averages", "Computes Averages",
        "Workshop Test Component - Averages",
        "Workshop", "Utilities")
    {
    }

    /// <summary>
    /// Registers all the input parameters for this component.
    /// </summary>
    protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
      pManager.AddNumberParameter("first num", "first", "the first num", GH_ParamAccess.item, 0.0);
      pManager.AddNumberParameter("second num", "second", "the second num", GH_ParamAccess.item, 0.0);
    }

    /// <summary>
    /// Registers all the output parameters for this component.
    /// </summary>
    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
      pManager.AddNumberParameter("Average", "Average", "average of inputs", GH_ParamAccess.item);
    }

    /// <summary>
    /// This is the method that actually does the work.
    /// </summary>
    /// <param name="DA">The DA object can be used to retrieve data from input parameters and 
    /// to store data in output parameters.</param>
    protected override void SolveInstance(IGH_DataAccess DA)
    {
      var nums = new List<double>();
      double a = double.NaN;
      double b = double.NaN;
      nums.Add(a);
      nums.Add(b);
      DA.GetData(0, ref a);
      DA.GetData(1, ref b);

      double average = 0.5 * (a + b);
      DA.SetData(0, average);
    }

    /// <summary>
    /// Provides an Icon for every component that will be visible in the User Interface.
    /// Icons need to be 24x24 pixels.
    /// You can add image files to your project resources and access them like this:
    /// return Resources.IconForThisComponent;
    /// </summary>
    //protected override System.Drawing.Bitmap Icon => null;
    protected override System.Drawing.Bitmap Icon
    {
      get
      {
        var assembly = System.Reflection.Assembly.GetExecutingAssembly();
        {
          var resourceName = assembly.GetManifestResourceNames().Single(n => n.EndsWith("icon.png"));
          var stream = assembly.GetManifestResourceStream(resourceName);
          if (stream != null) return new Bitmap(stream);
        }
        return null;
      }
    }

    /// <summary>
    /// Each component must have a unique Guid to identify it. 
    /// It is vital this Guid doesn't change otherwise old ghx files 
    /// that use the old ID will partially fail during loading.
    /// </summary>
    public override Guid ComponentGuid => new Guid("6CBE441F-4367-4146-9755-BF7296D4BFE1");
  }
}

Here’s how it turned out:
image

Also, kinda unrelated, but making a big difference for me with this kinda stuff. This plugin makes learning to write C# plugins so much less tedious:

image

3 Likes

Sorry, but I don’t understand what I’m doing wrong:

Try this ,and it’s better if you rename the icon to something different from Icon

protected override System.Drawing.Bitmap Icon => Properties.Resources.Icon;

1 Like

image
On the component it works, thanks. And above?

You can create a new component using existing template and compare it with your code, or post your project to get help from the developers

For those who might benefit from a visual explanation over a written one, I have found this video quite helpful for when I was first learning how to add icons.

5.5 Adding Icons to Your Plug-in! - Advanced Development in Grasshopper - YouTube

As well, @stevebaer I really like that method of auto compiling from the icon folder. I just might pick it up.

1 Like