Skip to content

Commit

Permalink
Refactor|Model Renderer: Improved model animator state serialization
Browse files Browse the repository at this point in the history
The special ASSET member of the animator state was renamed to
“__asset__” so it will be ignored in serialization.

The special THING member was also renamed to “__thing__”, and a
method called “thing()” was added to the Render.StateAnimator class
for convenience.

For scripting purposes, the model state animator now uses
AnimationValues for shader and transformation variables. These can
be (de)serialized as any other value.

The previous use of NativePointerValue was removed.
  • Loading branch information
skyjake committed Dec 10, 2016
1 parent dc41357 commit 3bce705
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 50 deletions.
8 changes: 4 additions & 4 deletions doomsday/apps/client/include/render/shadervar.h
Expand Up @@ -19,7 +19,7 @@
#ifndef DENG_CLIENT_RENDER_SHADERVAR_H
#define DENG_CLIENT_RENDER_SHADERVAR_H

#include <de/Animation>
#include <de/AnimationValue>
#include <de/GLUniform>
#include <de/Range>
#include <QList>
Expand All @@ -31,10 +31,10 @@
struct ShaderVar
{
struct Value {
de::Animation anim;
de::AnimationValue *anim; // not owned
de::Rangef wrap;

Value(de::Animation const &a) : anim(a) {}
Value(de::Animation const &a) : anim(new de::AnimationValue(a)) {}
};
QList<Value> values;
de::GLUniform *uniform = nullptr; // owned
Expand Down Expand Up @@ -75,7 +75,7 @@ struct ShaderVars
de::Record const &valueDef,
de::Record &bindingNames);

void addBinding(de::Record &names, de::String const &varName, de::Animation &anim);
void addBinding(de::Record &names, de::String const &varName, de::AnimationValue *anim);
};

#endif // DENG_CLIENT_RENDER_SHADERVAR_H
11 changes: 8 additions & 3 deletions doomsday/apps/client/include/render/stateanimator.h
Expand Up @@ -38,7 +38,7 @@ namespace render {
*
* The script object has the following constants:
* - `ID` (Text): asset identifier.
* - `ASSET` (Record): asset metadata.
* - `__asset__` (Record): asset metadata.
*/
class StateAnimator : public de::ModelDrawable::Animator,
public de::IObject
Expand All @@ -60,6 +60,11 @@ class StateAnimator : public de::ModelDrawable::Animator,
*/
void setOwnerNamespace(de::Record &names, de::String const &varName);

/**
* Returns the name of the variable pointing to the owning object's namespace.
*/
de::String ownerNamespaceName() const;

void triggerByState(de::String const &stateName);

void triggerDamage(int points, struct mobj_s const *inflictor);
Expand All @@ -75,8 +80,8 @@ class StateAnimator : public de::ModelDrawable::Animator,
de::Vector4f extraRotationForNode(de::String const &nodeName) const override;

// Implements IObject.
de::Record &objectNamespace() override;
de::Record const &objectNamespace() const override;
de::Record & objectNamespace() override;
de::Record const & objectNamespace() const override;

// ISerializable.
void operator >> (de::Writer &to) const override;
Expand Down
11 changes: 11 additions & 0 deletions doomsday/apps/client/src/render/modelrenderer.cpp
Expand Up @@ -893,6 +893,16 @@ static render::StateAnimator &animatorInstance(Context &ctx)
"No StateAnimator instance available");
}

static Value *Function_StateAnimator_Thing(Context &ctx, Function::ArgumentValues const &)
{
render::StateAnimator &anim = animatorInstance(ctx);
if (anim.ownerNamespaceName() == QStringLiteral("__thing__"))
{
return anim[anim.ownerNamespaceName()].value().duplicate();
}
return nullptr;
}

