Skip to content

Layouts

Tyler Reynolds edited this page Apr 27, 2021 · 11 revisions

Building your own Layout

Building your own TouchOSC layout is really quite easy. This document assumes you've already downloaded TouchOSC on whichever device you wish to use as your editor, and are ready to begin creating your own layout.

This document will cover some common use cases you may encounter when creating your own layout. If you still have questions, it might help to look at existing layouts to see how others accomplish similar tasks.

Basics

Core to all components

For all components, you'll have to specify the DCS-BIOS control that the component should interact with. You can do this under the Messages section on the right sidebar.

TouchDCS only cares about OSC messages. As such, you may delete the default MIDI messages that are created for any component.

In order for a component to do anything useful, it needs to know who to listen/talk to. We can customize this in the Address section. By default, the address is /<name>. For almost all purposes, this is fine. In the Control section, you can customize the name. You should name the component exactly the same as the name of the DCS-BIOS control you'll be interacting with. If you don't know how to find the name of the control you want, check out the DCS-BIOS installation instructions for info on how to get the DCS-BIOS Control Reference Page set up on your machine.

Two position switches

A BUTTON can be used to handle just about any two-position momentary or toggle switch. In most cases, these require no customization outside of the standard component naming.

Push buttons

By default, buttons are created as push buttons. This should require no customization.

Toggle buttons

For a toggle button, simply change Type from Momentary to Toggle Press or Toggle Release based on personal preference. Toggle Press will toggle as soon as you touch the button, whereas Toggle Release will toggle after you lift your finger up.

N-position switches

For a multi-position toggle switch or rotary selector, I've found the RADIO component to work best (give the TouchOSC devs some love for this component - it was created specifically for this!).

This component works great for 3-position toggle switches, or rotaries with any number of positions - though I've found it best to limit it to 6 or 7 as any more becomes cluttered.

Radio

Some customization is required here. DCS-BIOS only cares about the index of the item we want to select, so we need to change the Argument to x (+ -> VALUE -> x)

Some experimentation with the Orientation property may also be required, in case the buttons are working the opposite way you might expect them to.

Increment/decrement

In some cases, you may either have too many positions, or a RADIO simply may not be desirable. Any DCS-BIOS component with a fixed_step input interface can instead use push buttons to increment/decrement the rotary.

In this case, we'll be modifying the Messages section.

  1. Disable Receive, as there's no meaningful way for this to display anything without modifying the script
  2. Set Trigger to x -> RISE so that we only send a message when the button is pressed, not released
  3. Set Arguments to the constant INC - for the decrement button, use DEC

Using a radial

Sometimes, neither of those options are satisfactory. A third option is to use the RADIAL control. As of the time of writing it doesn't allow snapping, but it will otherwise work for the purpose of an n-position switch.

The important change that needs to be made here is to the Scale of the Argument. Adjust the max value of the Scale based on the number of positions that should be selectable. You can also set Conversion to INTEGER to force the value to snap to the grid positions.

Knobs (limited rotation)

For any knob with limited rotation, a RADIAL component is the easiest to configure. The only thing that needs to be done is for the Arguments to be set to x. A FADER component can also be substituted in and functions largely the same.

variable_step

If you'd like to use buttons to step through a knob's values, you can do that in a similar manner to incrementing/decrementing an n-position switch. Simply the the Arguments to a constant STRING +10 (or whatever number you prefer) for the increment button and -10 for the decrement button.

Encoders (unlimited rotation)

Set the Arguments to y, and set the Scale from -1 to 1. You may need to reverse these if the knob rotates the opposite direction in game.

By default, this will send a lot of values corresponding to the direction of movement - maybe more than you want. You can use a script to force a limited number of values to be sent with each rotation. I don't promise this script to be mathematically accurate, but it seems to be close enough for my purposes. Just set the Grid step size to the number of increments you'd like a full rotation to make.

local lastX = 0
local stepIncrement = 1.0 / self.properties.gridSteps

function onValueChanged()
    local d = math.abs(lastX - self.values.x);
    
    if d > 0.5 then d = math.abs(d - 1) end
    
    if d < stepIncrement then
        return true
    end
    
    lastX = math.floor((self.values.x / stepIncrement) + 0.5) * stepIncrement
    if math.abs(1 - lastX) < 0.01 then lastX = 0 end
end

Labels

Labels can receive string output from DCS-BIOS.

You'll need to add a new OSC Message, and then disable the Send functionality - this will only receive data from DCS-BIOS.

Advanced customization

LEDs

To create an LED, just create a button, uncheck Interactive, and under the OSC message uncheck Send. This will result in a control that will light up when it receives a message, but can't be modified by touch.

Switch covers (local messages)

You can use local messages to create switch covers that "open" and "close" to reveal the underlying control. To do this:

  1. Create a button to be the underlying control (we'll call this button)
  2. Create a button to be the cover (we'll call this cover
  3. On cover, create a local message, with a trigger of x -> ANY
    • set the source to x -> VALUE
    • set the target to frame.h -> cover
    • set the scale <full height> -> <open height>
  4. Create another local message with a trigger of x -> ANY
    • set the source to x -> VALUE
    • set the target to interactive -> control
    • this isn't strictly necessary, but will prevent you from modifying the underlying control when the cover is "closed"

Label remapping

Some text outputs send seemingly arbitrary strings for certain messages. In cases like these, you'll need a script in the label to translate the message. I've found something like the following to work:

local map = 
{
  ["   pww0w"] = "ERROR", -- the hornet sends this on the UFC
}

function onReceiveOSC(msg)
  local val = msg[2][1].value -- get the first value sent

  if (map[val]) then
    self.values.text = map[val] -- if the value matches something in our map, replace it with that
    return true -- exit early, don't allow the label to be set to msg since we've already set it
  end  
end

Discarding non-string values with scripts

Some controls output both an integer and a string to the same address, and sometimes those values are different. In these cases, you might want to filter to tell a control to only display one of the values. I've used the following script:

function onReceiveOSC(msg)
  local arguments = msg[2]
  if(#arguments > 0 and arguments[1].tag ~= 's') then
    return true -- replace s with i to only accept integers and not strings
  end
end