libtweak
lets you define parameters that can be adjusted while your
C++ program is running. It is particularly suited to realtime
applications like games, where you want instant feedback when making
changes.
- Supported languages: C++11
- Supported platforms
- Full Support: Linux, Mac
- Production mode only: All other platfoms
- Extra Requirements: Python 3
Run make
. Find libtweak.a
in build/
and link your program with
it. Add libtweak’s include
directory to your header file search path.
The examples below will also assume that libtweak’s bin
directory is
on your PATH
.
Declare tweakable parameters in your program:
#include <tweak.h>
TWEAK(float, sausage_length)
TWEAK(float, temperature)
Use them like ordinary variables:
int main()
{
tweak::init();
// ...
}
void do_frame()
{
tweak::process();
printf("The sausages are %fcm long and %f°C!", sausage_length, temperature);
}
While your program is running, adjust parameters using the GUI:
tweak
When distributing your program, you can build a version where libtweak
is not linked in, and your parameters compile to ordinary constants.
To do this:
- Generate a header file with the constants baked in:
tweakc > myconstants.h
- Include this file before
<tweak.h>
. - Define
TWEAK_BAKE
before including<tweak.h>
. This tellstweak.h
to use the constants from your generated header file. - No need to link to
libtweak.a
For example:
#ifdef MY_PRODUCTION_FLAG
# include "myconstants.h"
# define TWEAK_BAKE
#endif
#include <tweak.h>
As well as compiling libtweak
itself, make
will also compile a test
program called test
. This program will define some parameters and
continuously output them to the terminal.
To try out libtweak, run this program and, while it’s running, use
tweak
to adjust its parameters and see them update live.
When your program calls tweak::init
, a file named Tweakfile
is
written to the working directory, detailing the available parameters
and their values. A Unix FIFO called Tweakfifo
is also created.
The next time your program starts, values are read from the existing
Tweakfile
.
Additionally, when you call tweak::process
, commands are read from
the Tweakfifo
and used to update parameter values.
Tools that update values do two things:
- Update the
Tweakfile
so the program will see the value when it is next started. - Write a value change command to the
Tweakfifo
so the program can instantly update that value on its next call totweak::process
.
The tweakc
tool simply reads parameter values from the Tweakfile
and
writes them out in the form of a C++ header.
Define a tweakable parameter. If TWEAK_BAKE
is defined this simply defines
a constant. Otherwise, it defines a const reference to a value, which
may change when you call tweak::process
.
Use this to refer to a tweakable parameter defined in another translation unit.
Sets all parameters to their initial values. Reads the Tweakfile
or
creates one if not present. Sets up the mechanism for live updating
(Tweakfifo
).
You’ll usually want to call this early in your program’s startup, or
at least before you call tweak::process
for the first time.
If TWEAK_BAKE
is defined, tweak::init
is a no-op and your compiler
will optimize out any calls to it.
Check for new live-update messages and update any parameters. You’ll want to call this frequently during execution of your program.
In games, you can afford to call this every frame; if there’s nothing to update it is very cheap.
If TWEAK_BAKE
is defined, tweak::process
is a no-op and your compiler
will optimize out any calls to it.
All of these tools operate on the Tweakfile
and Tweakfifo
in the
working directory.
Starts a GUI for tweaking the program’s parameters.
Writes the current values of all parameters, formatted as a C++ header
file, to standard output. Use this file in conjunction with the
TWEAK_BAKE
option to optimize out all of libtweak
for production
builds.
Both Tweakfile
and Tweakfifo
have the same format: a list of lines
where each line is a command name followed by a space-separated list
of arguments. Possible commands are:
Specifies the type of a parameter. Every parameter must have a type. By
default, the available types are int
, float
, string
and bool
. You
can also add your own types; see Extending.
Specifies a value for a paramater. See Value Format.
Specifies the range for a parameter. Only applies to int
and float
parameters. This is only used by the GUI tool to display an
appropriate GUI; libtweak
itself ignores range
commands.
Values are converted to and from strings for storage in Tweakfile
and
transmission through Tweakfifo
. How a value is converted to and from a
string depends on its type:
These are read by the C++ formatted extraction operators and so are dependent on your locale.
0
or 1
.
Strings begin with a literal $
character, and end at the end of the
line. They may contain any characters except newlines.
(This is a strange format, but it’s very easy to parse and leaves the door open to implement proper delimited strings later.)
You can add support for your own custom types to libtweak
. To do
so, you need to:
- Specialize the
type_name
struct solibtweak
knows what your type is called:namespace tweak { template<> struct type_name<MyType> { static std::string get() { return "mytype"; } } }
This is the name that will be used in
type
commands in theTweakfile
. - If necessary, specialize the
io
struct solibtweak
knows how to load and save your type. If you don’t do this, the standardiostream
‘<<’ and ‘>>’ operators will be used. You can overload these instead of specializingio
.namespace tweak { template<> struct io<MyType> { static void load(MyType &value, std::istream &is) { /* ... */ } static void save(const MyType &value, std::ostream &os) { /* ... */ } } }
That’s enough for libtweak
to handle your type. You can now use it in
TWEAK
declarations.
However, the tools tweak
and tweakc
will not yet be able to
intelligently handle your type.
By default, tweak
will show a text entry field for any type it doesn’t
know about, allowing you to modify the raw textual representation of the
parameter’s value (as used by load
and save
).
tweakc
will take a shot at emitting C++ code for your type, but don’t hold
your breath.
You can override these default behaviours by putting some code in a
tweak_ext.py
file alongside your Tweakfile
:
import tweak
class MyWidget(tweak.Widget):
"..."
class MyType(tweak.Param):
widget = MyWidget
def cname(self):
return "c++ type name here"
def cvalue(self):
return "c++ value of self.value here"
tweak.types['mytypename'] = MyType
For guidance on implementing your own type and widget classes, see the existing
classes in bin/tweak
.
This library uses FIFOs which don’t exist on Windows. The code is organized for easy porting, and full Windows support shouldn’t be too much work.
In production mode (with TWEAK_BAKE
defined), Windows is supported,
as libtweak
becomes a trivial header-only library in that case. So,
it’s still possible to develop your program on Unix and support
Windows as a release target.