Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/rogual/libtweak
Runtime-editable variables for C++
https://github.com/rogual/libtweak
Last synced: 3 months ago
JSON representation
Runtime-editable variables for C++
- Host: GitHub
- URL: https://github.com/rogual/libtweak
- Owner: rogual
- Created: 2016-09-25T21:37:02.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2024-01-16T15:42:46.000Z (about 1 year ago)
- Last Synced: 2024-04-14T03:56:27.505Z (10 months ago)
- Language: C++
- Homepage:
- Size: 17.6 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.org
Awesome Lists containing this project
README
#+TITLE: libtweak
* Abstract
=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* Compiling
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=.* Usage
Declare tweakable parameters in your program:
#+BEGIN_SRC c++
#include
TWEAK(float, sausage_length)
TWEAK(float, temperature)#+END_SRC
Use them like ordinary variables:
#+BEGIN_SRC c++
int main()
{
tweak::init();
// ...
}void do_frame()
{
tweak::process();
printf("The sausages are %fcm long and %f°C!", sausage_length, temperature);
}#+END_SRC
While your program is running, adjust parameters using the GUI:
#+BEGIN_SRC sh
tweak
#+END_SRC* Production Mode
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:
1. Generate a header file with the constants baked in:
#+BEGIN_SRC sh
tweakc > myconstants.h
#+END_SRC
2. Include this file before ==.
3. Define =TWEAK_BAKE= before including ==. This tells
=tweak.h= to use the constants from your generated header file.4. No need to link to =libtweak.a=
For example:
#+BEGIN_SRC c++
#ifdef MY_PRODUCTION_FLAG
# include "myconstants.h"
# define TWEAK_BAKE
#endif#include
#+END_SRC
* Test Program
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.* Internals
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:
1. Update the =Tweakfile= so the program will see the value when it is
next started.2. Write a value change command to the =Tweakfifo= so the program can
instantly update that value on its next call to =tweak::process=.The =tweakc= tool simply reads parameter values from the =Tweakfile= and
writes them out in the form of a C++ header.* API Reference
** =tweak.h=
*** =#define TWEAK(type, name)=
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=.*** =#define EXTERN_TWEAK(type, name)=
Use this to refer to a tweakable parameter defined in another translation
unit.*** =void tweak::init()=
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.*** =void tweak::process()=
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.* Tools Reference
All of these tools operate on the =Tweakfile= and =Tweakfifo= in the
working directory.** =tweak=
Starts a GUI for tweaking the program's parameters.
** =tweakc=
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.* File Format
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:** =type NAME TYPE=
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][Extending]].** =set NAME VALUE=
Specifies a value for a paramater. See [[Value Format][Value Format]].
** =range NAME MIN MAX=
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.* Value Format
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:** =int=, =float=
These are read by the C++ formatted extraction operators and so are
dependent on your locale.** =bool=
=0= or =1=.
** =string=
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.)* Extending
You can add support for your own custom types to =libtweak=. To do
so, you need to:1. Specialize the =type_name= struct so =libtweak= knows what your
type is called:#+BEGIN_SRC C++
namespace tweak
{
template<> struct type_name
{
static std::string get() { return "mytype"; }
}
}#+END_SRC
This is the name that will be used in =type= commands in the =Tweakfile=.
2. If necessary, specialize the =io= struct so =libtweak= knows how to load
and save your type. If you don't do this, the standard =iostream= ‘<<’ and
‘>>’ operators will be used. You can overload these instead of specializing
=io=.#+BEGIN_SRC C++
namespace tweak
{
template<> struct io
{
static void load(MyType &value, std::istream &is) { /* ... */ }
static void save(const MyType &value, std::ostream &os) { /* ... */ }
}
}#+END_SRC
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.** =tweak=, =tweakc= and custom types
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=:#+BEGIN_SRC python
import tweak
class MyWidget(tweak.Widget):
"..."class MyType(tweak.Param):
widget = MyWidgetdef cname(self):
return "c++ type name here"def cvalue(self):
return "c++ value of self.value here"tweak.types['mytypename'] = MyType
#+END_SRC
For guidance on implementing your own type and widget classes, see the existing
classes in =bin/tweak=.* Further Work
** Windows Support
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.