@@ -187,7 +187,34 @@ csmFloat32 InverseSteppedEvaluate(const CubismMotionPoint* points, const csmFloa
187187 return points[1 ].Value ;
188188}
189189
190- csmFloat32 EvaluateCurve (const CubismMotionData* motionData, const csmInt32 index, csmFloat32 time)
190+ csmFloat32 CorrectEndPoint (
191+ const CubismMotionData* motionData,
192+ const csmInt32 segmentIndex,
193+ const csmInt32 beginIndex,
194+ const csmInt32 endIndex,
195+ const csmFloat32 time,
196+ const csmFloat32 endTime
197+ )
198+ {
199+ CubismMotionPoint motionPoint[2 ];
200+ motionPoint[0 ] = motionData->Points [endIndex];
201+ motionPoint[1 ] = motionData->Points [beginIndex];
202+ motionPoint[1 ].Time = endTime;
203+
204+ switch (motionData->Segments [segmentIndex].SegmentType )
205+ {
206+ case CubismMotionSegmentType_Linear:
207+ case CubismMotionSegmentType_Bezier:
208+ default :
209+ return LinearEvaluate (motionPoint, time);
210+ case CubismMotionSegmentType_Stepped:
211+ return SteppedEvaluate (motionPoint, time);
212+ case CubismMotionSegmentType_InverseStepped:
213+ return InverseSteppedEvaluate (motionPoint, time);
214+ }
215+ }
216+
217+ csmFloat32 EvaluateCurve (const CubismMotionData* motionData, const csmInt32 index, csmFloat32 time, const csmBool isCorrection, const csmFloat32 endTime)
191218{
192219 // Find segment to evaluate.
193220 const CubismMotionCurve& curve = motionData->Curves [index];
@@ -215,6 +242,19 @@ csmFloat32 EvaluateCurve(const CubismMotionData* motionData, const csmInt32 inde
215242
216243 if (target == -1 )
217244 {
245+ if (isCorrection && time < endTime)
246+ {
247+ // 終点から始点への補正処理
248+ return CorrectEndPoint (
249+ motionData,
250+ totalSegmentCount - 1 ,
251+ motionData->Segments [curve.BaseSegmentIndex ].BasePointIndex ,
252+ pointPosition,
253+ time,
254+ endTime
255+ );
256+ }
257+
218258 return motionData->Points [pointPosition].Value ;
219259 }
220260
@@ -229,8 +269,7 @@ csmFloat32 EvaluateCurve(const CubismMotionData* motionData, const csmInt32 inde
229269CubismMotion::CubismMotion ()
230270 : _sourceFrameRate(30 .0f )
231271 , _loopDurationSeconds(-1 .0f )
232- , _isLoop(false ) // trueから false へデフォルトを変更
233- , _isLoopFadeIn(true ) // ループ時にフェードインが有効かどうかのフラグ
272+ , _motionBehavior(MotionBehavior_V2)
234273 , _lastWeight(0 .0f )
235274 , _motionData(NULL )
236275 , _modelCurveIdEyeBlink(NULL )
@@ -282,6 +321,16 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
282321 _modelCurveIdOpacity = CubismFramework::GetIdManager ()->GetId (IdNameOpacity);
283322 }
284323
324+ if (_motionBehavior == MotionBehavior_V2)
325+ {
326+ if (_previousLoopState != _isLoop)
327+ {
328+ // 終了時間を再計算する
329+ AdjustEndTime (motionQueueEntry);
330+ _previousLoopState = _isLoop;
331+ }
332+ }
333+
285334 csmFloat32 timeOffsetSeconds = userTimeSeconds - motionQueueEntry->GetStartTime ();
286335
287336 if (timeOffsetSeconds < 0 .0f )
@@ -320,12 +369,18 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
320369
321370 // 'Repeat' time as necessary.
322371 csmFloat32 time = timeOffsetSeconds;
372+ csmFloat32 duration = _motionData->Duration ;
373+ csmBool isCorrection = _motionBehavior == MotionBehavior_V2 && _isLoop;
323374
324375 if (_isLoop)
325376 {
326- while (time > _motionData-> Duration )
377+ if (_motionBehavior == MotionBehavior_V2 )
327378 {
328- time -= _motionData->Duration ;
379+ duration += 1 .0f / _motionData->Fps ;
380+ }
381+ while (time > duration)
382+ {
383+ time -= duration;
329384 }
330385 }
331386
@@ -335,7 +390,7 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
335390 for (c = 0 ; c < _motionData->CurveCount && curves[c].Type == CubismMotionCurveTarget_Model; ++c)
336391 {
337392 // Evaluate curve and call handler.
338- value = EvaluateCurve (_motionData, c, time);
393+ value = EvaluateCurve (_motionData, c, time, isCorrection, duration );
339394
340395 if (curves[c].Id == _modelCurveIdEyeBlink)
341396 {
@@ -372,7 +427,7 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
372427 const csmFloat32 sourceValue = model->GetParameterValue (parameterIndex);
373428
374429 // Evaluate curve and apply value.
375- value = EvaluateCurve (_motionData, c, time);
430+ value = EvaluateCurve (_motionData, c, time, isCorrection, duration );
376431
377432 if (eyeBlinkValue != FLT_MAX)
378433 {
@@ -492,21 +547,16 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
492547 }
493548
494549 // Evaluate curve and apply value.
495- value = EvaluateCurve (_motionData, c, time);
550+ value = EvaluateCurve (_motionData, c, time, isCorrection, duration );
496551
497552 model->SetParameterValue (parameterIndex, value);
498553 }
499554
500- if (timeOffsetSeconds >= _motionData-> Duration )
555+ if (timeOffsetSeconds >= duration )
501556 {
502557 if (_isLoop)
503558 {
504- motionQueueEntry->SetStartTime (userTimeSeconds); // 最初の状態へ
505- if (_isLoopFadeIn)
506- {
507- // ループ中でループ用フェードインが有効のときは、フェードイン設定し直し
508- motionQueueEntry->SetFadeInStartTime (userTimeSeconds);
509- }
559+ UpdateForNextLoop (motionQueueEntry, userTimeSeconds, time);
510560 }
511561 else
512562 {
@@ -522,6 +572,37 @@ void CubismMotion::DoUpdateParameters(CubismModel* model, csmFloat32 userTimeSec
522572 _lastWeight = fadeWeight;
523573}
524574
575+ void CubismMotion::UpdateForNextLoop (CubismMotionQueueEntry* motionQueueEntry, const csmFloat32 userTimeSeconds, const csmFloat32 time)
576+ {
577+ switch (_motionBehavior)
578+ {
579+ case MotionBehavior_V2:
580+ default :
581+ motionQueueEntry->SetStartTime (userTimeSeconds - time); // 最初の状態へ
582+ if (_isLoopFadeIn)
583+ {
584+ // ループ中でループ用フェードインが有効のときは、フェードイン設定し直し
585+ motionQueueEntry->SetFadeInStartTime (userTimeSeconds - time);
586+ }
587+
588+ if (this ->_onFinishedMotion != NULL )
589+ {
590+ this ->_onFinishedMotion (this );
591+ }
592+ break ;
593+ case MotionBehavior_V1:
594+ // 旧ループ処理
595+
596+ motionQueueEntry->SetStartTime (userTimeSeconds); // 最初の状態へ
597+ if (_isLoopFadeIn)
598+ {
599+ // ループ中でループ用フェードインが有効のときは、フェードイン設定し直し
600+ motionQueueEntry->SetFadeInStartTime (userTimeSeconds);
601+ }
602+ break ;
603+ }
604+ }
605+
525606void CubismMotion::Parse (const csmByte* motionJson, const csmSizeInt size)
526607{
527608 _motionData = CSM_NEW CubismMotionData;
@@ -772,24 +853,42 @@ csmFloat32 CubismMotion::GetParameterFadeOutTime(CubismIdHandle parameterId) con
772853
773854void CubismMotion::IsLoop (csmBool loop)
774855{
856+ CubismLogWarning (" IsLoop(csmBool loop) is a deprecated function. Please use SetLoop(csmBool loop)." );
857+
775858 this ->_isLoop = loop;
776859}
777860
778861csmBool CubismMotion::IsLoop () const
779862{
863+ CubismLogWarning (" IsLoop() is a deprecated function. Please use GetLoop()." );
864+
780865 return this ->_isLoop ;
781866}
782867
783868void CubismMotion::IsLoopFadeIn (csmBool loopFadeIn)
784869{
870+ CubismLogWarning (" IsLoopFadeIn(csmBool loopFadeIn) is a deprecated function. Please use SetLoopFadeIn(csmBool loopFadeIn)." );
871+
785872 this ->_isLoopFadeIn = loopFadeIn;
786873}
787874
788875csmBool CubismMotion::IsLoopFadeIn () const
789876{
877+ CubismLogWarning (" IsLoopFadeIn() is a deprecated function. Please use GetLoopFadeIn()." );
878+
790879 return this ->_isLoopFadeIn ;
791880}
792881
882+ void CubismMotion::SetMotionBehavior (MotionBehavior motionBehavior)
883+ {
884+ _motionBehavior = motionBehavior;
885+ }
886+
887+ CubismMotion::MotionBehavior CubismMotion::GetMotionBehavior () const
888+ {
889+ return _motionBehavior;
890+ }
891+
793892csmFloat32 CubismMotion::GetLoopDuration ()
794893{
795894 return _loopDurationSeconds;
0 commit comments