Yet another chainsaw massacre. One of the most obnoxious annoyances with C++ metaprogramming is the need to insert `typename` and `template` qualifiers into most definitions, to help the compiler to cope with the syntax, which is not context-free. The recent standards adds several clarifications, so that most of these qualifiers are redundant now, at least at places where it is unambiguously clear that only a type can be given. GCC already supports most of these relaxing rules (Clang unfortunately lags way behind with support of newer language features...)
98 lines
4.1 KiB
C++
98 lines
4.1 KiB
C++
/*
|
||
Segmentation - Partitioning of a timeline for organising the render graph.
|
||
|
||
Copyright (C)
|
||
2023, Hermann Vosseler <Ichthyostega@web.de>
|
||
|
||
**Lumiera** is free software; you can redistribute it and/or modify it
|
||
under the terms of the GNU General Public License as published by the
|
||
Free Software Foundation; either version 2 of the License, or (at your
|
||
option) any later version. See the file COPYING for further details.
|
||
|
||
* *****************************************************************/
|
||
|
||
|
||
/** @file segmentation.cpp
|
||
** Implementation details regarding the Segmentation of the Fixture.
|
||
**
|
||
** @todo 2023 WIP-WIP-WIP »Playback Vertical Slice«
|
||
*/
|
||
|
||
#include "lib/error.hpp"
|
||
#include "steam/fixture/segmentation.hpp"
|
||
#include "lib/time/timevalue.hpp"
|
||
#include "lib/split-splice.hpp"
|
||
|
||
using lib::time::Time;
|
||
using lib::time::TimeSpan;
|
||
|
||
|
||
namespace steam {
|
||
namespace fixture {
|
||
|
||
namespace error = lumiera::error;
|
||
|
||
|
||
Segmentation::~Segmentation() { } // emit VTable here...
|
||
|
||
|
||
namespace {// Implementation details...
|
||
|
||
|
||
}//(End) impl
|
||
|
||
|
||
|
||
/**
|
||
* @param start (optional) definition of the new Segment's start point (inclusive)
|
||
* @param after (optional) definition of the end point (exclusive)
|
||
* @param jobTicket specification of provided render functionality for the new Segment
|
||
* @remarks missing definitions will be derived or interpolated according to context
|
||
* - if start point is omitted, the new Segment will start seamlessly after
|
||
* any preceding Segment's end, in case this preceding Segment ends earlier
|
||
* - otherwise the preceding Segment's start point will be used, thereby effectively
|
||
* replacing and expanding or trimming or inserting into the preceding Segment
|
||
* - similar for the end point: if the definition is omitted, the new Segment
|
||
* will cover the time range until the next Segmen's start
|
||
* - if upper/lower boundaries can not be established, the covered range will be
|
||
* expanded from Time::ANYTIME up to Time::NEVER, taking into account the current context
|
||
* - after start and end point have been established by the above rules, the actual
|
||
* splicing operation will be determined; either an existing Segment is replaced
|
||
* altogether, or it is trimmed to fit, or the new Segment is inserted, thereby
|
||
* creating a second (copied) part of the encompassing old Segment.
|
||
* - in case the JobTicket is omitted, the new Segment will be marked as _passive_
|
||
* and any job created from such a Segment will then be a »NOP-job«
|
||
* @see SplitSplice_test
|
||
*/
|
||
Segment const&
|
||
Segmentation::splitSplice (OptTime start, OptTime after, engine::ExitNodes&& modelLink)
|
||
{
|
||
ASSERT (!start or !after or start != after);
|
||
using Iter = list<Segment>::iterator;
|
||
|
||
auto getStart = [](Iter elm) -> Time { return elm->start(); };
|
||
auto getAfter = [](Iter elm) -> Time { return elm->after(); };
|
||
auto createSeg= [&](Iter pos, Time start, Time after) -> Iter { return segments_.emplace (pos, TimeSpan{start, after}, move(modelLink)); };
|
||
auto emptySeg = [&](Iter pos, Time start, Time after) -> Iter { return segments_.emplace (pos, TimeSpan{start, after}); };
|
||
auto cloneSeg = [&](Iter pos, Time start, Time after, Iter src) -> Iter { return segments_.emplace (pos, *src, TimeSpan{start, after}); };
|
||
auto discard = [&](Iter pos, Iter after) -> Iter { return segments_.erase (pos,after); };
|
||
|
||
|
||
lib::splitsplice::Algo splicer{ getStart
|
||
, getAfter
|
||
, createSeg
|
||
, emptySeg
|
||
, cloneSeg
|
||
, discard
|
||
, Time::NEVER
|
||
, segments_.begin(),segments_.end()
|
||
, start,after
|
||
};
|
||
splicer.determineRelations();
|
||
auto [s,n,e] = splicer.performSplitSplice();
|
||
return *n;
|
||
}
|
||
|
||
|
||
|
||
}} // namespace steam::fixture
|