Tech Note: Creating External Scenes with Hype

From Waltz
Revision as of 22:16, 28 February 2020 by Patrick Angle (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This tutorial assumes a basic understanding of HTML, CSS, and JavaScript, Hype and how those technologies interact with each other. Scenes can also be created by hand, as documented in Creating External Scenes by Hand.

Scenes in Waltz use standard web technologies, including HTML5, CSS, and JavaScript. As such, scenes can be created with external tools like Tumult's Hype 4 Pro (macOS only, requires in-app purchase of $99). You can learn more about Hype 4 on its official website. This documentation is by no means intended to be a full-fledged manual for using Hype, but rather shows the possible integrations between Waltz and pages built with Hype.

Adding Waltz Support to a Hype document

Waltz requires a small amount of JavaScript to be available in your project in order to communicate between the HTML page and Waltz itself. This can be done by following these steps:

  1. Select the View ▸ Document Inspector menu item to show the Document Inspector.
  2. In the Document Inspector, press the Edit Head HTML… button.
  3. Insert the following between the two head tags:
<script src="/api/jquery.js"></script>
<script src="/api/waltz.js"></script> 
<script>
    $(function() {
        Waltz.init(30);
    });
</script>

The 30 in the script above is the number of times per second that polled information will be updated. While it is normal to run Waltz at 60+ FPS, we generally recommend scenes run at about 30 FPS to reduce the amount of network traffic, particularly on wireless networks.

In order to use the Preview feature in Hype, you may need to modify the scripts above. The Advanced Initialization documentation covers the available options.

Performing Actions in Waltz

Actions are similar to Scripts in Waltz. They are able to interact with any node or nodes on the stage, and the output of the script does not matter. The script is execute every time an element is clicked/tapped or when any event as defined below has occurred.

Any element in the DOM that supports JavaScript events can execute an action on click/tap, or if desired on a specially assigned event for that element.

Waltz integration uses Classes to describe available functionality on an element. To perform an action, first add the waltzAction class to the element. The waltz.js library looks for this, as well as other special classes, to inform the configuration of an element. Multiple classes may be used on a single element. The classes defined by Waltz do not apply any style themselves, unless you configure them to do so via CSS. After adding the waltzAction class, you then add a custom data attribute named data-waltz-action to the element with the script you wish to be executed by Waltz as its value. This script is the same JavaScript you would use inside Waltz to perform an action, and in fact the full script you provide here will be executed inside Waltz, not on the local webpage.

For example, a button can be configured to send an OSC message using a node named oscOutput from our show with by taking the following steps in Hype:

  1. Select the element on your page you wish to have perform the action, like an Image or a Button.
  2. Select the View ▸ Identity Inspector menu item to show the Identity Inspector.
  3. In the Identity Inspector, find the Class Name field and enter waltzAction (if you want to assign multiple classes to the same element, just separate each class name with a single space).
  4. Below the Class Name field, find the Additional HTML Attributes table, and press the plus button.
  5. In the new entry, enter data-waltz-action as the key, and $.oscOutput.send(99) as the value.

These steps make sure the Waltz.js library correctly handles the element as an action, and defines that the action will send an OSC message with a value of 99.

It is considered best practice to, rather than call functions on nodes directly from a webpage, use a Script Function node that optionally takes any number of parameters, and set actions on the webpage to run that script function instead. In the example above, let's assume we have a Script Function node named sendMyMessage which has a single parameter configured. To use our new script function we would replace the value in step 5 with $.sendMyMessage.run(99) to accomplish this. This allows you to make edits to the exact way messages are handled without having to edit the webpage source later.

By default, the data-waltz-action is executed onclick for desktop browsers or ontouchstart for mobile browsers. While it might seem that ontap would be a closer analog for onclick, some users have trouble interacting with touch screens, and triggering ontouchstart is often more accessible for persons not accustomed to using touch screens, and is of little detriment to users who expect action to occur ontap instead. The type of trigger for an action can be configured.

Displaying Values from Waltz

Displaying values from Waltz is just as simple as performing actions, and works mostly in the same. The contents of the configured element will be emptied and replaced with the value from Waltz, so it is generally best to use an element that can contain text like Button, Text, or Rectangle to contain the value. Any existing text in deleted when the value is updated by Waltz. To make an element contain a value from Waltz, it must have waltzValue added to its classes, and have a data-waltz-value attribute with an expression from which the value will come.

For example, a Text element can be configured to display the value of a Wave node, conveniently called wave, by taking the following steps in Hype:

  1. Select the element on your page you wish to have display the value.
  2. Select the View ▸ Identity Inspector menu item to show the Identity Inspector.
  3. In the Identity Inspector, find the Class Name field and enter waltzValue (if you want to assign multiple classes to the same element, just separate each class name with a single space).
  4. Below the Class Name field, find the Additional HTML Attributes table, and press the plus button.
  5. In the new entry, enter data-waltz-value as the key, and $.wave.output as the value.

Styling Elements from Values in Waltz

In addition to displaying values inside elements, Waltz also allows you to dynamically style the element based on a value from inside of Waltz. This is accomplished with the waltzStyle class and knowledge of available CSS properties. After assigning the waltzStyle class to the desired element, you must provide an attribute for each css property you wish to effect on the element. Each data attribute must have a unique name and be in the format of:

data-waltz-style-{css-property-name}

For example, to change the background color of an element, you would use the data attribute key of:

data-waltz-style-background-color

Notice that all letters must be lower case.

To style the text color of an element based on the value of a Wave node, still conveniently called wave, you would do the following in Hype:

  1. Select the element on your page you wish to have display the value.
  2. Select the View ▸ Identity Inspector menu item to show the Identity Inspector.
  3. In the Identity Inspector, find the Class Name field and enter waltzValue (if you want to assign multiple classes to the same element, just separate each class name with a single space).
  4. Below the Class Name field, find the Additional HTML Attributes table, and press the plus button.
  5. In the new entry, enter data-waltz-style-color as the key.
  6. For the value, lets assume we want the text to be green (#00ff00) for values over 0 and red (#ff0000) for all other values. We use a ternary operator to provide this simple logic evaluation by setting the value of our tag to be $.wave.output > 0 ? '#00ff00' : '#ff0000'.

Not all CSS properties are supported. You can not define a @FontFace for reuse in other components, nor can you use vendor-specific prefixed properties like -webkit-border-radius. For border radii, you must use the standard border-radius property.