Enhanced ShapeRule type to carry more information and to be easier to use
This commit is contained in:
parent
b02f37e961
commit
9c9d79c54d
|
@ -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
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue