Provide a Custom Datatype to the Entity Graph
This walkthrough shows you how to extend the Entity Graph with a custom data type
- How to provide a custom compile step for your own data type.
Data Type Overview of the Entity Graph
The following overview lists all types that are supported by the engine build in with the Entity Graph Component
. If you wanted to support your own data type you need to implement the tm_graph_component_compile_data_i
interface manually.
Implement the tm_graph_component_compile_data_i
When you need to implement your own type you need to implement the tm_graph_component_compile_data_i
interface. This interface lives in the graph_component.h
header file. This header file is part of the graph_interpreter
plugin.
The interface is just a function typedef of the following signature:
{{$include {TM_SDK_DIR}/plugins/graph_interpreter/graph_component.h:66}}
How will the graph interpreter use this function?
The Graph Interpreter will call this function when ever it compiles data to a graph before the graph is initialized the first time. The function should return true if it compiled data to a wire otherwise it should return false and the graph interpreter will keep looking for the correct compile function.
The function provided multiple arguments but the following 2 arguments are the most important one:
Name | Description |
---|---|
tm_tt_id_t data_id | The data object the interpreter tries to compile to a wire but does not know how to. |
tm_strhash_t to_type_hash | The data the wire expects. |
For example in the Animation State Machine TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE
are objects that contain a string hash (TM_TT_PROP__ASM_EVENT__NAME
) that the animation state machine needs in order to execute a certain event. The list above shows that there is no translation from a TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE
to a wire. Therefore we need to provide our own function for this. The animation state machine plugin provides a compilation function for this.
The plugin knows that a TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE
is nothing else then a TM_TT_TYPE_HASH__STRING_HASH
at the end. This means we need to do the following steps:
- We need to figure out what kind of type is in
data_id
- We need to compare the type of
data_id
with theto_type_hash
being equal toTM_TT_TYPE_HASH__STRING_HASH
- perform our actual translation
Let us begin with figuring out the data type of data_id
:
const tm_tt_type_t type = tm_tt_type(data_id);
const tm_strhash_t type_hash = tm_the_truth_api->type_name_hash(tt, type);
const tm_the_truth_object_o *data_r = tm_tt_read(tt, data_id);
We also need to get a read object of the data_id
to read the data from it.
The next step is to compare the given data:
if (TM_STRHASH_EQUAL(type_hash, TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE) &&
TM_STRHASH_EQUAL(to_type_hash, TM_TT_TYPE_HASH__STRING_HASH))
If this is true we move on with our data compilation. Now that we know our object is of type TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE
we can use the Truth and extract that actual value we care about the TM_TT_PROP__ASM_EVENT__NAME
const tm_tt_id_t event_id = tm_the_truth_api->get_reference(tt, data_r, 0);
const tm_strhash_t event_name_hash = tm_the_truth_api->get_string_hash(
tt, tm_tt_read(tt, event_id), TM_TT_PROP__ASM_EVENT__NAME);
After this its time to compile or better write the data to the provided wire. For this we need to use the tm_graph_interpreter_api
API and its tm_graph_interpreter_api.write()
function. The function expects the current interpreter and the wire we write to (we have this one as function parameter of the tm_graph_component_compile_data_i
interface uint32_t wire
) as well as the size and the amount. Passing all these information to the write function enables it to allocate memory internally in the interpreters memory stack.
tm_strhash_t *v = (tm_strhash_t *)tm_graph_interpreter_api->write_wire(
gr, wire, 1, sizeof(*v));
Keep in mind the function is a bit miss leading since it says write
but what it actually does it just allocates memory for you (if needed) and give you back a writable pointer. At the end we write to the pointer our data and return true.
All together the translation looks like this:
if (TM_STRHASH_EQUAL(type_hash, TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE) &&
TM_STRHASH_EQUAL(to_type_hash, TM_TT_TYPE_HASH__STRING_HASH)) {
const tm_tt_id_t event_id = tm_the_truth_api->get_reference(tt, data_r, 0);
const tm_strhash_t event_name_hash = tm_the_truth_api->get_string_hash(
tt, tm_tt_read(tt, event_id), TM_TT_PROP__ASM_EVENT__NAME);
tm_strhash_t *v = (tm_strhash_t *)tm_graph_interpreter_api->write_wire(
gr, wire, 1, sizeof(*v));
*v = event_name_hash;
return true;
}
Source Code
The entire sample source code:
static struct tm_api_registry_api *tm_global_api_registry;
static struct tm_the_truth_api *tm_the_truth_api;
static struct tm_graph_interpreter_api *tm_graph_interpreter_api;
#include <foundation/api_registry.h>
#include <foundation/api_types.h>
#include <foundation/the_truth.h>
#include <foundation/the_truth_types.h>
#include <plugins/editor_views/graph.h>
#include <plugins/graph_interpreter/graph_component_node_type.h>
#include <plugins/graph_interpreter/graph_component.h>
#include <plugins/graph_interpreter/graph_interpreter.h>
#include <plugins/animation/animation_state_machine.h>
#define TM_TT_TYPE__ASM_EVENT_REFERENCE "tm_asm_event_reference"
#define TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE TM_STATIC_HASH("tm_asm_event_reference", 0x60cbc051e2b37c38ULL)
static bool compile_data_to_wire(tm_graph_interpreter_o *gr, uint32_t wire, const tm_the_truth_o *tt, tm_tt_id_t data_id, tm_strhash_t to_type_hash)
{
const tm_tt_type_t type = tm_tt_type(data_id);
const tm_strhash_t type_hash = tm_the_truth_api->type_name_hash(tt, type);
const tm_the_truth_object_o *data_r = tm_tt_read(tt, data_id);
if (TM_STRHASH_EQUAL(type_hash, TM_TT_TYPE_HASH__ASM_EVENT_REFERENCE) && TM_STRHASH_EQUAL(to_type_hash, TM_TT_TYPE_HASH__STRING_HASH))
{
const tm_tt_id_t event_id = tm_the_truth_api->get_reference(tt, data_r, 0);
const tm_strhash_t event_name_hash = tm_the_truth_api->get_string_hash(tt, tm_tt_read(tt, event_id), TM_TT_PROP__ASM_EVENT__NAME);
tm_strhash_t *v = (tm_strhash_t *)tm_graph_interpreter_api->write_wire(gr, wire, 1, sizeof(*v));
*v = event_name_hash;
return true;
}
//...
return false;
}
TM_DLL_EXPORT void tm_load_plugin(struct tm_api_registry_api *reg, bool load)
{
tm_global_api_registry = reg;
tm_the_truth_api = tm_get_api(reg, tm_the_truth_api);
tm_graph_interpreter_api = tm_get_api(reg, tm_graph_interpreter_api);
tm_add_or_remove_implementation(reg, load, tm_graph_component_compile_data_i, compile_data_to_wire);
}