Writing C# Functions

Creating Functions in C#

By uploading a function to Hypar you can produce multiple options for a building problem in just a few seconds, and combine them with other people's functions to create rich, realistic designs. In this introduction to Hypar, we'll work with a much simpler function that generates masses of variable dimensions.

Tutorial Video

Video preview

Things you might want to know

  • Basic familiarity with the C# programming language will help, but if you're not familiar with C# we'll do our best to walk you through making changes to the initial code you'll get by following the steps in this guide.
  • If you want to share your Hypar functions, you have to explicitly make your work public, so don't worry that perfect strangers are judging your work. They will, but only if you decide to make them public.
  • The procedures you'll use in this guide compile your code on your desktop and only upload the resulting binary file. No one at Hypar will examine your source code because we won't have it unless you make it public by some other means or if you send it to us so we can help you solve a problem.
  • None of the Hypar libraries you'll use in this guide bind your code to Hypar web services. For example, if you'd like to use the Elements library for a desktop application, it's an open source project on GitHub and will always be free for anyone to use or extend. You don't even have to tell us you're using it.

Creating a Function

  • Next, return to the Hypar web interface and sign in. Scroll down to see Your Functions, and click New Function followed by New C# Function.
    • notion image
      notion image
  • This wizard will take you through setting up your function. For consistency with the rest of this example, give your function the name Starter Function.
    • notion image
  • Click Next to proceed to configuring your function's inputs. Click or drag three "Range" inputs and name them Width, Length, and Height, and set their minimum values to 1:
    • notion image
  • You can also select "Preview" to visualize how the inputs will look in the function.
  • Go on to the next step. We'll save the Connections section for another tutorial, so click next again so that Step 4: Outputs is highlighted at the top. Click the + to add a new output to report the box's volume, and configure it like so:
    • notion image
  • Move on to the final step, Logic. Click "Publish Function," and then click the button to copy the terminal command.
    • notion image
