1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_ParticleUtil.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: 25777 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <nw/gfx/gfx_ParticleUtil.h>
19
20 namespace nw
21 {
22 namespace gfx
23 {
24
25 // パーティクルセットを探します。
26 ParticleSet*
FindParticleSet(const char * name,ut::MoveArray<SceneNode * > * sceneNodeArray)27 FindParticleSet(
28 const char* name,
29 ut::MoveArray<SceneNode*>* sceneNodeArray
30 )
31 {
32 for (ut::MoveArray<SceneNode*>::iterator i = sceneNodeArray->Begin();
33 i != sceneNodeArray->End();
34 ++i)
35 {
36 ParticleModel* particleModel = ut::DynamicCast<ParticleModel*>(*i);
37 if (!particleModel) { continue; }
38
39 for (int j = 0; j < (int)particleModel->GetParticleSetsCount(); ++j)
40 {
41 ParticleSet* itParticleSet = particleModel->GetParticleSets(j);
42 NW_NULL_ASSERT(itParticleSet);
43
44 const char* itParticleSetName= itParticleSet->GetResParticleSet().GetName();
45
46 if (std::strcmp(itParticleSetName, name) == 0)
47 {
48 return itParticleSet;
49 }
50 }
51 }
52
53 return NULL;
54 }
55
56 void
SetupParticleObject(ut::MoveArray<SceneNode * > * sceneNodeArray,ParticleContext * particleContext)57 ParticleUtil::SetupParticleObject(
58 ut::MoveArray<SceneNode*>* sceneNodeArray,
59 ParticleContext* particleContext
60 )
61 {
62 NW_NULL_ASSERT(sceneNodeArray);
63 NW_NULL_ASSERT(particleContext);
64
65 ResolveParticleObject(sceneNodeArray);
66
67 NW_FOREACH(SceneNode* node, *sceneNodeArray)
68 {
69 ResSceneNode resSceneNode = node->GetResSceneNode();
70 NW_ASSERT(resSceneNode.IsValid());
71
72 switch (resSceneNode.ptr()->typeInfo)
73 {
74 case ResParticleModel::TYPE_INFO:
75 {
76 ParticleModel* model = static_cast<ParticleModel*>(node);
77 NW_NULL_ASSERT(model);
78
79 for (u32 i = 0; i < model->GetParticleSetsCount(); ++i)
80 {
81 ParticleSet* particleSet = model->GetParticleSets(i);
82 NW_NULL_ASSERT(particleSet);
83
84 particleSet->Srand(particleContext->GetRandom());
85 }
86 }
87 break;
88 case ResParticleEmitter::TYPE_INFO:
89 {
90 ParticleEmitter* emitter = static_cast<ParticleEmitter*>(node);
91 NW_NULL_ASSERT(emitter);
92
93 emitter->Srand(particleContext->GetRandom());
94 }
95 }
96 }
97 }
98
99 void
ResolveParticleObject(ut::MoveArray<SceneNode * > * sceneNodeArray)100 ParticleUtil::ResolveParticleObject(
101 ut::MoveArray<SceneNode*>* sceneNodeArray
102 )
103 {
104 NW_NULL_ASSERT(sceneNodeArray);
105
106 NW_FOREACH(SceneNode* node, *sceneNodeArray)
107 {
108 ResSceneNode resSceneNode = node->GetResSceneNode();
109 NW_ASSERT(resSceneNode.IsValid());
110
111 switch (resSceneNode.ptr()->typeInfo)
112 {
113 case ResParticleModel::TYPE_INFO:
114 {
115 ParticleModel* model = static_cast<ParticleModel*>(node);
116 NW_NULL_ASSERT(model);
117
118 for (u32 i = 0; i < model->GetParticleSetsCount(); ++i)
119 {
120 ParticleSet* particleSet = model->GetParticleSets(i);
121 NW_NULL_ASSERT(particleSet);
122
123 ut::MoveArray<ParticleSet::Updater>* updaters =
124 particleSet->GetUpdaters();
125 NW_NULL_ASSERT(updaters);
126
127 ut::MoveArray<ParticleSet::Updater>::iterator endIter = updaters->end();
128 for (ut::MoveArray<ParticleSet::Updater>::iterator iter = updaters->begin();
129 iter != endIter;)
130 {
131 ParticleSet::Updater& updater = *iter++;
132
133 ResParticleUpdater resUpdater(updater.resource);
134 NW_ASSERT(resUpdater.IsValid());
135
136 if (resUpdater.GetTypeInfo() == ResParticleChildUpdater::TYPE_INFO)
137 {
138 ResParticleChildUpdater childUpdater =
139 ResDynamicCast<ResParticleChildUpdater>(resUpdater);
140
141 const char* particleSetPath = childUpdater.GetParticleSetPath();
142
143 ParticleSet* childParticleSet =
144 FindParticleSet(particleSetPath, sceneNodeArray);
145 if (childParticleSet != NULL)
146 {
147 updater.work = (u32)childParticleSet;
148 }
149 }
150 }
151 }
152 }
153 break;
154 case ResParticleEmitter::TYPE_INFO:
155 {
156 ParticleEmitter* emitter = static_cast<ParticleEmitter*>(node);
157 NW_NULL_ASSERT(emitter);
158
159 ResParticleEmitter resource = emitter->GetResParticleEmitter();
160 if (resource.IsValid())
161 {
162 ParticleSet* particleSet =
163 FindParticleSet(resource.GetParticleSetPath(), sceneNodeArray);
164
165 emitter->SetParticleSet(particleSet);
166 }
167 }
168 break;
169 }
170 }
171 }
172
173 bool
operator ()(const ParticleSet * lhs,const ParticleSet * rhs)174 ParticleSetCompare::operator() (
175 const ParticleSet* lhs,
176 const ParticleSet* rhs)
177 {
178 if (rhs == NULL)
179 {
180 return true;
181 }
182
183 if (lhs == NULL)
184 {
185 return false;
186 }
187
188 const ResParticleSet& lhsResource = lhs->GetResParticleSet();
189 const ResParticleSet& rhsResource = rhs->GetResParticleSet();
190 return lhsResource.GetParticleSetPriority() < rhsResource.GetParticleSetPriority();
191 }
192
193 void
GetMemorySizeForDuplicateResParticleInitializerInternal(os::MemorySizeCalculator * pSize,const ResParticleInitializer * src)194 ParticleUtil::GetMemorySizeForDuplicateResParticleInitializerInternal(
195 os::MemorySizeCalculator* pSize,
196 const ResParticleInitializer* src)
197 {
198 os::MemorySizeCalculator& size = *pSize;
199
200 int baseSize = 0;
201
202 switch (src->GetTypeInfo())
203 {
204 case ResParticleInitializer::TYPE_INFO:
205 baseSize += sizeof(ResParticleInitializerData);
206 break;
207 case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
208 baseSize += sizeof(ResParticleDirectionalVelocityInitializerData);
209 break;
210 case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
211 baseSize += sizeof(ResParticleRandomDirectionalVelocityInitializerData);
212 break;
213 case ResParticleOriginVelocityInitializer::TYPE_INFO:
214 baseSize += sizeof(ResParticleOriginVelocityInitializerData);
215 break;
216 case ResParticleRandomVelocityInitializer::TYPE_INFO:
217 baseSize += sizeof(ResParticleRandomVelocityInitializerData);
218 break;
219 case ResParticleYAxisVelocityInitializer::TYPE_INFO:
220 baseSize += sizeof(ResParticleYAxisVelocityInitializerData);
221 break;
222 case ResParticleVector3ImmediateInitializer::TYPE_INFO:
223 baseSize += sizeof(ResParticleVector3ImmediateInitializerData);
224 break;
225 case ResParticleFloatRandomInitializer::TYPE_INFO:
226 baseSize += sizeof(ResParticleFloatRandomInitializerData);
227 break;
228 case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
229 baseSize += sizeof(ResParticleFloatRangeRandomInitializerData);
230 break;
231 case ResParticleFloatImmediateInitializer::TYPE_INFO:
232 baseSize += sizeof(ResParticleFloatImmediateInitializerData);
233 break;
234 case ResParticleVector2ImmediateInitializer::TYPE_INFO:
235 baseSize += sizeof(ResParticleVector2ImmediateInitializerData);
236 break;
237 case ResParticleVector3Random1Initializer::TYPE_INFO:
238 baseSize += sizeof(ResParticleVector3Random1InitializerData);
239 break;
240 case ResParticleVector3Random3Initializer::TYPE_INFO:
241 baseSize += sizeof(ResParticleVector3Random3InitializerData);
242 break;
243 case ResParticleVector3MultRandomInitializer::TYPE_INFO:
244 baseSize += sizeof(ResParticleVector3MultRandomInitializerData);
245 break;
246 default:
247 NW_FATAL_ERROR("unknown initializer type");
248 }
249
250 size.Add(baseSize, 4);
251 }
252
253 ResParticleInitializerData*
DuplicateResParticleInitializer(const ResParticleInitializer * src,os::IAllocator * allocator)254 ParticleUtil::DuplicateResParticleInitializer(
255 const ResParticleInitializer* src,
256 os::IAllocator* allocator
257 )
258 {
259 NW_NULL_ASSERT(src);
260 NW_NULL_ASSERT(allocator);
261
262 int baseSize = 0;
263 int size = 0;
264
265 switch (src->GetTypeInfo())
266 {
267 case ResParticleInitializer::TYPE_INFO:
268 baseSize += sizeof(ResParticleInitializerData);
269 break;
270 case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
271 baseSize += sizeof(ResParticleDirectionalVelocityInitializerData);
272 break;
273 case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
274 baseSize += sizeof(ResParticleRandomDirectionalVelocityInitializerData);
275 break;
276 case ResParticleOriginVelocityInitializer::TYPE_INFO:
277 baseSize += sizeof(ResParticleOriginVelocityInitializerData);
278 break;
279 case ResParticleRandomVelocityInitializer::TYPE_INFO:
280 baseSize += sizeof(ResParticleRandomVelocityInitializerData);
281 break;
282 case ResParticleYAxisVelocityInitializer::TYPE_INFO:
283 baseSize += sizeof(ResParticleYAxisVelocityInitializerData);
284 break;
285 case ResParticleVector3ImmediateInitializer::TYPE_INFO:
286 baseSize += sizeof(ResParticleVector3ImmediateInitializerData);
287 break;
288 case ResParticleFloatRandomInitializer::TYPE_INFO:
289 baseSize += sizeof(ResParticleFloatRandomInitializerData);
290 break;
291 case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
292 baseSize += sizeof(ResParticleFloatRangeRandomInitializerData);
293 break;
294 case ResParticleFloatImmediateInitializer::TYPE_INFO:
295 baseSize += sizeof(ResParticleFloatImmediateInitializerData);
296 break;
297 case ResParticleVector2ImmediateInitializer::TYPE_INFO:
298 baseSize += sizeof(ResParticleVector2ImmediateInitializerData);
299 break;
300 case ResParticleVector3Random1Initializer::TYPE_INFO:
301 baseSize += sizeof(ResParticleVector3Random1InitializerData);
302 break;
303 case ResParticleVector3Random3Initializer::TYPE_INFO:
304 baseSize += sizeof(ResParticleVector3Random3InitializerData);
305 break;
306 case ResParticleVector3MultRandomInitializer::TYPE_INFO:
307 baseSize += sizeof(ResParticleVector3MultRandomInitializerData);
308 break;
309 default:
310 NW_FATAL_ERROR("unknown initializer type");
311 }
312
313 size += ut::RoundUp(baseSize, 4);
314
315 void* memory = allocator->Alloc(size, 4);
316 if (memory == NULL)
317 {
318 return NULL;
319 }
320
321 {
322 u8* dstPtr = (u8*)memory;
323
324 ResParticleInitializerData* dstData =
325 reinterpret_cast<ResParticleInitializerData*>(dstPtr);
326 const ResParticleInitializerData* srcData = src->ptr();
327
328 ::std::memcpy(dstPtr, srcData, baseSize);
329 dstPtr += ut::RoundUp(baseSize, 4);
330 }
331
332 switch (src->GetTypeInfo())
333 {
334 case ResParticleInitializer::TYPE_INFO:
335 case ResParticleDirectionalVelocityInitializer::TYPE_INFO:
336 case ResParticleRandomDirectionalVelocityInitializer::TYPE_INFO:
337 case ResParticleOriginVelocityInitializer::TYPE_INFO:
338 case ResParticleRandomVelocityInitializer::TYPE_INFO:
339 case ResParticleYAxisVelocityInitializer::TYPE_INFO:
340 case ResParticleVector3ImmediateInitializer::TYPE_INFO:
341 case ResParticleFloatRandomInitializer::TYPE_INFO:
342 case ResParticleFloatRangeRandomInitializer::TYPE_INFO:
343 case ResParticleFloatImmediateInitializer::TYPE_INFO:
344 case ResParticleVector2ImmediateInitializer::TYPE_INFO:
345 case ResParticleVector3Random1Initializer::TYPE_INFO:
346 case ResParticleVector3Random3Initializer::TYPE_INFO:
347 case ResParticleVector3MultRandomInitializer::TYPE_INFO:
348 // PRIMITIVEしかないので何もしなくてよい
349 break;
350 default:
351 NW_FATAL_ERROR("unknown initializer type");
352 }
353
354 return reinterpret_cast<ResParticleInitializerData*>(memory);
355 }
356
357 void
GetMemorySizeForDuplicateResParticleUpdaterInternal(os::MemorySizeCalculator * pSize,const ResParticleUpdater * src)358 ParticleUtil::GetMemorySizeForDuplicateResParticleUpdaterInternal(
359 os::MemorySizeCalculator* pSize,
360 const ResParticleUpdater* src)
361 {
362 int baseSize = 0;
363 os::MemorySizeCalculator& size = *pSize;
364 int childStrSize = 0;
365 int childFormSize = 0;
366 int childOptionSize = 0;
367
368 switch (src->GetTypeInfo())
369 {
370 case ResParticleUpdater::TYPE_INFO:
371 baseSize = sizeof(ResParticleUpdaterData);
372 break;
373 case ResParticleAccelarationUpdater::TYPE_INFO:
374 baseSize = sizeof(ResParticleAccelarationUpdaterData);
375 break;
376 case ResParticleGeneralUpdater::TYPE_INFO:
377 baseSize = sizeof(ResParticleGeneralUpdaterData);
378 break;
379 case ResParticleGravityUpdater::TYPE_INFO:
380 baseSize = sizeof(ResParticleGravityUpdaterData);
381 break;
382 case ResParticleSpinUpdater::TYPE_INFO:
383 baseSize = sizeof(ResParticleSpinUpdaterData);
384 break;
385 case ResParticleRandomUpdater::TYPE_INFO:
386 baseSize = sizeof(ResParticleRandomUpdaterData);
387 break;
388 case ResParticleChildUpdater::TYPE_INFO:
389 baseSize = sizeof(ResParticleChildUpdaterData);
390 {
391 const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
392 NW_ASSERT(child.IsValid());
393
394 childStrSize = strlen(child.GetParticleSetPath()) + 1;
395
396 const ResParticleForm& form = child.GetParticleForm();
397 const ResParticleChildUpdaterOption& option = child.GetTiming();
398
399 if (form.IsValid())
400 {
401 switch (form.GetTypeInfo())
402 {
403 case ResParticleForm::TYPE_INFO:
404 childFormSize = sizeof(ResParticleFormData);
405 break;
406 case ResParticleCubeForm::TYPE_INFO:
407 childFormSize = sizeof(ResParticleCubeFormData);
408 break;
409 case ResParticleCylinderForm::TYPE_INFO:
410 childFormSize = sizeof(ResParticleCylinderFormData);
411 break;
412 case ResParticleDiscForm::TYPE_INFO:
413 childFormSize = sizeof(ResParticleDiscFormData);
414 break;
415 case ResParticlePointForm::TYPE_INFO:
416 childFormSize = sizeof(ResParticlePointFormData);
417 break;
418 case ResParticleRectangleForm::TYPE_INFO:
419 childFormSize = sizeof(ResParticleRectangleFormData);
420 break;
421 case ResParticleSphereForm::TYPE_INFO:
422 childFormSize = sizeof(ResParticleSphereFormData);
423 break;
424 default:
425 NW_FATAL_ERROR("unknown form type");
426 }
427 }
428
429 if (option.IsValid())
430 {
431 switch (option.GetTypeInfo())
432 {
433 case ResParticleChildUpdaterFinalUpdateOption::TYPE_INFO:
434 childOptionSize = sizeof(ResParticleChildUpdaterFinalUpdateOptionData);
435 break;
436 case ResParticleChildUpdaterFirstUpdateOption::TYPE_INFO:
437 childOptionSize = sizeof(ResParticleChildUpdaterFirstUpdateOptionData);
438 break;
439 case ResParticleChildUpdaterIntervalOption::TYPE_INFO:
440 childOptionSize = sizeof(ResParticleChildUpdaterIntervalOptionData);
441 break;
442 default:
443 NW_FATAL_ERROR("unknown updateOption type");
444 }
445 }
446 }
447 break;
448 case ResParticleUserUpdater::TYPE_INFO:
449 baseSize = sizeof(ResParticleUserUpdaterData);
450 break;
451 case ResParticleVector2ImmediateUpdater::TYPE_INFO:
452 baseSize = sizeof(ResParticleVector2ImmediateUpdaterData);
453 break;
454 case ResParticleVector3Updater::TYPE_INFO:
455 baseSize = sizeof(ResParticleVector3UpdaterData);
456 break;
457 case ResParticleFloatUpdater::TYPE_INFO:
458 baseSize = sizeof(ResParticleFloatUpdaterData);
459 break;
460 case ResParticleRotateUpVectorUpdater::TYPE_INFO:
461 baseSize = sizeof(ResParticleRotateUpVectorUpdaterData);
462 break;
463 case ResParticleTexturePatternUpdater::TYPE_INFO:
464 baseSize = sizeof(ResParticleTexturePatternUpdaterData);
465 break;
466 case ResParticleVector3ImmediateUpdater::TYPE_INFO:
467 baseSize = sizeof(ResParticleVector3ImmediateUpdaterData);
468 break;
469 case ResParticleVector3AdditiveUpdater::TYPE_INFO:
470 baseSize = sizeof(ResParticleVector3AdditiveUpdaterData);
471 break;
472 case ResParticleVector3RandomAdditiveUpdater::TYPE_INFO:
473 baseSize = sizeof(ResParticleVector3RandomAdditiveUpdaterData);
474 break;
475 case ResParticleFloatImmediateUpdater::TYPE_INFO:
476 baseSize = sizeof(ResParticleFloatImmediateUpdaterData);
477 break;
478 default:
479 NW_FATAL_ERROR("unknown updater type");
480 break;
481 }
482
483 // アニメーションのサイズ計算
484 int animationSize = 0;
485 int enabledSize = 0;
486 int dataSize = 0;
487 int animationOptionSize = 0;
488 {
489 const ResParticleAnimation& resAnimation = src->GetParticleAnimation();
490 if (resAnimation.IsValid())
491 {
492 animationSize += sizeof(ResParticleAnimationData);
493
494 enabledSize = resAnimation.GetAnimationEnabledCount() * sizeof(bool);
495 dataSize = resAnimation.GetAnimationDataCount() * sizeof(s32);
496
497 const ResParticleAnimationOption& option =
498 resAnimation.GetParticleAnimationOption();
499 if (option.IsValid())
500 {
501 switch (option.GetTypeInfo())
502 {
503 case ResParticleAnimationOption::TYPE_INFO:
504 animationOptionSize = sizeof(ResParticleAnimationOptionData);
505 break;
506 case ResParticleFittingAnimationOption::TYPE_INFO:
507 animationOptionSize = sizeof(ResParticleFittingAnimationOptionData);
508 break;
509 case ResParticleFrameLoopAnimationOption::TYPE_INFO:
510 animationOptionSize = sizeof(ResParticleFrameLoopAnimationOptionData);
511 break;
512 case ResParticleRandomAnimationOption::TYPE_INFO:
513 animationOptionSize = sizeof(ResParticleRandomAnimationOptionData);
514 break;
515 default:
516 NW_FATAL_ERROR("unknown animationOption type");
517 }
518 }
519
520 animationSize +=
521 resAnimation.GetAnimationEnabledCount() * sizeof(u32);
522 animationSize +=
523 resAnimation.GetAnimationDataCount() * sizeof(u32);
524 }
525 }
526
527 size.Add(baseSize, 4);
528 size.Add(animationSize, 4);
529 size.Add(enabledSize, 4);
530 size.Add(dataSize, 4);
531 size.Add(animationOptionSize, 4);
532 size.Add(childStrSize, 4);
533 size.Add(childFormSize, 4);
534 size.Add(childOptionSize, 4);
535 }
536
537 ResParticleUpdaterData*
DuplicateResParticleUpdater(const ResParticleUpdater * src,os::IAllocator * allocator)538 ParticleUtil::DuplicateResParticleUpdater(
539 const ResParticleUpdater* src,
540 os::IAllocator* allocator
541 )
542 {
543 NW_NULL_ASSERT(src);
544 NW_NULL_ASSERT(allocator);
545
546 int baseSize = 0;
547 int size = 0;
548 int childStrSize = 0;
549 int childFormSize = 0;
550 int childOptionSize = 0;
551
552 switch (src->GetTypeInfo())
553 {
554 case ResParticleUpdater::TYPE_INFO:
555 baseSize = sizeof(ResParticleUpdaterData);
556 break;
557 case ResParticleAccelarationUpdater::TYPE_INFO:
558 baseSize = sizeof(ResParticleAccelarationUpdaterData);
559 break;
560 case ResParticleGeneralUpdater::TYPE_INFO:
561 baseSize = sizeof(ResParticleGeneralUpdaterData);
562 break;
563 case ResParticleGravityUpdater::TYPE_INFO:
564 baseSize = sizeof(ResParticleGravityUpdaterData);
565 break;
566 case ResParticleSpinUpdater::TYPE_INFO:
567 baseSize = sizeof(ResParticleSpinUpdaterData);
568 break;
569 case ResParticleRandomUpdater::TYPE_INFO:
570 baseSize = sizeof(ResParticleRandomUpdaterData);
571 break;
572 case ResParticleChildUpdater::TYPE_INFO:
573 baseSize = sizeof(ResParticleChildUpdaterData);
574 {
575 const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
576 NW_ASSERT(child.IsValid());
577
578 childStrSize = strlen(child.GetParticleSetPath()) + 1;
579
580 const ResParticleForm& form = child.GetParticleForm();
581 const ResParticleChildUpdaterOption& option = child.GetTiming();
582
583 if (form.IsValid())
584 {
585 switch (form.GetTypeInfo())
586 {
587 case ResParticleForm::TYPE_INFO:
588 childFormSize = sizeof(ResParticleFormData);
589 break;
590 case ResParticleCubeForm::TYPE_INFO:
591 childFormSize = sizeof(ResParticleCubeFormData);
592 break;
593 case ResParticleCylinderForm::TYPE_INFO:
594 childFormSize = sizeof(ResParticleCylinderFormData);
595 break;
596 case ResParticleDiscForm::TYPE_INFO:
597 childFormSize = sizeof(ResParticleDiscFormData);
598 break;
599 case ResParticlePointForm::TYPE_INFO:
600 childFormSize = sizeof(ResParticlePointFormData);
601 break;
602 case ResParticleRectangleForm::TYPE_INFO:
603 childFormSize = sizeof(ResParticleRectangleFormData);
604 break;
605 case ResParticleSphereForm::TYPE_INFO:
606 childFormSize = sizeof(ResParticleSphereFormData);
607 break;
608 default:
609 NW_FATAL_ERROR("unknown form type");
610 }
611 }
612
613 if (option.IsValid())
614 {
615 switch (option.GetTypeInfo())
616 {
617 case ResParticleChildUpdaterFinalUpdateOption::TYPE_INFO:
618 childOptionSize = sizeof(ResParticleChildUpdaterFinalUpdateOptionData);
619 break;
620 case ResParticleChildUpdaterFirstUpdateOption::TYPE_INFO:
621 childOptionSize = sizeof(ResParticleChildUpdaterFirstUpdateOptionData);
622 break;
623 case ResParticleChildUpdaterIntervalOption::TYPE_INFO:
624 childOptionSize = sizeof(ResParticleChildUpdaterIntervalOptionData);
625 break;
626 default:
627 NW_FATAL_ERROR("unknown updateOption type");
628 }
629 }
630 }
631 break;
632 case ResParticleUserUpdater::TYPE_INFO:
633 baseSize = sizeof(ResParticleUserUpdaterData);
634 break;
635 case ResParticleVector2ImmediateUpdater::TYPE_INFO:
636 baseSize = sizeof(ResParticleVector2ImmediateUpdaterData);
637 break;
638 case ResParticleVector3Updater::TYPE_INFO:
639 baseSize = sizeof(ResParticleVector3UpdaterData);
640 break;
641 case ResParticleFloatUpdater::TYPE_INFO:
642 baseSize = sizeof(ResParticleFloatUpdaterData);
643 break;
644 case ResParticleRotateUpVectorUpdater::TYPE_INFO:
645 baseSize = sizeof(ResParticleRotateUpVectorUpdaterData);
646 break;
647 case ResParticleTexturePatternUpdater::TYPE_INFO:
648 baseSize = sizeof(ResParticleTexturePatternUpdaterData);
649 break;
650 case ResParticleVector3ImmediateUpdater::TYPE_INFO:
651 baseSize = sizeof(ResParticleVector3ImmediateUpdaterData);
652 break;
653 case ResParticleVector3AdditiveUpdater::TYPE_INFO:
654 baseSize = sizeof(ResParticleVector3AdditiveUpdaterData);
655 break;
656 case ResParticleVector3RandomAdditiveUpdater::TYPE_INFO:
657 baseSize = sizeof(ResParticleVector3RandomAdditiveUpdaterData);
658 break;
659 case ResParticleFloatImmediateUpdater::TYPE_INFO:
660 baseSize = sizeof(ResParticleFloatImmediateUpdaterData);
661 break;
662 default:
663 NW_FATAL_ERROR("unknown updater type");
664 break;
665 }
666
667 // アニメーションのサイズ計算
668 int animationSize = 0;
669 int enabledSize = 0;
670 int dataSize = 0;
671 int animationOptionSize = 0;
672 {
673 const ResParticleAnimation& resAnimation = src->GetParticleAnimation();
674 if (resAnimation.IsValid())
675 {
676 animationSize += sizeof(ResParticleAnimationData);
677
678 enabledSize = resAnimation.GetAnimationEnabledCount() * sizeof(bool);
679 dataSize = resAnimation.GetAnimationDataCount() * sizeof(s32);
680
681 const ResParticleAnimationOption& option =
682 resAnimation.GetParticleAnimationOption();
683 if (option.IsValid())
684 {
685 switch (option.GetTypeInfo())
686 {
687 case ResParticleAnimationOption::TYPE_INFO:
688 animationOptionSize = sizeof(ResParticleAnimationOptionData);
689 break;
690 case ResParticleFittingAnimationOption::TYPE_INFO:
691 animationOptionSize = sizeof(ResParticleFittingAnimationOptionData);
692 break;
693 case ResParticleFrameLoopAnimationOption::TYPE_INFO:
694 animationOptionSize = sizeof(ResParticleFrameLoopAnimationOptionData);
695 break;
696 case ResParticleRandomAnimationOption::TYPE_INFO:
697 animationOptionSize = sizeof(ResParticleRandomAnimationOptionData);
698 break;
699 default:
700 NW_FATAL_ERROR("unknown animationOption type");
701 }
702 }
703
704 animationSize +=
705 resAnimation.GetAnimationEnabledCount() * sizeof(u32);
706 animationSize +=
707 resAnimation.GetAnimationDataCount() * sizeof(u32);
708 }
709 }
710
711 size += ut::RoundUp(baseSize, 4);
712 size += ut::RoundUp(animationSize, 4);
713 size += ut::RoundUp(enabledSize, 4);
714 size += ut::RoundUp(dataSize, 4);
715 size += ut::RoundUp(animationOptionSize, 4);
716 size += ut::RoundUp(childStrSize, 4);
717 size += ut::RoundUp(childFormSize, 4);
718 size += ut::RoundUp(childOptionSize, 4);
719
720 void* memory = allocator->Alloc(size, 4);
721 if (memory == NULL)
722 {
723 return NULL;
724 }
725
726 u8* dstPtr = (u8*)memory;
727
728 ResParticleUpdaterData* dstData =
729 reinterpret_cast<ResParticleUpdaterData*>(dstPtr);
730
731 {
732 const ResParticleUpdaterData* srcData = src->ptr();
733 ::std::memcpy(dstPtr, srcData, baseSize);
734 dstPtr += ut::RoundUp(baseSize, 4);
735 }
736
737 if (animationSize != 0)
738 {
739 const ResParticleAnimation& animation = src->GetParticleAnimation();
740
741 ResParticleAnimationData* dstAnimation =
742 reinterpret_cast<ResParticleAnimationData*>(dstPtr);
743
744 ::std::memcpy(
745 dstPtr,
746 animation.ptr(),
747 animationSize);
748 dstData->toParticleAnimation.set_ptr(dstPtr);
749 dstPtr += ut::RoundUp(animationSize, 4);
750
751 if (enabledSize > 0)
752 {
753 ::std::memcpy(
754 dstPtr,
755 animation.GetAnimationEnabled(),
756 enabledSize);
757 dstAnimation->toAnimationEnabledTable.set_ptr(dstPtr);
758 dstPtr += ut::RoundUp(enabledSize, 4);
759 }
760
761 if (dataSize > 0)
762 {
763 ::std::memcpy(
764 dstPtr,
765 animation.GetAnimationData(),
766 dataSize);
767 dstAnimation->toAnimationDataTable.set_ptr(dstPtr);
768 dstPtr += ut::RoundUp(dataSize, 4);
769 }
770
771 if (animationOptionSize != 0)
772 {
773 const ResParticleAnimationOption& option = animation.GetParticleAnimationOption();
774
775 ::std::memcpy(
776 dstPtr,
777 option.ptr(),
778 animationOptionSize);
779 dstAnimation->toParticleAnimationOption.set_ptr(dstPtr);
780 dstPtr += ut::RoundUp(animationOptionSize, 4);
781 }
782 }
783
784 switch (src->GetTypeInfo())
785 {
786 case ResParticleChildUpdater::TYPE_INFO:
787 {
788 ResParticleChildUpdaterData* childData =
789 reinterpret_cast<ResParticleChildUpdaterData*>(memory);
790
791 const ResParticleChildUpdater& child = ResDynamicCast<ResParticleChildUpdater>(*src);
792
793 if (childStrSize > 0)
794 {
795 const char* str = child.GetParticleSetPath();
796
797 ::std::memcpy(
798 dstPtr,
799 str,
800 childStrSize);
801 childData->toParticleSetPath.set_ptr((const char*)dstPtr);
802 dstPtr += ut::RoundUp(childStrSize, 4);
803 }
804
805 if (childFormSize > 0)
806 {
807 const ResParticleForm& form = child.GetParticleForm();
808
809 ::std::memcpy(
810 dstPtr,
811 form.ptr(),
812 childFormSize);
813 childData->toParticleForm.set_ptr(dstPtr);
814 dstPtr += ut::RoundUp(childFormSize, 4);
815 }
816
817 if (childOptionSize > 0)
818 {
819 const ResParticleChildUpdaterOption& option = child.GetTiming();
820
821 ::std::memcpy(
822 dstPtr,
823 option.ptr(),
824 childOptionSize);
825 childData->toTiming.set_ptr(dstPtr);
826 dstPtr += ut::RoundUp(childOptionSize, 4);
827 }
828 }
829 break;
830 }
831
832 return reinterpret_cast<ResParticleUpdaterData*>(memory);
833 }
834
835 } // namespace gfx
836 } // namespace nw
837