1#include "ExpressionComponent.h"
3#include "Foundation/HashSequence.h"
4#include "Foundation/Logging/Logger.h"
10#include "Services/Time.h"
11#include "Utilities/Parsing.h"
20void Cogs::Core::ExpressionComponent::registerType()
23 Field(
Name(
"targets"), &ExpressionComponent::targets),
24 Field(
Name(
"expressions"), &ExpressionComponent::expressions),
28 Method(
Name(
"update"), &ExpressionComponent::update),
29 Method(
Name(
"initialize"), &ExpressionComponent::initialize),
30 Method(
Name(
"cleanup"), &ExpressionComponent::cleanup),
33 DynamicComponent::registerDerivedType<ExpressionComponent>().setFields(fields).setMethods(methods);
36void Cogs::Core::ExpressionComponent::initialize(Context * context)
38 this->context = context;
41void Cogs::Core::ExpressionComponent::update()
43 ec.add(
"t", context->time->getAnimationTime());
44 ec.add(
"id",
static_cast<double>(getContainer()->getId()));
46 if (targets.size() != expressions.size()) {
47 LOG_ERROR(logger,
"Invalid field sizes (%zd, %zd)", targets.size(), expressions.size());
51 if (targets.size() < compiledExpressions.size()) {
52 for (
size_t i = targets.size() - 1; i < compiledExpressions.size(); ++i) {
53 ec.free(compiledExpressions[i].expression);
57 compiledExpressions.resize(targets.size());
59 for (
size_t i = 0; i < targets.size(); ++i) {
60 auto & compiledExpression = compiledExpressions[i];
62 if (!compiledExpression.expression || hasChanged()) {
65 if (compiledExpression.expression && compiledExpression.expression->hash ==
hash) {
69 if (compiledExpression.expression) {
70 ec.free(compiledExpression.expression);
73 if (!expressions[i].size())
continue;
75 ec.add(targets[i], 0);
76 compiledExpression.expression = ec.compile(expressions[i], targets[i]);
79 split(targets[i],
".", tokens);
81 if (tokens.size() == 2 || tokens.size() == 3) {
84 compiledExpression.componentHandle = getComponentHandle(componentType.getTypeId());
86 auto field = componentType.getField(tokens[1]);
89 LOG_ERROR(logger,
"Could not find field %.*s on type %.*s", StringViewFormat(tokens[1]), StringViewFormat(tokens[0]));
96 bool isValid = fieldType == TypeDatabase::getType<float>() ||
97 fieldType == TypeDatabase::getType<glm::vec2>() ||
98 fieldType == TypeDatabase::getType<glm::vec3>() ||
99 fieldType == TypeDatabase::getType<glm::vec4>() ||
100 fieldType == TypeDatabase::getType<glm::quat>();
103 LOG_ERROR(logger,
"Target field type %s not compatible with expression output.", fieldType.getName().c_str());
108 compiledExpression.componentId = componentType.getTypeId();
109 compiledExpression.fieldId = componentType.getFieldId(field);
111 if (tokens.size() == 3) {
112 auto memberField = fieldType.getField(tokens[2]);
115 LOG_ERROR(logger,
"Could not find field %.*s on type %s", StringViewFormat(tokens[2]), fieldType.getName().c_str());
119 compiledExpression.memberId = fieldType.getFieldId(memberField);
124 if (compiledExpression.expression &&
127 const double value = ec.update(compiledExpression.expression, 0.0);
129 auto component = compiledExpression.componentHandle.resolve();
130 assert(component &&
"Component must be valid pointer.");
133 assert(field &&
"Field must be valid pointer.");
136 auto fieldValue = field->getPtr<
float>(component);
139 auto memberField = fieldType.getField(compiledExpression.memberId);
141 auto memberValue = memberField->getPtr<
float>(fieldValue);
142 *memberValue =
static_cast<float>(value);
144 *fieldValue =
static_cast<float>(value);
147 component->setChanged();
152void Cogs::Core::ExpressionComponent::cleanup(Context * )
155 compiledExpressions.clear();
Log implementation class.
Field definition describing a single data member of a data structure.
Simple method definition.
static const Type & getType()
Get the Type of the given template argument.
const Field * getField(const Name &name) const
Get a pointer to the field info of the field with the given name.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Contains reflection support.
constexpr FieldId NoField
No field id.
constexpr TypeId NoType
Definition of no type.
constexpr size_t hash() noexcept
Simple getter function that returns the initial value for fnv1a hashing.
constexpr size_t hashSequence(const T &t, const U &u)
Hash the last two items in a sequence of objects.
Represents an unique name.