notion image
  • Now your function has been published (privately) to Hypar! Next, we'll write some code to define the logic for the function.
  • Return to your command prompt. Decide where you want Hypar to save the code for your function on your computer, and use the cd command to set that location as the current working directory:
    • cd C:/users/yourUserName/repos
  • Then paste the command you copied from the Hypar web interface, and run that (don't copy the one below, it won't have the right ID):
    • hypar new --function-id=96a0df70-2a7d-4612-9c0e-7f6d86830576
  • A bunch of messages will go by as Hypar sets up your local project.
    • notion image
  • Next, open VS Code and open the project folder we just created. It should be in the location you picked earlier, with the folder name "StarterFunction."
  • The Hypar CLI just created a bunch of files for you. Here's what that looks like in VS Code:
    • notion image
  • It may seem like a lot, but the good news is you rarely have to edit most of these files — Hypar takes care of all of that for you. Any file you see that ends with .g.cs is not meant to be edited by you.
    • The file we care about most is StarterFunction.cs in the /src directory — this contains the logic for your function. Let's open it up.
      The Execute method is the entry point into our function. It doesn't do anything very exciting right away; it creates an "Outputs" object, and returns it.
      notion image
      Note that the method has a few arguments. The one called input contains the inputs we defined earlier, like Width, Length, and Height. Let's use some of those inputs to create a rectangle. Add this line to your function, in between the two existing lines of the method:
      var rectangle = Polygon.Rectangle(input.Width, input.Length);
      notion image
  • Next we'll make a Mass Element to pass out to the Hypar 3d environment. Note that if you want something to show up in the 3d view, it has to be an Element of some kind. Add this line after the rectangle:
    • var mass = new Mass(rectangle, input.Height);
      notion image
  • We also have to put the mass we created in the output model, like so:
    • output.Model.AddElement(mass);
      notion image
  • Finally, we created an output called Volume to report the box's volume. These data outputs are provided to the constructor for the Outputs object — so let's edit the first line of our method to look like this:
    • var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height);
  • Our function should look like this when we're all done. Be sure to save the file!
    • public static StarterFunctionOutputs Execute(Dictionary<string, Model> inputModels, StarterFunctionInputs input) { // create an outputs object and populate any output values var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height); // create a rectangle var rectangle = Polygon.Rectangle(input.Width, input.Length); // create a mass from the rectangle var mass = new Mass(rectangle, input.Height); // add the mass to the output model output.Model.AddElement(mass); return output; }
  • To publish our changes to the web, open up your command prompt again (or open VS Code's integrated terminal). Make sure your working directory is the one Hypar created for you — you might need to cd StarterFunction first. Then publish your function logic like this:
    • hypar publish
      notion image
  • Now your function logic has been added to your function on Hypar. Let's go test it out! Return to hypar.io and sign in.
  • Create a new workflow by clicking New Workflow and selecting New Blank Workflow. Once it opens up, give it a name in the nav bar. Type in any name you want (perhaps "Starter workflow"). You'll see this screen:
    • notion image
  • In the Function Library panel, search for "Starter Function" (or whatever you named your function).
  • Now let's try out our function. Click Insert on Starter Function and hide the Function Library by clicking the "X" to close it. Your function will run automatically and you should see something like this:
    • notion image
      You've just run a web application that you created!
  • Click in the 3D view to zoom, pan, and rotate the result. Now click on Starter Function to open up its inputs. Try adjusting the sliders to see how the mass changes shape. Check the "Sample Range" checkbox under the height and width sliders. Then click the "Alternatives" button on your workflow to see the options that have been generated.
    • notion image
      In the alternatives list, you can see that your function has actually run many times with different input values. Click different alternatives to view them in 3D. The range sliders on the left are set to allow all possible lengths and widths. You can shrink these ranges to generate just the options you want.
notion image
  • This diagram summarizes the process we just went through to create, define, and publish our function:
    • notion image

Editing your function

While developing a function, you may need to add additional inputs or outputs and change function logic. In this section we'll see how to do this.
notion image
In your workflow, you should see an "About" link under the name of your function. Click it to open the function details. As the owner of this function, you have the ability to make changes here.
notion image
Switch to the Inputs tab and click Edit Function Details at the bottom of the window. This brings us to the same interface we used to create the inputs originally.
notion image
Let's add a new Color input by dragging "Color" to the top. We'll call it "Mass Color" and click the color swatch to set a different color as the default. Any value you set in this window will be the default value that shows up when your function is added to a workflow.
notion image
Switch to the Outputs tab so we can add an output for the base area of our mass. Click + to add it, and configure it like so:
notion image
Click Save Changes to register your changes to the function's configuration.
Next, we'll need to pull those changes into our local code files, so that we can use the new input and output. Switch to the Logic tab and copy the second command:
hypar pull && hypar init
hypar pull pulls the changes we made in the web interface to our hypar.json configuration file, and hypar init generates new code files from that configuration. You are also welcome to run these commands independently — you don't need to copy them from the web every time.
Let's return to VS Code, and take a closer look. If you select hypar.json in the righthand side, you can view the configuration that describes this function.
notion image
If you scroll down, you should see our new Color input and Area output reflected:
notion image
Advanced users may find it easier to edit hypar.json manually rather than editing the function in the web UI and running hypar pull — it's completely up to you. Just remember to use hypar init after any changes to hypar.json to make sure the corresponding C# code gets regenerated.
Returning to StarterFunction.cs, we can take advantage of our new inputs and outputs. We'll edit the first line to add the base area output:
var output = new StarterFunctionOutputs(input.Width * input.Length * input.Height, input.Width * input.Length);
And create a new material before we create our mass:
var material = new Material("Box Color", input.MassColor);
And finally add the material to the mass.
var mass = new Mass(rectangle, input.Height, material);
Here's how the updated Execute method code should look now:
public static StarterFunctionOutputs Execute(Dictionary<string, Model> inputModels, StarterFunctionInputs input) { // create an output objectvar output = new StarterFunctionOutputs(input.Width * input.Length * input.Height, input.Width * input.Length); // create a rectanglevar rectangle = Polygon.Rectangle(input.Width, input.Length); // create a new materialvar material = new Material("Box Color", input.MassColor); // create a mass from the rectanglevar mass = new Mass(rectangle, input.Height, material); // add the mass to the output model output.Model.AddElement(mass); return output; }
Be sure to save the file, and then publish these changes by running
hypar publish
again. Then we'll return to our workflow on Hypar, and reload the page to update the function. You may have to adjust a slider value to cause the function to recompute.
notion image
This diagram summarizes the steps we've taken to edit and update our function:
notion image

Sharing your function

Your function always starts out private to you: only you can see and use it in a workflow. Once you're happy with your function, you can share it with the world!
Click the "About" link under your function name again, and this time navigate to the Permissions tab.
notion image
Uncheck the Private checkbox to make your function public. You can also choose to share it in a more limited way, by sharing with specific email addresses or with a whole email domain (like myfirm.com).
You may also want to add a thumbnail to your function so others can get a sense of what it does. To do this, go to the
tab, click
Edit Function Details
, and drag-and-drop an image on the drop zone. Then click
Save Changes
to save the thumbnail.
notion image

Testing your function

There are two ways to test a function.
  • hypar run is a live, highly interactive method, that lets you see the results of your code changes in a workflow, nearly instantly.
  • hypar test generate constructs a local test for in-depth debugging, or testing against multiple scenarios.
Testing with hypar run
Generating a local test
Here is a video that demonstrates both methods:
Video preview

What's next?

Congratulations on creating your first Hypar function! There's more to learn, but you should start thinking about building a real, useful function. Here are a few tips for deciding what to make:
  • Solve one small problem. Hypar Functions are easy to compose. No single function needs to do too much on its own.
  • Take something you've done before and do it again on Hypar.
  • Scratch an itch. What do you hate doing manually? What would look cool? What would look silly?
  • You don't need to be original. Just get started. Feel free to make another version of something you've already seen.
Here are some other good resources:
  • Hypar's Building Blocks repo has the source code for many Hypar functions. Read those to see how they work, and feel free to branch or improve any of them.

Advanced Topics

  • Use Function Staging to safely test out new updates to your function without breaking anything for existing users:
  • Learn about Overrides, to create richer, more intelligent interactions with your functions, in way that can balance automation with human design intervention:
  • Learn about Element Instances, to efficiently create multiple copies of a piece of geometry as output from your function:
  • Use Queries to select elements and get data: