prog
This commit is contained in:
@@ -9,6 +9,11 @@ if(NOT cglm_FOUND)
|
||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC cglm)
|
||||
endif()
|
||||
|
||||
if(NOT yyjson_FOUND)
|
||||
find_package(yyjson REQUIRED)
|
||||
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PUBLIC yyjson::yyjson)
|
||||
endif()
|
||||
|
||||
|
||||
if(DUSK_BACKTRACE)
|
||||
target_link_options(${DUSK_LIBRARY_TARGET_NAME} PUBLIC -rdynamic)
|
||||
|
||||
@@ -12,15 +12,17 @@
|
||||
componentdefinition_t COMPONENT_DEFINITIONS[] = {
|
||||
[COMPONENT_TYPE_NULL] = { 0 },
|
||||
|
||||
#define X(enm, type, field, iMethod, dMethod, rMethod) \
|
||||
#define X(enm, type, field, iMethod, dMethod, rMethod, sMethod, dsMethod) \
|
||||
[COMPONENT_TYPE_##enm] = { \
|
||||
.enumName = #enm, \
|
||||
.name = #field, \
|
||||
.init = iMethod, \
|
||||
.dispose = dMethod, \
|
||||
.render = rMethod \
|
||||
.render = rMethod, \
|
||||
.serialize = sMethod, \
|
||||
.deserialize = dsMethod \
|
||||
},
|
||||
|
||||
|
||||
#include "componentlist.h"
|
||||
#undef X
|
||||
|
||||
@@ -130,6 +132,43 @@ errorret_t componentRenderAll(void) {
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void componentSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
|
||||
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
|
||||
assertNotNull(doc, "JSON doc cannot be null");
|
||||
assertNotNull(obj, "JSON obj cannot be null");
|
||||
|
||||
componentindex_t index = componentGetIndex(entityId, componentId);
|
||||
component_t *cmp = &ENTITY_MANAGER.components[index];
|
||||
if(cmp->type == COMPONENT_TYPE_NULL) return;
|
||||
if(!COMPONENT_DEFINITIONS[cmp->type].serialize) return;
|
||||
COMPONENT_DEFINITIONS[cmp->type].serialize(entityId, componentId, doc, obj);
|
||||
}
|
||||
|
||||
errorret_t componentDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
|
||||
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
|
||||
assertNotNull(obj, "JSON obj cannot be null");
|
||||
|
||||
componentindex_t index = componentGetIndex(entityId, componentId);
|
||||
component_t *cmp = &ENTITY_MANAGER.components[index];
|
||||
if(cmp->type == COMPONENT_TYPE_NULL) errorOk();
|
||||
if(!COMPONENT_DEFINITIONS[cmp->type].deserialize) errorOk();
|
||||
errorChain(
|
||||
COMPONENT_DEFINITIONS[cmp->type].deserialize(entityId, componentId, obj)
|
||||
);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
void componentDispose(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
|
||||
@@ -7,14 +7,18 @@
|
||||
|
||||
#pragma once
|
||||
#include "entitybase.h"
|
||||
#include "error/error.h"
|
||||
|
||||
#define X(enumName, type, field, init, dispose, render) \
|
||||
#include <yyjson.h>
|
||||
|
||||
#define X(enumName, type, field, init, dispose, render, serialize, deserialize) \
|
||||
// do nothing
|
||||
#include "componentlist.h"
|
||||
#undef X
|
||||
|
||||
typedef union {
|
||||
#define X(enumName, type, field, init, dispose, render) type field;
|
||||
#define X(enumName, type, field, init, dispose, render, serialize, deserialize) \
|
||||
type field;
|
||||
#include "componentlist.h"
|
||||
#undef X
|
||||
} componentdata_t;
|
||||
@@ -25,12 +29,23 @@ typedef struct {
|
||||
void (*init)(const entityid_t, const componentid_t);
|
||||
void (*dispose)(const entityid_t, const componentid_t);
|
||||
errorret_t (*render)(const entityid_t, const componentid_t);
|
||||
void (*serialize)(
|
||||
const entityid_t,
|
||||
const componentid_t,
|
||||
yyjson_mut_doc *,
|
||||
yyjson_mut_val *
|
||||
);
|
||||
errorret_t (*deserialize)(
|
||||
const entityid_t,
|
||||
const componentid_t,
|
||||
yyjson_val *
|
||||
);
|
||||
} componentdefinition_t;
|
||||
|
||||
typedef enum {
|
||||
COMPONENT_TYPE_NULL,
|
||||
|
||||
#define X(enumName, type, field, init, dispose, render) \
|
||||
#define X(enumName, type, field, init, dispose, render, serialize, deserialize) \
|
||||
COMPONENT_TYPE_##enumName,
|
||||
#include "componentlist.h"
|
||||
#undef X
|
||||
@@ -117,4 +132,34 @@ void componentDispose(
|
||||
*
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t componentRenderAll(void);
|
||||
errorret_t componentRenderAll(void);
|
||||
|
||||
/**
|
||||
* Serializes a component's configurable state into a JSON object. The caller
|
||||
* is responsible for creating and owning the doc and obj.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void componentSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes a component's configurable state from a JSON object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t componentDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
@@ -10,6 +10,9 @@
|
||||
#include "entity/component/display/entityposition.h"
|
||||
#include "display/framebuffer/framebuffer.h"
|
||||
#include "display/screen/screen.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
void entityCameraInit(const entityid_t ent, const componentid_t comp) {
|
||||
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||
@@ -117,4 +120,88 @@ void entityCameraGetRight(const entityid_t entityId, vec2 out) {
|
||||
if(len > 1e-6f) { rx /= len; rz /= len; }
|
||||
out[0] = rx;
|
||||
out[1] = rz;
|
||||
}
|
||||
|
||||
void entityCameraSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_CAMERA
|
||||
);
|
||||
assertNotNull(cam, "Failed to get camera component.");
|
||||
|
||||
const char_t *projStr = "perspective";
|
||||
if(cam->projType == ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED) {
|
||||
projStr = "perspective_flipped";
|
||||
} else if(cam->projType == ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) {
|
||||
projStr = "orthographic";
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_str(doc, obj, "projType", projStr);
|
||||
yyjson_mut_obj_add_real(doc, obj, "nearClip", (double)cam->nearClip);
|
||||
yyjson_mut_obj_add_real(doc, obj, "farClip", (double)cam->farClip);
|
||||
|
||||
if(cam->projType == ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) {
|
||||
yyjson_mut_obj_add_real(doc, obj, "left", (double)cam->orthographic.left);
|
||||
yyjson_mut_obj_add_real(doc, obj, "right", (double)cam->orthographic.right);
|
||||
yyjson_mut_obj_add_real(doc, obj, "top", (double)cam->orthographic.top);
|
||||
yyjson_mut_obj_add_real(
|
||||
doc, obj, "bottom", (double)cam->orthographic.bottom
|
||||
);
|
||||
} else {
|
||||
yyjson_mut_obj_add_real(doc, obj, "fov", (double)cam->perspective.fov);
|
||||
}
|
||||
}
|
||||
|
||||
errorret_t entityCameraDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
entitycamera_t *cam = (entitycamera_t *)componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_CAMERA
|
||||
);
|
||||
assertNotNull(cam, "Failed to get camera component.");
|
||||
|
||||
yyjson_val *v;
|
||||
|
||||
v = yyjson_obj_get(obj, "projType");
|
||||
if(v && yyjson_is_str(v)) {
|
||||
const char_t *s = yyjson_get_str(v);
|
||||
if(stringCompare(s, "perspective_flipped") == 0) {
|
||||
cam->projType = ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED;
|
||||
} else if(stringCompare(s, "orthographic") == 0) {
|
||||
cam->projType = ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC;
|
||||
} else {
|
||||
cam->projType = ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "nearClip");
|
||||
if(v) cam->nearClip = (float_t)yyjson_get_num(v);
|
||||
|
||||
v = yyjson_obj_get(obj, "farClip");
|
||||
if(v) cam->farClip = (float_t)yyjson_get_num(v);
|
||||
|
||||
if(cam->projType == ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) {
|
||||
v = yyjson_obj_get(obj, "left");
|
||||
if(v) cam->orthographic.left = (float_t)yyjson_get_num(v);
|
||||
|
||||
v = yyjson_obj_get(obj, "right");
|
||||
if(v) cam->orthographic.right = (float_t)yyjson_get_num(v);
|
||||
|
||||
v = yyjson_obj_get(obj, "top");
|
||||
if(v) cam->orthographic.top = (float_t)yyjson_get_num(v);
|
||||
|
||||
v = yyjson_obj_get(obj, "bottom");
|
||||
if(v) cam->orthographic.bottom = (float_t)yyjson_get_num(v);
|
||||
} else {
|
||||
v = yyjson_obj_get(obj, "fov");
|
||||
if(v) cam->perspective.fov = (float_t)yyjson_get_num(v);
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
#include "error/error.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
typedef enum {
|
||||
ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE,
|
||||
@@ -96,4 +98,35 @@ void entityCameraLookAtPixelPerfect(
|
||||
const vec3 point,
|
||||
const vec3 eyeOffset,
|
||||
const float_t scale
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes camera projection settings to a JSON object. Writes "projType"
|
||||
* as a string ("perspective", "perspective_flipped", or "orthographic"),
|
||||
* "nearClip", "farClip", and the projection-specific parameters.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void entityCameraSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes camera projection settings from a JSON object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityCameraDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
@@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "entity/entitymanager.h"
|
||||
#include "assert/assert.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
// Decompose localTransform into the PRS cache. Only called when PRS_DIRTY.
|
||||
static void entityPositionEnsurePRS(entityposition_t *pos) {
|
||||
@@ -628,3 +630,68 @@ void entityPositionDecompose(entityposition_t *pos) {
|
||||
: -atan2f(r01, r11);
|
||||
}
|
||||
}
|
||||
|
||||
void entityPositionSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
entityposition_t *pos = entityPositionGet(entityId, componentId);
|
||||
assertNotNull(pos, "Failed to get position component.");
|
||||
|
||||
yyjson_mut_val *arr;
|
||||
|
||||
arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->position[0]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->position[1]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->position[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "position", arr);
|
||||
|
||||
arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->rotation[0]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->rotation[1]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->rotation[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "rotation", arr);
|
||||
|
||||
arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->scale[0]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->scale[1]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)pos->scale[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "scale", arr);
|
||||
}
|
||||
|
||||
errorret_t entityPositionDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
entityposition_t *pos = entityPositionGet(entityId, componentId);
|
||||
assertNotNull(pos, "Failed to get position component.");
|
||||
|
||||
yyjson_val *v;
|
||||
|
||||
v = yyjson_obj_get(obj, "position");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
pos->position[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
pos->position[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
pos->position[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "rotation");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
pos->rotation[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
pos->rotation[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
pos->rotation[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "scale");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
pos->scale[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
pos->scale[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
pos->scale[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
entityPositionRebuild(pos);
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
#include "error/error.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
/** Maximum number of child position components this node can track. */
|
||||
#define ENTITY_POSITION_CHILDREN_MAX 8
|
||||
@@ -373,3 +375,34 @@ void entityPositionDisposeDeep(
|
||||
* @param pos The position component to decompose.
|
||||
*/
|
||||
void entityPositionDecompose(entityposition_t *pos);
|
||||
|
||||
/**
|
||||
* Serializes position, rotation, and scale (local space) to a JSON object.
|
||||
* Parent/child linkage and computed matrices are not included.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void entityPositionSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes position, rotation, and scale from a JSON object and rebuilds
|
||||
* the local transform.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityPositionDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "display/mesh/cube.h"
|
||||
#include "util/memory.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/string.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
void entityRenderableInit(
|
||||
const entityid_t entityId,
|
||||
@@ -140,3 +142,77 @@ errorret_t entityRenderableDraw(
|
||||
assertUnreachable("Invalid renderable type");
|
||||
}
|
||||
}
|
||||
|
||||
void entityRenderableSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
entityrenderable_t *r = (entityrenderable_t *)componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_RENDERABLE
|
||||
);
|
||||
assertNotNull(r, "Failed to get renderable component.");
|
||||
|
||||
const char_t *typeStr = "custom";
|
||||
if(r->type == ENTITY_RENDERABLE_TYPE_SPRITEBATCH) {
|
||||
typeStr = "spritebatch";
|
||||
} else if(r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL) {
|
||||
typeStr = "shader_material";
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_str(doc, obj, "type", typeStr);
|
||||
yyjson_mut_obj_add_int(doc, obj, "priority", (int64_t)r->priority);
|
||||
|
||||
if(r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL) {
|
||||
yyjson_mut_obj_add_int(
|
||||
doc, obj, "shaderType", (int64_t)r->data.material.shaderType
|
||||
);
|
||||
yyjson_mut_obj_add_int(
|
||||
doc, obj, "stateFlags", (int64_t)r->data.material.state.flags
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
errorret_t entityRenderableDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
entityrenderable_t *r = (entityrenderable_t *)componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_RENDERABLE
|
||||
);
|
||||
assertNotNull(r, "Failed to get renderable component.");
|
||||
|
||||
yyjson_val *v;
|
||||
|
||||
v = yyjson_obj_get(obj, "type");
|
||||
if(v && yyjson_is_str(v)) {
|
||||
const char_t *s = yyjson_get_str(v);
|
||||
if(stringCompare(s, "spritebatch") == 0) {
|
||||
entityRenderableSetType(entityId, componentId,
|
||||
ENTITY_RENDERABLE_TYPE_SPRITEBATCH);
|
||||
} else if(stringCompare(s, "shader_material") == 0) {
|
||||
entityRenderableSetType(entityId, componentId,
|
||||
ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL);
|
||||
} else {
|
||||
entityRenderableSetType(entityId, componentId,
|
||||
ENTITY_RENDERABLE_TYPE_CUSTOM);
|
||||
}
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "priority");
|
||||
if(v) r->priority = (int8_t)yyjson_get_sint(v);
|
||||
|
||||
if(r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL) {
|
||||
v = yyjson_obj_get(obj, "shaderType");
|
||||
if(v) {
|
||||
r->data.material.shaderType = (shaderlistshader_t)yyjson_get_sint(v);
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "stateFlags");
|
||||
if(v) r->data.material.state.flags = (uint8_t)yyjson_get_sint(v);
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "display/shader/shadermaterial.h"
|
||||
#include "display/spritebatch/spritebatch.h"
|
||||
#include "display/displaystate.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
#define ENTITY_RENDERABLE_SPRITEBATCH_SPRITES_MAX 64
|
||||
#define ENTITY_RENDERABLE_MESHES_MAX 8
|
||||
@@ -145,3 +146,33 @@ errorret_t entityRenderableDraw(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes renderable type, priority, and material settings to a JSON
|
||||
* object. Custom and spritebatch renderables only serialize type and priority.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void entityRenderableSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes renderable settings from a JSON object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityRenderableDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "physics/physicsmanager.h"
|
||||
#include "assert/assert.h"
|
||||
#include "util/memory.h"
|
||||
#include "util/string.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
void entityPhysicsInit(
|
||||
const entityid_t entityId,
|
||||
@@ -124,3 +126,172 @@ void entityPhysicsDispose(
|
||||
const componentid_t componentId
|
||||
) {
|
||||
}
|
||||
|
||||
void entityPhysicsSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||
assertNotNull(phys, "Failed to get physics component.");
|
||||
|
||||
const char_t *bodyStr = "static";
|
||||
if(phys->type == PHYSICS_BODY_DYNAMIC) {
|
||||
bodyStr = "dynamic";
|
||||
} else if(phys->type == PHYSICS_BODY_KINEMATIC) {
|
||||
bodyStr = "kinematic";
|
||||
}
|
||||
yyjson_mut_obj_add_str(doc, obj, "bodyType", bodyStr);
|
||||
|
||||
const char_t *shapeStr = "cube";
|
||||
if(phys->shape.type == PHYSICS_SHAPE_SPHERE) {
|
||||
shapeStr = "sphere";
|
||||
} else if(phys->shape.type == PHYSICS_SHAPE_CAPSULE) {
|
||||
shapeStr = "capsule";
|
||||
} else if(phys->shape.type == PHYSICS_SHAPE_PLANE) {
|
||||
shapeStr = "plane";
|
||||
}
|
||||
yyjson_mut_obj_add_str(doc, obj, "shapeType", shapeStr);
|
||||
|
||||
switch(phys->shape.type) {
|
||||
case PHYSICS_SHAPE_CUBE: {
|
||||
yyjson_mut_val *he = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, he, (double)phys->shape.data.cube.halfExtents[0]
|
||||
);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, he, (double)phys->shape.data.cube.halfExtents[1]
|
||||
);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, he, (double)phys->shape.data.cube.halfExtents[2]
|
||||
);
|
||||
yyjson_mut_obj_add_val(doc, obj, "halfExtents", he);
|
||||
break;
|
||||
}
|
||||
case PHYSICS_SHAPE_SPHERE:
|
||||
yyjson_mut_obj_add_real(
|
||||
doc, obj, "radius", (double)phys->shape.data.sphere.radius
|
||||
);
|
||||
break;
|
||||
case PHYSICS_SHAPE_CAPSULE:
|
||||
yyjson_mut_obj_add_real(
|
||||
doc, obj, "radius", (double)phys->shape.data.capsule.radius
|
||||
);
|
||||
yyjson_mut_obj_add_real(
|
||||
doc, obj, "halfHeight", (double)phys->shape.data.capsule.halfHeight
|
||||
);
|
||||
break;
|
||||
case PHYSICS_SHAPE_PLANE: {
|
||||
yyjson_mut_val *n = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, n, (double)phys->shape.data.plane.normal[0]
|
||||
);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, n, (double)phys->shape.data.plane.normal[1]
|
||||
);
|
||||
yyjson_mut_arr_add_real(
|
||||
doc, n, (double)phys->shape.data.plane.normal[2]
|
||||
);
|
||||
yyjson_mut_obj_add_val(doc, obj, "normal", n);
|
||||
yyjson_mut_obj_add_real(
|
||||
doc, obj, "distance", (double)phys->shape.data.plane.distance
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
yyjson_mut_val *vel = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, vel, (double)phys->velocity[0]);
|
||||
yyjson_mut_arr_add_real(doc, vel, (double)phys->velocity[1]);
|
||||
yyjson_mut_arr_add_real(doc, vel, (double)phys->velocity[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "velocity", vel);
|
||||
|
||||
yyjson_mut_obj_add_real(doc, obj, "gravityScale", (double)phys->gravityScale);
|
||||
}
|
||||
|
||||
errorret_t entityPhysicsDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
|
||||
assertNotNull(phys, "Failed to get physics component.");
|
||||
|
||||
yyjson_val *v;
|
||||
|
||||
v = yyjson_obj_get(obj, "bodyType");
|
||||
if(v && yyjson_is_str(v)) {
|
||||
const char_t *s = yyjson_get_str(v);
|
||||
if(stringCompare(s, "dynamic") == 0) {
|
||||
phys->type = PHYSICS_BODY_DYNAMIC;
|
||||
} else if(stringCompare(s, "kinematic") == 0) {
|
||||
phys->type = PHYSICS_BODY_KINEMATIC;
|
||||
} else {
|
||||
phys->type = PHYSICS_BODY_STATIC;
|
||||
}
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "shapeType");
|
||||
if(v && yyjson_is_str(v)) {
|
||||
physicsshape_t shape;
|
||||
memoryZero(&shape, sizeof(physicsshape_t));
|
||||
const char_t *s = yyjson_get_str(v);
|
||||
if(stringCompare(s, "sphere") == 0) {
|
||||
shape.type = PHYSICS_SHAPE_SPHERE;
|
||||
yyjson_val *r = yyjson_obj_get(obj, "radius");
|
||||
if(r) shape.data.sphere.radius = (float_t)yyjson_get_num(r);
|
||||
} else if(stringCompare(s, "capsule") == 0) {
|
||||
shape.type = PHYSICS_SHAPE_CAPSULE;
|
||||
yyjson_val *r = yyjson_obj_get(obj, "radius");
|
||||
if(r) shape.data.capsule.radius = (float_t)yyjson_get_num(r);
|
||||
yyjson_val *hh = yyjson_obj_get(obj, "halfHeight");
|
||||
if(hh) shape.data.capsule.halfHeight = (float_t)yyjson_get_num(hh);
|
||||
} else if(stringCompare(s, "plane") == 0) {
|
||||
shape.type = PHYSICS_SHAPE_PLANE;
|
||||
yyjson_val *n = yyjson_obj_get(obj, "normal");
|
||||
if(n && yyjson_is_arr(n) && yyjson_arr_size(n) == 3) {
|
||||
shape.data.plane.normal[0] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(n, 0)
|
||||
);
|
||||
shape.data.plane.normal[1] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(n, 1)
|
||||
);
|
||||
shape.data.plane.normal[2] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(n, 2)
|
||||
);
|
||||
}
|
||||
yyjson_val *d = yyjson_obj_get(obj, "distance");
|
||||
if(d) shape.data.plane.distance = (float_t)yyjson_get_num(d);
|
||||
} else {
|
||||
shape.type = PHYSICS_SHAPE_CUBE;
|
||||
yyjson_val *he = yyjson_obj_get(obj, "halfExtents");
|
||||
if(he && yyjson_is_arr(he) && yyjson_arr_size(he) == 3) {
|
||||
shape.data.cube.halfExtents[0] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(he, 0)
|
||||
);
|
||||
shape.data.cube.halfExtents[1] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(he, 1)
|
||||
);
|
||||
shape.data.cube.halfExtents[2] = (float_t)yyjson_get_num(
|
||||
yyjson_arr_get(he, 2)
|
||||
);
|
||||
}
|
||||
}
|
||||
entityPhysicsSetShape(entityId, componentId, shape);
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "velocity");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
phys->velocity[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
phys->velocity[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
phys->velocity[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "gravityScale");
|
||||
if(v) phys->gravityScale = (float_t)yyjson_get_num(v);
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "entity/entitybase.h"
|
||||
#include "physics/physicsshape.h"
|
||||
#include "physics/physicsbodytype.h"
|
||||
#include "error/error.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
typedef struct {
|
||||
physicsbodytype_t type;
|
||||
@@ -155,3 +157,34 @@ void entityPhysicsDispose(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes body type, shape, velocity, and gravity scale to a JSON object.
|
||||
* Runtime state (onGround) is not included.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void entityPhysicsSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes body type, shape, velocity, and gravity scale from a JSON
|
||||
* object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityPhysicsDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
*/
|
||||
|
||||
#include "entity/entitymanager.h"
|
||||
#include "assert/assert.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
void entityTriggerInit(
|
||||
const entityid_t entityId,
|
||||
@@ -52,3 +54,54 @@ void entityTriggerSetBounds(
|
||||
glm_vec3_copy((float_t*)min, t->min);
|
||||
glm_vec3_copy((float_t*)max, t->max);
|
||||
}
|
||||
|
||||
void entityTriggerSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
) {
|
||||
entitytrigger_t *trigger = entityTriggerGet(entityId, componentId);
|
||||
assertNotNull(trigger, "Failed to get trigger component.");
|
||||
|
||||
yyjson_mut_val *arr;
|
||||
|
||||
arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->min[0]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->min[1]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->min[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "min", arr);
|
||||
|
||||
arr = yyjson_mut_arr(doc);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->max[0]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->max[1]);
|
||||
yyjson_mut_arr_add_real(doc, arr, (double)trigger->max[2]);
|
||||
yyjson_mut_obj_add_val(doc, obj, "max", arr);
|
||||
}
|
||||
|
||||
errorret_t entityTriggerDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
) {
|
||||
entitytrigger_t *trigger = entityTriggerGet(entityId, componentId);
|
||||
assertNotNull(trigger, "Failed to get trigger component.");
|
||||
|
||||
yyjson_val *v;
|
||||
|
||||
v = yyjson_obj_get(obj, "min");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
trigger->min[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
trigger->min[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
trigger->min[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
v = yyjson_obj_get(obj, "max");
|
||||
if(v && yyjson_is_arr(v) && yyjson_arr_size(v) == 3) {
|
||||
trigger->max[0] = (float_t)yyjson_get_num(yyjson_arr_get(v, 0));
|
||||
trigger->max[1] = (float_t)yyjson_get_num(yyjson_arr_get(v, 1));
|
||||
trigger->max[2] = (float_t)yyjson_get_num(yyjson_arr_get(v, 2));
|
||||
}
|
||||
|
||||
errorOk();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
#include "error/error.h"
|
||||
#include <yyjson.h>
|
||||
|
||||
typedef struct {
|
||||
vec3 min;
|
||||
@@ -47,3 +49,32 @@ void entityTriggerSetBounds(
|
||||
const vec3 min,
|
||||
const vec3 max
|
||||
);
|
||||
|
||||
/**
|
||||
* Serializes the trigger's min and max bounds to a JSON object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param doc The mutable JSON document to allocate values from.
|
||||
* @param obj The JSON object to write fields into.
|
||||
*/
|
||||
void entityTriggerSerialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_mut_doc *doc,
|
||||
yyjson_mut_val *obj
|
||||
);
|
||||
|
||||
/**
|
||||
* Deserializes the trigger's min and max bounds from a JSON object.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param obj The JSON object to read fields from.
|
||||
* @return Error state.
|
||||
*/
|
||||
errorret_t entityTriggerDeserialize(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
yyjson_val *obj
|
||||
);
|
||||
|
||||
@@ -17,11 +17,21 @@
|
||||
// Init function (optional)
|
||||
// Dispose function (optional)
|
||||
// Render function (optional)
|
||||
// Serialize function (optional)
|
||||
// Deserialize function (optional)
|
||||
|
||||
X(POSITION, entityposition_t, position, entityPositionInit, NULL, NULL)
|
||||
X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL, NULL)
|
||||
X(POSITION, entityposition_t, position,
|
||||
entityPositionInit, NULL, NULL,
|
||||
entityPositionSerialize, entityPositionDeserialize)
|
||||
X(CAMERA, entitycamera_t, camera,
|
||||
entityCameraInit, NULL, NULL,
|
||||
entityCameraSerialize, entityCameraDeserialize)
|
||||
X(RENDERABLE, entityrenderable_t, renderable,
|
||||
entityRenderableInit, entityRenderableDispose, NULL)
|
||||
entityRenderableInit, entityRenderableDispose, NULL,
|
||||
entityRenderableSerialize, entityRenderableDeserialize)
|
||||
X(PHYSICS, entityphysics_t, physics,
|
||||
entityPhysicsInit, entityPhysicsDispose, NULL)
|
||||
X(TRIGGER, entitytrigger_t, trigger, entityTriggerInit, NULL, NULL)
|
||||
entityPhysicsInit, entityPhysicsDispose, NULL,
|
||||
entityPhysicsSerialize, entityPhysicsDeserialize)
|
||||
X(TRIGGER, entitytrigger_t, trigger,
|
||||
entityTriggerInit, NULL, NULL,
|
||||
entityTriggerSerialize, entityTriggerDeserialize)
|
||||
|
||||
Reference in New Issue
Block a user