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