Path: blob/master/RSDKv5/RSDK/Scene/Object.hpp
1163 views
#ifndef OBJECT_H1#define OBJECT_H23#if RETRO_USE_MOD_LOADER4#include <functional>5#endif67namespace RSDK8{910#define RSDK_SIGNATURE_OBJ (0x4A424F) // "OBJ"1112#define OBJECT_COUNT (0x400)1314// 0x800 scene objects, 0x40 reserved ones, and 0x100 spare slots for creation15#define RESERVE_ENTITY_COUNT (0x40)16#define TEMPENTITY_COUNT (0x100)17#define SCENEENTITY_COUNT (0x800)18#define ENTITY_COUNT (RESERVE_ENTITY_COUNT + SCENEENTITY_COUNT + TEMPENTITY_COUNT)19#define TEMPENTITY_START (ENTITY_COUNT - TEMPENTITY_COUNT)2021#define TYPE_COUNT (0x100)22#define EDITABLEVAR_COUNT (0x100)23#define TYPEGROUP_COUNT (0x104)2425#define FOREACH_STACK_COUNT (0x400)2627// Used for DefaultObject & DevOutput28#define RSDK_THIS(class) Entity##class *self = (Entity##class *)sceneInfo.entity2930enum StaticVariableTypes {31SVAR_UINT8,32SVAR_UINT16,33SVAR_UINT32,34SVAR_INT8,35SVAR_INT16,36SVAR_INT32,37SVAR_BOOL,38SVAR_POINTER,39SVAR_VECTOR2,40SVAR_STRING,41SVAR_ANIMATOR,42SVAR_HITBOX,43SVAR_SPRITEFRAME,44};4546enum TypeGroups {47GROUP_ALL = 0,4849GROUP_CUSTOM0 = TYPE_COUNT,50GROUP_CUSTOM1,51GROUP_CUSTOM2,52GROUP_CUSTOM3,53};5455enum VariableTypes {56VAR_UINT8,57VAR_UINT16,58VAR_UINT32,59VAR_INT8,60VAR_INT16,61VAR_INT32,62VAR_ENUM,63VAR_BOOL,64VAR_STRING,65VAR_VECTOR2,66VAR_FLOAT, // Not actually used in Sonic Mania so it's just an assumption, but this is the only thing that'd fit the 32 bit limit and make sense67VAR_COLOR,68};6970enum ActiveFlags {71ACTIVE_NEVER, // never update72ACTIVE_ALWAYS, // always update (even if paused/frozen)73ACTIVE_NORMAL, // always update (unless paused/frozen)74ACTIVE_PAUSED, // update only when paused/frozen75ACTIVE_BOUNDS, // update if in x & y bounds76ACTIVE_XBOUNDS, // update only if in x bounds (y bounds dont matter)77ACTIVE_YBOUNDS, // update only if in y bounds (x bounds dont matter)78ACTIVE_RBOUNDS, // update based on radius boundaries (updateRange.x == radius)7980// Not really even a real active value, but some objects set their active states to this so here it is I suppose81ACTIVE_DISABLED = 0xFF,82};8384enum DefaultObjects {85TYPE_DEFAULTOBJECT = 0,86#if RETRO_REV0287TYPE_DEVOUTPUT,88#endif8990TYPE_DEFAULT_COUNT, // max91};9293struct Object {94int16 classID;95uint8 active;96};9798struct Entity {99#if RETRO_REV0U100// used for languages such as beeflang that always have vfTables in classes101void *vfTable;102#endif103Vector2 position;104Vector2 scale;105Vector2 velocity;106Vector2 updateRange;107int32 angle;108int32 alpha;109int32 rotation;110int32 groundVel;111int32 zdepth;112uint16 group;113uint16 classID;114bool32 inRange;115bool32 isPermanent;116bool32 tileCollisions;117bool32 interaction;118bool32 onGround;119uint8 active;120#if RETRO_REV02121uint8 filter;122#endif123uint8 direction;124uint8 drawGroup;125uint8 collisionLayers;126uint8 collisionPlane;127uint8 collisionMode;128uint8 drawFX;129uint8 inkEffect;130uint8 visible;131uint8 onScreen;132};133134struct EntityBase : Entity {135void *data[0x100];136#if RETRO_REV0U137void *unknown;138#endif139};140141struct ObjectClass {142RETRO_HASH_MD5(hash);143144// Events145#if RETRO_USE_MOD_LOADER // using std::function makes it easier to use stuff like lambdas146std::function<void()> update;147std::function<void()> lateUpdate;148std::function<void()> staticUpdate;149std::function<void()> draw;150std::function<void(void *)> create;151std::function<void()> stageLoad;152std::function<void()> editorLoad;153std::function<void()> editorDraw;154std::function<void()> serialize;155#if RETRO_REV0U156std::function<void(Object *)> staticLoad;157#endif158#else159void (*update)();160void (*lateUpdate)();161void (*staticUpdate)();162void (*draw)();163void (*create)(void *);164void (*stageLoad)();165void (*editorLoad)();166void (*editorDraw)();167void (*serialize)();168#if RETRO_REV0U169void (*staticLoad)(Object *);170#endif171#endif172173// Classes174Object **staticVars;175int32 entityClassSize;176int32 staticClassSize;177178#if RETRO_USE_MOD_LOADER179ObjectClass *inherited;180#endif181182#if !RETRO_USE_ORIGINAL_CODE183const char *name; // for debugging purposes184#endif185};186187struct EditableVarInfo {188RETRO_HASH_MD5(hash);189int32 offset;190int32 active;191uint8 type;192};193194struct ForeachStackInfo {195int32 id;196};197198struct TypeGroupList {199uint16 entries[ENTITY_COUNT];200int32 entryCount;201};202203extern ObjectClass objectClassList[OBJECT_COUNT];204extern int32 objectClassCount;205206// Loaded Global Objects207extern int32 globalObjectCount;208extern int32 globalObjectIDs[OBJECT_COUNT];209210// Loaded Stage Objects (includes Globals if "loadGlobals" is enabled)211extern int32 stageObjectIDs[OBJECT_COUNT];212213extern EntityBase objectEntityList[ENTITY_COUNT];214215extern EditableVarInfo *editableVarList;216extern int32 editableVarCount;217218extern ForeachStackInfo foreachStackList[FOREACH_STACK_COUNT];219extern ForeachStackInfo *foreachStackPtr;220221extern TypeGroupList typeGroups[TYPEGROUP_COUNT];222223extern bool32 validDraw;224225#if RETRO_REV0U226void RegisterObject(Object **staticVars, const char *name, uint32 entityClassSize, uint32 staticClassSize, void (*update)(), void (*lateUpdate)(),227void (*staticUpdate)(), void (*draw)(), void (*create)(void *), void (*stageLoad)(), void (*editorLoad)(), void (*editorDraw)(),228void (*serialize)(), void (*staticLoad)(Object *));229230#if RETRO_USE_MOD_LOADER231void RegisterObject_STD(Object **staticVars, const char *name, uint32 entityClassSize, uint32 staticClassSize, std::function<void()> update,232std::function<void()> lateUpdate, std::function<void()> staticUpdate, std::function<void()> draw,233std::function<void(void *)> create, std::function<void()> stageLoad, std::function<void()> editorLoad,234std::function<void()> editorDraw, std::function<void()> serialize, std::function<void(Object *)> staticLoad);235#endif236#else237void RegisterObject(Object **staticVars, const char *name, uint32 entityClassSize, uint32 staticClassSize, void (*update)(), void (*lateUpdate)(),238void (*staticUpdate)(), void (*draw)(), void (*create)(void *), void (*stageLoad)(), void (*editorLoad)(), void (*editorDraw)(),239void (*serialize)());240241#if RETRO_USE_MOD_LOADER242void RegisterObject_STD(Object **staticVars, const char *name, uint32 entityClassSize, uint32 staticClassSize, std::function<void()> update,243std::function<void()> lateUpdate, std::function<void()> staticUpdate, std::function<void()> draw,244std::function<void(void *)> create, std::function<void()> stageLoad, std::function<void()> editorLoad,245std::function<void()> editorDraw, std::function<void()> serialize);246#endif247#endif248249#if RETRO_REV02 || RETRO_USE_MOD_LOADER250void RegisterStaticVariables(void **varClass, const char *name, uint32 classSize);251#endif252253void LoadStaticVariables(uint8 *classPtr, uint32 *hash, int32 readOffset);254255#define RSDK_EDITABLE_VAR(object, type, var) RSDK.SetEditableVar(type, #var, (uint8)object->classID, offsetof(Entity##object, var))256257// Bug Details(?):258// classID isn't used AND is a uint8, how strange259// assuming classID would be used in-editor (it is in RetroED2, but not sure about official RSDK SDK)260// not sure why it's a uint8, given the original value is a uint16, so there's some small warnings about that261inline void SetEditableVar(uint8 type, const char *name, uint8 classID, int32 offset)262{263if (editableVarCount < EDITABLEVAR_COUNT - 1) {264EditableVarInfo *var = &editableVarList[editableVarCount];265266GEN_HASH_MD5(name, var->hash);267var->type = type;268var->offset = offset;269var->active = true;270271editableVarCount++;272}273}274275inline void SetActiveVariable(int32 classID, const char *name)276{277// Editor-Only function278}279inline void AddEnumVariable(const char *name)280{281// Editor-Only function282}283284void InitObjects();285void ProcessObjects();286void ProcessPausedObjects();287void ProcessFrozenObjects();288void ProcessObjectDrawLists();289290uint16 FindObject(const char *name);291292inline Entity *GetEntity(uint16 slot) { return &objectEntityList[slot < ENTITY_COUNT ? slot : (ENTITY_COUNT - 1)]; }293inline int32 GetEntitySlot(EntityBase *entity) { return (int32)((uint32)(entity - objectEntityList) < ENTITY_COUNT ? entity - objectEntityList : 0); }294int32 GetEntityCount(uint16 classID, bool32 isActive);295296void ResetEntity(Entity *entity, uint16 classID, void *data);297void ResetEntitySlot(uint16 slot, uint16 classID, void *data);298Entity *CreateEntity(uint16 classID, void *data, int32 x, int32 y);299300inline void CopyEntity(void *destEntity, void *srcEntity, bool32 clearSrcEntity)301{302if (destEntity && srcEntity) {303memcpy(destEntity, srcEntity, sizeof(EntityBase));304305if (clearSrcEntity)306memset(srcEntity, 0, sizeof(EntityBase));307}308}309310bool32 GetActiveEntities(uint16 group, Entity **entity);311bool32 GetAllEntities(uint16 classID, Entity **entity);312313inline void BreakForeachLoop() { --foreachStackPtr; }314315// CheckPosOnScreen but if range is NULL it'll use entity->updateRange316bool32 CheckOnScreen(Entity *entity, Vector2 *range);317// Checks if a position is on screen & within range318bool32 CheckPosOnScreen(Vector2 *position, Vector2 *range);319320void ClearStageObjects();321322#if RETRO_REV0U323#include "Legacy/ObjectLegacy.hpp"324#endif325326} // namespace RSDK327328#endif // !OBJECT_H329330331