Enhanced ShapeRule type to carry more information and to be easier to use

This commit is contained in:
Daniel Wolf 2016-12-29 18:51:41 +01:00
parent b02f37e961
commit 9c9d79c54d
10 changed files with 61 additions and 27 deletions

View File

@ -226,8 +226,8 @@ add_library(rhubarb-animation
src/animation/pauseAnimation.h
src/animation/roughAnimation.cpp
src/animation/roughAnimation.h
src/animation/shapeRule.cpp
src/animation/shapeRule.h
src/animation/ShapeRule.cpp
src/animation/ShapeRule.h
src/animation/shapeShorthands.h
src/animation/targetShapeSet.cpp
src/animation/targetShapeSet.h

View File

@ -1,4 +1,4 @@
#include "shapeRule.h"
#include "ShapeRule.h"
#include <boost/range/adaptor/transformed.hpp>
#include "ContinuousTimeline.h"
@ -13,12 +13,37 @@ ContinuousTimeline<optional<T>, AutoJoin> boundedTimelinetoContinuousOptional(co
};
}
ShapeRule::ShapeRule(const ShapeSet& shapeSet, const optional<Phone>& phone, TimeRange phoneTiming) :
shapeSet(shapeSet),
phone(phone),
phoneTiming(phoneTiming)
{}
ShapeRule ShapeRule::getInvalid() {
return {{}, boost::none,{0_cs, 0_cs}};
}
bool ShapeRule::operator==(const ShapeRule& rhs) const {
return shapeSet == rhs.shapeSet && phone == rhs.phone && phoneTiming == rhs.phoneTiming;
}
bool ShapeRule::operator!=(const ShapeRule& rhs) const {
return !operator==(rhs);
}
bool ShapeRule::operator<(const ShapeRule& rhs) const {
return shapeSet < rhs.shapeSet
|| phone < rhs.phone
|| phoneTiming.getStart() < rhs.phoneTiming.getStart()
|| phoneTiming.getEnd() < rhs.phoneTiming.getEnd();
}
ContinuousTimeline<ShapeRule> getShapeRules(const BoundedTimeline<Phone>& phones) {
// Convert to continuous timeline so that silences aren't skipped when iterating
auto continuousPhones = boundedTimelinetoContinuousOptional(phones);
// Create timeline of shape rules
ContinuousTimeline<ShapeRule> shapeRules(phones.getRange(), ShapeRule({Shape::X}, boost::none));
ContinuousTimeline<ShapeRule> shapeRules(phones.getRange(), {{Shape::X}, boost::none, {0_cs, 0_cs}});
centiseconds previousDuration = 0_cs;
for (const auto& timedPhone : continuousPhones) {
optional<Phone> phone = timedPhone.getValue();
@ -34,7 +59,7 @@ ContinuousTimeline<ShapeRule> getShapeRules(const BoundedTimeline<Phone>& phones
// Copy to timeline.
// Later shape sets may overwrite earlier ones if overlapping.
for (const auto& timedShapeSet : phoneShapeSets) {
shapeRules.set(timedShapeSet.getTimeRange(), ShapeRule(timedShapeSet.getValue(), phone));
shapeRules.set(timedShapeSet.getTimeRange(), ShapeRule(timedShapeSet.getValue(), phone, timedPhone.getTimeRange()));
}
}

23
src/animation/ShapeRule.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "Phone.h"
#include "animationRules.h"
#include "BoundedTimeline.h"
#include "ContinuousTimeline.h"
struct ShapeRule {
ShapeSet shapeSet;
boost::optional<Phone> phone;
TimeRange phoneTiming;
ShapeRule(const ShapeSet& shapeSet, const boost::optional<Phone>& phone, TimeRange phoneTiming);
static ShapeRule getInvalid();
bool operator==(const ShapeRule&) const;
bool operator!=(const ShapeRule&) const;
bool operator<(const ShapeRule&) const;
};
// Returns shape rules for an entire timeline of phones.
ContinuousTimeline<ShapeRule> getShapeRules(const BoundedTimeline<Phone>& phones);

View File

@ -1,6 +1,6 @@
#include "mouthAnimation.h"
#include "timedLogging.h"
#include "shapeRule.h"
#include "ShapeRule.h"
#include "roughAnimation.h"
#include "pauseAnimation.h"
#include "tweening.h"

View File

@ -19,11 +19,9 @@ JoiningContinuousTimeline<Shape> animateRough(const ContinuousTimeline<ShapeRule
centiseconds lastAnticipatedShapeStart = -1_cs;
for (auto it = shapeRules.begin(); it != shapeRules.end(); ++it) {
const ShapeRule shapeRule = it->getValue();
const ShapeSet shapeSet = std::get<ShapeSet>(shapeRule);
const Shape shape = getClosestShape(referenceShape, shapeSet);
const Shape shape = getClosestShape(referenceShape, shapeRule.shapeSet);
animation.set(it->getTimeRange(), shape);
const auto phone = std::get<optional<Phone>>(shapeRule);
const bool anticipateShape = phone && isVowel(*phone) && shapeSet.size() == 1;
const bool anticipateShape = shapeRule.phone && isVowel(*shapeRule.phone) && shapeRule.shapeSet.size() == 1;
if (anticipateShape) {
// Animate backwards a little
const Shape anticipatedShape = shape;
@ -40,7 +38,7 @@ JoiningContinuousTimeline<Shape> animateRough(const ContinuousTimeline<ShapeRule
if (anticipationDuration > maxAnticipationDuration) break;
// Overwrite forward-animated shape with backwards-animated, anticipating shape
const Shape anticipatingShape = getClosestShape(referenceShape, std::get<ShapeSet>(reverseIt->getValue()));
const Shape anticipatingShape = getClosestShape(referenceShape, reverseIt->getValue().shapeSet);
animation.set(reverseIt->getTimeRange(), anticipatingShape);
// Make sure the new, backwards-animated shape still resembles the anticipated shape

View File

@ -1,6 +1,6 @@
#pragma once
#include "shapeRule.h"
#include "ShapeRule.h"
// Does a rough animation (no tweening, special pause animation, etc.) using a bidirectional algorithm.
JoiningContinuousTimeline<Shape> animateRough(const ContinuousTimeline<ShapeRule>& shapeRules);

View File

@ -1,12 +0,0 @@
#pragma once
#include "Phone.h"
#include "animationRules.h"
#include "BoundedTimeline.h"
#include "ContinuousTimeline.h"
// A shape set with its original phone
using ShapeRule = std::tuple<ShapeSet, boost::optional<Phone>>;
// Returns shape rules for an entire timeline of phones.
ContinuousTimeline<ShapeRule> getShapeRules(const BoundedTimeline<Phone>& phones);

View File

@ -23,7 +23,7 @@ ContinuousTimeline<ShapeRule> convertToTargetShapeSet(const ContinuousTimeline<S
ContinuousTimeline<ShapeRule> result(shapeRules);
for (const auto& timedShapeRule : shapeRules) {
ShapeRule rule = timedShapeRule.getValue();
std::get<ShapeSet>(rule) = convertToTargetShapeSet(std::get<ShapeSet>(rule), targetShapeSet);
rule.shapeSet = convertToTargetShapeSet(rule.shapeSet, targetShapeSet);
result.set(timedShapeRule.getTimeRange(), rule);
}
return result;

View File

@ -1,7 +1,7 @@
#pragma once
#include "Shape.h"
#include "shapeRule.h"
#include "ShapeRule.h"
// Returns the closest shape to the specified one that occurs in the target shape set.
Shape convertToTargetShapeSet(Shape shape, const ShapeSet& targetShapeSet);

View File

@ -3,7 +3,7 @@
#include <boost/lexical_cast.hpp>
#include <map>
#include <algorithm>
#include "shapeRule.h"
#include "ShapeRule.h"
using std::string;
using std::map;