static Value *Function_StateAnimator_PlayingSequences(Context &ctx, Function::ArgumentValues const &)
{
render::StateAnimator &anim = animatorInstance(ctx);
Expand All @@ -910,6 +920,7 @@ void ModelRenderer::initBindings(Binder &binder, Record &module) // static
{
Record &anim = module.addSubrecord("StateAnimator");
binder.init(anim)
<< DENG2_FUNC_NOARG(StateAnimator_Thing, "thing")
<< DENG2_FUNC_NOARG(StateAnimator_PlayingSequences, "playingSequences");
}
}
9 changes: 3 additions & 6 deletions doomsday/apps/client/src/render/shadervar.cpp
Expand Up @@ -18,7 +18,6 @@

#include "render/shadervar.h"

#include <de/NativePointerValue>
#include <de/ScriptedInfo>
#include <de/ScriptSystem>

Expand All @@ -44,7 +43,7 @@ ShaderVar::~ShaderVar()
float ShaderVar::currentValue(int index) const
{
auto const &val = values.at(index);
float v = val.anim.value();
float v = val.anim->animation();
if (val.wrap.isEmpty())
{
return v;
Expand Down Expand Up @@ -164,9 +163,7 @@ ShaderVars::~ShaderVars()
qDeleteAll(members.values());
}

void ShaderVars::addBinding(Record &names, String const &varName, Animation &anim)
void ShaderVars::addBinding(Record &names, String const &varName, AnimationValue *anim)
{
names.add(varName)
.set(new NativePointerValue(&anim, &ScriptSystem::builtInClass(QStringLiteral("Animation"))))
.setReadOnly();
names.add(varName).set(anim).setReadOnly();
}
63 changes: 39 additions & 24 deletions doomsday/apps/client/src/render/stateanimator.cpp
Expand Up @@ -50,8 +50,8 @@ static String const DEF_SPEED ("speed");
static String const DEF_ANGLE ("angle");
static String const DEF_AXIS ("axis");

static String const VAR_ID ("ID");
static String const VAR_ASSET ("ASSET");
static String const VAR_ID ("ID"); // model asset ID
static String const VAR_ASSET ("__asset__"); // runtime reference to asset metadata
static String const VAR_ENABLED ("enabled");
static String const VAR_MATERIAL ("material");

Expand Down Expand Up @@ -143,6 +143,7 @@ DENG2_PIMPL(StateAnimator)
QHash<String, Sequence> pendingAnimForNode;
String currentStateName;
Record names; ///< Local context for scripts, i.e., per-object model state.
String ownerNamespaceVarName;

ModelDrawable::Appearance appearance;

Expand All @@ -153,9 +154,9 @@ DENG2_PIMPL(StateAnimator)

struct AnimVar
{
Animation angle { 0, Animation::Linear };
SafePtr<AnimationValue> angle; // not owned
/// Units per second; added to value independently of its animation.
Animation speed { 0, Animation::Linear };
SafePtr<AnimationValue> speed; // not owned
Vector3f axis;
};
typedef QHash<String, AnimVar *> AnimVars;
Expand Down Expand Up @@ -297,9 +298,9 @@ DENG2_PIMPL(StateAnimator)
try
{
std::unique_ptr<AnimVar> var(new AnimVar);
var->angle = variableDef.getf(DEF_ANGLE, 0.f);
var->speed = variableDef.getf(DEF_SPEED, 0.f);
var->axis = vectorFromValue<Vector3f>(variableDef.get(DEF_AXIS));
var->angle.reset(new AnimationValue(Animation(variableDef.getf(DEF_ANGLE, 0.f), Animation::Linear)));
var->speed.reset(new AnimationValue(Animation(variableDef.getf(DEF_SPEED, 0.f), Animation::Linear)));
var->axis = vectorFromValue<Vector3f>(variableDef.get(DEF_AXIS));

addBinding(variableName.concatenateMember(DEF_ANGLE), var->angle);
addBinding(variableName.concatenateMember(DEF_SPEED), var->speed);
Expand All @@ -318,11 +319,11 @@ DENG2_PIMPL(StateAnimator)
}
}

