mirror of
https://github.com/pret/pokeplatinum.git
synced 2026-03-21 17:55:13 -05:00
748 lines
21 KiB
C
748 lines
21 KiB
C
#include "particle_system.h"
|
|
|
|
#include <nitro.h>
|
|
#include <nitro/fx/fx_trig.h>
|
|
#include <string.h>
|
|
|
|
#include "camera.h"
|
|
#include "fx_util.h"
|
|
#include "heap.h"
|
|
#include "narc.h"
|
|
#include "spl_behavior.h"
|
|
#include "spl_manager.h"
|
|
#include "sys_task.h"
|
|
#include "sys_task_manager.h"
|
|
|
|
#define FIXED_POLYGON_ID 5
|
|
#define MIN_POLYGON_ID 6
|
|
#define MAX_POLYGON_ID 63
|
|
|
|
enum SPLBehaviorType {
|
|
SPL_BEHAVIOR_GRAVITY = 0,
|
|
SPL_BEHAVIOR_RANDOM,
|
|
SPL_BEHAVIOR_MAGNET,
|
|
SPL_BEHAVIOR_SPIN,
|
|
SPL_BEHAVIOR_COLLISION_PLANE,
|
|
SPL_BEHAVIOR_CONVERGENCE,
|
|
};
|
|
|
|
static void *sParticleSystems[MAX_PARTICLE_SYSTEMS];
|
|
|
|
// Current callback parameter for the emitter creation callback.
|
|
static void *sEmitterCallbackParam;
|
|
|
|
// Particle system whose resources are currently being uploaded to VRAM.
|
|
// Used so custom Texture/Palette allocators can save the resources.
|
|
// See ParticleSystem_Register*Key
|
|
static ParticleSystem *sUploadingParticleSystem;
|
|
|
|
static const VecFx32 sParticleSystemDefaultCameraPos = VEC_FX32(0, 0, 4);
|
|
static const VecFx32 sParticleSystemDefaultCameraUp = VEC_FX32(0, 1, 0);
|
|
static const VecFx32 sParticleSystemDefaultCameraTarget = VEC_FX32(0, 0, 0);
|
|
|
|
static void *ParticleSystem00_AllocMemory(u32 size);
|
|
static void *ParticleSystem01_AllocMemory(u32 size);
|
|
static void *ParticleSystem02_AllocMemory(u32 size);
|
|
static void *ParticleSystem03_AllocMemory(u32 size);
|
|
static void *ParticleSystem04_AllocMemory(u32 size);
|
|
static void *ParticleSystem05_AllocMemory(u32 size);
|
|
static void *ParticleSystem06_AllocMemory(u32 size);
|
|
static void *ParticleSystem07_AllocMemory(u32 size);
|
|
static void *ParticleSystem08_AllocMemory(u32 size);
|
|
static void *ParticleSystem09_AllocMemory(u32 size);
|
|
static void *ParticleSystem10_AllocMemory(u32 size);
|
|
static void *ParticleSystem11_AllocMemory(u32 size);
|
|
static void *ParticleSystem12_AllocMemory(u32 size);
|
|
static void *ParticleSystem13_AllocMemory(u32 size);
|
|
static void *ParticleSystem14_AllocMemory(u32 size);
|
|
static void *ParticleSystem15_AllocMemory(u32 size);
|
|
static inline void *ParticleSystem_AllocMemory(ParticleSystem *particleSystem, u32 size);
|
|
static void ParticleSystem_UploadResourcesInternal(ParticleSystem *particleSystem);
|
|
static void ParticleSystem_VBlankResourceUploadInternal(SysTask *task, void *param);
|
|
|
|
static const SPLAllocFunc sParticleSystemAllocFuncs[] = {
|
|
ParticleSystem00_AllocMemory,
|
|
ParticleSystem01_AllocMemory,
|
|
ParticleSystem02_AllocMemory,
|
|
ParticleSystem03_AllocMemory,
|
|
ParticleSystem04_AllocMemory,
|
|
ParticleSystem05_AllocMemory,
|
|
ParticleSystem06_AllocMemory,
|
|
ParticleSystem07_AllocMemory,
|
|
ParticleSystem08_AllocMemory,
|
|
ParticleSystem09_AllocMemory,
|
|
ParticleSystem10_AllocMemory,
|
|
ParticleSystem11_AllocMemory,
|
|
ParticleSystem12_AllocMemory,
|
|
ParticleSystem13_AllocMemory,
|
|
ParticleSystem14_AllocMemory,
|
|
ParticleSystem15_AllocMemory,
|
|
};
|
|
|
|
void ParticleSystem_ZeroAll(void)
|
|
{
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
sParticleSystems[i] = NULL;
|
|
}
|
|
}
|
|
|
|
ParticleSystem *ParticleSystem_New(SPLTexVRAMAllocFunc texAllocFunc, SPLPalVRAMAllocFunc palAllocFunc, void *heap, int heapSize, BOOL hasCamera, enum HeapID heapID)
|
|
{
|
|
ParticleSystem *particleSystem;
|
|
int id;
|
|
|
|
for (id = 0; id < MAX_PARTICLE_SYSTEMS; id++) {
|
|
if (sParticleSystems[id] == NULL) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (id >= MAX_PARTICLE_SYSTEMS) {
|
|
return NULL;
|
|
}
|
|
|
|
particleSystem = Heap_Alloc(heapID, sizeof(ParticleSystem));
|
|
if (particleSystem == NULL) {
|
|
GF_ASSERT(FALSE);
|
|
}
|
|
|
|
memset(particleSystem, 0, sizeof(ParticleSystem));
|
|
|
|
particleSystem->texAllocFunc = texAllocFunc;
|
|
particleSystem->palAllocFunc = palAllocFunc;
|
|
|
|
particleSystem->cameraPos = sParticleSystemDefaultCameraPos;
|
|
particleSystem->cameraUp = sParticleSystemDefaultCameraUp;
|
|
particleSystem->cameraTarget = sParticleSystemDefaultCameraTarget;
|
|
|
|
memset(heap, 0, heapSize);
|
|
particleSystem->heapStart = heap;
|
|
particleSystem->heap = heap;
|
|
particleSystem->heapEnd = (void *)((u32)heap + heapSize);
|
|
particleSystem->id = id;
|
|
sParticleSystems[id] = particleSystem;
|
|
|
|
if (hasCamera == TRUE) {
|
|
particleSystem->camera = Camera_Alloc(heapID);
|
|
|
|
VEC_Set(&particleSystem->unused1, 0, 0, 0);
|
|
particleSystem->cameraFov = FX_DEG_TO_IDX(FX32_CONST(45.0f));
|
|
|
|
Camera_InitWithTargetAndPosition(
|
|
&sParticleSystemDefaultCameraTarget,
|
|
&sParticleSystemDefaultCameraPos,
|
|
particleSystem->cameraFov,
|
|
CAMERA_PROJECTION_PERSPECTIVE,
|
|
FALSE,
|
|
particleSystem->camera);
|
|
|
|
particleSystem->cameraProjection = CAMERA_PROJECTION_PERSPECTIVE;
|
|
Camera_SetAsActive(particleSystem->camera);
|
|
}
|
|
|
|
particleSystem->manager = SPLManager_New(
|
|
sParticleSystemAllocFuncs[id],
|
|
MAX_EMITTERS,
|
|
MAX_PARTICLES,
|
|
FIXED_POLYGON_ID,
|
|
MIN_POLYGON_ID,
|
|
MAX_POLYGON_ID);
|
|
|
|
ParticleSystem_SetCameraUp(particleSystem, &sParticleSystemDefaultCameraUp);
|
|
|
|
return particleSystem;
|
|
}
|
|
|
|
void ParticleSystem_Free(ParticleSystem *particleSystem)
|
|
{
|
|
ParticleSystem_DeleteAllEmitters(particleSystem);
|
|
|
|
if (particleSystem->vramAutoRelease & VRAM_AUTO_RELEASE_TEXTURE_FRM) {
|
|
NNS_GfdSetFrmTexVramState(&particleSystem->textureVRAMState);
|
|
} else if (particleSystem->vramAutoRelease & VRAM_AUTO_RELEASE_TEXTURE_LNK) {
|
|
for (int i = 0; i < MAX_TEXTURE_KEYS; i++) {
|
|
if (particleSystem->textureKeys[i] != NNS_GFD_ALLOC_ERROR_TEXKEY) {
|
|
NNS_GfdFreeLnkTexVram(particleSystem->textureKeys[i]);
|
|
particleSystem->textureKeys[i] = NNS_GFD_ALLOC_ERROR_TEXKEY;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (particleSystem->vramAutoRelease & (1 << 2)) {
|
|
NNS_GfdSetFrmPlttVramState(&particleSystem->paletteVRAMState);
|
|
} else if (particleSystem->vramAutoRelease & (1 << 3)) {
|
|
for (int i = 0; i < MAX_PALETTE_KEYS; i++) {
|
|
if (particleSystem->paletteKeys[i] != NNS_GFD_ALLOC_ERROR_PLTTKEY) {
|
|
NNS_GfdFreeLnkPlttVram(particleSystem->paletteKeys[i]);
|
|
particleSystem->paletteKeys[i] = NNS_GFD_ALLOC_ERROR_PLTTKEY;
|
|
}
|
|
}
|
|
}
|
|
|
|
particleSystem->vramAutoRelease = VRAM_AUTO_RELEASE_NONE;
|
|
particleSystem->lastAddedEmitter = NULL;
|
|
|
|
if (particleSystem->resource != NULL) {
|
|
Heap_Free(particleSystem->resource);
|
|
particleSystem->resource = NULL;
|
|
}
|
|
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
if (sParticleSystems[i] == particleSystem) {
|
|
sParticleSystems[i] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (particleSystem->camera != NULL) {
|
|
Camera_Delete(particleSystem->camera);
|
|
}
|
|
|
|
Heap_Free(particleSystem);
|
|
}
|
|
|
|
void ParticleSystem_FreeAll(void)
|
|
{
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
if (sParticleSystems[i] != NULL) {
|
|
ParticleSystem_Free(sParticleSystems[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
static inline void *ParticleSystem_AllocMemory(ParticleSystem *particleSystem, u32 size)
|
|
{
|
|
void *allocated = particleSystem->heap;
|
|
|
|
u32 newHeapPos = (u32)particleSystem->heap + size;
|
|
u32 offset = newHeapPos % 4;
|
|
if (offset > 0) {
|
|
newHeapPos += 4 - offset;
|
|
}
|
|
|
|
particleSystem->heap = (void *)newHeapPos;
|
|
if (particleSystem->heap >= particleSystem->heapEnd) {
|
|
GF_ASSERT(FALSE);
|
|
}
|
|
|
|
return allocated;
|
|
}
|
|
|
|
static void *ParticleSystem00_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[0], size);
|
|
}
|
|
|
|
static void *ParticleSystem01_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[1], size);
|
|
}
|
|
|
|
static void *ParticleSystem02_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[2], size);
|
|
}
|
|
|
|
static void *ParticleSystem03_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[3], size);
|
|
}
|
|
|
|
static void *ParticleSystem04_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[4], size);
|
|
}
|
|
|
|
static void *ParticleSystem05_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[5], size);
|
|
}
|
|
|
|
static void *ParticleSystem06_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[6], size);
|
|
}
|
|
|
|
static void *ParticleSystem07_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[7], size);
|
|
}
|
|
|
|
static void *ParticleSystem08_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[8], size);
|
|
}
|
|
|
|
static void *ParticleSystem09_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[9], size);
|
|
}
|
|
|
|
static void *ParticleSystem10_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[10], size);
|
|
}
|
|
|
|
static void *ParticleSystem11_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[11], size);
|
|
}
|
|
|
|
static void *ParticleSystem12_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[12], size);
|
|
}
|
|
|
|
static void *ParticleSystem13_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[13], size);
|
|
}
|
|
|
|
static void *ParticleSystem14_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[14], size);
|
|
}
|
|
|
|
static void *ParticleSystem15_AllocMemory(u32 size)
|
|
{
|
|
return ParticleSystem_AllocMemory(sParticleSystems[15], size);
|
|
}
|
|
|
|
void *ParticleSystem_LoadResourceFromNARC(enum NarcID narcID, int memberIndex, enum HeapID heapID)
|
|
{
|
|
return NARC_AllocAndReadWholeMemberByIndexPair(narcID, memberIndex, heapID);
|
|
}
|
|
|
|
void ParticleSystem_SetResource(ParticleSystem *particleSystem, void *resource, enum VRAMAutoRelease autoRelease, BOOL uploadImmediately)
|
|
{
|
|
GF_ASSERT(particleSystem->manager != NULL);
|
|
GF_ASSERT(particleSystem->resource == NULL);
|
|
|
|
particleSystem->vramAutoRelease = autoRelease;
|
|
|
|
if (autoRelease & VRAM_AUTO_RELEASE_TEXTURE_FRM) {
|
|
NNS_GfdGetFrmTexVramState(&particleSystem->textureVRAMState);
|
|
} else if (autoRelease & VRAM_AUTO_RELEASE_TEXTURE_LNK) {
|
|
for (int i = 0; i < MAX_TEXTURE_KEYS; i++) {
|
|
particleSystem->textureKeys[i] = NNS_GFD_ALLOC_ERROR_TEXKEY;
|
|
}
|
|
}
|
|
|
|
if (autoRelease & VRAM_AUTO_RELEASE_PALETTE_FRM) {
|
|
NNS_GfdGetFrmPlttVramState(&particleSystem->paletteVRAMState);
|
|
} else if (autoRelease & VRAM_AUTO_RELEASE_PALETTE_LNK) {
|
|
for (int i = 0; i < MAX_PALETTE_KEYS; i++) {
|
|
particleSystem->paletteKeys[i] = NNS_GFD_ALLOC_ERROR_PLTTKEY;
|
|
}
|
|
}
|
|
|
|
particleSystem->resource = resource;
|
|
|
|
if (uploadImmediately == TRUE) {
|
|
ParticleSystem_UploadResourcesInternal(particleSystem);
|
|
} else {
|
|
SysTask_ExecuteAfterVBlank(ParticleSystem_VBlankResourceUploadInternal, particleSystem, 5);
|
|
}
|
|
}
|
|
|
|
static void ParticleSystem_UploadResourcesInternal(ParticleSystem *particleSystem)
|
|
{
|
|
SPLManager_LoadResources(particleSystem->manager, particleSystem->resource);
|
|
|
|
sUploadingParticleSystem = particleSystem;
|
|
|
|
if (particleSystem->texAllocFunc == NULL) {
|
|
SPLManager_UploadTextures(particleSystem->manager);
|
|
} else {
|
|
SPLManager_UploadTexturesEx(particleSystem->manager, particleSystem->texAllocFunc);
|
|
}
|
|
|
|
if (particleSystem->palAllocFunc == NULL) {
|
|
SPLManager_UploadPalettes(particleSystem->manager);
|
|
} else {
|
|
SPLManager_UploadPalettesEx(particleSystem->manager, particleSystem->palAllocFunc);
|
|
}
|
|
|
|
sUploadingParticleSystem = NULL;
|
|
}
|
|
|
|
static void ParticleSystem_VBlankResourceUploadInternal(SysTask *task, void *param)
|
|
{
|
|
ParticleSystem *particleSystem = param;
|
|
|
|
ParticleSystem_UploadResourcesInternal(particleSystem);
|
|
SysTask_Done(task);
|
|
}
|
|
|
|
void ParticleSystem_RegisterTextureKey(NNSGfdTexKey key)
|
|
{
|
|
GF_ASSERT(key != NNS_GFD_ALLOC_ERROR_TEXKEY);
|
|
GF_ASSERT(sUploadingParticleSystem != NULL);
|
|
|
|
ParticleSystem *particleSystem = sUploadingParticleSystem;
|
|
|
|
for (int i = 0; i < MAX_TEXTURE_KEYS; i++) {
|
|
if (particleSystem->textureKeys[i] == NNS_GFD_ALLOC_ERROR_TEXKEY) {
|
|
particleSystem->textureKeys[i] = key;
|
|
return;
|
|
}
|
|
}
|
|
|
|
GF_ASSERT(FALSE);
|
|
}
|
|
|
|
void ParticleSystem_RegisterPaletteKey(NNSGfdPlttKey key)
|
|
{
|
|
GF_ASSERT(key != NNS_GFD_ALLOC_ERROR_PLTTKEY);
|
|
GF_ASSERT(sUploadingParticleSystem != NULL);
|
|
|
|
ParticleSystem *particleSystem = sUploadingParticleSystem;
|
|
|
|
for (int i = 0; i < MAX_PALETTE_KEYS; i++) {
|
|
if (particleSystem->paletteKeys[i] == NNS_GFD_ALLOC_ERROR_PLTTKEY) {
|
|
particleSystem->paletteKeys[i] = key;
|
|
return;
|
|
}
|
|
}
|
|
|
|
GF_ASSERT(FALSE);
|
|
}
|
|
|
|
void ParticleSystem_Draw(ParticleSystem *particleSystem)
|
|
{
|
|
if (particleSystem->camera != NULL) {
|
|
Camera_ComputeProjectionMatrix(particleSystem->cameraProjection, particleSystem->camera);
|
|
Camera_SetAsActive(particleSystem->camera);
|
|
Camera_ComputeViewMatrix();
|
|
}
|
|
|
|
NNS_G3dGlbFlush();
|
|
|
|
const MtxFx43 *viewMatrix = NNS_G3dGlbGetCameraMtx();
|
|
SPLManager_Draw(particleSystem->manager, viewMatrix);
|
|
|
|
if (particleSystem->camera != NULL) {
|
|
Camera_ClearActive();
|
|
}
|
|
|
|
NNS_G3dGlbFlush();
|
|
}
|
|
|
|
void ParticleSystem_Update(ParticleSystem *particleSystem)
|
|
{
|
|
SPLManager_Update(particleSystem->manager);
|
|
}
|
|
|
|
int ParticleSystem_GetActiveAmount(void)
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
if (sParticleSystems[i] != NULL) {
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
int ParticleSystem_DrawAll(void)
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
if (sParticleSystems[i] != NULL) {
|
|
ParticleSystem_Draw(sParticleSystems[i]);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
int ParticleSystem_UpdateAll(void)
|
|
{
|
|
int count = 0;
|
|
for (int i = 0; i < MAX_PARTICLE_SYSTEMS; i++) {
|
|
if (sParticleSystems[i] != NULL) {
|
|
ParticleSystem_Update(sParticleSystems[i]);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
SPLEmitter *ParticleSystem_CreateEmitter(ParticleSystem *particleSystem, int resourceID, const VecFx32 *position)
|
|
{
|
|
SPLEmitter *emitter = SPLManager_CreateEmitter(particleSystem->manager, resourceID, position);
|
|
particleSystem->lastAddedEmitter = emitter;
|
|
|
|
return emitter;
|
|
}
|
|
|
|
SPLEmitter *ParticleSystem_CreateEmitterWithCallback(ParticleSystem *particleSystem, int resourceID, SPLEmitterCallback callback, void *param)
|
|
{
|
|
sEmitterCallbackParam = param;
|
|
SPLEmitter *emitter = SPLManager_CreateEmitterWithCallback(particleSystem->manager, resourceID, callback);
|
|
sEmitterCallbackParam = NULL;
|
|
particleSystem->lastAddedEmitter = emitter;
|
|
|
|
return emitter;
|
|
}
|
|
|
|
s32 ParticleSystem_GetActiveEmitterCount(ParticleSystem *particleSystem)
|
|
{
|
|
return particleSystem->manager->activeEmitters.count;
|
|
}
|
|
|
|
void ParticleSystem_DeleteAllEmitters(ParticleSystem *particleSystem)
|
|
{
|
|
SPLManager_DeleteAllEmitters(particleSystem->manager);
|
|
}
|
|
|
|
void ParticleSystem_DeleteEmitter(ParticleSystem *particleSystem, SPLEmitter *emitter)
|
|
{
|
|
SPLManager_DeleteEmitter(particleSystem->manager, emitter);
|
|
}
|
|
|
|
void *ParticleSystem_GetHeapStart(ParticleSystem *particleSystem)
|
|
{
|
|
return particleSystem->heapStart;
|
|
}
|
|
|
|
void ParticleSystem_GetCameraUp(ParticleSystem *particleSystem, VecFx32 *up)
|
|
{
|
|
*up = particleSystem->cameraUp;
|
|
}
|
|
|
|
void ParticleSystem_SetCameraUp(ParticleSystem *particleSystem, const VecFx32 *up)
|
|
{
|
|
particleSystem->cameraUp = *up;
|
|
Camera_SetUp(up, particleSystem->camera);
|
|
}
|
|
|
|
void *ParticleSystem_GetEmitterCallbackParam(void)
|
|
{
|
|
return sEmitterCallbackParam;
|
|
}
|
|
|
|
void ParticleSystem_GetDefaultCameraUp(VecFx32 *up)
|
|
{
|
|
*up = sParticleSystemDefaultCameraUp;
|
|
}
|
|
|
|
Camera *ParticleSystem_GetCamera(ParticleSystem *particleSystem)
|
|
{
|
|
return particleSystem->camera;
|
|
}
|
|
|
|
void ParticleSystem_SetCameraProjection(ParticleSystem *particleSystem, enum CameraProjection projection)
|
|
{
|
|
particleSystem->cameraProjection = projection;
|
|
}
|
|
|
|
u8 ParticleSystem_GetCameraProjection(ParticleSystem *particleSystem)
|
|
{
|
|
return particleSystem->cameraProjection;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterAxis(SPLEmitter *emitter, VecFx16 *axis)
|
|
{
|
|
*axis = emitter->axis;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterEmissionCount(SPLEmitter *emitter, fx32 count)
|
|
{
|
|
emitter->resource->header->emissionCount = count;
|
|
}
|
|
|
|
static const void *ParticleSystem_GetEmitterBehaviorInternal(SPLEmitter *emitter, int behaviorType)
|
|
{
|
|
int i; // Required to match
|
|
|
|
int behaviorCount = emitter->resource->behaviorCount;
|
|
if (behaviorCount == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; i < behaviorCount; i++) {
|
|
SPLBehavior *behavior = &emitter->resource->behaviors[i];
|
|
|
|
if (behavior == NULL) {
|
|
continue;
|
|
}
|
|
|
|
switch (behaviorType) {
|
|
case SPL_BEHAVIOR_GRAVITY:
|
|
if (behavior->applyFunc == SPLBehavior_ApplyGravity) {
|
|
return behavior->object;
|
|
}
|
|
continue;
|
|
case SPL_BEHAVIOR_RANDOM:
|
|
if (behavior->applyFunc == SPLBehavior_ApplyRandom) {
|
|
return behavior->object;
|
|
}
|
|
continue;
|
|
case SPL_BEHAVIOR_MAGNET:
|
|
if (behavior->applyFunc == SPLBehavior_ApplyMagnet) {
|
|
return behavior->object;
|
|
}
|
|
continue;
|
|
case SPL_BEHAVIOR_SPIN:
|
|
if (behavior->applyFunc == SPLBehavior_ApplySpin) {
|
|
return behavior->object;
|
|
}
|
|
continue;
|
|
case SPL_BEHAVIOR_COLLISION_PLANE:
|
|
if (behavior->applyFunc == SPLBehavior_ApplyCollisionPlane) {
|
|
return behavior->object;
|
|
}
|
|
break;
|
|
case SPL_BEHAVIOR_CONVERGENCE:
|
|
if (behavior->applyFunc == SPLBehavior_ApplyConvergence) {
|
|
return behavior->object;
|
|
}
|
|
continue;
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterGravityMagnitude(SPLEmitter *emitter, VecFx16 *magnitude)
|
|
{
|
|
SPLGravityBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_GRAVITY);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->magnitude = *magnitude;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterMagnetTarget(SPLEmitter *emitter, VecFx32 *target)
|
|
{
|
|
SPLMagnetBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_MAGNET);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->target = *target;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterMagnetTarget(SPLEmitter *emitter, VecFx32 *target)
|
|
{
|
|
SPLMagnetBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_MAGNET);
|
|
if (behavior == NULL) {
|
|
*target = (VecFx32) { 0, 0, 0 };
|
|
return;
|
|
}
|
|
|
|
*target = behavior->target;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterMagnetForce(SPLEmitter *emitter, fx16 *force)
|
|
{
|
|
SPLMagnetBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_MAGNET);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->force = *force;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterMagnetForce(SPLEmitter *emitter, fx16 *force)
|
|
{
|
|
SPLMagnetBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_MAGNET);
|
|
if (behavior == NULL) {
|
|
*force = 0;
|
|
return;
|
|
}
|
|
|
|
*force = behavior->force;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterSpinAngle(SPLEmitter *emitter, u16 *angle)
|
|
{
|
|
SPLSpinBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_SPIN);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->angle = *angle;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterSpinAngle(SPLEmitter *emitter, u16 *angle)
|
|
{
|
|
SPLSpinBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_SPIN);
|
|
if (behavior == NULL) {
|
|
*angle = 0;
|
|
return;
|
|
}
|
|
|
|
*angle = behavior->angle;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterSpinAxis(SPLEmitter *emitter, u16 *axis)
|
|
{
|
|
SPLSpinBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_SPIN);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->axis = *axis;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterSpinAxis(SPLEmitter *emitter, u16 *axis)
|
|
{
|
|
SPLSpinBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_SPIN);
|
|
if (behavior == NULL) {
|
|
*axis = 0;
|
|
return;
|
|
}
|
|
|
|
*axis = behavior->axis;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterConvergenceTarget(SPLEmitter *emitter, VecFx32 *target)
|
|
{
|
|
SPLConvergenceBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_CONVERGENCE);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->target = *target;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterConvergenceTarget(SPLEmitter *emitter, VecFx32 *target)
|
|
{
|
|
SPLConvergenceBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_CONVERGENCE);
|
|
if (behavior == NULL) {
|
|
*target = (VecFx32) { 0, 0, 0 };
|
|
return;
|
|
}
|
|
|
|
*target = behavior->target;
|
|
}
|
|
|
|
void ParticleSystem_SetEmitterConvergenceForce(SPLEmitter *emitter, fx16 *force)
|
|
{
|
|
SPLConvergenceBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_CONVERGENCE);
|
|
if (behavior == NULL) {
|
|
return;
|
|
}
|
|
|
|
behavior->force = *force;
|
|
}
|
|
|
|
void ParticleSystem_GetEmitterConvergenceForce(SPLEmitter *emitter, fx16 *force)
|
|
{
|
|
SPLConvergenceBehavior *behavior = ParticleSystem_GetEmitterBehaviorInternal(emitter, SPL_BEHAVIOR_CONVERGENCE);
|
|
if (behavior == NULL) {
|
|
*force = 0;
|
|
return;
|
|
}
|
|
|
|
*force = behavior->force;
|
|
}
|