1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: lyt_Animation.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 19854 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/lyt/lyt_Common.h>
19 #include <nw/lyt/lyt_Pane.h>
20 #include <nw/lyt/lyt_Group.h>
21 #include <nw/lyt/lyt_Material.h>
22 #include <nw/lyt/lyt_Animation.h>
23 #include <nw/lyt/lyt_Layout.h>
24 #include <nw/lyt/lyt_ResourceAccessor.h>
25 #include <nw/lyt/lyt_Util.h>
26
27 const f32 R_SAME_TOLERANCE = 1.0e-5F;
28 const f32 R_FRAME_TOLERANCE = 0.001F;
29
30 namespace nw
31 {
32 namespace lyt
33 {
34 namespace
35 {
36
37 /*---------------------------------------------------------------------------*
38 @brief f32 型の値を許容値付きで比較します。
39
40 @param a 比較する値です。
41 @param b 比較する値です。
42 @param tolerance 許容値です。
43
44 @return 2つの値の差の絶対値が許容値未満なら true を返します。
45 *---------------------------------------------------------------------------*/
46 inline bool
RIsSame(const f32 a,const f32 b,const f32 tolerance=R_SAME_TOLERANCE)47 RIsSame(
48 const f32 a,
49 const f32 b,
50 const f32 tolerance = R_SAME_TOLERANCE
51 )
52 {
53 f32 c = a - b;
54 return (-tolerance < c && c < tolerance);
55 }
56
57 /*---------------------------------------------------------------------------*
58 @brief ステップ形式カーブの特定フレームでの値を取得します。
59
60 @param frame 値を取得するフレームです。
61 @param keyArray ステップ形式キーの配列です。
62 @param keySize キー数です。
63
64 @return 値です。
65 *---------------------------------------------------------------------------*/
66 u16
GetStepCurveValue(f32 frame,const res::StepKey * keyArray,u32 keySize)67 GetStepCurveValue(
68 f32 frame,
69 const res::StepKey* keyArray,
70 u32 keySize
71 )
72 {
73 NW_ASSERT(keySize > 0);
74
75 if (keySize == 1 || frame <= keyArray[0].frame)
76 {
77 return keyArray[0].value;
78 }
79 else if (frame >= keyArray[keySize - 1].frame)
80 {
81 return keyArray[keySize - 1].value;
82 }
83
84 int ikeyL = 0;
85 int ikeyR = (int)keySize - 1;
86 while (ikeyL != ikeyR - 1 && ikeyL != ikeyR)
87 {
88 int ikeyCenter = (ikeyL + ikeyR) / 2;
89 const res::StepKey& centerKey = keyArray[ikeyCenter];
90 if (frame < centerKey.frame)
91 {
92 ikeyR = ikeyCenter;
93 }
94 else
95 {
96 ikeyL = ikeyCenter;
97 }
98 }
99
100 if (RIsSame(frame, keyArray[ikeyR].frame, R_FRAME_TOLERANCE))
101 {
102 return keyArray[ikeyR].value;
103 }
104 else
105 {
106 return keyArray[ikeyL].value;
107 }
108 }
109
110 /*---------------------------------------------------------------------------*
111 @brief エルミート形式カーブの特定フレームでの値を取得します。
112
113 @param frame 値を取得するフレームです。
114 @param keyArray エルミート形式キーの配列です。
115 @param keySize キー数です。
116
117 @return 値です。
118 *---------------------------------------------------------------------------*/
119 f32
GetHermiteCurveValue(f32 frame,const res::HermiteKey * keyArray,u32 keySize)120 GetHermiteCurveValue(
121 f32 frame,
122 const res::HermiteKey* keyArray,
123 u32 keySize
124 )
125 {
126 NW_ASSERT(keySize > 0);
127
128 // outside of curve
129 if (keySize == 1 || frame <= keyArray[0].frame)
130 {
131 return keyArray[0].value;
132 }
133 else if (frame >= keyArray[keySize - 1].frame)
134 {
135 return keyArray[keySize - 1].value;
136 }
137
138 // find 2 keys
139 u32 ikeyL = 0;
140 u32 ikeyR = keySize - 1;
141 while (ikeyL != ikeyR - 1 && ikeyL != ikeyR)
142 {
143 int ikeyCenter = (ikeyL + ikeyR) / 2;
144 if (frame <= keyArray[ikeyCenter].frame)
145 {
146 ikeyR = ikeyCenter;
147 }
148 else
149 {
150 ikeyL = ikeyCenter;
151 }
152 }
153
154 // calculate hermite interpolation
155 const res::HermiteKey& key0 = keyArray[ikeyL];
156 const res::HermiteKey& key1 = keyArray[ikeyR];
157 if (RIsSame(frame, key1.frame, R_FRAME_TOLERANCE))
158 {
159 if (ikeyR < keySize - 1 &&
160 key1.frame == keyArray[ikeyR + 1].frame)
161 {
162 // 同一フレームに値の異なるキーがある場合
163 return keyArray[ikeyR + 1].value;
164 }
165 else
166 {
167 return key1.value;
168 }
169 }
170 f32 t1 = frame - key0.frame;
171 f32 t2 = 1.0F / (key1.frame - key0.frame);
172 f32 v0 = key0.value;
173 f32 v1 = key1.value;
174 f32 s0 = key0.slope;
175 f32 s1 = key1.slope;
176
177 f32 t1t1t2 = t1 * t1 * t2;
178 f32 t1t1t2t2 = t1t1t2 * t2;
179 f32 t1t1t1t2t2 = t1 * t1t1t2t2;
180 f32 t1t1t1t2t2t2 = t1t1t1t2t2 * t2;
181
182 return v0 * (2.0F * t1t1t1t2t2t2 - 3.0F * t1t1t2t2 + 1.0F)
183 + v1 * (-2.0F * t1t1t1t2t2t2 + 3.0F * t1t1t2t2)
184 + s0 * (t1t1t1t2t2 - 2.0F * t1t1t2 + t1)
185 + s1 * (t1t1t1t2t2 - t1t1t2);
186 }
187
188 void
AnimatePaneSRT(Pane * pPane,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame)189 AnimatePaneSRT(
190 Pane* pPane,
191 const res::AnimationInfo* pAnimInfo,
192 const u32* animTargetOffsets,
193 f32 frame
194 )
195 {
196 for (int i = 0; i < pAnimInfo->num; ++i)
197 {
198 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
199
200 NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_MAX);
201 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ
202
203 const res::HermiteKey* keys = internal::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
204 pPane->SetSRTElement(pAnimTarget->target, GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum));
205 }
206 }
207
208 void
AnimateVisibility(Pane * pPane,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame)209 AnimateVisibility(
210 Pane* pPane,
211 const res::AnimationInfo* pAnimInfo,
212 const u32* animTargetOffsets,
213 f32 frame
214 )
215 {
216 for (int i = 0; i < pAnimInfo->num; ++i)
217 {
218 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
219
220 NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_MAX);
221 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_STEP);
222
223 const res::StepKey* keys = internal::ConvertOffsToPtr<res::StepKey>(pAnimTarget, pAnimTarget->keysOffset);
224 pPane->SetVisible(0 != GetStepCurveValue(frame, keys, pAnimTarget->keyNum));
225 }
226 }
227
228 void
AnimateVertexColor(Pane * pPane,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame)229 AnimateVertexColor(
230 Pane* pPane,
231 const res::AnimationInfo* pAnimInfo,
232 const u32* animTargetOffsets,
233 f32 frame
234 )
235 {
236 for (int i = 0; i < pAnimInfo->num; ++i)
237 {
238 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
239
240 NW_ASSERT(pAnimTarget->target < ANIMTARGET_PANE_COLOR_MAX);
241 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ
242
243 const res::HermiteKey* keys = internal::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
244 f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum);
245 value += 0.5f;
246 u8 u8Val = static_cast<u8>(value);
247 pPane->SetColorElement(pAnimTarget->target, u8Val);
248 }
249 }
250
251 void
AnimateMaterialColor(Material * pMaterial,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame)252 AnimateMaterialColor(
253 Material* pMaterial,
254 const res::AnimationInfo* pAnimInfo,
255 const u32* animTargetOffsets,
256 f32 frame
257 )
258 {
259 for (int i = 0; i < pAnimInfo->num; ++i)
260 {
261 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
262 NW_ASSERT(pAnimTarget->target < ANIMTARGET_MATCOLOR_MAX);
263 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ
264
265 const res::HermiteKey* keys = internal::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
266 f32 value = GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum);
267 value += 0.5f;
268 u8 val = static_cast<u8>(ut::Min(ut::Max(value, 0.f), 255.f));
269 pMaterial->SetColorElement(pAnimTarget->target, val);
270 }
271 }
272
273 void
AnimateTextureSRT(Material * pMaterial,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame)274 AnimateTextureSRT(
275 Material* pMaterial,
276 const res::AnimationInfo* pAnimInfo,
277 const u32* animTargetOffsets,
278 f32 frame
279 )
280 {
281 for (int i = 0; i < pAnimInfo->num; ++i)
282 {
283 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[i]);
284 NW_ASSERT(pAnimTarget->id < TexMapMax);
285 if (pAnimTarget->id < pMaterial->GetTexSRTCap())
286 {
287 NW_ASSERT(pAnimTarget->target < ANIMTARGET_TEXSRT_MAX);
288 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_HERMITE); // 現時点ではHERMITEのみ
289
290 const res::HermiteKey* keys = internal::ConvertOffsToPtr<res::HermiteKey>(pAnimTarget, pAnimTarget->keysOffset);
291 pMaterial->SetTexSRTElement(pAnimTarget->id, pAnimTarget->target, GetHermiteCurveValue(frame, keys, pAnimTarget->keyNum));
292 }
293 }
294 }
295
296 void
AnimateTexturePattern(Material * pMaterial,const res::AnimationInfo * pAnimInfo,const u32 * animTargetOffsets,f32 frame,const TextureInfo * texInfos)297 AnimateTexturePattern(
298 Material* pMaterial,
299 const res::AnimationInfo* pAnimInfo,
300 const u32* animTargetOffsets,
301 f32 frame,
302 const TextureInfo* texInfos
303 )
304 {
305 for (int j = 0; j < pAnimInfo->num; ++j)
306 {
307 const res::AnimationTarget* pAnimTarget = internal::ConvertOffsToPtr<res::AnimationTarget>(pAnimInfo, animTargetOffsets[j]);
308
309 if (pAnimTarget->id < pMaterial->GetTexMapNum())
310 {
311 NW_ASSERT(pAnimTarget->curveType == ANIMCURVE_STEP); // 現時点ではSTEPのみ
312 NW_ASSERT(pAnimTarget->target == ANIMTARGET_TEXPATTURN_IMAGE); // 現状ではimageのみ
313
314 const res::StepKey* keys = internal::ConvertOffsToPtr<res::StepKey>(pAnimTarget, pAnimTarget->keysOffset);
315 const u16 fileIdx = GetStepCurveValue(frame, keys, pAnimTarget->keyNum);
316
317 if (texInfos[fileIdx].IsValid())
318 {
319 pMaterial->SetTexMap(pAnimTarget->id, texInfos[fileIdx]);
320 }
321 }
322 }
323 }
324
325 inline bool
IsBindAnimation(Pane * pPane,AnimTransform * pAnimTrans)326 IsBindAnimation(
327 Pane* pPane,
328 AnimTransform* pAnimTrans
329 )
330 {
331 #if defined(NW_RELEASE)
332
333 NW_UNUSED_VARIABLE(pPane)
334 NW_UNUSED_VARIABLE(pAnimTrans)
335
336 #else
337
338 if (pPane->FindAnimationLinkSelf(pAnimTrans))
339 {
340 NW_WARNING(false, "already bind animation.");
341 return true;
342 }
343
344 #endif // #if !defined(NW_RELEASE)
345
346 return false;
347 }
348
349 inline bool
IsBindAnimation(Material * pMaterial,AnimTransform * pAnimTrans)350 IsBindAnimation(
351 Material* pMaterial,
352 AnimTransform* pAnimTrans
353 )
354 {
355 #if defined(NW_RELEASE)
356
357 NW_UNUSED_VARIABLE(pMaterial)
358 NW_UNUSED_VARIABLE(pAnimTrans)
359
360 #else
361
362 if (pMaterial->FindAnimationLink(pAnimTrans))
363 {
364 NW_WARNING(false, "already bind animation.");
365 return true;
366 }
367
368 #endif // #if !defined(NW_RELEASE)
369
370 return false;
371 }
372
373 } // namespace nw::lyt::{no-name}
374
AnimTransform()375 AnimTransform::AnimTransform()
376 : m_pRes(0),
377 m_Frame(0)
378 {
379 }
380
~AnimTransform()381 AnimTransform::~AnimTransform()
382 {
383 }
384
385 u16
GetFrameSize() const386 AnimTransform::GetFrameSize() const
387 {
388 return m_pRes->frameSize;
389 }
390
391 bool
IsLoopData() const392 AnimTransform::IsLoopData() const
393 {
394 return m_pRes->loop != 0;
395 }
396
AnimTransformBasic()397 AnimTransformBasic::AnimTransformBasic()
398 : m_pTexAry(0),
399 m_pAnimLinkAry(0),
400 m_AnimLinkNum(0)
401 {
402 }
403
~AnimTransformBasic()404 AnimTransformBasic::~AnimTransformBasic()
405 {
406 Layout::DeleteArray(m_pAnimLinkAry, m_AnimLinkNum);
407 Layout::DeletePrimArray(m_pTexAry);
408 }
409
410 void
SetResource(const res::AnimationBlock * pRes,ResourceAccessor * pResAccessor)411 AnimTransformBasic::SetResource(
412 const res::AnimationBlock* pRes,
413 ResourceAccessor* pResAccessor
414 )
415 {
416 NW_NULL_ASSERT(pRes);
417 SetResource(pRes, pResAccessor, pRes->animContNum);
418 }
419
420 void
SetResource(const res::AnimationBlock * pRes,ResourceAccessor * pResAccessor,u16 animNum)421 AnimTransformBasic::SetResource(
422 const res::AnimationBlock* pRes,
423 ResourceAccessor* pResAccessor,
424 u16 animNum
425 )
426 {
427 NW_ASSERT(m_pTexAry == 0);
428 NW_ASSERT(m_pAnimLinkAry == 0);
429 NW_NULL_ASSERT(pRes);
430
431 this->SetAnimResource(pRes);
432 m_pTexAry = 0;
433
434 if (pRes->fileNum > 0)
435 {
436 NW_NULL_ASSERT(pResAccessor);
437
438 m_pTexAry = Layout::NewArray<TextureInfo>(pRes->fileNum);
439 if (m_pTexAry)
440 {
441 const u32* fileNameOffsets = internal::ConvertOffsToPtr<u32>(pRes, sizeof(*pRes));
442
443 for (int i = 0; i < pRes->fileNum; ++i)
444 {
445 const char *const fileName = internal::GetStrTableStr(fileNameOffsets, i);
446
447 // テクスチャオブジェクトをロードする。
448 m_pTexAry[i] = pResAccessor->GetTexture(fileName);
449 }
450 }
451 }
452
453 m_pAnimLinkAry = Layout::NewArray<AnimationLink>(animNum);
454 if (m_pAnimLinkAry)
455 {
456 m_AnimLinkNum = animNum;
457 }
458 }
459
460 void
Bind(Pane * pPane,bool bRecursive,bool bDisable)461 AnimTransformBasic::Bind(
462 Pane* pPane,
463 bool bRecursive,
464 bool bDisable
465 )
466 {
467 NW_NULL_ASSERT(pPane);
468
469 AnimationLink* pCrAnimLink = 0;
470 const res::AnimationBlock* pRes = this->GetAnimResource();
471
472 const u32 *const animContOffsets = internal::ConvertOffsToPtr<u32>(pRes, pRes->animContOffsetsOffset);
473 for (u16 i = 0; i < pRes->animContNum; ++i)
474 {
475 const res::AnimationContent& animCont = *internal::ConvertOffsToPtr<res::AnimationContent>(pRes, animContOffsets[i]);
476 if (animCont.type == ANIMCONTENTTYPE_PANE)
477 {
478 if (Pane *const pFindPane = pPane->FindPaneByName(animCont.name, bRecursive))
479 {
480 if (! IsBindAnimation(pFindPane, this))
481 {
482 pCrAnimLink = Bind(pFindPane, pCrAnimLink, i, bDisable);
483 if (! pCrAnimLink)
484 {
485 break;
486 }
487 }
488 }
489 }
490 else
491 {
492 if (Material *const pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive))
493 {
494 if (! IsBindAnimation(pFindMat, this))
495 {
496 pCrAnimLink = Bind(pFindMat, pCrAnimLink, i, bDisable);
497 if (! pCrAnimLink)
498 {
499 break;
500 }
501 }
502 }
503 }
504 }
505 }
506
507 void
Bind(Material * pMaterial,bool bDisable)508 AnimTransformBasic::Bind(
509 Material* pMaterial,
510 bool bDisable
511 )
512 {
513 NW_NULL_ASSERT(pMaterial);
514
515 AnimationLink* pCrAnimLink = 0;
516 const res::AnimationBlock* pRes = this->GetAnimResource();
517
518 const u32 *const animContOffsets = internal::ConvertOffsToPtr<u32>(pRes, pRes->animContOffsetsOffset);
519 for (u16 i = 0; i < pRes->animContNum; ++i)
520 {
521 const res::AnimationContent& animCont = *internal::ConvertOffsToPtr<res::AnimationContent>(pRes, animContOffsets[i]);
522 if (animCont.type == ANIMCONTENTTYPE_MATERIAL)
523 {
524 if (internal::EqualsMaterialName(pMaterial->GetName(), animCont.name))
525 {
526 if (! IsBindAnimation(pMaterial, this))
527 {
528 pCrAnimLink = Bind(pMaterial, pCrAnimLink, i, bDisable);
529 if (! pCrAnimLink)
530 {
531 break;
532 }
533 }
534 }
535 }
536 }
537 }
538
539 template<typename T>
540 AnimationLink*
Bind(T * pTarget,AnimationLink * pAnimLink,u16 idx,bool bDisable)541 AnimTransformBasic::Bind(
542 T* pTarget,
543 AnimationLink* pAnimLink,
544 u16 idx,
545 bool bDisable
546 )
547 {
548 NW_NULL_ASSERT(pTarget);
549
550 pAnimLink = FindUnbindLink(pAnimLink);
551 if (! pAnimLink)
552 {
553 NW_WARNING(false, "all AnimationLink used.");
554 return 0;
555 }
556
557 pAnimLink->Set(this, idx, bDisable);
558 pTarget->AddAnimationLink(pAnimLink);
559
560 return ++pAnimLink;
561 }
562
563 void
Animate(u32 idx,Pane * pPane)564 AnimTransformBasic::Animate(u32 idx, Pane* pPane)
565 {
566 NW_NULL_ASSERT(pPane);
567
568 const res::AnimationBlock* pRes = this->GetAnimResource();
569
570 u32 animContOffsets = internal::ConvertOffsToPtr<u32>(pRes, pRes->animContOffsetsOffset)[idx];
571 const res::AnimationContent* pAnimCont = internal::ConvertOffsToPtr<res::AnimationContent>(pRes, animContOffsets);
572
573 const u32* animInfoOffsets = internal::ConvertOffsToPtr<u32>(pAnimCont, sizeof(*pAnimCont));
574 for (int i = 0; i < pAnimCont->num; ++i)
575 {
576 const res::AnimationInfo* pAnimInfo = internal::ConvertOffsToPtr<res::AnimationInfo>(pAnimCont, animInfoOffsets[i]);
577 const u32* animTargetOffsets = internal::ConvertOffsToPtr<u32>(pAnimInfo, sizeof(*pAnimInfo));
578
579 switch (pAnimInfo->kind)
580 {
581 case res::ANIMATIONTYPE_PANESRT:
582 AnimatePaneSRT(pPane, pAnimInfo, animTargetOffsets, this->GetFrame());
583 break;
584 case res::ANIMATIONTYPE_VISIBILITY:
585 AnimateVisibility(pPane, pAnimInfo, animTargetOffsets, this->GetFrame());
586 break;
587 case res::ANIMATIONTYPE_VTXCOLOR:
588 AnimateVertexColor(pPane, pAnimInfo, animTargetOffsets, this->GetFrame());
589 break;
590 }
591 }
592 }
593
594 void
Animate(u32 idx,Material * pMaterial)595 AnimTransformBasic::Animate(u32 idx, Material* pMaterial)
596 {
597 NW_NULL_ASSERT(pMaterial);
598
599 const res::AnimationBlock* pRes = this->GetAnimResource();
600 if (pRes == NULL)
601 {
602 NW_WARNING(false, "Animation resource is not set.");
603 return;
604 }
605
606 u32 animContOffsets = internal::ConvertOffsToPtr<u32>(pRes, pRes->animContOffsetsOffset)[idx];
607 const res::AnimationContent* pAnimCont = internal::ConvertOffsToPtr<res::AnimationContent>(pRes, animContOffsets);
608
609 const u32* animInfoOffsets = internal::ConvertOffsToPtr<u32>(pAnimCont, sizeof(*pAnimCont));
610 for (int i = 0; i < pAnimCont->num; ++i)
611 {
612 const res::AnimationInfo* pAnimInfo = internal::ConvertOffsToPtr<res::AnimationInfo>(pAnimCont, animInfoOffsets[i]);
613 const u32* animTargetOffsets = internal::ConvertOffsToPtr<u32>(pAnimInfo, sizeof(*pAnimInfo));
614
615 switch (pAnimInfo->kind)
616 {
617 case res::ANIMATIONTYPE_MATCOLOR:
618 AnimateMaterialColor(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame());
619 break;
620 case res::ANIMATIONTYPE_TEXSRT:
621 AnimateTextureSRT(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame());
622 break;
623 case res::ANIMATIONTYPE_TEXPATTERN:
624 if (m_pTexAry)
625 {
626 AnimateTexturePattern(pMaterial, pAnimInfo, animTargetOffsets, this->GetFrame(), m_pTexAry);
627 }
628 break;
629 }
630 }
631 }
632
633 AnimationLink*
FindUnbindLink(AnimationLink * pLink) const634 AnimTransformBasic::FindUnbindLink(AnimationLink* pLink) const
635 {
636 if (pLink == 0)
637 {
638 if (m_pAnimLinkAry == 0)
639 {
640 NW_WARNING(false, "Animation resource is not set.");
641 return 0;
642 }
643 pLink = m_pAnimLinkAry;
644 }
645
646 while (pLink < m_pAnimLinkAry + m_AnimLinkNum)
647 {
648 if (pLink->GetAnimTransform() == 0)
649 {
650 return pLink;
651 }
652
653 ++pLink;
654 }
655
656 return 0;
657 }
658
AnimResource()659 AnimResource::AnimResource()
660 {
661 Init();
662 }
663
664 bool
CheckResource() const665 AnimResource::CheckResource() const
666 {
667 if (!m_pResBlock)
668 {
669 NW_WARNING(false, "Animation resource is not set.");
670 return false;
671 }
672 return true;
673 }
674
675 void
Set(const void * anmResBuf)676 AnimResource::Set(const void* anmResBuf)
677 {
678 NW_NULL_ASSERT(anmResBuf);
679
680 Init();
681
682 const ut::BinaryFileHeader *const pFileHeader = static_cast<const ut::BinaryFileHeader*>(anmResBuf);
683
684 if (!ut::IsValidBinaryFile(pFileHeader, res::FILESIGNATURE_CLAN, res::BinaryFileFormatVersion))
685 {
686 NW_WARNING(false, "not valid layout animation file.");
687 return;
688 }
689
690 m_pFileHeader = pFileHeader;
691
692 const ut::BinaryBlockHeader* pDataBlockHead = internal::ConvertOffsToPtr<ut::BinaryBlockHeader>(m_pFileHeader, m_pFileHeader->headerSize);
693 for (int i = 0; i < m_pFileHeader->dataBlocks; ++i)
694 {
695 ut::SigWord kind = pDataBlockHead->kind;
696 switch (kind)
697 {
698 case res::DATABLOCKKIND_PANEANIMTAG:
699 m_pTagBlock = reinterpret_cast<const res::AnimationTagBlock*>(pDataBlockHead);
700 break;
701
702 case res::DATABLOCKKIND_PANEANIMSHARE:
703 m_pShareBlock = reinterpret_cast<const res::AnimationShareBlock*>(pDataBlockHead);
704 break;
705
706 case res::DATABLOCKKIND_PANEANIMINFO:
707 m_pResBlock = reinterpret_cast<const res::AnimationBlock*>(pDataBlockHead);
708 break;
709 }
710
711 // 次のブロック位置へ
712 pDataBlockHead = internal::ConvertOffsToPtr<ut::BinaryBlockHeader>(pDataBlockHead, pDataBlockHead->size);
713 }
714
715 NW_WARNING(m_pResBlock != NULL, "Animation resource is empty.");
716 }
717
718 void
Init()719 AnimResource::Init()
720 {
721 m_pFileHeader = 0;
722 m_pResBlock = 0;
723 m_pTagBlock = 0;
724 m_pShareBlock = 0;
725 }
726
727 u16
GetTagOrder() const728 AnimResource::GetTagOrder() const
729 {
730 if (! m_pTagBlock)
731 {
732 return u16(-1);
733 }
734
735 return m_pTagBlock->tagOrder;
736 }
737
738 const char*
GetTagName() const739 AnimResource::GetTagName() const
740 {
741 if (! m_pTagBlock)
742 {
743 return 0;
744 }
745
746 return internal::ConvertOffsToPtr<const char>(m_pTagBlock, m_pTagBlock->nameOffset);
747 }
748
749 u16
GetGroupNum() const750 AnimResource::GetGroupNum() const
751 {
752 if (! m_pTagBlock)
753 {
754 return 0;
755 }
756
757 return m_pTagBlock->groupNum;
758 }
759
760 const AnimationGroupRef*
GetGroupArray() const761 AnimResource::GetGroupArray() const
762 {
763 if (! m_pTagBlock)
764 {
765 return 0;
766 }
767
768 const AnimationGroupRef *const groups = internal::ConvertOffsToPtr<const AnimationGroupRef>(m_pTagBlock, m_pTagBlock->groupsOffset);
769
770 return groups;
771
772 }
773
774 bool
IsDescendingBind() const775 AnimResource::IsDescendingBind() const
776 {
777 if (! m_pTagBlock)
778 {
779 return false;
780 }
781
782 return internal::TestBit(m_pTagBlock->flag, ANIMTAGFLAG_DESCENDINGBIND);
783 }
784
785 u16
GetAnimationShareInfoNum() const786 AnimResource::GetAnimationShareInfoNum() const
787 {
788 if (! m_pShareBlock)
789 {
790 return 0;
791 }
792
793 return m_pShareBlock->shareNum;
794 }
795
796 const AnimationShareInfo*
GetAnimationShareInfoArray() const797 AnimResource::GetAnimationShareInfoArray() const
798 {
799 if (! m_pShareBlock)
800 {
801 return 0;
802 }
803
804 return internal::ConvertOffsToPtr<const AnimationShareInfo>(m_pShareBlock, m_pShareBlock->animShareInfoOffset);
805 }
806
807 u16
CalcAnimationNum(Pane * pPane,bool bRecursive) const808 AnimResource::CalcAnimationNum(
809 Pane* pPane,
810 bool bRecursive
811 ) const
812 {
813 if (! CheckResource())
814 {
815 return 0;
816 }
817
818 u16 linkNum = 0;
819
820 const u32 *const animContOffsets = internal::ConvertOffsToPtr<u32>(m_pResBlock, m_pResBlock->animContOffsetsOffset);
821 for (u16 i = 0; i < m_pResBlock->animContNum; ++i)
822 {
823 const res::AnimationContent& animCont = *internal::ConvertOffsToPtr<res::AnimationContent>(m_pResBlock, animContOffsets[i]);
824 if (animCont.type == ANIMCONTENTTYPE_PANE)
825 {
826 if (Pane *const pFindPane = pPane->FindPaneByName(animCont.name, bRecursive))
827 {
828 ++linkNum;
829 }
830 }
831 else
832 {
833 if (Material *const pFindMat = pPane->FindMaterialByName(animCont.name, bRecursive))
834 {
835 ++linkNum;
836 }
837 }
838 }
839
840 return linkNum;
841 }
842
843 u16
CalcAnimationNum(Material * pMaterial) const844 AnimResource::CalcAnimationNum(Material* pMaterial) const
845 {
846 if (! CheckResource())
847 {
848 return 0;
849 }
850
851 u16 linkNum = 0;
852
853 const u32 *const animContOffsets = internal::ConvertOffsToPtr<u32>(m_pResBlock, m_pResBlock->animContOffsetsOffset);
854 for (u16 i = 0; i < m_pResBlock->animContNum; ++i)
855 {
856 const res::AnimationContent& animCont = *internal::ConvertOffsToPtr<res::AnimationContent>(m_pResBlock, animContOffsets[i]);
857 if (animCont.type == ANIMCONTENTTYPE_MATERIAL)
858 {
859 if (internal::EqualsMaterialName(pMaterial->GetName(), animCont.name))
860 {
861 ++linkNum;
862 break; // 同じ名前の res::AnimationContent が複数存在することはないため、
863 // 見つかったらすぐに抜ける。
864 }
865 }
866 }
867
868 return linkNum;
869 }
870
871 u16
CalcAnimationNum(Group * pGroup,bool bRecursive) const872 AnimResource::CalcAnimationNum(
873 Group* pGroup,
874 bool bRecursive
875 ) const
876 {
877 NW_NULL_ASSERT(pGroup);
878
879 u16 linkNum = 0;
880
881 PaneLinkList& paneList = pGroup->GetPaneList();
882 for (PaneLinkList::Iterator it = paneList.GetBeginIter(); it != paneList.GetEndIter(); ++it)
883 {
884 linkNum += CalcAnimationNum(it->target, bRecursive);
885 }
886
887 return linkNum;
888 }
889
890 namespace internal
891 {
892
AnimPaneTree()893 AnimPaneTree::AnimPaneTree()
894 {
895 Init();
896 }
897
AnimPaneTree(Pane * pTargetPane,const AnimResource & animRes)898 AnimPaneTree::AnimPaneTree(
899 Pane* pTargetPane,
900 const AnimResource& animRes)
901 {
902 Init();
903 Set(pTargetPane, animRes);
904 }
905
906 u16
FindAnimContent(const res::AnimationBlock * pAnimBlock,const char * animContName,u8 animContType)907 AnimPaneTree::FindAnimContent(
908 const res::AnimationBlock* pAnimBlock,
909 const char* animContName,
910 u8 animContType
911 )
912 {
913 NW_NULL_ASSERT(pAnimBlock);
914
915 const u32 *const animContOffsets = ConvertOffsToPtr<u32>(pAnimBlock, pAnimBlock->animContOffsetsOffset);
916 for (u16 i = 0; i < pAnimBlock->animContNum; ++i)
917 {
918 const res::AnimationContent *const pAnimCont = ConvertOffsToPtr<res::AnimationContent>(pAnimBlock, animContOffsets[i]);
919 if (pAnimCont->type == animContType &&
920 internal::EqualsMaterialName(pAnimCont->name, animContName))
921 {
922 return i;
923 }
924 }
925
926 return NOBIND;
927 }
928
929 void
Init()930 AnimPaneTree::Init()
931 {
932 m_LinkNum = 0;
933
934 m_AnimPaneIdx = 0;
935 m_AnimMatCnt = 0;
936 for (u8 i = 0; i < MATERIAL_NUM_MAX; ++i)
937 {
938 m_AnimMatIdxs[i] = 0;
939 }
940 }
941
942 void
Set(Pane * pTargetPane,const AnimResource & animRes)943 AnimPaneTree::Set(
944 Pane* pTargetPane,
945 const AnimResource& animRes
946 )
947 {
948 NW_NULL_ASSERT(pTargetPane);
949
950 u16 linkNum = 0;
951 const res::AnimationBlock* pAnimBlock = animRes.GetResourceBlock();
952
953 const u16 animContIdx = FindAnimContent(pAnimBlock, pTargetPane->GetName(), ANIMCONTENTTYPE_PANE);
954 if (animContIdx != NOBIND)
955 {
956 ++linkNum;
957 }
958
959 // マテリアルの処理
960 const u8 animMatCnt = pTargetPane->GetMaterialNum();
961 NW_ASSERT(animMatCnt <= MATERIAL_NUM_MAX);
962 u16 animMatIdxs[MATERIAL_NUM_MAX];
963
964 for (u8 i = 0; i < animMatCnt; ++i)
965 {
966 animMatIdxs[i] = FindAnimContent(pAnimBlock, pTargetPane->GetMaterial(i)->GetName(), ANIMCONTENTTYPE_MATERIAL);
967 if (animMatIdxs[i] != NOBIND)
968 {
969 ++linkNum;
970 }
971 }
972
973 // アニメーション対象がひとつも無い
974 if (linkNum == 0)
975 {
976 return;
977 }
978
979 m_AnimRes = animRes;
980 m_AnimPaneIdx = animContIdx;
981 m_AnimMatCnt = animMatCnt;
982 for (u8 i = 0; i < animMatCnt; ++i)
983 {
984 m_AnimMatIdxs[i] = animMatIdxs[i];
985 }
986 m_LinkNum = linkNum;
987 }
988
989 AnimTransform*
Bind(Layout * pLayout,Pane * pTargetPane,ResourceAccessor * pResAccessor) const990 AnimPaneTree::Bind(
991 Layout* pLayout,
992 Pane* pTargetPane,
993 ResourceAccessor* pResAccessor
994 ) const
995 {
996 NW_NULL_ASSERT(pLayout);
997 NW_NULL_ASSERT(pTargetPane);
998
999 AnimTransformBasic *const pAnimTrans = static_cast<AnimTransformBasic*>(pLayout->CreateAnimTransform());
1000 pAnimTrans->SetResource(m_AnimRes.GetResourceBlock(), pResAccessor, m_LinkNum);
1001
1002 AnimationLink* pCrAnimLink = 0;
1003
1004 // ペインのアニメのバインド
1005 if (m_AnimPaneIdx != NOBIND)
1006 {
1007 pCrAnimLink = pAnimTrans->Bind(pTargetPane, pCrAnimLink, m_AnimPaneIdx, true/*bDisable*/);
1008 }
1009
1010 // マテリアルアニメのバインド
1011 // ※マテリアルの個数が共有元ペインと等しいとは限りません。
1012 const u32 animMatMax = ut::Min(m_AnimMatCnt, pTargetPane->GetMaterialNum());
1013 for (u32 i = 0; i < animMatMax; ++i)
1014 {
1015 if (m_AnimMatIdxs[i] != NOBIND)
1016 {
1017 Material *const pMaterial = pTargetPane->GetMaterial(i);
1018 NW_NULL_ASSERT(pMaterial);
1019 pCrAnimLink = pAnimTrans->Bind(pMaterial, pCrAnimLink, m_AnimMatIdxs[i], true/*bDisable*/);
1020 }
1021 }
1022
1023 return pAnimTrans;
1024 }
1025
1026 AnimationLink*
FindAnimationLink(AnimationList * pAnimList,AnimTransform * pAnimTrans)1027 FindAnimationLink(
1028 AnimationList* pAnimList,
1029 AnimTransform* pAnimTrans
1030 )
1031 {
1032 NW_NULL_ASSERT(pAnimList);
1033 NW_NULL_ASSERT(pAnimTrans);
1034
1035 for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); ++it)
1036 {
1037 if (pAnimTrans == it->GetAnimTransform())
1038 {
1039 return &(*it);
1040 }
1041 }
1042
1043 return 0;
1044 }
1045
1046 AnimationLink*
FindAnimationLink(AnimationList * pAnimList,const AnimResource & animRes)1047 FindAnimationLink(
1048 AnimationList* pAnimList,
1049 const AnimResource& animRes
1050 )
1051 {
1052 NW_NULL_ASSERT(pAnimList);
1053
1054 for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter(); ++it)
1055 {
1056 if (animRes.GetResourceBlock() == it->GetAnimTransform()->GetAnimResource())
1057 {
1058 return &(*it);
1059 }
1060 }
1061
1062 return 0;
1063 }
1064
1065 void
UnbindAnimationLink(AnimationList * pAnimList,AnimTransform * pAnimTrans)1066 UnbindAnimationLink(
1067 AnimationList* pAnimList,
1068 AnimTransform* pAnimTrans
1069 )
1070 {
1071 NW_NULL_ASSERT(pAnimList);
1072
1073 for (AnimationList::Iterator it = pAnimList->GetBeginIter(); it != pAnimList->GetEndIter();)
1074 {
1075 AnimationList::Iterator currIt = it++;
1076 if (! pAnimTrans || currIt->GetAnimTransform() == pAnimTrans)
1077 {
1078 pAnimList->Erase(currIt);
1079 currIt->Reset();
1080 }
1081 }
1082 }
1083
1084 } // namespace nw::lyt::internal
1085 } // namespace nw::lyt
1086 } // namespace nw
1087