void addBinding(String const &varName, Animation &anim)
void addBinding(String const &varName, AnimationValue *anim)
{
names.add(varName)
.set(new NativePointerValue(&anim, &ScriptSystem::builtInClass("Animation")))
.setReadOnly();
names.add(varName).set(anim).setReadOnly(); // ownership of anim taken
//.set(new NativePointerValue(&anim, &ScriptSystem::builtInClass("Animation")))
//.setReadOnly();
}

void deinitVariables()
Expand Down Expand Up @@ -512,19 +513,25 @@ Model const &StateAnimator::model() const

void StateAnimator::setOwnerNamespace(Record &names, String const &varName)
{
d->names.add(varName).set(new RecordValue(names));
d->ownerNamespaceVarName = varName;
d->names.add(d->ownerNamespaceVarName).set(new RecordValue(names));

// Call the onInit() function if there is one.
if (d->names.has(QStringLiteral("ASSET.onInit")))
if (d->names.has(VAR_ASSET + QStringLiteral(".onInit")))
{
Record ns;
ns.add(QStringLiteral("self")).set(new RecordValue(d->names));
Process::scriptCall(Process::IgnoreResult, ns,
QStringLiteral("self().ASSET.onInit"),
"self." + VAR_ASSET + ".onInit",
"$self");
}
}

String StateAnimator::ownerNamespaceName() const
{
return d->ownerNamespaceVarName;
}

void StateAnimator::triggerByState(String const &stateName)
{
using Sequence = Impl::Sequence;
Expand Down Expand Up @@ -608,19 +615,19 @@ void StateAnimator::triggerByState(String const &stateName)
}

/*LOG_GL_XVERBOSE("Mobj %i starting animation: " _E(b))
<< d->names.geti("self().__id__") << seq.name;*/
<< d->names.geti("self.__id__") << seq.name;*/
break;
}
}

