#include "shape-rule.h" #include #include #include "time/continuous-timeline.h" using boost::optional; using boost::adaptors::transformed; template ContinuousTimeline, AutoJoin> boundedTimelinetoContinuousOptional( const BoundedTimeline& timeline ) { return { timeline.getRange(), boost::none, timeline | transformed([](const Timed& timedValue) { return Timed>(timedValue.getTimeRange(), timedValue.getValue()); }) }; } ShapeRule::ShapeRule(ShapeSet shapeSet, optional phone, TimeRange phoneTiming) : shapeSet(std::move(shapeSet)), phone(std::move(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 getShapeRules(const BoundedTimeline& phones) { // Convert to continuous timeline so that silences aren't skipped when iterating auto continuousPhones = boundedTimelinetoContinuousOptional(phones); // Create timeline of shape rules ContinuousTimeline shapeRules( phones.getRange(), {{Shape::X}, boost::none, {0_cs, 0_cs}} ); centiseconds previousDuration = 0_cs; for (const auto& timedPhone : continuousPhones) { optional phone = timedPhone.getValue(); const centiseconds duration = timedPhone.getDuration(); if (phone) { // Animate one phone Timeline phoneShapeSets = getShapeSets(*phone, duration, previousDuration); // Result timing is relative to phone. Make absolute. phoneShapeSets.shift(timedPhone.getStart()); // 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, timedPhone.getTimeRange()) ); } } previousDuration = duration; } return shapeRules; }