void StateAnimator::triggerDamage(int points, struct mobj_s const *inflictor)
{
/*
* Here we check for the onDamage() function in the asset. The ASSET
* Here we check for the onDamage() function in the asset. The __asset__
* variable holds a direct pointer to the asset definition, where the
* function is defined.
*/
if (d->names.has(QStringLiteral("ASSET.onDamage")))
if (d->names.has(VAR_ASSET + QStringLiteral(".onDamage")))
{
/*
* We need to provide the StateAnimator instance to the script as an
Expand All @@ -630,7 +637,7 @@ void StateAnimator::triggerDamage(int points, struct mobj_s const *inflictor)
Record ns;
ns.add(QStringLiteral("self")).set(new RecordValue(d->names));
Process::scriptCall(Process::IgnoreResult, ns,
QStringLiteral("self().ASSET.onDamage"),
"self." + VAR_ASSET + ".onDamage",
"$self", points,
inflictor? &THINKER_DATA(inflictor->thinker, ThinkerData) :
nullptr);
Expand All @@ -655,12 +662,14 @@ void StateAnimator::advanceTime(TimeDelta const &elapsed)
// Update animation variables values.
for (auto *var : d->animVars.values())
{
var->angle.shift(var->speed * elapsed);
if (!var->angle || !var->speed) continue;

var->angle->animation().shift(var->speed->animation() * elapsed);

// Keep the angle in the 0..360 range.
float varAngle = var->angle;
if (varAngle > 360) var->angle.shift(-360);
else if (varAngle < 0) var->angle.shift(+360);
float varAngle = var->angle->animation();
if (varAngle > 360) var->angle->animation().shift(-360);
else if (varAngle < 0) var->angle->animation().shift(+360);
}

for (int i = 0; i < count(); ++i)
Expand Down Expand Up @@ -743,7 +752,10 @@ Vector4f StateAnimator::extraRotationForNode(String const &nodeName) const
if (found != d->animVars.constEnd())
{
Impl::AnimVar const &var = *found.value();
return Vector4f(var.axis, var.angle);
if (var.angle)
{
return Vector4f(var.axis, var.angle->animation());
}
}
return Vector4f();
}
Expand All @@ -767,11 +779,14 @@ void StateAnimator::operator >> (Writer &to) const
{
ModelDrawable::Animator::operator >> (to);

to << d->currentStateName << d->names;
to << d->currentStateName
<< Record(d->names, Record::IgnoreDoubleUnderscoreMembers);
}

void StateAnimator::operator << (Reader &from)
{
qDebug() << "StateAnimator: deserializing" << this;

d->pendingAnimForNode.clear();

ModelDrawable::Animator::operator << (from);
Expand Down
13 changes: 5 additions & 8 deletions doomsday/apps/client/src/ui/editors/modelasseteditor.cpp
Expand Up @@ -30,9 +30,9 @@
#include "render/stateanimator.h"
#include "render/playerweaponanimator.h"

#include <de/AnimationValue>
#include <de/App>
#include <de/DialogContentStylist>
#include <de/NativePointerValue>
#include <de/NumberValue>
#include <de/PackageLoader>
#include <de/ScriptedInfo>
Expand Down Expand Up @@ -93,11 +93,6 @@ DENG_GUI_PIMPL(ModelAssetEditor)
.setInput(Rule::Top, instLabel->rule().top());
}

// ~Impl()
// {
// App::packageLoader().audienceForActivity() -= this;
// }

void setOfLoadedPackagesChanged()
{
updateAssetsList();
Expand Down Expand Up @@ -349,7 +344,7 @@ DENG_GUI_PIMPL(ModelAssetEditor)

for (String const &name : names)
{
if (name.startsWith("__") || name == "ASSET" || name == "ID" || name == "uMapTime")
if (name.startsWith("__") || name == "ID" || name == "uMapTime")
continue;

Variable &var = rec[name];
Expand All @@ -358,6 +353,8 @@ DENG_GUI_PIMPL(ModelAssetEditor)
double step = .01;
int precision = 2;

/// @todo Hardcoded... -jk

if (name == "uGlossiness")
{
range = Ranged(0, 200);
Expand Down Expand Up @@ -397,7 +394,7 @@ DENG_GUI_PIMPL(ModelAssetEditor)
g->addLabel(varLabel(label));
g->addLineEdit(var);
}
else if (var.value().is<NativePointerValue>()) // assumed to be Animation
else if (var.value().is<AnimationValue>())
{
g->addLabel(varLabel(label));
g->addSlider(var, range, step, precision);
Expand Down
10 changes: 5 additions & 5 deletions doomsday/sdk/libappfw/src/widgets/variablesliderwidget.cpp
Expand Up @@ -18,9 +18,8 @@

#include "de/VariableSliderWidget"

#include <de/AnimationValue>
#include <de/NumberValue>
#include <de/NativePointerValue>
#include <de/Animation>

namespace de {

Expand All @@ -34,7 +33,7 @@ DENG2_PIMPL(VariableSliderWidget)
Impl(Public *i, Variable &variable) : Base(i), var(&variable)
{
var->audienceForDeletion() += this;
var->audienceForChange() += this;
var->audienceForChange() += this;
}

void init()
Expand All @@ -55,7 +54,7 @@ DENG2_PIMPL(VariableSliderWidget)
break;

case VariableSliderWidget::Animation:
self().setValue(var->value<NativePointerValue>().nativeObject<de::Animation>()->target());
self().setValue(var->value<AnimationValue>().animation().target());
break;
}
}
Expand All @@ -72,7 +71,7 @@ DENG2_PIMPL(VariableSliderWidget)
break;

case VariableSliderWidget::Animation:
var->value<NativePointerValue>().nativeObject<de::Animation>()->setValue(float(self().value()));
var->value<AnimationValue>().animation().setValue(float(self().value()));
break;
}
var->audienceForChange() += this;
Expand All @@ -97,6 +96,7 @@ VariableSliderWidget::VariableSliderWidget(Variable &variable, Ranged const &ran
{
if (!variable.value().is<NumberValue>())
{
// Animation is the only other supported type.
d->valueType = VariableSliderWidget::Animation;
}
setRange(range, step);
Expand Down

0 comments on commit 3bce705

Please sign in to comment.