diff --git a/assets/entities/CubeEntity.js b/assets/entities/CubeEntity.js index a86f994f..2dff2fd1 100644 --- a/assets/entities/CubeEntity.js +++ b/assets/entities/CubeEntity.js @@ -3,11 +3,10 @@ var OverworldEntity = include('entities/OverworldEntity.js'); function CubeEntity() { OverworldEntity.call(this); - this.add(MESH); - this.add(MATERIAL); + this.add(RENDERABLE); this.cubeMesh = Mesh.createCube(); - this.mesh.mesh = this.cubeMesh; + this.renderable.mesh = this.cubeMesh; } CubeEntity.prototype = Object.create(OverworldEntity.prototype); @@ -19,7 +18,7 @@ CubeEntity.prototype.update = function() { var move = Input.axis2D(INPUT_ACTION_LEFT, INPUT_ACTION_RIGHT, INPUT_ACTION_UP, INPUT_ACTION_DOWN); this.position.position.x += move.x * speed * TIME.delta; this.position.position.z += move.y * speed * TIME.delta; - this.material.color = Color.rainbow(); + this.renderable.color = Color.rainbow(); }; module = CubeEntity; diff --git a/assets/init.js b/assets/init.js index 1c3947fb..26e4c743 100644 --- a/assets/init.js +++ b/assets/init.js @@ -76,18 +76,18 @@ if (typeof PSP !== 'undefined') { Scene.set('scenes/cube.js'); -Console.print("Testing save stuff;"); -Console.print("Save Count: " + Save.count); -Console.print("Save 0 exists? " + Save.exists(0)); -try { - Save.load(0); - Console.print("Successfully loaded save 0."); -} catch (e) { - Console.print("Error loading save 0: " + e); - Save.delete(0); -} -Console.print("Save 0 exists? " + Save.exists(0)); -Console.print("Writing..."); -Save.write(0); -Console.print("Save 0 exists? " + Save.exists(0)); -Console.print("Save 0 data: " + Save.load(0)); \ No newline at end of file +// Console.print("Testing save stuff;"); +// Console.print("Save Count: " + Save.count); +// Console.print("Save 0 exists? " + Save.exists(0)); +// try { +// Save.load(0); +// Console.print("Successfully loaded save 0."); +// } catch (e) { +// Console.print("Error loading save 0: " + e); +// Save.delete(0); +// } +// Console.print("Save 0 exists? " + Save.exists(0)); +// Console.print("Writing..."); +// Save.write(0); +// Console.print("Save 0 exists? " + Save.exists(0)); +// Console.print("Save 0 data: " + Save.load(0)); \ No newline at end of file diff --git a/src/dusk/display/spritebatch/spritebatch.c b/src/dusk/display/spritebatch/spritebatch.c index 8f1a4015..ab2f4f8c 100644 --- a/src/dusk/display/spritebatch/spritebatch.c +++ b/src/dusk/display/spritebatch/spritebatch.c @@ -175,9 +175,26 @@ errorret_t spriteBatchPush3D( ); } +errorret_t spriteBatchBufferSprite(const spritebatchsprite_t *sprite) { + if(sprite->texture != SPRITEBATCH.currentTexture) { + errorChain(spriteBatchFlush()); + SPRITEBATCH.currentTexture = sprite->texture; + } + return spriteBatchPush3D( + sprite->min, + sprite->max, + #if MESH_ENABLE_COLOR + sprite->color, + #endif + sprite->uvMin, + sprite->uvMax + ); +} + void spriteBatchClear() { SPRITEBATCH.spriteCount = 0; SPRITEBATCH.spriteFlush = 0; + SPRITEBATCH.currentTexture = NULL; } errorret_t spriteBatchFlush() { diff --git a/src/dusk/display/spritebatch/spritebatch.h b/src/dusk/display/spritebatch/spritebatch.h index 131ffc8b..6632fbdc 100644 --- a/src/dusk/display/spritebatch/spritebatch.h +++ b/src/dusk/display/spritebatch/spritebatch.h @@ -7,18 +7,31 @@ #pragma once #include "display/mesh/quad.h" +#include "display/texture/texture.h" #define SPRITEBATCH_SPRITES_MAX 512 -#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT) +#define SPRITEBATCH_VERTEX_COUNT (SPRITEBATCH_SPRITES_MAX * QUAD_VERTEX_COUNT) #define SPRITEBATCH_FLUSH_COUNT 16 #define SPRITEBATCH_SPRITES_MAX_PER_FLUSH (\ SPRITEBATCH_SPRITES_MAX / SPRITEBATCH_FLUSH_COUNT \ ) +typedef struct { + vec3 min; + vec3 max; + vec2 uvMin; + vec2 uvMax; + texture_t *texture; +#if MESH_ENABLE_COLOR + color_t color; +#endif +} spritebatchsprite_t; + typedef struct { mesh_t mesh; int32_t spriteCount; int32_t spriteFlush; + texture_t *currentTexture; } spritebatch_t; // Have to define these seperately because of alignment in certain platforms. @@ -119,6 +132,15 @@ errorret_t spriteBatchPush3D( const vec2 uvMax ); +/** + * Buffers a sprite defined by a spritebatchsprite_t. Automatically flushes + * if the texture changes from the previously buffered sprite. + * + * @param sprite The sprite to buffer. + * @return An error code indicating success or failure. + */ +errorret_t spriteBatchBufferSprite(const spritebatchsprite_t *sprite); + /** * Clears the sprite batch. This will mean calling flush renders nothing. */ diff --git a/src/dusk/entity/component/CMakeLists.txt b/src/dusk/entity/component/CMakeLists.txt index e5d8792f..4558fc62 100644 --- a/src/dusk/entity/component/CMakeLists.txt +++ b/src/dusk/entity/component/CMakeLists.txt @@ -5,4 +5,5 @@ add_subdirectory(display) add_subdirectory(physics) -add_subdirectory(script) \ No newline at end of file +add_subdirectory(script) +add_subdirectory(trigger) \ No newline at end of file diff --git a/src/dusk/entity/component/display/CMakeLists.txt b/src/dusk/entity/component/display/CMakeLists.txt index d0b84aa4..eeca751f 100644 --- a/src/dusk/entity/component/display/CMakeLists.txt +++ b/src/dusk/entity/component/display/CMakeLists.txt @@ -8,6 +8,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC entityposition.c entitycamera.c - entitymesh.c - entitymaterial.c + entityrenderable.c ) \ No newline at end of file diff --git a/src/dusk/entity/component/display/entitycamera.c b/src/dusk/entity/component/display/entitycamera.c index a21e5b48..50479512 100644 --- a/src/dusk/entity/component/display/entitycamera.c +++ b/src/dusk/entity/component/display/entitycamera.c @@ -75,8 +75,8 @@ void entityCameraGetForward(const entityid_t entityId, vec2 out) { entityposition_t *pos = entityPositionGet(entityId, posComp); // View matrix column layout: M[col][row], // forward = {-M[0][2], -M[1][2], -M[2][2]} - float_t fx = -pos->transform[0][2]; - float_t fz = -pos->transform[2][2]; + float_t fx = -pos->worldTransform[0][2]; + float_t fz = -pos->worldTransform[2][2]; float_t len = sqrtf(fx * fx + fz * fz); if(len > 1e-6f) { fx /= len; fz /= len; } out[0] = fx; @@ -87,8 +87,8 @@ void entityCameraGetRight(const entityid_t entityId, vec2 out) { componentid_t posComp = entityGetComponent(entityId, COMPONENT_TYPE_POSITION); entityposition_t *pos = entityPositionGet(entityId, posComp); // View matrix column layout: right = {M[0][0], M[1][0], M[2][0]} - float_t rx = pos->transform[0][0]; - float_t rz = pos->transform[2][0]; + float_t rx = pos->worldTransform[0][0]; + float_t rz = pos->worldTransform[2][0]; float_t len = sqrtf(rx * rx + rz * rz); if(len > 1e-6f) { rx /= len; rz /= len; } out[0] = rx; diff --git a/src/dusk/entity/component/display/entitymaterial.c b/src/dusk/entity/component/display/entitymaterial.c deleted file mode 100644 index da65d78d..00000000 --- a/src/dusk/entity/component/display/entitymaterial.c +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entity/entitymanager.h" -#include "display/shader/shaderunlit.h" - -void entityMaterialInit( - const entityid_t entityId, - const componentid_t componentId -) { - entitymaterial_t *mat = componentGetData( - entityId, componentId, COMPONENT_TYPE_MATERIAL - ); - mat->shader = &SHADER_UNLIT; - mat->material.unlit.color = COLOR_WHITE; -} - -shadermaterial_t * entityMaterialGetShaderMaterial( - const entityid_t entityId, - const componentid_t componentId -) { - entitymaterial_t *mat = componentGetData( - entityId, componentId, COMPONENT_TYPE_MATERIAL - ); - return &mat->material; -} - -shader_t * entityMaterialGetShader( - const entityid_t entityId, - const componentid_t componentId -) { - entitymaterial_t *mat = componentGetData( - entityId, componentId, COMPONENT_TYPE_MATERIAL - ); - return mat->shader; -} - -void entityMaterialSetShader( - const entityid_t entityId, - const componentid_t componentId, - shader_t *shader -) { - entitymaterial_t *mat = componentGetData( - entityId, componentId, COMPONENT_TYPE_MATERIAL - ); - mat->shader = shader; -} - -void entityMaterialSetColor( - const entityid_t entityId, - const componentid_t componentId, - const color_t color -) { - entitymaterial_t *mat = componentGetData( - entityId, componentId, COMPONENT_TYPE_MATERIAL - ); - mat->material.unlit.color = color; -} \ No newline at end of file diff --git a/src/dusk/entity/component/display/entitymaterial.h b/src/dusk/entity/component/display/entitymaterial.h deleted file mode 100644 index 341ff0d0..00000000 --- a/src/dusk/entity/component/display/entitymaterial.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entity/entitybase.h" -#include "display/shader/shadermaterial.h" - -typedef struct { - shader_t *shader; - shadermaterial_t material; -} entitymaterial_t; - -/** - * Initializes the entity material component, defaulting to the unlit shader. - * - * @param entityId The entity ID. - * @param componentId The component ID. - */ -void entityMaterialInit( - const entityid_t entityId, - const componentid_t componentId -); - -/** - * Gets the shader material for the given entity and component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @return The shader material for the given entity and component. - */ -shadermaterial_t * entityMaterialGetShaderMaterial( - const entityid_t entityId, - const componentid_t componentId -); - -/** - * Gets the shader for the given entity and component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @return The shader for the given entity and component. - */ -shader_t * entityMaterialGetShader( - const entityid_t entityId, - const componentid_t componentId -); - -/** - * Sets the shader for the given entity and component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @param shader The shader to set. - */ -void entityMaterialSetShader( - const entityid_t entityId, - const componentid_t componentId, - shader_t *shader -); - -/** - * Sets the unlit color for the given entity and component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @param color The color to set. - */ -void entityMaterialSetColor( - const entityid_t entityId, - const componentid_t componentId, - const color_t color -); \ No newline at end of file diff --git a/src/dusk/entity/component/display/entitymesh.c b/src/dusk/entity/component/display/entitymesh.c deleted file mode 100644 index c0fd2c2a..00000000 --- a/src/dusk/entity/component/display/entitymesh.c +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "entitymesh.h" -#include "entity/entitymanager.h" - -void entityMeshInit( - const entityid_t entityId, - const componentid_t componentId -) { - entitymesh_t *comp = componentGetData( - entityId, componentId, COMPONENT_TYPE_MESH - ); - comp->mesh = NULL; -} - -mesh_t * entityMeshGetMesh( - const entityid_t entityId, - const componentid_t componentId -) { - entitymesh_t *comp = componentGetData( - entityId, componentId, COMPONENT_TYPE_MESH - ); - return comp->mesh; -} - -void entityMeshSetMesh( - const entityid_t entityId, - const componentid_t componentId, - mesh_t *mesh -) { - entitymesh_t *comp = componentGetData( - entityId, componentId, COMPONENT_TYPE_MESH - ); - comp->mesh = mesh; -} - -void entityMeshDispose( - const entityid_t entityId, - const componentid_t componentId -) { -} diff --git a/src/dusk/entity/component/display/entitymesh.h b/src/dusk/entity/component/display/entitymesh.h deleted file mode 100644 index 008cdc1d..00000000 --- a/src/dusk/entity/component/display/entitymesh.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "entity/entitybase.h" -#include "display/mesh/mesh.h" - -typedef struct { - mesh_t *mesh; -} entitymesh_t; - -/** - * Initializes the entity mesh component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - */ -void entityMeshInit( - const entityid_t entityId, - const componentid_t componentId -); - -/** - * Retrieves the mesh associated with the entity mesh component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @return A pointer to the mesh associated with the entity mesh component. - */ -mesh_t * entityMeshGetMesh( - const entityid_t entityId, - const componentid_t componentId -); - -/** - * Sets the mesh associated with the entity mesh component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - * @param mesh A pointer to the mesh to associate. - */ -void entityMeshSetMesh( - const entityid_t entityId, - const componentid_t componentId, - mesh_t *mesh -); - -/** - * Disposes the entity mesh component. - * - * @param entityId The entity ID. - * @param componentId The component ID. - */ -void entityMeshDispose( - const entityid_t entityId, - const componentid_t componentId -); diff --git a/src/dusk/entity/component/display/entityposition.c b/src/dusk/entity/component/display/entityposition.c index 8856ead5..3c1c0c30 100644 --- a/src/dusk/entity/component/display/entityposition.c +++ b/src/dusk/entity/component/display/entityposition.c @@ -227,6 +227,37 @@ void entityPositionRebuild(entityposition_t *pos) { entityPositionMarkDirty(pos); } +void entityPositionDisposeDeep( + const entityid_t entityId, + const componentid_t componentId +) { + entityposition_t *pos = entityPositionGet(entityId, componentId); + + // Detach from parent so the parent's child list stays consistent. + if(pos->parentEntityId != ENTITY_ID_INVALID) { + entityPositionSetParent(entityId, componentId, ENTITY_ID_INVALID, COMPONENT_ID_INVALID); + } + + // Copy the child list before disposing self (entityDispose invalidates pos). + uint8_t childCount = pos->childCount; + entityid_t childEntityIds[ENTITY_POSITION_CHILDREN_MAX]; + componentid_t childComponentIds[ENTITY_POSITION_CHILDREN_MAX]; + for(uint8_t i = 0; i < childCount; i++) { + childEntityIds[i] = pos->childEntityIds[i]; + childComponentIds[i] = pos->childComponentIds[i]; + // Sever the child's parent link so it won't try to modify our disposed data. + entityposition_t *child = entityPositionGet(childEntityIds[i], childComponentIds[i]); + child->parentEntityId = ENTITY_ID_INVALID; + child->parentComponentId = COMPONENT_ID_INVALID; + } + + entityDispose(entityId); + + for(uint8_t i = 0; i < childCount; i++) { + entityPositionDisposeDeep(childEntityIds[i], childComponentIds[i]); + } +} + void entityPositionDecompose(entityposition_t *pos) { // Translation: column 3 pos->position[0] = pos->localTransform[3][0]; diff --git a/src/dusk/entity/component/display/entityposition.h b/src/dusk/entity/component/display/entityposition.h index d9843960..1513bfbb 100644 --- a/src/dusk/entity/component/display/entityposition.h +++ b/src/dusk/entity/component/display/entityposition.h @@ -165,6 +165,18 @@ void entityPositionRebuild(entityposition_t *pos); */ void entityPositionMarkDirty(entityposition_t *pos); +/** + * Disposes this entity and all of its position-component descendants + * recursively. Detaches from any parent before destroying. + * + * @param entityId The root entity ID. + * @param componentId The root position component ID. + */ +void entityPositionDisposeDeep( + const entityid_t entityId, + const componentid_t componentId +); + /** * Decomposes the local transform matrix back into the position, rotation * (XYZ euler, radians), and scale cache fields. diff --git a/src/dusk/entity/component/display/entityrenderable.c b/src/dusk/entity/component/display/entityrenderable.c new file mode 100644 index 00000000..abcfc784 --- /dev/null +++ b/src/dusk/entity/component/display/entityrenderable.c @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entityrenderable.h" +#include "entity/entitymanager.h" +#include "display/shader/shaderunlit.h" +#include "display/mesh/cube.h" + +void entityRenderableInit( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->type = ENTITY_RENDERABLE_TYPE_MATERIAL; + r->mesh = &CUBE_MESH_SIMPLE; + r->shader = &SHADER_UNLIT; + r->material.unlit.color = COLOR_WHITE; +} + +entityrenderabletype_t entityRenderableGetType( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + return r->type; +} + +void entityRenderableSetType( + const entityid_t entityId, + const componentid_t componentId, + const entityrenderabletype_t type +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->type = type; +} + +mesh_t * entityRenderableGetMesh( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + return r->mesh; +} + +void entityRenderableSetMesh( + const entityid_t entityId, + const componentid_t componentId, + mesh_t *mesh +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->mesh = mesh; +} + +shader_t * entityRenderableGetShader( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + return r->shader; +} + +void entityRenderableSetShader( + const entityid_t entityId, + const componentid_t componentId, + shader_t *shader +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->shader = shader; +} + +shadermaterial_t * entityRenderableGetShaderMaterial( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + return &r->material; +} + +void entityRenderableSetColor( + const entityid_t entityId, + const componentid_t componentId, + const color_t color +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->material.unlit.color = color; +} + +void entityRenderableSpriteBatchAdd( + const entityid_t entityId, + const componentid_t componentId, + const spritebatchsprite_t *sprite +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + if(r->spritebatch.spriteCount >= ENTITY_RENDERABLE_SPRITEBATCH_SPRITES_MAX) return; + r->spritebatch.sprites[r->spritebatch.spriteCount++] = *sprite; +} + +void entityRenderableSpriteBatchClear( + const entityid_t entityId, + const componentid_t componentId +) { + entityrenderable_t *r = componentGetData( + entityId, componentId, COMPONENT_TYPE_RENDERABLE + ); + r->spritebatch.spriteCount = 0; +} diff --git a/src/dusk/entity/component/display/entityrenderable.h b/src/dusk/entity/component/display/entityrenderable.h new file mode 100644 index 00000000..ea483344 --- /dev/null +++ b/src/dusk/entity/component/display/entityrenderable.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity/entitybase.h" +#include "display/mesh/mesh.h" +#include "display/shader/shadermaterial.h" +#include "display/spritebatch/spritebatch.h" + +#define ENTITY_RENDERABLE_SPRITEBATCH_SPRITES_MAX 64 + +typedef enum { + ENTITY_RENDERABLE_TYPE_MATERIAL = 0, + ENTITY_RENDERABLE_TYPE_SPRITEBATCH, +} entityrenderabletype_t; + +typedef struct { + spritebatchsprite_t sprites[ENTITY_RENDERABLE_SPRITEBATCH_SPRITES_MAX]; + uint16_t spriteCount; +} entityrenderablespritebatch_t; + +typedef struct { + entityrenderabletype_t type; + shader_t *shader; + union { + struct { + mesh_t *mesh; + shadermaterial_t material; + }; + entityrenderablespritebatch_t spritebatch; + }; +} entityrenderable_t; + +/** + * Initializes the entity renderable component. Defaults to + * ENTITY_RENDERABLE_TYPE_MATERIAL, the unlit shader, white color, no mesh. + */ +void entityRenderableInit( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Gets the renderable type. + */ +entityrenderabletype_t entityRenderableGetType( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Sets the renderable type. + */ +void entityRenderableSetType( + const entityid_t entityId, + const componentid_t componentId, + const entityrenderabletype_t type +); + +/** + * Gets the mesh pointer (ENTITY_RENDERABLE_TYPE_MATERIAL only). + */ +mesh_t * entityRenderableGetMesh( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Sets the mesh pointer (ENTITY_RENDERABLE_TYPE_MATERIAL only). + */ +void entityRenderableSetMesh( + const entityid_t entityId, + const componentid_t componentId, + mesh_t *mesh +); + +/** + * Gets the shader pointer. + */ +shader_t * entityRenderableGetShader( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Sets the shader pointer. + */ +void entityRenderableSetShader( + const entityid_t entityId, + const componentid_t componentId, + shader_t *shader +); + +/** + * Gets a pointer to the shader material union + * (ENTITY_RENDERABLE_TYPE_MATERIAL only). + */ +shadermaterial_t * entityRenderableGetShaderMaterial( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Sets the unlit color (ENTITY_RENDERABLE_TYPE_MATERIAL only). + */ +void entityRenderableSetColor( + const entityid_t entityId, + const componentid_t componentId, + const color_t color +); + +/** + * Appends a sprite to the spritebatch renderable + * (ENTITY_RENDERABLE_TYPE_SPRITEBATCH only). + * Does nothing if the sprite buffer is full. + */ +void entityRenderableSpriteBatchAdd( + const entityid_t entityId, + const componentid_t componentId, + const spritebatchsprite_t *sprite +); + +/** + * Clears all buffered sprites from the spritebatch renderable + * (ENTITY_RENDERABLE_TYPE_SPRITEBATCH only). + */ +void entityRenderableSpriteBatchClear( + const entityid_t entityId, + const componentid_t componentId +); diff --git a/src/dusk/entity/component/trigger/CMakeLists.txt b/src/dusk/entity/component/trigger/CMakeLists.txt new file mode 100644 index 00000000..b8c409f8 --- /dev/null +++ b/src/dusk/entity/component/trigger/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2026 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +target_sources(${DUSK_LIBRARY_TARGET_NAME} + PUBLIC + entitytrigger.c +) diff --git a/src/dusk/entity/component/trigger/entitytrigger.c b/src/dusk/entity/component/trigger/entitytrigger.c new file mode 100644 index 00000000..bba57269 --- /dev/null +++ b/src/dusk/entity/component/trigger/entitytrigger.c @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entity/entitymanager.h" + +void entityTriggerInit( + const entityid_t entityId, + const componentid_t componentId +) { + entitytrigger_t *t = componentGetData( + entityId, componentId, COMPONENT_TYPE_TRIGGER + ); + glm_vec3_zero(t->min); + glm_vec3_zero(t->max); +} + +entitytrigger_t * entityTriggerGet( + const entityid_t entityId, + const componentid_t componentId +) { + return componentGetData(entityId, componentId, COMPONENT_TYPE_TRIGGER); +} + +bool_t entityTriggerContains( + const entityid_t entityId, + const componentid_t componentId, + const vec3 point +) { + entitytrigger_t *t = componentGetData( + entityId, componentId, COMPONENT_TYPE_TRIGGER + ); + return ( + point[0] >= t->min[0] && point[0] <= t->max[0] && + point[1] >= t->min[1] && point[1] <= t->max[1] && + point[2] >= t->min[2] && point[2] <= t->max[2] + ); +} + +void entityTriggerSetBounds( + const entityid_t entityId, + const componentid_t componentId, + const vec3 min, + const vec3 max +) { + entitytrigger_t *t = componentGetData( + entityId, componentId, COMPONENT_TYPE_TRIGGER + ); + glm_vec3_copy((float_t*)min, t->min); + glm_vec3_copy((float_t*)max, t->max); +} diff --git a/src/dusk/entity/component/trigger/entitytrigger.h b/src/dusk/entity/component/trigger/entitytrigger.h new file mode 100644 index 00000000..fdbef2c8 --- /dev/null +++ b/src/dusk/entity/component/trigger/entitytrigger.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity/entitybase.h" + +typedef struct { + vec3 min; + vec3 max; +} entitytrigger_t; + +/** + * Initializes the trigger component with zeroed bounds. + */ +void entityTriggerInit( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Returns a pointer to the trigger component data. + */ +entitytrigger_t * entityTriggerGet( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Returns true if the given world-space point lies within [min, max]. + */ +bool_t entityTriggerContains( + const entityid_t entityId, + const componentid_t componentId, + const vec3 point +); + +/** + * Sets both bounds at once. + */ +void entityTriggerSetBounds( + const entityid_t entityId, + const componentid_t componentId, + const vec3 min, + const vec3 max +); diff --git a/src/dusk/entity/componentlist.h b/src/dusk/entity/componentlist.h index 0b9c09be..812cad11 100644 --- a/src/dusk/entity/componentlist.h +++ b/src/dusk/entity/componentlist.h @@ -1,15 +1,15 @@ /** * Copyright (c) 2026 Dominic Masters - * + * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "entity/component/display/entityposition.h" #include "entity/component/display/entitycamera.h" -#include "entity/component/display/entitymesh.h" -#include "entity/component/display/entitymaterial.h" +#include "entity/component/display/entityrenderable.h" #include "entity/component/physics/entityphysics.h" +#include "entity/component/trigger/entitytrigger.h" // Name (Uppercase) // Structure @@ -17,8 +17,8 @@ // Init function (optional) // Dispose function (optional) -X(POSITION, entityposition_t, position, entityPositionInit, NULL) -X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL) -X(MESH, entitymesh_t, mesh, entityMeshInit, entityMeshDispose) -X(MATERIAL, entitymaterial_t, material, entityMaterialInit, NULL) -X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose) \ No newline at end of file +X(POSITION, entityposition_t, position, entityPositionInit, NULL) +X(CAMERA, entitycamera_t, camera, entityCameraInit, NULL) +X(RENDERABLE, entityrenderable_t, renderable, entityRenderableInit, NULL) +X(PHYSICS, entityphysics_t, physics, entityPhysicsInit, entityPhysicsDispose) +X(TRIGGER, entitytrigger_t, trigger, entityTriggerInit, NULL) diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c index 8b36824e..82529516 100644 --- a/src/dusk/entity/entity.c +++ b/src/dusk/entity/entity.c @@ -6,6 +6,7 @@ */ #include "entitymanager.h" +#include "component/display/entityposition.h" #include "util/memory.h" #include "assert/assert.h" @@ -70,6 +71,15 @@ componentid_t entityGetComponent( return compId; } +void entityDisposeDeep(const entityid_t entityId) { + componentid_t posComp = entityGetComponent(entityId, COMPONENT_TYPE_POSITION); + if(posComp != COMPONENT_ID_INVALID) { + entityPositionDisposeDeep(entityId, posComp); + } else { + entityDispose(entityId); + } +} + void entityDispose(const entityid_t entityId) { componentindex_t compInd; entity_t *ent = &ENTITY_MANAGER.entities[entityId]; diff --git a/src/dusk/entity/entity.h b/src/dusk/entity/entity.h index 651ce03d..de437669 100644 --- a/src/dusk/entity/entity.h +++ b/src/dusk/entity/entity.h @@ -48,7 +48,16 @@ componentid_t entityGetComponent( /** * Disposes of an entity with the given ID. - * + * * @param entityId The ID of the entity to dispose of. */ -void entityDispose(const entityid_t entityId); \ No newline at end of file +void entityDispose(const entityid_t entityId); + +/** + * Disposes of an entity and all of its position-component descendants + * recursively. If the entity has no position component, behaves like + * entityDispose. + * + * @param entityId The root entity ID. + */ +void entityDisposeDeep(const entityid_t entityId); \ No newline at end of file diff --git a/src/dusk/save/savestream.c b/src/dusk/save/savestream.c index 4d70d944..9c1da979 100644 --- a/src/dusk/save/savestream.c +++ b/src/dusk/save/savestream.c @@ -314,3 +314,15 @@ errorret_t saveStreamWriteDateImpl( errorOk(); } + +errorret_t saveFileLoad(savestream_t *stream, savefile_t *file) { + saveFileReadHeader(stream, file->header); + saveFileReadVersion(stream, &file->version); + errorOk(); +} + +errorret_t saveFileWrite(savestream_t *stream, savefile_t *file) { + saveFileWriteHeader(stream, file->header); + saveFileWriteVersion(stream, &file->version); + errorOk(); +} diff --git a/src/dusk/scene/scene.c b/src/dusk/scene/scene.c index edce48c5..239e2557 100644 --- a/src/dusk/scene/scene.c +++ b/src/dusk/scene/scene.c @@ -10,7 +10,9 @@ #include "time/time.h" #include "display/screen/screen.h" #include "entity/entitymanager.h" +#include "entity/component/display/entityrenderable.h" #include "display/shader/shaderunlit.h" +#include "display/spritebatch/spritebatch.h" #include "display/screen/screen.h" #include "console/console.h" #include "util/string.h" @@ -67,7 +69,7 @@ errorret_t sceneRender(void) { entityid_t camEnt = camEnts[camIndex]; componentid_t camComp = camComps[camIndex]; componentid_t camPos = entityGetComponent(camEnt, COMPONENT_TYPE_POSITION); - if(camPos == 0xFF) { + if(camPos == COMPONENT_ID_INVALID) { logError("Camera entity without entity position found\n"); continue; } @@ -75,63 +77,59 @@ errorret_t sceneRender(void) { entityCameraGetProjection(camEnt, camComp, proj); entityPositionGetTransform(camEnt, camPos, view); - // For each entity (I could iterate only over entities with mesh/material) - // but in future I may have different renderable types. for(entityid_t entityId = 0; entityId < ENTITY_COUNT_MAX; entityId++) { - // Does this entity have a material? - componentid_t matComp = entityGetComponent( - entityId, COMPONENT_TYPE_MATERIAL + componentid_t renderComp = entityGetComponent( + entityId, COMPONENT_TYPE_RENDERABLE ); - if(matComp != 0xFF) { - // Yes, get the mesh - componentid_t meshComp = entityGetComponent( - entityId, COMPONENT_TYPE_MESH - ); - if(meshComp == 0xFF) { - logError("Entity with material but no mesh found\n"); - continue; - } - mesh_t *mesh = entityMeshGetMesh(entityId, meshComp); - if(mesh == NULL) { - logError("Entity with material but no mesh found\n"); - continue; - } + if(renderComp == COMPONENT_ID_INVALID) continue; - // Yes, get the material and shader. - shadermaterial_t *material = entityMaterialGetShaderMaterial( - entityId, matComp - ); - shader_t *shader = entityMaterialGetShader(entityId, matComp); - if(shader == NULL) { - logError("Entity with material but no shader found\n"); - continue; - } + entityrenderable_t *r = componentGetData( + entityId, renderComp, COMPONENT_TYPE_RENDERABLE + ); - // Get the transform. - componentid_t meshPos = entityGetComponent( - entityId, COMPONENT_TYPE_POSITION - ); - if(meshPos == 0xFF) { - glm_mat4_identity(model); - } else { - entityPositionGetTransform(entityId, meshPos, model); - } - - // Render the mesh. - if(shaderCurrent != shader) { - shaderCurrent = shader; - errorChain(shaderBind(shaderCurrent)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); - } - - errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); - errorChain(shaderSetMaterial(shader, material)); - errorChain(meshDraw(mesh, 0, -1)); - continue; + componentid_t posComp = entityGetComponent( + entityId, COMPONENT_TYPE_POSITION + ); + if(posComp == COMPONENT_ID_INVALID) { + glm_mat4_identity(model); + } else { + entityPositionGetTransform(entityId, posComp, model); } - // No, in future there may be other renderable types. + shader_t *shader = r->shader; + if(!shader) continue; + + switch(r->type) { + case ENTITY_RENDERABLE_TYPE_MATERIAL: { + if(!r->mesh) continue; + if(shaderCurrent != shader) { + shaderCurrent = shader; + errorChain(shaderBind(shaderCurrent)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); + } + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); + errorChain(shaderSetMaterial(shader, &r->material)); + errorChain(meshDraw(r->mesh, 0, -1)); + break; + } + + case ENTITY_RENDERABLE_TYPE_SPRITEBATCH: { + if(r->spritebatch.spriteCount == 0) continue; + if(shaderCurrent != shader) { + shaderCurrent = shader; + errorChain(shaderBind(shaderCurrent)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_PROJECTION, proj)); + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_VIEW, view)); + } + errorChain(shaderSetMatrix(shader, SHADER_UNLIT_MODEL, model)); + for(uint16_t si = 0; si < r->spritebatch.spriteCount; si++) { + errorChain(spriteBatchBufferSprite(&r->spritebatch.sprites[si])); + } + errorChain(spriteBatchFlush()); + break; + } + } } } diff --git a/src/dusk/script/module/animation/moduleanimation.h b/src/dusk/script/module/animation/moduleanimation.h index a5ab2b84..94f772a6 100644 --- a/src/dusk/script/module/animation/moduleanimation.h +++ b/src/dusk/script/module/animation/moduleanimation.h @@ -5,6 +5,7 @@ #pragma once #include "script/module/modulebase.h" +#include "script/module/event/moduleEvent.h" #include "script/scriptproto.h" #include "animation/animation.h" #include "util/memory.h" @@ -36,24 +37,6 @@ static inline animation_t *moduleAnimationGet( return (animation_t *)moduleAnimationGetWrapper(callInfo); } -static easingtype_t moduleAnimationReadEasing(const jerry_value_t val) { - if(jerry_value_is_number(val)) { - return (easingtype_t)(uint32_t)jerry_value_as_number(val); - } - if(jerry_value_is_object(val) || jerry_value_is_function(val)) { - jerry_value_t key = jerry_string_sz("type"); - jerry_value_t typeVal = jerry_object_get(val, key); - jerry_value_free(key); - easingtype_t result = EASING_LINEAR; - if(jerry_value_is_number(typeVal)) { - result = (easingtype_t)(uint32_t)jerry_value_as_number(typeVal); - } - jerry_value_free(typeVal); - return result; - } - return EASING_LINEAR; -} - static void jsAnimationPropertyFree(void *ptr, jerry_object_native_info_t *info) { (void)info; memoryFree(ptr); @@ -98,9 +81,7 @@ static jerry_value_t moduleAnimationFireKeyframes( float_t prevTime, float_t newTime ) { - jerry_value_t kfKey = jerry_string_sz("_keyframes"); - jerry_value_t kfArr = jerry_object_get(propObj, kfKey); - jerry_value_free(kfKey); + jerry_value_t kfArr = moduleBaseGetProp(propObj, "_keyframes"); if(!jerry_value_is_array(kfArr)) { jerry_value_free(kfArr); @@ -111,16 +92,12 @@ static jerry_value_t moduleAnimationFireKeyframes( for(jerry_length_t i = 0; i < len; i++) { jerry_value_t kfObj = jerry_object_get_index(kfArr, i); - jerry_value_t tKey = jerry_string_sz("time"); - jerry_value_t tVal = jerry_object_get(kfObj, tKey); - jerry_value_free(tKey); - float_t kfTime = (float_t)jerry_value_as_number(tVal); + jerry_value_t tVal = moduleBaseGetProp(kfObj, "time"); + float_t kfTime = moduleBaseValueFloat(tVal); jerry_value_free(tVal); if(prevTime < kfTime && newTime >= kfTime) { - jerry_value_t cbKey = jerry_string_sz("onReach"); - jerry_value_t cb = jerry_object_get(kfObj, cbKey); - jerry_value_free(cbKey); + jerry_value_t cb = moduleBaseGetProp(kfObj, "onReach"); if(jerry_value_is_function(cb)) { jerry_value_t r = jerry_call(cb, propObj, NULL, 0); @@ -187,22 +164,16 @@ moduleBaseFunction(moduleAnimationConstructor) { for(jerry_length_t i = 0; i < kfLen; i++) { jerry_value_t kf = jerry_object_get_index(kfArr, i); - jerry_value_t tKey = jerry_string_sz("time"); - jerry_value_t tVal = jerry_object_get(kf, tKey); - jerry_value_free(tKey); - float_t t = (float_t)jerry_value_as_number(tVal); + jerry_value_t tVal = moduleBaseGetProp(kf, "time"); + float_t t = moduleBaseValueFloat(tVal); jerry_value_free(tVal); - jerry_value_t vKey = jerry_string_sz("value"); - jerry_value_t vVal = jerry_object_get(kf, vKey); - jerry_value_free(vKey); - float_t v = (float_t)jerry_value_as_number(vVal); + jerry_value_t vVal = moduleBaseGetProp(kf, "value"); + float_t v = moduleBaseValueFloat(vVal); jerry_value_free(vVal); - jerry_value_t eKey = jerry_string_sz("easing"); - jerry_value_t eVal = jerry_object_get(kf, eKey); - jerry_value_free(eKey); - easingtype_t e = moduleAnimationReadEasing(eVal); + jerry_value_t eVal = moduleBaseGetProp(kf, "easing"); + easingtype_t e = moduleReadEasing(eVal); jerry_value_free(eVal); jerry_value_free(kf); @@ -236,16 +207,12 @@ moduleBaseFunction(moduleAnimationConstructor) { moduleBaseFunction(moduleAnimationUpdate) { jsAnimation_t *janim = moduleAnimationGetWrapper(callInfo); if(!janim) return moduleBaseThrow("Invalid Animation instance"); - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("update() expects a number delta"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); float_t prevTime = janim->anim.time; - animationUpdate(&janim->anim, (float_t)jerry_value_as_number(args[0])); + animationUpdate(&janim->anim, moduleBaseArgFloat(0)); - jerry_value_t propsKey = jerry_string_sz("properties"); - jerry_value_t propsArr = jerry_object_get(callInfo->this_value, propsKey); - jerry_value_free(propsKey); + jerry_value_t propsArr = moduleBaseGetProp(callInfo->this_value, "properties"); if(jerry_value_is_array(propsArr)) { jerry_length_t len = jerry_array_length(propsArr); for(jerry_length_t p = 0; p < len; p++) { @@ -286,8 +253,8 @@ moduleBaseFunction(moduleAnimationGetLoop) { moduleBaseFunction(moduleAnimationSetLoop) { animation_t *anim = moduleAnimationGet(callInfo); if(!anim) return moduleBaseThrow("Invalid Animation instance"); - if(argc < 1) return moduleBaseThrow("Expected boolean"); - if(jerry_value_is_true(args[0])) { + moduleBaseRequireArgs(1); + if(moduleBaseArgBool(0)) { anim->flags |= ANIMATION_FLAG_LOOP_ENABLED; } else { anim->flags &= ~ANIMATION_FLAG_LOOP_ENABLED; diff --git a/src/dusk/script/module/console/moduleconsole.h b/src/dusk/script/module/console/moduleconsole.h index 53c801e3..c09de362 100644 --- a/src/dusk/script/module/console/moduleconsole.h +++ b/src/dusk/script/module/console/moduleconsole.h @@ -43,11 +43,8 @@ moduleBaseFunction(moduleConsoleGetVisible) { } moduleBaseFunction(moduleConsoleSetVisible) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - if(!jerry_value_is_boolean(args[0])) { - return moduleBaseThrow("Console.visible: expected boolean"); - } - CONSOLE.visible = jerry_value_is_true(args[0]); + moduleBaseRequireArgs(1); + CONSOLE.visible = moduleBaseArgBool(0); return jerry_undefined(); } diff --git a/src/dusk/script/module/cutscene/modulecutscene.h b/src/dusk/script/module/cutscene/modulecutscene.h index 62342d89..b1f8219f 100644 --- a/src/dusk/script/module/cutscene/modulecutscene.h +++ b/src/dusk/script/module/cutscene/modulecutscene.h @@ -85,10 +85,7 @@ moduleBaseFunction(moduleCutsceneDefaultDispose) { * Returns the instance for optional chaining. */ moduleBaseFunction(moduleCutsceneThen) { - if(argc < 1 || !jerry_value_is_function(args[0])) { - return moduleBaseThrow("then() expects a function argument"); - } - + moduleBaseRequireArgs(1); moduleBaseRequireFunction(0); jerry_value_t key = jerry_string_sz("_onFinished"); jerry_object_set(callInfo->this_value, key, args[0]); jerry_value_free(key); @@ -104,10 +101,7 @@ moduleBaseFunction(moduleCutsceneThen) { * Returns the instance to allow chaining .then() directly. */ moduleBaseFunction(moduleCutscenePlay) { - if(argc < 1 || !jerry_value_is_object(args[0])) { - return moduleBaseThrow("play() expects a cutscene instance"); - } - + moduleBaseRequireArgs(1); moduleBaseRequireObject(0); if(CUTSCENE.activeRef != CUTSCENE_SCRIPT_REF_NONE) { moduleCutsceneReset(); } diff --git a/src/dusk/script/module/display/modulecolor.h b/src/dusk/script/module/display/modulecolor.h index a92673ab..0228b290 100644 --- a/src/dusk/script/module/display/modulecolor.h +++ b/src/dusk/script/module/display/modulecolor.h @@ -22,76 +22,55 @@ static inline color_t * moduleColorGet( } moduleBaseFunction(moduleColorGetR) { - color_t *c = moduleColorGet(callInfo); - return c ? jerry_number(c->r) : jerry_undefined(); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + return jerry_number(c->r); } moduleBaseFunction(moduleColorGetG) { - color_t *c = moduleColorGet(callInfo); - return c ? jerry_number(c->g) : jerry_undefined(); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + return jerry_number(c->g); } moduleBaseFunction(moduleColorGetB) { - color_t *c = moduleColorGet(callInfo); - return c ? jerry_number(c->b) : jerry_undefined(); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + return jerry_number(c->b); } moduleBaseFunction(moduleColorGetA) { - color_t *c = moduleColorGet(callInfo); - return c ? jerry_number(c->a) : jerry_undefined(); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + return jerry_number(c->a); } moduleBaseFunction(moduleColorSetR) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - color_t *c = moduleColorGet(callInfo); - if(!c) return jerry_undefined(); - c->r = (colorchannel8_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + c->r = (colorchannel8_t)moduleBaseArgInt(0); return args[0]; } moduleBaseFunction(moduleColorSetG) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - color_t *c = moduleColorGet(callInfo); - if(!c) return jerry_undefined(); - c->g = (colorchannel8_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + c->g = (colorchannel8_t)moduleBaseArgInt(0); return args[0]; } moduleBaseFunction(moduleColorSetB) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - color_t *c = moduleColorGet(callInfo); - if(!c) return jerry_undefined(); - c->b = (colorchannel8_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + c->b = (colorchannel8_t)moduleBaseArgInt(0); return args[0]; } moduleBaseFunction(moduleColorSetA) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - color_t *c = moduleColorGet(callInfo); - if(!c) return jerry_undefined(); - c->a = (colorchannel8_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); + c->a = (colorchannel8_t)moduleBaseArgInt(0); return args[0]; } moduleBaseFunction(moduleColorToString) { - color_t *c = moduleColorGet(callInfo); - if(!c) return jerry_undefined(); + moduleBaseGetOrReturn(color_t, c, moduleColorGet); char_t buf[64]; stringFormat( buf, sizeof(buf), @@ -107,38 +86,21 @@ static jerry_value_t moduleColorMakeObject(color_t color) { } moduleBaseFunction(moduleColorConstructor) { - if(argc > 0 && !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Color: r must be a number"); - } - if(argc > 1 && !jerry_value_is_number(args[1])) { - return moduleBaseThrow("Color: g must be a number"); - } - if(argc > 2 && !jerry_value_is_number(args[2])) { - return moduleBaseThrow("Color: b must be a number"); - } - if(argc > 3 && !jerry_value_is_number(args[3])) { - return moduleBaseThrow("Color: a must be a number"); - } + if(argc > 0 && !jerry_value_is_number(args[0])) return moduleBaseThrow("Color: r must be a number"); + if(argc > 1 && !jerry_value_is_number(args[1])) return moduleBaseThrow("Color: g must be a number"); + if(argc > 2 && !jerry_value_is_number(args[2])) return moduleBaseThrow("Color: b must be a number"); + if(argc > 3 && !jerry_value_is_number(args[3])) return moduleBaseThrow("Color: a must be a number"); color_t c; - c.r = argc > 0 ? (colorchannel8_t)jerry_value_as_number(args[0]) : 255; - c.g = argc > 1 ? (colorchannel8_t)jerry_value_as_number(args[1]) : 255; - c.b = argc > 2 ? (colorchannel8_t)jerry_value_as_number(args[2]) : 255; - c.a = argc > 3 ? (colorchannel8_t)jerry_value_as_number(args[3]) : 255; + c.r = (colorchannel8_t)moduleBaseOptInt(0, 255); + c.g = (colorchannel8_t)moduleBaseOptInt(1, 255); + c.b = (colorchannel8_t)moduleBaseOptInt(2, 255); + c.a = (colorchannel8_t)moduleBaseOptInt(3, 255); return moduleColorMakeObject(c); } moduleBaseFunction(moduleColorRainbow) { - float_t t; - - if(argc >= 1 && jerry_value_is_number(args[0])) { - t = (float_t)jerry_value_as_number(args[0]); - } else { - t = TIME.time * 4.0f; - } - - if(argc >= 2 && jerry_value_is_number(args[1])) { - t *= (float_t)jerry_value_as_number(args[1]); - } + float_t t = moduleBaseOptFloat(0, TIME.time * 4.0f); + if(argc >= 2 && jerry_value_is_number(args[1])) t *= moduleBaseArgFloat(1); color_t c; c.r = (colorchannel8_t)((sinf(t) + 1.0f) * 0.5f * 255.0f); diff --git a/src/dusk/script/module/display/modulemesh.h b/src/dusk/script/module/display/modulemesh.h index b81e6c21..163b6772 100644 --- a/src/dusk/script/module/display/modulemesh.h +++ b/src/dusk/script/module/display/modulemesh.h @@ -101,20 +101,22 @@ static jerry_value_t moduleMeshFinalize( // ---- MeshVertex ---- -moduleBaseFunction(moduleMeshVertexGetPosition) { - meshvertexscript_t *mv = (meshvertexscript_t*)scriptProtoGetValue( +static inline meshvertexscript_t * moduleMeshVertexGet( + const jerry_call_info_t *callInfo +) { + return (meshvertexscript_t*)scriptProtoGetValue( &MODULE_MESH_VERTEX_PROTO, callInfo->this_value ); - if(!mv) return jerry_undefined(); +} + +moduleBaseFunction(moduleMeshVertexGetPosition) { + moduleBaseGetOrReturn(meshvertexscript_t, mv, moduleMeshVertexGet); return moduleVec3RefPush(mv->vertex->pos, NULL, NULL); } moduleBaseFunction(moduleMeshVertexSetPosition) { - if(argc < 1) return moduleBaseThrow("Expected position argument"); - meshvertexscript_t *mv = (meshvertexscript_t*)scriptProtoGetValue( - &MODULE_MESH_VERTEX_PROTO, callInfo->this_value - ); - if(!mv) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(meshvertexscript_t, mv, moduleMeshVertexGet); vec3 v; if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); glm_vec3_copy(v, mv->vertex->pos); @@ -124,10 +126,9 @@ moduleBaseFunction(moduleMeshVertexSetPosition) { // ---- Mesh instance ---- moduleBaseFunction(moduleMeshConstructor) { - if(argc < 1) return moduleBaseThrow("Expected vertex count"); - moduleBaseRequireNumber(0); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); - int32_t vertexCount = (int32_t)jerry_value_as_number(args[0]); + int32_t vertexCount = moduleBaseArgInt(0); if(vertexCount <= 0) return moduleBaseThrow("Vertex count must be > 0"); meshscript_t *ms = moduleMeshAlloc(vertexCount); @@ -159,14 +160,12 @@ moduleBaseFunction(moduleMeshGetVertices) { } moduleBaseFunction(moduleMeshGetVertexCount) { - meshscript_t *ms = moduleMeshGet(callInfo); - if(!ms) return jerry_undefined(); + moduleBaseGetOrReturn(meshscript_t, ms, moduleMeshGet); return jerry_number((double)ms->vertexCount); } moduleBaseFunction(moduleMeshFlush) { - meshscript_t *ms = moduleMeshGet(callInfo); - if(!ms) return jerry_undefined(); + moduleBaseGetOrReturn(meshscript_t, ms, moduleMeshGet); if(!ms->initialized) { (void)meshInit( &ms->mesh, @@ -182,8 +181,7 @@ moduleBaseFunction(moduleMeshFlush) { } moduleBaseFunction(moduleMeshDispose) { - meshscript_t *ms = moduleMeshGet(callInfo); - if(!ms) return jerry_undefined(); + moduleBaseGetOrReturn(meshscript_t, ms, moduleMeshGet); if(ms->initialized) { (void)meshDispose(&ms->mesh); ms->initialized = false; @@ -256,10 +254,10 @@ moduleBaseFunction(moduleMeshCreateQuad) { !jerry_value_is_number(args[2]) || !jerry_value_is_number(args[3])) { return moduleBaseThrow("Mesh.createQuad: expected (minX, minY, maxX, maxY)"); } - minX = (float_t)jerry_value_as_number(args[0]); - minY = (float_t)jerry_value_as_number(args[1]); - maxX = (float_t)jerry_value_as_number(args[2]); - maxY = (float_t)jerry_value_as_number(args[3]); + minX = moduleBaseArgFloat(0); + minY = moduleBaseArgFloat(1); + maxX = moduleBaseArgFloat(2); + maxY = moduleBaseArgFloat(3); } meshscript_t *ms = moduleMeshAlloc(QUAD_VERTEX_COUNT); quadBuffer( @@ -275,18 +273,9 @@ moduleBaseFunction(moduleMeshCreateQuad) { // Mesh.createSphere(radius?, stacks?, sectors?) moduleBaseFunction(moduleMeshCreateSphere) { - float_t radius = 0.5f; - int32_t stacks = SPHERE_STACKS; - int32_t sectors = SPHERE_SECTORS; - if(argc >= 1 && jerry_value_is_number(args[0])) { - radius = (float_t)jerry_value_as_number(args[0]); - } - if(argc >= 2 && jerry_value_is_number(args[1])) { - stacks = (int32_t)jerry_value_as_number(args[1]); - } - if(argc >= 3 && jerry_value_is_number(args[2])) { - sectors = (int32_t)jerry_value_as_number(args[2]); - } + float_t radius = moduleBaseOptFloat(0, 0.5f); + int32_t stacks = moduleBaseOptInt(1, SPHERE_STACKS); + int32_t sectors = moduleBaseOptInt(2, SPHERE_SECTORS); int32_t vertexCount = stacks * sectors * 6; vec3 center = { 0.0f, 0.0f, 0.0f }; meshscript_t *ms = moduleMeshAlloc(vertexCount); @@ -301,13 +290,8 @@ moduleBaseFunction(moduleMeshCreateSphere) { // Mesh.createPlane(width?, height?) — XZ-aligned, centered at origin moduleBaseFunction(moduleMeshCreatePlane) { - float_t width = 1.0f, height = 1.0f; - if(argc >= 1 && jerry_value_is_number(args[0])) { - width = (float_t)jerry_value_as_number(args[0]); - } - if(argc >= 2 && jerry_value_is_number(args[1])) { - height = (float_t)jerry_value_as_number(args[1]); - } + float_t width = moduleBaseOptFloat(0, 1.0f); + float_t height = moduleBaseOptFloat(1, 1.0f); vec3 min = { -width * 0.5f, 0.0f, -height * 0.5f }; vec3 max = { width * 0.5f, 0.0f, height * 0.5f }; vec2 uvMin = { 0.0f, 0.0f }; @@ -325,22 +309,10 @@ moduleBaseFunction(moduleMeshCreatePlane) { // Mesh.createCapsule(radius?, halfHeight?, capRings?, sectors?) moduleBaseFunction(moduleMeshCreateCapsule) { - float_t radius = 0.5f; - float_t halfHeight = 0.5f; - int32_t capRings = CAPSULE_CAP_RINGS; - int32_t sectors = CAPSULE_SECTORS; - if(argc >= 1 && jerry_value_is_number(args[0])) { - radius = (float_t)jerry_value_as_number(args[0]); - } - if(argc >= 2 && jerry_value_is_number(args[1])) { - halfHeight = (float_t)jerry_value_as_number(args[1]); - } - if(argc >= 3 && jerry_value_is_number(args[2])) { - capRings = (int32_t)jerry_value_as_number(args[2]); - } - if(argc >= 4 && jerry_value_is_number(args[3])) { - sectors = (int32_t)jerry_value_as_number(args[3]); - } + float_t radius = moduleBaseOptFloat(0, 0.5f); + float_t halfHeight = moduleBaseOptFloat(1, 0.5f); + int32_t capRings = moduleBaseOptInt(2, CAPSULE_CAP_RINGS); + int32_t sectors = moduleBaseOptInt(3, CAPSULE_SECTORS); int32_t vertexCount = (2 * capRings + 1) * sectors * 6; vec3 center = { 0.0f, 0.0f, 0.0f }; meshscript_t *ms = moduleMeshAlloc(vertexCount); @@ -355,19 +327,15 @@ moduleBaseFunction(moduleMeshCreateCapsule) { // Mesh.createTriPrism(x0, y0, x1, y1, x2, y2, minZ, maxZ) moduleBaseFunction(moduleMeshCreateTriPrism) { - if(argc < 8) { - return moduleBaseThrow( - "Mesh.createTriPrism: expected (x0,y0, x1,y1, x2,y2, minZ, maxZ)" - ); - } - float_t x0 = (float_t)jerry_value_as_number(args[0]); - float_t y0 = (float_t)jerry_value_as_number(args[1]); - float_t x1 = (float_t)jerry_value_as_number(args[2]); - float_t y1 = (float_t)jerry_value_as_number(args[3]); - float_t x2 = (float_t)jerry_value_as_number(args[4]); - float_t y2 = (float_t)jerry_value_as_number(args[5]); - float_t minZ = (float_t)jerry_value_as_number(args[6]); - float_t maxZ = (float_t)jerry_value_as_number(args[7]); + moduleBaseRequireArgs(8); + float_t x0 = moduleBaseArgFloat(0); + float_t y0 = moduleBaseArgFloat(1); + float_t x1 = moduleBaseArgFloat(2); + float_t y1 = moduleBaseArgFloat(3); + float_t x2 = moduleBaseArgFloat(4); + float_t y2 = moduleBaseArgFloat(5); + float_t minZ = moduleBaseArgFloat(6); + float_t maxZ = moduleBaseArgFloat(7); meshscript_t *ms = moduleMeshAlloc(TRIPRISM_VERTEX_COUNT); triPrismBuffer( ms->vertices, x0, y0, x1, y1, x2, y2, minZ, maxZ diff --git a/src/dusk/script/module/display/modulescreen.h b/src/dusk/script/module/display/modulescreen.h index e2ef22dc..386ebaeb 100644 --- a/src/dusk/script/module/display/modulescreen.h +++ b/src/dusk/script/module/display/modulescreen.h @@ -28,15 +28,9 @@ moduleBaseFunction(moduleScreenGetBackground) { } moduleBaseFunction(moduleScreenSetBackground) { - if(argc < 1 || !jerry_value_is_object(args[0])) { - return moduleBaseThrow("Screen background color must be a color object"); - } - color_t *color = (color_t*)scriptProtoGetValue( - &MODULE_COLOR_PROTO, args[0] - ); - if(!color) { - return moduleBaseThrow("Background must be a valid color object"); - } + moduleBaseRequireArgs(1); moduleBaseRequireObject(0); + color_t *color = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[0]); + if(!color) return moduleBaseThrow("Background must be a valid color object"); memoryCopy(&SCREEN.background, color, sizeof(color_t)); return jerry_undefined(); } diff --git a/src/dusk/script/module/display/modulespritebatch.h b/src/dusk/script/module/display/modulespritebatch.h index 25e0f557..34db28b5 100644 --- a/src/dusk/script/module/display/modulespritebatch.h +++ b/src/dusk/script/module/display/modulespritebatch.h @@ -21,9 +21,9 @@ moduleBaseFunction(moduleSpriteBatchGetSpriteCount) { moduleBaseFunction(moduleSpriteBatchPush) { #if MESH_ENABLE_COLOR - if(argc < 9) return moduleBaseThrow("expected 9 arguments"); + moduleBaseRequireArgs(9); #else - if(argc < 8) return moduleBaseThrow("expected 8 arguments"); + moduleBaseRequireArgs(8); #endif moduleBaseRequireNumber(0); @@ -32,27 +32,18 @@ moduleBaseFunction(moduleSpriteBatchPush) { moduleBaseRequireNumber(3); #if MESH_ENABLE_COLOR - if(!jerry_value_is_object(args[4])) { - return moduleBaseThrow("color must be a Color object"); - } color_t *col = (color_t *)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[4]); - if(!col) { - return moduleBaseThrow("color must be a Color object"); - } + if(!col) return moduleBaseThrow("color must be a Color object"); moduleBaseRequireNumber(5); moduleBaseRequireNumber(6); moduleBaseRequireNumber(7); moduleBaseRequireNumber(8); spriteBatchPush( - (float_t)jerry_value_as_number(args[0]), - (float_t)jerry_value_as_number(args[1]), - (float_t)jerry_value_as_number(args[2]), - (float_t)jerry_value_as_number(args[3]), + moduleBaseArgFloat(0), moduleBaseArgFloat(1), + moduleBaseArgFloat(2), moduleBaseArgFloat(3), *col, - (float_t)jerry_value_as_number(args[5]), - (float_t)jerry_value_as_number(args[6]), - (float_t)jerry_value_as_number(args[7]), - (float_t)jerry_value_as_number(args[8]) + moduleBaseArgFloat(5), moduleBaseArgFloat(6), + moduleBaseArgFloat(7), moduleBaseArgFloat(8) ); #else moduleBaseRequireNumber(4); @@ -60,14 +51,10 @@ moduleBaseFunction(moduleSpriteBatchPush) { moduleBaseRequireNumber(6); moduleBaseRequireNumber(7); spriteBatchPush( - (float_t)jerry_value_as_number(args[0]), - (float_t)jerry_value_as_number(args[1]), - (float_t)jerry_value_as_number(args[2]), - (float_t)jerry_value_as_number(args[3]), - (float_t)jerry_value_as_number(args[4]), - (float_t)jerry_value_as_number(args[5]), - (float_t)jerry_value_as_number(args[6]), - (float_t)jerry_value_as_number(args[7]) + moduleBaseArgFloat(0), moduleBaseArgFloat(1), + moduleBaseArgFloat(2), moduleBaseArgFloat(3), + moduleBaseArgFloat(4), moduleBaseArgFloat(5), + moduleBaseArgFloat(6), moduleBaseArgFloat(7) ); #endif @@ -76,58 +63,29 @@ moduleBaseFunction(moduleSpriteBatchPush) { moduleBaseFunction(moduleSpriteBatchPush3D) { #if MESH_ENABLE_COLOR - if(argc < 5) return moduleBaseThrow("expected 5 arguments"); + moduleBaseRequireArgs(5); #else - if(argc < 4) return moduleBaseThrow("expected 4 arguments"); + moduleBaseRequireArgs(4); #endif - if(!jerry_value_is_object(args[0])) { - return moduleBaseThrow("min must be a Vec3"); - } float_t *min = moduleVec3From(args[0]); if(!min) return moduleBaseThrow("min must be a Vec3"); - - if(!jerry_value_is_object(args[1])) { - return moduleBaseThrow("max must be a Vec3"); - } float_t *max = moduleVec3From(args[1]); if(!max) return moduleBaseThrow("max must be a Vec3"); #if MESH_ENABLE_COLOR - if(!jerry_value_is_object(args[2])) { - return moduleBaseThrow("color must be a Color object"); - } color_t *col = (color_t *)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[2]); - if(!col) { - return moduleBaseThrow("color must be a Color object"); - } - - if(!jerry_value_is_object(args[3])) { - return moduleBaseThrow("uvMin must be a Vec2"); - } + if(!col) return moduleBaseThrow("color must be a Color object"); float_t *uvMin = moduleVec2From(args[3]); if(!uvMin) return moduleBaseThrow("uvMin must be a Vec2"); - - if(!jerry_value_is_object(args[4])) { - return moduleBaseThrow("uvMax must be a Vec2"); - } float_t *uvMax = moduleVec2From(args[4]); if(!uvMax) return moduleBaseThrow("uvMax must be a Vec2"); - spriteBatchPush3D(min, max, *col, uvMin, uvMax); #else - if(!jerry_value_is_object(args[2])) { - return moduleBaseThrow("uvMin must be a Vec2"); - } float_t *uvMin = moduleVec2From(args[2]); if(!uvMin) return moduleBaseThrow("uvMin must be a Vec2"); - - if(!jerry_value_is_object(args[3])) { - return moduleBaseThrow("uvMax must be a Vec2"); - } float_t *uvMax = moduleVec2From(args[3]); if(!uvMax) return moduleBaseThrow("uvMax must be a Vec2"); - spriteBatchPush3D(min, max, uvMin, uvMax); #endif diff --git a/src/dusk/script/module/display/moduletext.h b/src/dusk/script/module/display/moduletext.h index ab84561e..55135bba 100644 --- a/src/dusk/script/module/display/moduletext.h +++ b/src/dusk/script/module/display/moduletext.h @@ -14,21 +14,17 @@ static scriptproto_t MODULE_TEXT_PROTO; moduleBaseFunction(moduleTextDraw) { - if(argc < 3) return moduleBaseThrow("expected at least 3 arguments"); - moduleBaseRequireNumber(0); - moduleBaseRequireNumber(1); - if(!jerry_value_is_string(args[2])) { - return moduleBaseThrow("text must be a string"); - } + moduleBaseRequireArgs(3); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + moduleBaseRequireString(2); - float_t x = (float_t)jerry_value_as_number(args[0]); - float_t y = (float_t)jerry_value_as_number(args[1]); + float_t x = moduleBaseArgFloat(0); + float_t y = moduleBaseArgFloat(1); char_t text[1024]; moduleBaseToString(args[2], text, sizeof(text)); color_t col = COLOR_WHITE; - if(argc >= 4 && jerry_value_is_object(args[3])) { + if(argc >= 4) { color_t *c = (color_t *)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[3]); if(c) col = *c; } @@ -45,10 +41,7 @@ moduleBaseFunction(moduleTextDraw) { } moduleBaseFunction(moduleTextMeasure) { - if(argc < 1) return moduleBaseThrow("expected at least 1 argument"); - if(!jerry_value_is_string(args[0])) { - return moduleBaseThrow("text must be a string"); - } + moduleBaseRequireArgs(1); moduleBaseRequireString(0); char_t text[1024]; moduleBaseToString(args[0], text, sizeof(text)); diff --git a/src/dusk/script/module/entity/component/moduleentitycamera.h b/src/dusk/script/module/entity/component/moduleentitycamera.h index e32af40e..c3500ece 100644 --- a/src/dusk/script/module/entity/component/moduleentitycamera.h +++ b/src/dusk/script/module/entity/component/moduleentitycamera.h @@ -21,177 +21,133 @@ static entitycamera_t * moduleEntityCameraGet( &MODULE_ENTITY_CAMERA_PROTO, callInfo->this_value ); if(!h) return NULL; - return (entitycamera_t*)componentGetData( - h->eid, h->cid, COMPONENT_TYPE_CAMERA - ); + return (entitycamera_t*)componentGetData(h->eid, h->cid, COMPONENT_TYPE_CAMERA); } +// ---- Getters ---- + moduleBaseFunction(moduleEntityCameraGetZNear) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); return jerry_number(cam->nearClip); } moduleBaseFunction(moduleEntityCameraGetZFar) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); return jerry_number(cam->farClip); } -moduleBaseFunction(moduleEntityCameraGetOrthoTop) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - return jerry_number(cam->orthographic.top); -} - -moduleBaseFunction(moduleEntityCameraGetOrthoBottom) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - return jerry_number(cam->orthographic.bottom); -} - -moduleBaseFunction(moduleEntityCameraGetOrthoLeft) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - return jerry_number(cam->orthographic.left); -} - -moduleBaseFunction(moduleEntityCameraGetOrthoRight) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - return jerry_number(cam->orthographic.right); -} - moduleBaseFunction(moduleEntityCameraGetFov) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || ( + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if( cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE && cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED - )) { - return jerry_undefined(); - } + ) return jerry_undefined(); return jerry_number(cam->perspective.fov); } moduleBaseFunction(moduleEntityCameraGetProjectionType) { - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); return jerry_number(cam->projType); } +moduleBaseFunction(moduleEntityCameraGetOrthoTop) { + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + return jerry_number(cam->orthographic.top); +} + +moduleBaseFunction(moduleEntityCameraGetOrthoBottom) { + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + return jerry_number(cam->orthographic.bottom); +} + +moduleBaseFunction(moduleEntityCameraGetOrthoLeft) { + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + return jerry_number(cam->orthographic.left); +} + +moduleBaseFunction(moduleEntityCameraGetOrthoRight) { + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + return jerry_number(cam->orthographic.right); +} + +// ---- Setters ---- + moduleBaseFunction(moduleEntityCameraSetZNear) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); - cam->nearClip = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + cam->nearClip = moduleBaseArgFloat(0); return args[0]; } moduleBaseFunction(moduleEntityCameraSetZFar) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); - cam->farClip = (float_t)jerry_value_as_number(args[0]); - return args[0]; -} - -moduleBaseFunction(moduleEntityCameraSetOrthoTop) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - cam->orthographic.top = (float_t)jerry_value_as_number(args[0]); - return args[0]; -} - -moduleBaseFunction(moduleEntityCameraSetOrthoBottom) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - cam->orthographic.bottom = (float_t)jerry_value_as_number(args[0]); - return args[0]; -} - -moduleBaseFunction(moduleEntityCameraSetOrthoLeft) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - cam->orthographic.left = (float_t)jerry_value_as_number(args[0]); - return args[0]; -} - -moduleBaseFunction(moduleEntityCameraSetOrthoRight) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) { - return jerry_undefined(); - } - cam->orthographic.right = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + cam->farClip = moduleBaseArgFloat(0); return args[0]; } moduleBaseFunction(moduleEntityCameraSetFov) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam || ( + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if( cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE && cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE_FLIPPED - )) { - return jerry_undefined(); - } - cam->perspective.fov = (float_t)jerry_value_as_number(args[0]); + ) return jerry_undefined(); + cam->perspective.fov = moduleBaseArgFloat(0); return args[0]; } moduleBaseFunction(moduleEntityCameraSetProjectionType) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected a number"); - } - entitycamera_t *cam = moduleEntityCameraGet(callInfo); - if(!cam) return jerry_undefined(); - int32_t projType = (int32_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + int32_t t = moduleBaseArgInt(0); if( - projType < ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE || - projType > ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC - ) { - return moduleBaseThrow("Invalid projection type"); - } - cam->projType = (entitycameraprojectiontype_t)projType; + t < ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE || + t > ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC + ) return moduleBaseThrow("Invalid projection type"); + cam->projType = (entitycameraprojectiontype_t)t; + return args[0]; +} + +moduleBaseFunction(moduleEntityCameraSetOrthoTop) { + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + cam->orthographic.top = moduleBaseArgFloat(0); + return args[0]; +} + +moduleBaseFunction(moduleEntityCameraSetOrthoBottom) { + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + cam->orthographic.bottom = moduleBaseArgFloat(0); + return args[0]; +} + +moduleBaseFunction(moduleEntityCameraSetOrthoLeft) { + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + cam->orthographic.left = moduleBaseArgFloat(0); + return args[0]; +} + +moduleBaseFunction(moduleEntityCameraSetOrthoRight) { + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + if(cam->projType != ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC) return jerry_undefined(); + cam->orthographic.right = moduleBaseArgFloat(0); return args[0]; } moduleBaseFunction(moduleEntityCameraAdd) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - moduleBaseRequireNumber(0); - - entityid_t id = (entityid_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + entityid_t id = (entityid_t)moduleBaseArgInt(0); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_CAMERA); componenthandle_t h = { .eid = id, .cid = comp }; return scriptProtoCreateValue(&MODULE_ENTITY_CAMERA_PROTO, &h); @@ -202,45 +158,25 @@ static void moduleEntityCAMERA(void) { &MODULE_ENTITY_CAMERA_PROTO, NULL, sizeof(componenthandle_t), NULL ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "zNear", - moduleEntityCameraGetZNear, moduleEntityCameraSetZNear - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "zFar", - moduleEntityCameraGetZFar, moduleEntityCameraSetZFar - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "orthoTop", - moduleEntityCameraGetOrthoTop, moduleEntityCameraSetOrthoTop - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "orthoBottom", - moduleEntityCameraGetOrthoBottom, moduleEntityCameraSetOrthoBottom - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "orthoLeft", - moduleEntityCameraGetOrthoLeft, moduleEntityCameraSetOrthoLeft - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "orthoRight", - moduleEntityCameraGetOrthoRight, moduleEntityCameraSetOrthoRight - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "fov", - moduleEntityCameraGetFov, moduleEntityCameraSetFov - ); - scriptProtoDefineProp( - &MODULE_ENTITY_CAMERA_PROTO, "projectionType", - moduleEntityCameraGetProjectionType, moduleEntityCameraSetProjectionType - ); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "zNear", + moduleEntityCameraGetZNear, moduleEntityCameraSetZNear); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "zFar", + moduleEntityCameraGetZFar, moduleEntityCameraSetZFar); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "fov", + moduleEntityCameraGetFov, moduleEntityCameraSetFov); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "projectionType", + moduleEntityCameraGetProjectionType, moduleEntityCameraSetProjectionType); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "orthoTop", + moduleEntityCameraGetOrthoTop, moduleEntityCameraSetOrthoTop); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "orthoBottom", + moduleEntityCameraGetOrthoBottom, moduleEntityCameraSetOrthoBottom); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "orthoLeft", + moduleEntityCameraGetOrthoLeft, moduleEntityCameraSetOrthoLeft); + scriptProtoDefineProp(&MODULE_ENTITY_CAMERA_PROTO, "orthoRight", + moduleEntityCameraGetOrthoRight, moduleEntityCameraSetOrthoRight); - moduleBaseSetInt( - "CAMERA_TYPE_ORTHOGRAPHIC", - ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC - ); - moduleBaseSetInt( - "CAMERA_TYPE_PERSPECTIVE", - ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE - ); + moduleBaseSetInt("CAMERA_TYPE_ORTHOGRAPHIC", + ENTITY_CAMERA_PROJECTION_TYPE_ORTHOGRAPHIC); + moduleBaseSetInt("CAMERA_TYPE_PERSPECTIVE", + ENTITY_CAMERA_PROJECTION_TYPE_PERSPECTIVE); } diff --git a/src/dusk/script/module/entity/component/moduleentitymaterial.h b/src/dusk/script/module/entity/component/moduleentitymaterial.h deleted file mode 100644 index f6527055..00000000 --- a/src/dusk/script/module/entity/component/moduleentitymaterial.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "script/module/modulebase.h" -#include "script/module/display/modulecolor.h" -#include "script/scriptproto.h" -#include "entity/entity.h" -#include "entity/component/display/entitymaterial.h" -#include "moduleentityposition.h" - -static scriptproto_t MODULE_ENTITY_MATERIAL_PROTO; - -static entitymaterial_t * moduleEntityMaterialGet( - const jerry_call_info_t *callInfo -) { - componenthandle_t *h = scriptProtoGetValue( - &MODULE_ENTITY_MATERIAL_PROTO, callInfo->this_value - ); - if(!h) return NULL; - return (entitymaterial_t*)componentGetData( - h->eid, h->cid, COMPONENT_TYPE_MATERIAL - ); -} - -moduleBaseFunction(moduleEntityMaterialGetColor) { - entitymaterial_t *mat = moduleEntityMaterialGet(callInfo); - if(!mat) return jerry_undefined(); - return moduleColorMakeObject(mat->material.unlit.color); -} - -moduleBaseFunction(moduleEntityMaterialSetColor) { - if(argc < 1 || !jerry_value_is_object(args[0])) { - return moduleBaseThrow("Material.color: expected color object"); - } - color_t *color = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[0]); - if(!color) { - return moduleBaseThrow("Material.color: expected valid color object"); - } - entitymaterial_t *mat = moduleEntityMaterialGet(callInfo); - if(!mat) return jerry_undefined(); - memoryCopy(&mat->material.unlit.color, color, sizeof(color_t)); - return jerry_undefined(); -} - -moduleBaseFunction(moduleEntityMaterialAdd) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Expected at least 1 argument"); - } - entityid_t id = (entityid_t)jerry_value_as_number(args[0]); - componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_MATERIAL); - componenthandle_t h = { .eid = id, .cid = comp }; - return scriptProtoCreateValue(&MODULE_ENTITY_MATERIAL_PROTO, &h); -} - -static void moduleEntityMATERIAL(void) { - scriptProtoInit( - &MODULE_ENTITY_MATERIAL_PROTO, - NULL, - sizeof(componenthandle_t), - NULL - ); - - scriptProtoDefineProp( - &MODULE_ENTITY_MATERIAL_PROTO, "color", - moduleEntityMaterialGetColor, moduleEntityMaterialSetColor - ); -} diff --git a/src/dusk/script/module/entity/component/moduleentitymesh.h b/src/dusk/script/module/entity/component/moduleentitymesh.h deleted file mode 100644 index aa6befec..00000000 --- a/src/dusk/script/module/entity/component/moduleentitymesh.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright (c) 2026 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#pragma once -#include "script/module/modulebase.h" -#include "script/scriptproto.h" -#include "script/module/display/modulemesh.h" -#include "entity/entity.h" -#include "entity/component/display/entitymesh.h" -#include "moduleentityposition.h" - -static scriptproto_t MODULE_ENTITY_MESH_PROTO; - -static entitymesh_t * moduleEntityMeshGet( - const jerry_call_info_t *callInfo -) { - componenthandle_t *h = scriptProtoGetValue( - &MODULE_ENTITY_MESH_PROTO, callInfo->this_value - ); - if(!h) return NULL; - return (entitymesh_t*)componentGetData(h->eid, h->cid, COMPONENT_TYPE_MESH); -} - -moduleBaseFunction(moduleEntityMeshGetMesh) { - entitymesh_t *comp = moduleEntityMeshGet(callInfo); - if(!comp || !comp->mesh) return jerry_undefined(); - return moduleBaseWrapPointer(comp->mesh); -} - -moduleBaseFunction(moduleEntityMeshSetMesh) { - if(argc < 1) return moduleBaseThrow("Expected a Mesh argument"); - entitymesh_t *comp = moduleEntityMeshGet(callInfo); - if(!comp) return jerry_undefined(); - - meshscript_t *ms = moduleMeshFrom(args[0]); - if(ms) { - comp->mesh = &ms->mesh; - return jerry_undefined(); - } - - mesh_t *raw = (mesh_t*)moduleBaseUnwrapPointer(args[0]); - if(raw) { - comp->mesh = raw; - return jerry_undefined(); - } - - return moduleBaseThrow("Expected a Mesh object or mesh constant"); -} - -static void moduleEntityMESH(void) { - scriptProtoInit( - &MODULE_ENTITY_MESH_PROTO, NULL, - sizeof(componenthandle_t), NULL - ); - scriptProtoDefineProp( - &MODULE_ENTITY_MESH_PROTO, "mesh", - moduleEntityMeshGetMesh, moduleEntityMeshSetMesh - ); -} diff --git a/src/dusk/script/module/entity/component/moduleentityphysics.h b/src/dusk/script/module/entity/component/moduleentityphysics.h index 976e0aa0..c75d73d5 100644 --- a/src/dusk/script/module/entity/component/moduleentityphysics.h +++ b/src/dusk/script/module/entity/component/moduleentityphysics.h @@ -26,123 +26,87 @@ static entityphysics_t * moduleEntityPhysicsGet( } moduleBaseFunction(moduleEntityPhysicsGetVelocity) { - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); return moduleVec3RefPush(phys->velocity, NULL, NULL); } moduleBaseFunction(moduleEntityPhysicsSetVelocity) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); vec3 v; - if(!moduleVec3AnyCheck(args[0], v)) { - return moduleBaseThrow("expected Vec3"); - } + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); glm_vec3_copy(v, phys->velocity); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsGetOnGround) { - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); return jerry_boolean(phys->onGround); } moduleBaseFunction(moduleEntityPhysicsGetBodyType) { - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); return jerry_number(phys->type); } moduleBaseFunction(moduleEntityPhysicsSetBodyType) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); - phys->type = (physicsbodytype_t)(int32_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); + phys->type = (physicsbodytype_t)moduleBaseArgInt(0); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsApplyImpulse) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); if(phys->type == PHYSICS_BODY_STATIC) return jerry_undefined(); vec3 impulse; - if(!moduleVec3Check(args[0], impulse)) { - return moduleBaseThrow("expected Vec3 impulse"); - } + if(!moduleVec3Check(args[0], impulse)) return moduleBaseThrow("Expected Vec3 impulse"); glm_vec3_add(phys->velocity, impulse, phys->velocity); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsSetShapeCube) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); vec3 half; - if(!moduleVec3Check(args[0], half)) { - return moduleBaseThrow("expected Vec3 halfExtents"); - } + if(!moduleVec3Check(args[0], half)) return moduleBaseThrow("Expected Vec3 halfExtents"); phys->shape.type = PHYSICS_SHAPE_CUBE; glm_vec3_copy(half, phys->shape.data.cube.halfExtents); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsSetShapeSphere) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); phys->shape.type = PHYSICS_SHAPE_SPHERE; - phys->shape.data.sphere.radius = (float_t)jerry_value_as_number(args[0]); + phys->shape.data.sphere.radius = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsSetShapeCapsule) { - if(argc < 2) return moduleBaseThrow("Expected at least 2 arguments"); - moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); phys->shape.type = PHYSICS_SHAPE_CAPSULE; - phys->shape.data.capsule.radius = (float_t)jerry_value_as_number(args[0]); - phys->shape.data.capsule.halfHeight = - (float_t)jerry_value_as_number(args[1]); + phys->shape.data.capsule.radius = moduleBaseArgFloat(0); + phys->shape.data.capsule.halfHeight = moduleBaseArgFloat(1); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsSetShapePlane) { - if(argc < 2) { - return moduleBaseThrow("Expected at least 2 arguments"); - } - moduleBaseRequireNumber(1); - - entityphysics_t *phys = moduleEntityPhysicsGet(callInfo); - if(!phys) return jerry_undefined(); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(1); + moduleBaseGetOrReturn(entityphysics_t, phys, moduleEntityPhysicsGet); vec3 normal; - if(!moduleVec3Check(args[0], normal)) { - return moduleBaseThrow("expected Vec3 normal"); - } + if(!moduleVec3Check(args[0], normal)) return moduleBaseThrow("Expected Vec3 normal"); phys->shape.type = PHYSICS_SHAPE_PLANE; glm_vec3_copy(normal, phys->shape.data.plane.normal); - phys->shape.data.plane.distance = (float_t)jerry_value_as_number(args[1]); + phys->shape.data.plane.distance = moduleBaseArgFloat(1); return jerry_undefined(); } moduleBaseFunction(moduleEntityPhysicsAdd) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - entityid_t id = (entityid_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + entityid_t id = (entityid_t)moduleBaseArgInt(0); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_PHYSICS); componenthandle_t h = { .eid = id, .cid = comp }; return scriptProtoCreateValue(&MODULE_ENTITY_PHYSICS_PROTO, &h); @@ -150,43 +114,26 @@ moduleBaseFunction(moduleEntityPhysicsAdd) { static void moduleEntityPHYSICS(void) { scriptProtoInit( - &MODULE_ENTITY_PHYSICS_PROTO, NULL, - sizeof(componenthandle_t), NULL + &MODULE_ENTITY_PHYSICS_PROTO, NULL, sizeof(componenthandle_t), NULL ); - scriptProtoDefineProp( - &MODULE_ENTITY_PHYSICS_PROTO, "velocity", - moduleEntityPhysicsGetVelocity, moduleEntityPhysicsSetVelocity - ); - scriptProtoDefineProp( - &MODULE_ENTITY_PHYSICS_PROTO, "onGround", - moduleEntityPhysicsGetOnGround, NULL - ); - scriptProtoDefineProp( - &MODULE_ENTITY_PHYSICS_PROTO, "bodyType", - moduleEntityPhysicsGetBodyType, moduleEntityPhysicsSetBodyType - ); + scriptProtoDefineProp(&MODULE_ENTITY_PHYSICS_PROTO, "velocity", + moduleEntityPhysicsGetVelocity, moduleEntityPhysicsSetVelocity); + scriptProtoDefineProp(&MODULE_ENTITY_PHYSICS_PROTO, "onGround", + moduleEntityPhysicsGetOnGround, NULL); + scriptProtoDefineProp(&MODULE_ENTITY_PHYSICS_PROTO, "bodyType", + moduleEntityPhysicsGetBodyType, moduleEntityPhysicsSetBodyType); - scriptProtoDefineFunc( - &MODULE_ENTITY_PHYSICS_PROTO, "applyImpulse", - moduleEntityPhysicsApplyImpulse - ); - scriptProtoDefineFunc( - &MODULE_ENTITY_PHYSICS_PROTO, "setShapeCube", - moduleEntityPhysicsSetShapeCube - ); - scriptProtoDefineFunc( - &MODULE_ENTITY_PHYSICS_PROTO, "setShapeSphere", - moduleEntityPhysicsSetShapeSphere - ); - scriptProtoDefineFunc( - &MODULE_ENTITY_PHYSICS_PROTO, "setShapeCapsule", - moduleEntityPhysicsSetShapeCapsule - ); - scriptProtoDefineFunc( - &MODULE_ENTITY_PHYSICS_PROTO, "setShapePlane", - moduleEntityPhysicsSetShapePlane - ); + scriptProtoDefineFunc(&MODULE_ENTITY_PHYSICS_PROTO, "applyImpulse", + moduleEntityPhysicsApplyImpulse); + scriptProtoDefineFunc(&MODULE_ENTITY_PHYSICS_PROTO, "setShapeCube", + moduleEntityPhysicsSetShapeCube); + scriptProtoDefineFunc(&MODULE_ENTITY_PHYSICS_PROTO, "setShapeSphere", + moduleEntityPhysicsSetShapeSphere); + scriptProtoDefineFunc(&MODULE_ENTITY_PHYSICS_PROTO, "setShapeCapsule", + moduleEntityPhysicsSetShapeCapsule); + scriptProtoDefineFunc(&MODULE_ENTITY_PHYSICS_PROTO, "setShapePlane", + moduleEntityPhysicsSetShapePlane); moduleBaseSetInt("PHYSICS_BODY_STATIC", PHYSICS_BODY_STATIC); moduleBaseSetInt("PHYSICS_BODY_DYNAMIC", PHYSICS_BODY_DYNAMIC); diff --git a/src/dusk/script/module/entity/component/moduleentityposition.h b/src/dusk/script/module/entity/component/moduleentityposition.h index cc1132eb..9786e28f 100644 --- a/src/dusk/script/module/entity/component/moduleentityposition.h +++ b/src/dusk/script/module/entity/component/moduleentityposition.h @@ -33,95 +33,67 @@ static entityposition_t * moduleEntityPositionGet( } moduleBaseFunction(moduleEntityPositionGetPosition) { - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); - return moduleVec3RefPush( - pos->position, (void(*)(void*))entityPositionRebuild, pos - ); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); + return moduleVec3RefPush(pos->position, (void(*)(void*))entityPositionRebuild, pos); } moduleBaseFunction(moduleEntityPositionSetPosition) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); vec3 v; - if(!moduleVec3AnyCheck(args[0], v)) { - return moduleBaseThrow("expected Vec3"); - } + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); glm_vec3_copy(v, pos->position); entityPositionRebuild(pos); return jerry_undefined(); } moduleBaseFunction(moduleEntityPositionGetRotation) { - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); - return moduleVec3RefPush( - pos->rotation, (void(*)(void*))entityPositionRebuild, pos - ); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); + return moduleVec3RefPush(pos->rotation, (void(*)(void*))entityPositionRebuild, pos); } moduleBaseFunction(moduleEntityPositionSetRotation) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); vec3 v; - if(!moduleVec3AnyCheck(args[0], v)) { - return moduleBaseThrow("expected Vec3"); - } + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); glm_vec3_copy(v, pos->rotation); entityPositionRebuild(pos); return jerry_undefined(); } moduleBaseFunction(moduleEntityPositionGetScale) { - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); - return moduleVec3RefPush( - pos->scale, (void(*)(void*))entityPositionRebuild, pos - ); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); + return moduleVec3RefPush(pos->scale, (void(*)(void*))entityPositionRebuild, pos); } moduleBaseFunction(moduleEntityPositionSetScale) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - entityposition_t *pos = moduleEntityPositionGet(callInfo); - if(!pos) return jerry_undefined(); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); vec3 v; - if(!moduleVec3AnyCheck(args[0], v)) { - return moduleBaseThrow("expected Vec3"); - } + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); glm_vec3_copy(v, pos->scale); entityPositionRebuild(pos); return jerry_undefined(); } moduleBaseFunction(moduleEntityPositionLookAt) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); + vec3 target; + if(!moduleVec3AnyCheck(args[0], target)) return moduleBaseThrow("Expected Vec3 target"); + vec3 up = { 0.0f, 1.0f, 0.0f }; + if(argc >= 2 && !moduleVec3AnyCheck(args[1], up)) return moduleBaseThrow("Expected Vec3 up"); componenthandle_t *h = scriptProtoGetValue( &MODULE_ENTITY_POSITION_PROTO, callInfo->this_value ); - if(!h) return jerry_undefined(); - entityposition_t *pos = entityPositionGet(h->eid, h->cid); - if(!pos) return jerry_undefined(); - vec3 target; - if(!moduleVec3AnyCheck(args[0], target)) { - return moduleBaseThrow("expected Vec3 target"); - } - vec3 up = { 0.0f, 1.0f, 0.0f }; - if(argc >= 2 && !moduleVec3AnyCheck(args[1], up)) { - return moduleBaseThrow("expected Vec3 up"); - } entityPositionLookAt(h->eid, h->cid, target, up, pos->position); return jerry_undefined(); } moduleBaseFunction(moduleEntityPositionGetParent) { - componenthandle_t *h = scriptProtoGetValue( - &MODULE_ENTITY_POSITION_PROTO, callInfo->this_value - ); - if(!h) return jerry_undefined(); - entityposition_t *pos = entityPositionGet(h->eid, h->cid); - if(!pos || pos->parentEntityId == ENTITY_ID_INVALID) return jerry_null(); + moduleBaseGetOrReturn(entityposition_t, pos, moduleEntityPositionGet); + if(pos->parentEntityId == ENTITY_ID_INVALID) return jerry_null(); componenthandle_t ph = { .eid = pos->parentEntityId, .cid = pos->parentComponentId }; return scriptProtoCreateValue(&MODULE_ENTITY_POSITION_PROTO, &ph); } @@ -131,27 +103,19 @@ moduleBaseFunction(moduleEntityPositionSetParentProp) { &MODULE_ENTITY_POSITION_PROTO, callInfo->this_value ); if(!h) return jerry_undefined(); - if(argc < 1 || jerry_value_is_null(args[0]) || jerry_value_is_undefined(args[0])) { entityPositionSetParent(h->eid, h->cid, ENTITY_ID_INVALID, COMPONENT_ID_INVALID); return jerry_undefined(); } - - componenthandle_t *ph = scriptProtoGetValue( - &MODULE_ENTITY_POSITION_PROTO, args[0] - ); - if(!ph) return moduleBaseThrow("expected EntityPosition"); + componenthandle_t *ph = scriptProtoGetValue(&MODULE_ENTITY_POSITION_PROTO, args[0]); + if(!ph) return moduleBaseThrow("Expected EntityPosition"); entityPositionSetParent(h->eid, h->cid, ph->eid, ph->cid); return jerry_undefined(); } moduleBaseFunction(moduleEntityPositionAdd) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - entityid_t id = (entityid_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + entityid_t id = (entityid_t)moduleBaseArgInt(0); componentid_t comp = entityAddComponent(id, COMPONENT_TYPE_POSITION); componenthandle_t h = { .eid = id, .cid = comp }; return scriptProtoCreateValue(&MODULE_ENTITY_POSITION_PROTO, &h); @@ -159,30 +123,16 @@ moduleBaseFunction(moduleEntityPositionAdd) { static void moduleEntityPOSITION(void) { scriptProtoInit( - &MODULE_ENTITY_POSITION_PROTO, NULL, - sizeof(componenthandle_t), NULL + &MODULE_ENTITY_POSITION_PROTO, NULL, sizeof(componenthandle_t), NULL ); - - scriptProtoDefineProp( - &MODULE_ENTITY_POSITION_PROTO, "position", - moduleEntityPositionGetPosition, moduleEntityPositionSetPosition - ); - scriptProtoDefineProp( - &MODULE_ENTITY_POSITION_PROTO, "rotation", - moduleEntityPositionGetRotation, moduleEntityPositionSetRotation - ); - scriptProtoDefineProp( - &MODULE_ENTITY_POSITION_PROTO, "scale", - moduleEntityPositionGetScale, moduleEntityPositionSetScale - ); - - scriptProtoDefineFunc( - &MODULE_ENTITY_POSITION_PROTO, "lookAt", - moduleEntityPositionLookAt - ); - - scriptProtoDefineProp( - &MODULE_ENTITY_POSITION_PROTO, "parent", - moduleEntityPositionGetParent, moduleEntityPositionSetParentProp - ); -} \ No newline at end of file + scriptProtoDefineProp(&MODULE_ENTITY_POSITION_PROTO, "position", + moduleEntityPositionGetPosition, moduleEntityPositionSetPosition); + scriptProtoDefineProp(&MODULE_ENTITY_POSITION_PROTO, "rotation", + moduleEntityPositionGetRotation, moduleEntityPositionSetRotation); + scriptProtoDefineProp(&MODULE_ENTITY_POSITION_PROTO, "scale", + moduleEntityPositionGetScale, moduleEntityPositionSetScale); + scriptProtoDefineProp(&MODULE_ENTITY_POSITION_PROTO, "parent", + moduleEntityPositionGetParent, moduleEntityPositionSetParentProp); + scriptProtoDefineFunc(&MODULE_ENTITY_POSITION_PROTO, "lookAt", + moduleEntityPositionLookAt); +} diff --git a/src/dusk/script/module/entity/component/moduleentityrenderable.h b/src/dusk/script/module/entity/component/moduleentityrenderable.h new file mode 100644 index 00000000..06e8f364 --- /dev/null +++ b/src/dusk/script/module/entity/component/moduleentityrenderable.h @@ -0,0 +1,132 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/module/modulebase.h" +#include "script/module/display/modulemesh.h" +#include "script/module/display/modulecolor.h" +#include "script/scriptproto.h" +#include "entity/entity.h" +#include "entity/component/display/entityrenderable.h" +#include "moduleentityposition.h" + +static scriptproto_t MODULE_ENTITY_RENDERABLE_PROTO; + +static entityrenderable_t * moduleEntityRenderableGet( + const jerry_call_info_t *callInfo +) { + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_RENDERABLE_PROTO, callInfo->this_value + ); + if(!h) return NULL; + return (entityrenderable_t*)componentGetData( + h->eid, h->cid, COMPONENT_TYPE_RENDERABLE + ); +} + +moduleBaseFunction(moduleEntityRenderableGetType) { + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + return jerry_number(r->type); +} + +moduleBaseFunction(moduleEntityRenderableSetType) { + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + r->type = (entityrenderabletype_t)moduleBaseArgInt(0); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityRenderableGetMesh) { + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + if(!r->mesh) return jerry_undefined(); + return moduleBaseWrapPointer(r->mesh); +} + +moduleBaseFunction(moduleEntityRenderableSetMesh) { + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + meshscript_t *ms = moduleMeshFrom(args[0]); + if(ms) { r->mesh = &ms->mesh; return jerry_undefined(); } + mesh_t *raw = (mesh_t*)moduleBaseUnwrapPointer(args[0]); + if(raw) { r->mesh = raw; return jerry_undefined(); } + return moduleBaseThrow("Expected a Mesh object or mesh constant"); +} + +moduleBaseFunction(moduleEntityRenderableGetColor) { + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + return moduleColorMakeObject(r->material.unlit.color); +} + +moduleBaseFunction(moduleEntityRenderableSetColor) { + moduleBaseRequireArgs(1); moduleBaseRequireObject(0); + color_t *color = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[0]); + if(!color) return moduleBaseThrow("Renderable.color: expected valid color object"); + moduleBaseGetOrReturn(entityrenderable_t, r, moduleEntityRenderableGet); + memoryCopy(&r->material.unlit.color, color, sizeof(color_t)); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityRenderableSpriteBatchAdd) { + moduleBaseRequireArgs(1); + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_RENDERABLE_PROTO, callInfo->this_value + ); + if(!h) return jerry_undefined(); + + spritebatchsprite_t sprite; + glm_vec3_zero(sprite.min); + glm_vec3_zero(sprite.max); + glm_vec2_zero(sprite.uvMin); + glm_vec2_zero(sprite.uvMax); + sprite.texture = NULL; +#if MESH_ENABLE_COLOR + sprite.color = COLOR_WHITE; +#endif + + jerry_value_t obj = args[0]; +#define getVecField(name, dst, n) do { \ + jerry_value_t _v = jerry_object_get_sz(obj, name); \ + if(!jerry_value_is_undefined(_v)) moduleVec##n##AnyCheck(_v, dst); \ + jerry_value_free(_v); \ + } while(0) + getVecField("min", sprite.min, 3); + getVecField("max", sprite.max, 3); + getVecField("uvMin", sprite.uvMin, 2); + getVecField("uvMax", sprite.uvMax, 2); +#undef getVecField + + entityRenderableSpriteBatchAdd(h->eid, h->cid, &sprite); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityRenderableSpriteBatchClear) { + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_RENDERABLE_PROTO, callInfo->this_value + ); + if(!h) return jerry_undefined(); + entityRenderableSpriteBatchClear(h->eid, h->cid); + return jerry_undefined(); +} + +static void moduleEntityRENDERABLE(void) { + scriptProtoInit( + &MODULE_ENTITY_RENDERABLE_PROTO, NULL, sizeof(componenthandle_t), NULL + ); + scriptProtoDefineProp(&MODULE_ENTITY_RENDERABLE_PROTO, "type", + moduleEntityRenderableGetType, moduleEntityRenderableSetType); + scriptProtoDefineProp(&MODULE_ENTITY_RENDERABLE_PROTO, "mesh", + moduleEntityRenderableGetMesh, moduleEntityRenderableSetMesh); + scriptProtoDefineProp(&MODULE_ENTITY_RENDERABLE_PROTO, "color", + moduleEntityRenderableGetColor, moduleEntityRenderableSetColor); + scriptProtoDefineFunc(&MODULE_ENTITY_RENDERABLE_PROTO, "addSprite", + moduleEntityRenderableSpriteBatchAdd); + scriptProtoDefineFunc(&MODULE_ENTITY_RENDERABLE_PROTO, "clearSprites", + moduleEntityRenderableSpriteBatchClear); + + moduleBaseSetInt("ENTITY_RENDERABLE_TYPE_MATERIAL", ENTITY_RENDERABLE_TYPE_MATERIAL); + moduleBaseSetInt("ENTITY_RENDERABLE_TYPE_SPRITEBATCH", ENTITY_RENDERABLE_TYPE_SPRITEBATCH); +} diff --git a/src/dusk/script/module/entity/component/moduleentitytrigger.h b/src/dusk/script/module/entity/component/moduleentitytrigger.h new file mode 100644 index 00000000..8de39bc3 --- /dev/null +++ b/src/dusk/script/module/entity/component/moduleentitytrigger.h @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "script/module/modulebase.h" +#include "script/module/math/modulevec3.h" +#include "script/scriptproto.h" +#include "entity/entity.h" +#include "entity/component/trigger/entitytrigger.h" +#include "moduleentityposition.h" + +static scriptproto_t MODULE_ENTITY_TRIGGER_PROTO; + +static entitytrigger_t * moduleEntityTriggerGet( + const jerry_call_info_t *callInfo +) { + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_TRIGGER_PROTO, callInfo->this_value + ); + if(!h) return NULL; + return entityTriggerGet(h->eid, h->cid); +} + +moduleBaseFunction(moduleEntityTriggerGetMin) { + moduleBaseGetOrReturn(entitytrigger_t, t, moduleEntityTriggerGet); + return moduleVec3Push(t->min); +} + +moduleBaseFunction(moduleEntityTriggerSetMin) { + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entitytrigger_t, t, moduleEntityTriggerGet); + vec3 v; + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); + glm_vec3_copy(v, t->min); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityTriggerGetMax) { + moduleBaseGetOrReturn(entitytrigger_t, t, moduleEntityTriggerGet); + return moduleVec3Push(t->max); +} + +moduleBaseFunction(moduleEntityTriggerSetMax) { + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(entitytrigger_t, t, moduleEntityTriggerGet); + vec3 v; + if(!moduleVec3AnyCheck(args[0], v)) return moduleBaseThrow("Expected Vec3"); + glm_vec3_copy(v, t->max); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityTriggerSetBounds) { + moduleBaseRequireArgs(2); + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_TRIGGER_PROTO, callInfo->this_value + ); + if(!h) return jerry_undefined(); + vec3 mn, mx; + if(!moduleVec3AnyCheck(args[0], mn)) return moduleBaseThrow("Expected Vec3 min"); + if(!moduleVec3AnyCheck(args[1], mx)) return moduleBaseThrow("Expected Vec3 max"); + entityTriggerSetBounds(h->eid, h->cid, mn, mx); + return jerry_undefined(); +} + +moduleBaseFunction(moduleEntityTriggerContains) { + moduleBaseRequireArgs(1); + componenthandle_t *h = scriptProtoGetValue( + &MODULE_ENTITY_TRIGGER_PROTO, callInfo->this_value + ); + if(!h) return jerry_boolean(false); + vec3 point; + if(!moduleVec3AnyCheck(args[0], point)) return moduleBaseThrow("Expected Vec3"); + return jerry_boolean(entityTriggerContains(h->eid, h->cid, point)); +} + +static void moduleEntityTRIGGER(void) { + scriptProtoInit( + &MODULE_ENTITY_TRIGGER_PROTO, NULL, sizeof(componenthandle_t), NULL + ); + scriptProtoDefineProp(&MODULE_ENTITY_TRIGGER_PROTO, "min", + moduleEntityTriggerGetMin, moduleEntityTriggerSetMin); + scriptProtoDefineProp(&MODULE_ENTITY_TRIGGER_PROTO, "max", + moduleEntityTriggerGetMax, moduleEntityTriggerSetMax); + scriptProtoDefineFunc(&MODULE_ENTITY_TRIGGER_PROTO, "setBounds", + moduleEntityTriggerSetBounds); + scriptProtoDefineFunc(&MODULE_ENTITY_TRIGGER_PROTO, "contains", + moduleEntityTriggerContains); +} diff --git a/src/dusk/script/module/entity/moduleentity.h b/src/dusk/script/module/entity/moduleentity.h index cf6573c4..52708c04 100644 --- a/src/dusk/script/module/entity/moduleentity.h +++ b/src/dusk/script/module/entity/moduleentity.h @@ -13,9 +13,9 @@ #include "component/moduleentityposition.h" #include "component/moduleentitycamera.h" -#include "component/moduleentitymesh.h" -#include "component/moduleentitymaterial.h" +#include "component/moduleentityrenderable.h" #include "component/moduleentityphysics.h" +#include "component/moduleentitytrigger.h" typedef struct { entityid_t id; @@ -23,12 +23,17 @@ typedef struct { static scriptproto_t MODULE_ENTITY_PROTO; -// Getters -moduleBaseFunction(moduleEntityGetId) { - entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( +static inline entityscript_t * moduleEntityGet( + const jerry_call_info_t *callInfo +) { + return (entityscript_t*)scriptProtoGetValue( &MODULE_ENTITY_PROTO, callInfo->this_value ); - if(!inst) return jerry_undefined(); +} + +// Getters +moduleBaseFunction(moduleEntityGetId) { + moduleBaseGetOrReturn(entityscript_t, inst, moduleEntityGet); return jerry_number(inst->id); } @@ -50,16 +55,13 @@ static jerry_value_t moduleEntityGetComponent( entityid_t entityId; componentid_t compId; - // Get the entity script data. - entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( - &MODULE_ENTITY_PROTO, callInfo->this_value - ); + entityscript_t *inst = moduleEntityGet(callInfo); if(!inst) return jerry_undefined(); entityId = inst->id; // Find the component ID of the requested type. compId = entityGetComponent(entityId, type); - if(compId == 0xFF) { + if(compId == COMPONENT_ID_INVALID) { return jerry_undefined(); } @@ -81,9 +83,7 @@ static jerry_value_t moduleEntityGetComponent( #undef X moduleBaseFunction(moduleEntityToString) { - entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( - &MODULE_ENTITY_PROTO, callInfo->this_value - ); + entityscript_t *inst = moduleEntityGet(callInfo); if(!inst) return jerry_string_sz("Entity(?)"); char_t components[128]; @@ -91,7 +91,7 @@ moduleBaseFunction(moduleEntityToString) { bool_t first = true; for(componenttype_t t = 1; t < COMPONENT_TYPE_COUNT; t++) { - if(entityGetComponent(inst->id, t) == 0xFF) continue; + if(entityGetComponent(inst->id, t) == COMPONENT_ID_INVALID) continue; if(!first) { stringCopy(components + clen, ", ", sizeof(components) - clen); clen += 2; @@ -130,30 +130,29 @@ moduleBaseFunction(moduleEntityConstructor) { } moduleBaseFunction(moduleEntityAddComponent) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Entity.add: expected a valid component type"); - } - - componenttype_t type = (componenttype_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + componenttype_t type = (componenttype_t)moduleBaseArgInt(0); if(type <= COMPONENT_TYPE_NULL || type >= COMPONENT_TYPE_COUNT) { return moduleBaseThrow("Entity.add: invalid component type"); } - // Get the entity script data. - entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( - &MODULE_ENTITY_PROTO, callInfo->this_value - ); + entityscript_t *inst = moduleEntityGet(callInfo); if(!inst) return moduleBaseThrow("Entity.add: invalid entity"); componentid_t id = entityAddComponent(inst->id, type); - return jerry_number(id); + componenthandle_t h = { .eid = inst->id, .cid = id }; + switch(type) { + #define X(enumName, stype, field, init, dispose) \ + case COMPONENT_TYPE_##enumName: \ + return scriptProtoCreateValue(&MODULE_ENTITY_##enumName##_PROTO, &h); + #include "entity/componentlist.h" + #undef X + default: return jerry_number(id); + } } moduleBaseFunction(moduleEntityDisposeMethod) { - entityscript_t *inst = (entityscript_t*)scriptProtoGetValue( - &MODULE_ENTITY_PROTO, callInfo->this_value - ); - if(!inst) return jerry_undefined(); + moduleBaseGetOrReturn(entityscript_t, inst, moduleEntityGet); entityDispose(inst->id); return jerry_undefined(); } @@ -183,8 +182,6 @@ static void moduleEntity(void) { ); // Init component type modules. - char_t buffer[64]; - #define X(enumName, type, field, iMethod, dMethod) \ moduleEntity##enumName(); \ scriptProtoDefineProp( \ @@ -193,13 +190,7 @@ static void moduleEntity(void) { moduleEntityGet##enumName, \ NULL \ ); \ - snprintf( \ - buffer, sizeof(buffer), \ - "%s = %d\n", \ - #enumName, \ - COMPONENT_TYPE_##enumName \ - ); \ - moduleBaseEval(buffer); + moduleBaseSetInt(#enumName, COMPONENT_TYPE_##enumName); #include "entity/componentlist.h" #undef X } diff --git a/src/dusk/script/module/event/moduleEvent.h b/src/dusk/script/module/event/moduleEvent.h index 82a38af7..866af248 100644 --- a/src/dusk/script/module/event/moduleEvent.h +++ b/src/dusk/script/module/event/moduleEvent.h @@ -7,6 +7,7 @@ #include "script/module/modulebase.h" #include "event/event.h" #include "assert/assert.h" +#include "animation/easing.h" #define MODULE_EVENT_POOL_MAX 32 @@ -67,3 +68,36 @@ static void moduleEventJsUnsubscribe(event_t *event, jerry_value_t callback) { return; } } + +/** + * Swap a pool-based event callback slot. Unsubscribes and frees the previous + * function (if any), then subscribes fn if it is callable. Pass + * jerry_undefined() as fn to clear without setting a new callback. + */ +static inline void moduleEventSetCallback( + jerry_value_t *slot, event_t *event, jerry_value_t fn +) { + if(*slot) { + moduleEventJsUnsubscribe(event, *slot); + jerry_value_free(*slot); + *slot = 0; + } + if(jerry_value_is_function(fn)) { + *slot = jerry_value_copy(fn); + moduleEventJsSubscribe(event, fn); + } +} + +/** + * Read an easing type from a JS value. Accepts either a raw number (easing + * enum) or an easing function object with a .type property. Returns + * EASING_LINEAR for any other input. + */ +static inline easingtype_t moduleReadEasing(jerry_value_t val) { + if(jerry_value_is_number(val)) return (easingtype_t)moduleBaseValueInt(val); + jerry_value_t typeVal = moduleBaseGetProp(val, "type"); + easingtype_t type = jerry_value_is_number(typeVal) + ? (easingtype_t)moduleBaseValueInt(typeVal) : EASING_LINEAR; + jerry_value_free(typeVal); + return type; +} diff --git a/src/dusk/script/module/input/moduleinput.h b/src/dusk/script/module/input/moduleinput.h index 39242d98..25afb05c 100644 --- a/src/dusk/script/module/input/moduleinput.h +++ b/src/dusk/script/module/input/moduleinput.h @@ -16,9 +16,7 @@ static scriptproto_t MODULE_INPUT_PROTO; // Static Methods moduleBaseFunction(moduleInputBind) { - if(argc < 2) return moduleBaseThrow("Expected at least 2 arguments"); - moduleBaseRequireString(0); - moduleBaseRequireNumber(1); + moduleBaseRequireArgs(2); moduleBaseRequireString(0); moduleBaseRequireNumber(1); char_t strBtn[128]; moduleBaseToString(args[0], strBtn, sizeof(strBtn)); @@ -26,7 +24,7 @@ moduleBaseFunction(moduleInputBind) { return moduleBaseThrow("Input.bind: button name cannot be empty"); } - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[1]); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(1); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.bind: invalid action"); } @@ -41,12 +39,8 @@ moduleBaseFunction(moduleInputBind) { } moduleBaseFunction(moduleInputIsDown) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.isDown: invalid action"); } @@ -54,12 +48,8 @@ moduleBaseFunction(moduleInputIsDown) { } moduleBaseFunction(moduleInputPressed) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.pressed: invalid action"); } @@ -67,12 +57,8 @@ moduleBaseFunction(moduleInputPressed) { } moduleBaseFunction(moduleInputReleased) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.released: invalid action"); } @@ -80,12 +66,8 @@ moduleBaseFunction(moduleInputReleased) { } moduleBaseFunction(moduleInputGetValue) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.getValue: invalid action"); } @@ -93,10 +75,9 @@ moduleBaseFunction(moduleInputGetValue) { } moduleBaseFunction(moduleInputAxis) { - if(argc < 2) return moduleBaseThrow("Expected at least 2 arguments"); - moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); - const inputaction_t neg = (inputaction_t)jerry_value_as_number(args[0]); - const inputaction_t pos = (inputaction_t)jerry_value_as_number(args[1]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + const inputaction_t neg = (inputaction_t)moduleBaseArgInt(0); + const inputaction_t pos = (inputaction_t)moduleBaseArgInt(1); if(neg <= INPUT_ACTION_NULL || neg >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.axis: invalid negative action"); } @@ -107,13 +88,13 @@ moduleBaseFunction(moduleInputAxis) { } moduleBaseFunction(moduleInputAxis2D) { - if(argc < 4) return moduleBaseThrow("Expected at least 4 arguments"); + moduleBaseRequireArgs(4); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); moduleBaseRequireNumber(2); moduleBaseRequireNumber(3); - const inputaction_t negX = (inputaction_t)jerry_value_as_number(args[0]); - const inputaction_t posX = (inputaction_t)jerry_value_as_number(args[1]); - const inputaction_t negY = (inputaction_t)jerry_value_as_number(args[2]); - const inputaction_t posY = (inputaction_t)jerry_value_as_number(args[3]); + const inputaction_t negX = (inputaction_t)moduleBaseArgInt(0); + const inputaction_t posX = (inputaction_t)moduleBaseArgInt(1); + const inputaction_t negY = (inputaction_t)moduleBaseArgInt(2); + const inputaction_t posY = (inputaction_t)moduleBaseArgInt(3); if(negX <= INPUT_ACTION_NULL || negX >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.axis2D: invalid negX action"); } @@ -132,10 +113,8 @@ moduleBaseFunction(moduleInputAxis2D) { } moduleBaseFunction(moduleInputOnPressed) { - if(argc < 2) return moduleBaseThrow("Input.onPressed: expected (action, fn)"); - moduleBaseRequireNumber(0); - moduleBaseRequireFunction(1); - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireFunction(1); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.onPressed: invalid action"); } @@ -144,10 +123,8 @@ moduleBaseFunction(moduleInputOnPressed) { } moduleBaseFunction(moduleInputOffPressed) { - if(argc < 2) return moduleBaseThrow("Input.offPressed: expected (action, fn)"); - moduleBaseRequireNumber(0); - moduleBaseRequireFunction(1); - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireFunction(1); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.offPressed: invalid action"); } @@ -156,10 +133,8 @@ moduleBaseFunction(moduleInputOffPressed) { } moduleBaseFunction(moduleInputOnReleased) { - if(argc < 2) return moduleBaseThrow("Input.onReleased: expected (action, fn)"); - moduleBaseRequireNumber(0); - moduleBaseRequireFunction(1); - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireFunction(1); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.onReleased: invalid action"); } @@ -168,10 +143,8 @@ moduleBaseFunction(moduleInputOnReleased) { } moduleBaseFunction(moduleInputOffReleased) { - if(argc < 2) return moduleBaseThrow("Input.offReleased: expected (action, fn)"); - moduleBaseRequireNumber(0); - moduleBaseRequireFunction(1); - const inputaction_t action = (inputaction_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireFunction(1); + const inputaction_t action = (inputaction_t)moduleBaseArgInt(0); if(action <= INPUT_ACTION_NULL || action >= INPUT_ACTION_COUNT) { return moduleBaseThrow("Input.offReleased: invalid action"); } diff --git a/src/dusk/script/module/item/moduleitem.h b/src/dusk/script/module/item/moduleitem.h index 00cd4e7d..1cb75d94 100644 --- a/src/dusk/script/module/item/moduleitem.h +++ b/src/dusk/script/module/item/moduleitem.h @@ -27,88 +27,57 @@ static inline inventory_t * moduleInventoryGet( } moduleBaseFunction(moduleInventoryAdd) { - if(argc < 2) return moduleBaseThrow("Expected (itemId, quantity)"); - moduleBaseRequireNumber(0); - moduleBaseRequireNumber(1); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - inventoryAdd( - inv, - (itemid_t)jerry_value_as_number(args[0]), - (uint8_t)jerry_value_as_number(args[1]) - ); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + inventoryAdd(inv, (itemid_t)moduleBaseArgInt(0), (uint8_t)moduleBaseArgInt(1)); return jerry_undefined(); } moduleBaseFunction(moduleInventoryRemove) { - if(argc < 1) return moduleBaseThrow("Expected itemId"); - moduleBaseRequireNumber(0); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - inventoryRemove(inv, (itemid_t)jerry_value_as_number(args[0])); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + inventoryRemove(inv, (itemid_t)moduleBaseArgInt(0)); return jerry_undefined(); } moduleBaseFunction(moduleInventorySet) { - if(argc < 2) return moduleBaseThrow("Expected (itemId, quantity)"); - moduleBaseRequireNumber(0); - moduleBaseRequireNumber(1); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - inventorySet( - inv, - (itemid_t)jerry_value_as_number(args[0]), - (uint8_t)jerry_value_as_number(args[1]) - ); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + inventorySet(inv, (itemid_t)moduleBaseArgInt(0), (uint8_t)moduleBaseArgInt(1)); return jerry_undefined(); } moduleBaseFunction(moduleInventoryCount) { - if(argc < 1) return moduleBaseThrow("Expected itemId"); - moduleBaseRequireNumber(0); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - return jerry_number( - (double)inventoryGetCount(inv, (itemid_t)jerry_value_as_number(args[0])) - ); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + return jerry_number((double)inventoryGetCount(inv, (itemid_t)moduleBaseArgInt(0))); } moduleBaseFunction(moduleInventoryHas) { - if(argc < 1) return moduleBaseThrow("Expected itemId"); - moduleBaseRequireNumber(0); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - return jerry_boolean( - inventoryItemExists(inv, (itemid_t)jerry_value_as_number(args[0])) - ); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + return jerry_boolean(inventoryItemExists(inv, (itemid_t)moduleBaseArgInt(0))); } moduleBaseFunction(moduleInventoryIsItemFull) { - if(argc < 1) return moduleBaseThrow("Expected itemId"); - moduleBaseRequireNumber(0); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); - return jerry_boolean( - inventoryItemFull(inv, (itemid_t)jerry_value_as_number(args[0])) - ); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); + return jerry_boolean(inventoryItemFull(inv, (itemid_t)moduleBaseArgInt(0))); } moduleBaseFunction(moduleInventorySort) { - if(argc < 1) return moduleBaseThrow("Expected sortBy"); - moduleBaseRequireNumber(0); - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); inventorySort( inv, - (inventorysort_t)jerry_value_as_number(args[0]), + (inventorysort_t)moduleBaseArgInt(0), (argc >= 2 && jerry_value_is_true(args[1])) ); return jerry_undefined(); } moduleBaseFunction(moduleInventoryGetFull) { - inventory_t *inv = moduleInventoryGet(callInfo); - if(!inv) return jerry_undefined(); + moduleBaseGetOrReturn(inventory_t, inv, moduleInventoryGet); return jerry_boolean(inventoryIsFull(inv)); } diff --git a/src/dusk/script/module/math/modulemat4.h b/src/dusk/script/module/math/modulemat4.h index c138a0b3..11baa97c 100644 --- a/src/dusk/script/module/math/modulemat4.h +++ b/src/dusk/script/module/math/modulemat4.h @@ -28,7 +28,7 @@ moduleBaseFunction(moduleMatConstructor) { } moduleBaseFunction(moduleMatMul) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t (*a)[4] = (float_t (*)[4])moduleMatGet(callInfo); if(!a) return moduleBaseThrow("Mat4.mul: invalid this"); float_t (*b)[4] = (float_t (*)[4])scriptProtoGetValue( @@ -63,22 +63,21 @@ moduleBaseFunction(moduleMatDeterminant) { } moduleBaseFunction(moduleMatMulVec3) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t (*m)[4] = (float_t (*)[4])moduleMatGet(callInfo); if(!m) return moduleBaseThrow("Mat4.mulVec3: invalid this"); vec3 vin; if(!moduleVec3Check(args[0], vin)) { return moduleBaseThrow("Mat4.mulVec3: argument must be a Vec3"); } - float_t w = (argc >= 2 && jerry_value_is_number(args[1])) - ? (float_t)jerry_value_as_number(args[1]) : 1.0f; + float_t w = moduleBaseOptFloat(1, 1.0f); vec3 vout; glm_mat4_mulv3(m, vin, w, vout); return moduleVec3Push(vout); } moduleBaseFunction(moduleMatMulVec4) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t (*m)[4] = (float_t (*)[4])moduleMatGet(callInfo); if(!m) return moduleBaseThrow("Mat4.mulVec4: invalid this"); vec4 vin; @@ -91,7 +90,7 @@ moduleBaseFunction(moduleMatMulVec4) { } moduleBaseFunction(moduleMatTranslate) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t (*m)[4] = (float_t (*)[4])moduleMatGet(callInfo); if(!m) return moduleBaseThrow("Mat4.translate: invalid this"); vec3 tv; @@ -105,7 +104,7 @@ moduleBaseFunction(moduleMatTranslate) { } moduleBaseFunction(moduleMatScale) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t (*m)[4] = (float_t (*)[4])moduleMatGet(callInfo); if(!m) return moduleBaseThrow("Mat4.scale: invalid this"); vec3 sv; @@ -125,22 +124,20 @@ moduleBaseFunction(moduleMatStaticIdentity) { } moduleBaseFunction(moduleMatStaticPerspective) { - if(argc < 4) return moduleBaseThrow("Expected at least 4 arguments"); + moduleBaseRequireArgs(4); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); moduleBaseRequireNumber(2); moduleBaseRequireNumber(3); mat4 r; glm_perspective( - (float_t)jerry_value_as_number(args[0]), - (float_t)jerry_value_as_number(args[1]), - (float_t)jerry_value_as_number(args[2]), - (float_t)jerry_value_as_number(args[3]), + moduleBaseArgFloat(0), moduleBaseArgFloat(1), + moduleBaseArgFloat(2), moduleBaseArgFloat(3), r ); return scriptProtoCreateValue(&MODULE_MAT4_PROTO, r); } moduleBaseFunction(moduleMatStaticLookAt) { - if(argc < 3) return moduleBaseThrow("Expected at least 3 arguments"); + moduleBaseRequireArgs(3); vec3 eye, center, up; if(!moduleVec3Check(args[0], eye)) { return moduleBaseThrow("Mat4.lookAt: eye must be a Vec3"); diff --git a/src/dusk/script/module/math/modulevec2.h b/src/dusk/script/module/math/modulevec2.h index 46da014b..b63fa248 100644 --- a/src/dusk/script/module/math/modulevec2.h +++ b/src/dusk/script/module/math/modulevec2.h @@ -24,10 +24,8 @@ static inline float_t * moduleVec2From(jerry_value_t val) { moduleBaseFunction(moduleVec2Constructor) { float_t *ptr = (float_t *)memoryAllocate(sizeof(vec2)); - ptr[0] = (argc >= 1 && jerry_value_is_number(args[0])) - ? (float_t)jerry_value_as_number(args[0]) : 0.0f; - ptr[1] = (argc >= 2 && jerry_value_is_number(args[1])) - ? (float_t)jerry_value_as_number(args[1]) : 0.0f; + ptr[0] = moduleBaseOptFloat(0, 0.0f); + ptr[1] = moduleBaseOptFloat(1, 0.0f); jerry_object_set_native_ptr( callInfo->this_value, &MODULE_VEC2_PROTO.info, ptr ); @@ -35,27 +33,29 @@ moduleBaseFunction(moduleVec2Constructor) { } moduleBaseFunction(moduleVec2GetX) { - float_t *v = moduleVec2Get(callInfo); - return v ? jerry_number(v[0]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec2Get); + return jerry_number(v[0]); } moduleBaseFunction(moduleVec2SetX) { - float_t *v = moduleVec2Get(callInfo); - if(v && argc > 0) v[0] = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(float_t, v, moduleVec2Get); + v[0] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec2GetY) { - float_t *v = moduleVec2Get(callInfo); - return v ? jerry_number(v[1]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec2Get); + return jerry_number(v[1]); } moduleBaseFunction(moduleVec2SetY) { - float_t *v = moduleVec2Get(callInfo); - if(v && argc > 0) v[1] = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(float_t, v, moduleVec2Get); + v[1] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec2Dot) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec2Get(callInfo); if(!a) return moduleBaseThrow("Vec2.dot: invalid this"); float_t *b = moduleVec2From(args[0]); @@ -92,7 +92,7 @@ moduleBaseFunction(moduleVec2Negate) { } moduleBaseFunction(moduleVec2Add) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec2Get(callInfo); if(!a) return moduleBaseThrow("Vec2.add: invalid this"); float_t *b = moduleVec2From(args[0]); @@ -103,7 +103,7 @@ moduleBaseFunction(moduleVec2Add) { } moduleBaseFunction(moduleVec2Sub) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec2Get(callInfo); if(!a) return moduleBaseThrow("Vec2.sub: invalid this"); float_t *b = moduleVec2From(args[0]); @@ -114,35 +114,27 @@ moduleBaseFunction(moduleVec2Sub) { } moduleBaseFunction(moduleVec2Scale) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); float_t *v = moduleVec2Get(callInfo); if(!v) return moduleBaseThrow("Vec2.scale: invalid this"); vec2 r; - glm_vec2_scale(v, (float_t)jerry_value_as_number(args[0]), r); + glm_vec2_scale(v, moduleBaseArgFloat(0), r); return scriptProtoCreateValue(&MODULE_VEC2_PROTO, r); } moduleBaseFunction(moduleVec2Lerp) { - if(argc < 2) { - return moduleBaseThrow("Expected at least 2 arguments"); - } - moduleBaseRequireNumber(1); - + moduleBaseRequireArgs(2); moduleBaseRequireNumber(1); float_t *a = moduleVec2Get(callInfo); if(!a) return moduleBaseThrow("Vec2.lerp: invalid this"); float_t *b = moduleVec2From(args[0]); if(!b) return moduleBaseThrow("Vec2.lerp: first argument must be a Vec2"); vec2 r; - glm_vec2_lerp(a, b, (float_t)jerry_value_as_number(args[1]), r); + glm_vec2_lerp(a, b, moduleBaseArgFloat(1), r); return scriptProtoCreateValue(&MODULE_VEC2_PROTO, r); } moduleBaseFunction(moduleVec2Distance) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec2Get(callInfo); if(!a) return moduleBaseThrow("Vec2.distance: invalid this"); float_t *b = moduleVec2From(args[0]); @@ -170,6 +162,10 @@ static inline bool_t moduleVec2Check(jerry_value_t val, float_t *out) { return true; } +static inline bool_t moduleVec2AnyCheck(jerry_value_t val, float_t *out) { + return moduleVec2Check(val, out); +} + static void moduleVec2(void) { scriptProtoInit( &MODULE_VEC2_PROTO, "Vec2", sizeof(vec2), moduleVec2Constructor diff --git a/src/dusk/script/module/math/modulevec3.h b/src/dusk/script/module/math/modulevec3.h index ec4af698..165d577f 100644 --- a/src/dusk/script/module/math/modulevec3.h +++ b/src/dusk/script/module/math/modulevec3.h @@ -24,12 +24,9 @@ static inline float_t * moduleVec3From(jerry_value_t val) { moduleBaseFunction(moduleVec3Constructor) { float_t *ptr = (float_t *)memoryAllocate(sizeof(vec3)); - ptr[0] = (argc >= 1 && jerry_value_is_number(args[0])) - ? (float_t)jerry_value_as_number(args[0]) : 0.0f; - ptr[1] = (argc >= 2 && jerry_value_is_number(args[1])) - ? (float_t)jerry_value_as_number(args[1]) : 0.0f; - ptr[2] = (argc >= 3 && jerry_value_is_number(args[2])) - ? (float_t)jerry_value_as_number(args[2]) : 0.0f; + ptr[0] = moduleBaseOptFloat(0, 0.0f); + ptr[1] = moduleBaseOptFloat(1, 0.0f); + ptr[2] = moduleBaseOptFloat(2, 0.0f); jerry_object_set_native_ptr( callInfo->this_value, &MODULE_VEC3_PROTO.info, ptr ); @@ -37,37 +34,40 @@ moduleBaseFunction(moduleVec3Constructor) { } moduleBaseFunction(moduleVec3GetX) { - float_t *v = moduleVec3Get(callInfo); - return v ? jerry_number(v[0]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + return jerry_number(v[0]); } moduleBaseFunction(moduleVec3SetX) { - float_t *v = moduleVec3Get(callInfo); - if(v && argc > 0) v[0] = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + v[0] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec3GetY) { - float_t *v = moduleVec3Get(callInfo); - return v ? jerry_number(v[1]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + return jerry_number(v[1]); } moduleBaseFunction(moduleVec3SetY) { - float_t *v = moduleVec3Get(callInfo); - if(v && argc > 0) v[1] = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + v[1] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec3GetZ) { - float_t *v = moduleVec3Get(callInfo); - return v ? jerry_number(v[2]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + return jerry_number(v[2]); } moduleBaseFunction(moduleVec3SetZ) { - float_t *v = moduleVec3Get(callInfo); - if(v && argc > 0) v[2] = (float_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(float_t, v, moduleVec3Get); + v[2] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec3Dot) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.dot: invalid this"); float_t *b = moduleVec3From(args[0]); @@ -76,7 +76,7 @@ moduleBaseFunction(moduleVec3Dot) { } moduleBaseFunction(moduleVec3Cross) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.cross: invalid this"); float_t *b = moduleVec3From(args[0]); @@ -115,7 +115,7 @@ moduleBaseFunction(moduleVec3Negate) { } moduleBaseFunction(moduleVec3Add) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.add: invalid this"); float_t *b = moduleVec3From(args[0]); @@ -126,7 +126,7 @@ moduleBaseFunction(moduleVec3Add) { } moduleBaseFunction(moduleVec3Sub) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.sub: invalid this"); float_t *b = moduleVec3From(args[0]); @@ -137,35 +137,27 @@ moduleBaseFunction(moduleVec3Sub) { } moduleBaseFunction(moduleVec3Scale) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); float_t *v = moduleVec3Get(callInfo); if(!v) return moduleBaseThrow("Vec3.scale: invalid this"); vec3 r; - glm_vec3_scale(v, (float_t)jerry_value_as_number(args[0]), r); + glm_vec3_scale(v, moduleBaseArgFloat(0), r); return scriptProtoCreateValue(&MODULE_VEC3_PROTO, r); } moduleBaseFunction(moduleVec3Lerp) { - if(argc < 2) { - return moduleBaseThrow("Expected at least 2 arguments"); - } - moduleBaseRequireNumber(1); - + moduleBaseRequireArgs(2); moduleBaseRequireNumber(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.lerp: invalid this"); float_t *b = moduleVec3From(args[0]); if(!b) return moduleBaseThrow("Vec3.lerp: first argument must be a Vec3"); vec3 r; - glm_vec3_lerp(a, b, (float_t)jerry_value_as_number(args[1]), r); + glm_vec3_lerp(a, b, moduleBaseArgFloat(1), r); return scriptProtoCreateValue(&MODULE_VEC3_PROTO, r); } moduleBaseFunction(moduleVec3Distance) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec3Get(callInfo); if(!a) return moduleBaseThrow("Vec3.distance: invalid this"); float_t *b = moduleVec3From(args[0]); diff --git a/src/dusk/script/module/math/modulevec3ref.h b/src/dusk/script/module/math/modulevec3ref.h index 89e12cf2..d7c8cf85 100644 --- a/src/dusk/script/module/math/modulevec3ref.h +++ b/src/dusk/script/module/math/modulevec3ref.h @@ -36,41 +36,38 @@ static inline void moduleVec3RefNotify(vec3ref_t *ref) { } moduleBaseFunction(moduleVec3RefGetX) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - return ref ? jerry_number(ref->data[0]) : jerry_undefined(); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + return jerry_number(ref->data[0]); } moduleBaseFunction(moduleVec3RefSetX) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - if(ref && argc > 0) { - ref->data[0] = (float_t)jerry_value_as_number(args[0]); - moduleVec3RefNotify(ref); - } + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + ref->data[0] = moduleBaseArgFloat(0); + moduleVec3RefNotify(ref); return jerry_undefined(); } moduleBaseFunction(moduleVec3RefGetY) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - return ref ? jerry_number(ref->data[1]) : jerry_undefined(); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + return jerry_number(ref->data[1]); } moduleBaseFunction(moduleVec3RefSetY) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - if(ref && argc > 0) { - ref->data[1] = (float_t)jerry_value_as_number(args[0]); - moduleVec3RefNotify(ref); - } + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + ref->data[1] = moduleBaseArgFloat(0); + moduleVec3RefNotify(ref); return jerry_undefined(); } moduleBaseFunction(moduleVec3RefGetZ) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - return ref ? jerry_number(ref->data[2]) : jerry_undefined(); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + return jerry_number(ref->data[2]); } moduleBaseFunction(moduleVec3RefSetZ) { - vec3ref_t *ref = moduleVec3RefGet(callInfo); - if(ref && argc > 0) { - ref->data[2] = (float_t)jerry_value_as_number(args[0]); - moduleVec3RefNotify(ref); - } + moduleBaseRequireArgs(1); + moduleBaseGetOrReturn(vec3ref_t, ref, moduleVec3RefGet); + ref->data[2] = moduleBaseArgFloat(0); + moduleVec3RefNotify(ref); return jerry_undefined(); } diff --git a/src/dusk/script/module/math/modulevec4.h b/src/dusk/script/module/math/modulevec4.h index 79274431..52751b56 100644 --- a/src/dusk/script/module/math/modulevec4.h +++ b/src/dusk/script/module/math/modulevec4.h @@ -24,14 +24,10 @@ static inline float_t * moduleVec4From(jerry_value_t val) { moduleBaseFunction(moduleVec4Constructor) { float_t *ptr = (float_t *)memoryAllocate(sizeof(vec4)); - ptr[0] = (argc >= 1 && jerry_value_is_number(args[0])) - ? (float_t)jerry_value_as_number(args[0]) : 0.0f; - ptr[1] = (argc >= 2 && jerry_value_is_number(args[1])) - ? (float_t)jerry_value_as_number(args[1]) : 0.0f; - ptr[2] = (argc >= 3 && jerry_value_is_number(args[2])) - ? (float_t)jerry_value_as_number(args[2]) : 0.0f; - ptr[3] = (argc >= 4 && jerry_value_is_number(args[3])) - ? (float_t)jerry_value_as_number(args[3]) : 0.0f; + ptr[0] = moduleBaseOptFloat(0, 0.0f); + ptr[1] = moduleBaseOptFloat(1, 0.0f); + ptr[2] = moduleBaseOptFloat(2, 0.0f); + ptr[3] = moduleBaseOptFloat(3, 0.0f); jerry_object_set_native_ptr( callInfo->this_value, &MODULE_VEC4_PROTO.info, ptr ); @@ -40,88 +36,72 @@ moduleBaseFunction(moduleVec4Constructor) { // x/y/z/w moduleBaseFunction(moduleVec4GetX) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[0]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[0]); } moduleBaseFunction(moduleVec4SetX) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[0] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[0] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetY) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[1]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[1]); } moduleBaseFunction(moduleVec4SetY) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[1] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[1] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetZ) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[2]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[2]); } moduleBaseFunction(moduleVec4SetZ) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[2] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[2] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetW) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[3]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[3]); } moduleBaseFunction(moduleVec4SetW) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[3] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[3] = moduleBaseArgFloat(0); return jerry_undefined(); } // u0/v0/u1/v1 aliases for UV coordinates moduleBaseFunction(moduleVec4GetU0) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[0]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[0]); } moduleBaseFunction(moduleVec4SetU0) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[0] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[0] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetV0) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[1]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[1]); } moduleBaseFunction(moduleVec4SetV0) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[1] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[1] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetU1) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[2]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[2]); } moduleBaseFunction(moduleVec4SetU1) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[2] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[2] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4GetV1) { - float_t *v = moduleVec4Get(callInfo); - return v ? jerry_number(v[3]) : jerry_undefined(); + moduleBaseGetOrReturn(float_t, v, moduleVec4Get); return jerry_number(v[3]); } moduleBaseFunction(moduleVec4SetV1) { - float_t *v = moduleVec4Get(callInfo); - if(v && argc > 0) v[3] = (float_t)jerry_value_as_number(args[0]); - return jerry_undefined(); + moduleBaseRequireArgs(1); moduleBaseGetOrReturn(float_t, v, moduleVec4Get); + v[3] = moduleBaseArgFloat(0); return jerry_undefined(); } moduleBaseFunction(moduleVec4Dot) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec4Get(callInfo); if(!a) return moduleBaseThrow("Vec4.dot: invalid this"); float_t *b = moduleVec4From(args[0]); @@ -158,7 +138,7 @@ moduleBaseFunction(moduleVec4Negate) { } moduleBaseFunction(moduleVec4Add) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec4Get(callInfo); if(!a) return moduleBaseThrow("Vec4.add: invalid this"); float_t *b = moduleVec4From(args[0]); @@ -169,7 +149,7 @@ moduleBaseFunction(moduleVec4Add) { } moduleBaseFunction(moduleVec4Sub) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); + moduleBaseRequireArgs(1); float_t *a = moduleVec4Get(callInfo); if(!a) return moduleBaseThrow("Vec4.sub: invalid this"); float_t *b = moduleVec4From(args[0]); @@ -180,30 +160,22 @@ moduleBaseFunction(moduleVec4Sub) { } moduleBaseFunction(moduleVec4Scale) { - if(argc < 1) { - return moduleBaseThrow("Expected at least 1 argument"); - } - moduleBaseRequireNumber(0); - + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); float_t *v = moduleVec4Get(callInfo); if(!v) return moduleBaseThrow("Vec4.scale: invalid this"); vec4 r; - glm_vec4_scale(v, (float_t)jerry_value_as_number(args[0]), r); + glm_vec4_scale(v, moduleBaseArgFloat(0), r); return scriptProtoCreateValue(&MODULE_VEC4_PROTO, r); } moduleBaseFunction(moduleVec4Lerp) { - if(argc < 2) { - return moduleBaseThrow("Expected at least 2 arguments"); - } - moduleBaseRequireNumber(1); - + moduleBaseRequireArgs(2); moduleBaseRequireNumber(1); float_t *a = moduleVec4Get(callInfo); if(!a) return moduleBaseThrow("Vec4.lerp: invalid this"); float_t *b = moduleVec4From(args[0]); if(!b) return moduleBaseThrow("Vec4.lerp: first argument must be a Vec4"); vec4 r; - glm_vec4_lerp(a, b, (float_t)jerry_value_as_number(args[1]), r); + glm_vec4_lerp(a, b, moduleBaseArgFloat(1), r); return scriptProtoCreateValue(&MODULE_VEC4_PROTO, r); } diff --git a/src/dusk/script/module/modulebase.h b/src/dusk/script/module/modulebase.h index 9eb82ab4..cad94673 100644 --- a/src/dusk/script/module/modulebase.h +++ b/src/dusk/script/module/modulebase.h @@ -264,6 +264,59 @@ static void moduleBaseCreateGlobalObject( } \ } while(0) +/** + * Require at least N arguments; throw a TypeError if fewer were provided. + * + * Example: moduleBaseRequireArgs(2); + */ +#define moduleBaseRequireArgs(n) do { \ + if(argc < (jerry_length_t)(n)) { \ + return moduleBaseThrow("Expected at least " #n " argument(s)"); \ + } \ +} while(0) + +/** + * Declare a typed pointer from a getter and immediately return undefined if it + * is NULL. The named variable is available for the rest of the function. + * + * Example: + * moduleBaseGetOrReturn(entitycamera_t, cam, moduleEntityCameraGet); + * return jerry_number(cam->nearClip); + */ +#define moduleBaseGetOrReturn(type, var, getter) \ + type *var = (getter)(callInfo); \ + if(!(var)) return jerry_undefined() + +/** + * Cast argument i to float_t. Call after validating the arg is a number. + */ +#define moduleBaseArgFloat(i) ((float_t)jerry_value_as_number(args[(i)])) + +/** + * Cast argument i to int32_t. Call after validating the arg is a number. + */ +#define moduleBaseArgInt(i) ((int32_t)jerry_value_as_number(args[(i)])) + +/** + * Read argument i as a boolean (true/false). + */ +#define moduleBaseArgBool(i) (jerry_value_is_true(args[(i)])) + +/** + * Read optional argument i as float_t. Returns def if the argument is missing + * or not a number. + */ +#define moduleBaseOptFloat(i, def) \ + ((jerry_length_t)(i) < argc && jerry_value_is_number(args[(i)]) \ + ? (float_t)jerry_value_as_number(args[(i)]) : (def)) + +/** + * Read optional argument i as int32_t. Returns def if the argument is missing + * or not a number. + */ +#define moduleBaseOptInt(i, def) \ + ((jerry_length_t)(i) < argc && jerry_value_is_number(args[(i)]) \ + ? (int32_t)jerry_value_as_number(args[(i)]) : (def)) /** * Set a global numeric constant. @@ -418,7 +471,7 @@ static inline void moduleBaseExceptionMessage( /** * Define a named global function. - * + * * @param name The name of the function as seen in JavaScript. * @param fn The C handler function for the method. */ @@ -429,4 +482,32 @@ static inline void moduleBaseDefineGlobalMethod( jerry_value_t global = jerry_current_realm(); moduleBaseDefineMethod(global, name, fn); jerry_value_free(global); +} + +/** + * Get a named property from a JS object. Caller must free the returned value. + */ +static inline jerry_value_t moduleBaseGetProp( + jerry_value_t obj, const char_t *name +) { + jerry_value_t key = jerry_string_sz(name); + jerry_value_t val = jerry_object_get(obj, key); + jerry_value_free(key); + return val; +} + +/** + * Cast a JS value to float_t. Use for non-args[] values (e.g. object + * properties). For args[], prefer moduleBaseArgFloat. + */ +static inline float_t moduleBaseValueFloat(jerry_value_t val) { + return (float_t)jerry_value_as_number(val); +} + +/** + * Cast a JS value to int32_t. Use for non-args[] values (e.g. object + * properties). For args[], prefer moduleBaseArgInt. + */ +static inline int32_t moduleBaseValueInt(jerry_value_t val) { + return (int32_t)jerry_value_as_number(val); } \ No newline at end of file diff --git a/src/dusk/script/module/save/modulesave.h b/src/dusk/script/module/save/modulesave.h index 2e07de5b..4c127dee 100644 --- a/src/dusk/script/module/save/modulesave.h +++ b/src/dusk/script/module/save/modulesave.h @@ -22,58 +22,43 @@ moduleBaseFunction(moduleSaveGetCount) { // Static Methods moduleBaseFunction(moduleSaveLoad) { - if(argc < 1) return moduleBaseThrow("Save.load: expected (slot)"); - moduleBaseRequireNumber(0); - const uint8_t slot = (uint8_t)jerry_value_as_number(args[0]); - if(slot >= SAVE_FILE_COUNT_MAX) { - return moduleBaseThrow("Save.load: slot out of range"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const uint8_t slot = (uint8_t)moduleBaseArgInt(0); + if(slot >= SAVE_FILE_COUNT_MAX) return moduleBaseThrow("Save.load: slot out of range"); errorret_t err = saveLoad(slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); } moduleBaseFunction(moduleSaveWrite) { - if(argc < 1) return moduleBaseThrow("Save.write: expected (slot)"); - moduleBaseRequireNumber(0); - const uint8_t slot = (uint8_t)jerry_value_as_number(args[0]); - if(slot >= SAVE_FILE_COUNT_MAX) { - return moduleBaseThrow("Save.write: slot out of range"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const uint8_t slot = (uint8_t)moduleBaseArgInt(0); + if(slot >= SAVE_FILE_COUNT_MAX) return moduleBaseThrow("Save.write: slot out of range"); errorret_t err = saveWrite(slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); } moduleBaseFunction(moduleSaveDelete) { - if(argc < 1) return moduleBaseThrow("Save.delete: expected (slot)"); - moduleBaseRequireNumber(0); - const uint8_t slot = (uint8_t)jerry_value_as_number(args[0]); - if(slot >= SAVE_FILE_COUNT_MAX) { - return moduleBaseThrow("Save.delete: slot out of range"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const uint8_t slot = (uint8_t)moduleBaseArgInt(0); + if(slot >= SAVE_FILE_COUNT_MAX) return moduleBaseThrow("Save.delete: slot out of range"); errorret_t err = saveDelete(slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); } moduleBaseFunction(moduleSaveExists) { - if(argc < 1) return moduleBaseThrow("Save.exists: expected (slot)"); - moduleBaseRequireNumber(0); - const uint8_t slot = (uint8_t)jerry_value_as_number(args[0]); - if(slot >= SAVE_FILE_COUNT_MAX) { - return moduleBaseThrow("Save.exists: slot out of range"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const uint8_t slot = (uint8_t)moduleBaseArgInt(0); + if(slot >= SAVE_FILE_COUNT_MAX) return moduleBaseThrow("Save.exists: slot out of range"); return jerry_boolean(saveExists(slot)); } moduleBaseFunction(moduleSaveGet) { - if(argc < 1) return moduleBaseThrow("Save.get: expected (slot)"); - moduleBaseRequireNumber(0); - const uint8_t slot = (uint8_t)jerry_value_as_number(args[0]); - if(slot >= SAVE_FILE_COUNT_MAX) { - return moduleBaseThrow("Save.get: slot out of range"); - } + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + const uint8_t slot = (uint8_t)moduleBaseArgInt(0); + if(slot >= SAVE_FILE_COUNT_MAX) return moduleBaseThrow("Save.get: slot out of range"); return moduleSaveSlotCreate(slot); } diff --git a/src/dusk/script/module/save/modulesaveslot.h b/src/dusk/script/module/save/modulesaveslot.h index f272589f..15c7a58e 100644 --- a/src/dusk/script/module/save/modulesaveslot.h +++ b/src/dusk/script/module/save/modulesaveslot.h @@ -27,44 +27,38 @@ static inline saveslotscript_t * moduleSaveSlotGet( // Properties moduleBaseFunction(moduleSaveSlotGetSlot) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_undefined(); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); return jerry_number((double)s->slot); } moduleBaseFunction(moduleSaveSlotGetExists) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_boolean(false); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); return jerry_boolean(saveExists(s->slot)); } moduleBaseFunction(moduleSaveSlotGetVersion) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_undefined(); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); return jerry_number((double)saveGet(s->slot)->version); } // Methods moduleBaseFunction(moduleSaveSlotLoad) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_undefined(); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); errorret_t err = saveLoad(s->slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); } moduleBaseFunction(moduleSaveSlotWrite) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_undefined(); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); errorret_t err = saveWrite(s->slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); } moduleBaseFunction(moduleSaveSlotDelete) { - saveslotscript_t *s = moduleSaveSlotGet(callInfo); - if(!s) return jerry_undefined(); + moduleBaseGetOrReturn(saveslotscript_t, s, moduleSaveSlotGet); errorret_t err = saveDelete(s->slot); if(err.code != ERROR_OK) return moduleBaseThrowError(err); return jerry_undefined(); diff --git a/src/dusk/script/module/scene/modulescene.h b/src/dusk/script/module/scene/modulescene.h index 4bba7926..a520ef8e 100644 --- a/src/dusk/script/module/scene/modulescene.h +++ b/src/dusk/script/module/scene/modulescene.h @@ -25,8 +25,7 @@ moduleBaseFunction(moduleSceneDefaultConstructor) { } moduleBaseFunction(moduleSceneSet) { - if(argc < 1) return moduleBaseThrow("Expected at least 1 argument"); - moduleBaseRequireString(0); + moduleBaseRequireArgs(1); moduleBaseRequireString(0); char_t name[ASSET_FILE_NAME_MAX]; moduleBaseToString(args[0], name, sizeof(name)); diff --git a/src/dusk/script/module/script/moduleinclude.h b/src/dusk/script/module/script/moduleinclude.h index c7d927b8..01ebece2 100644 --- a/src/dusk/script/module/script/moduleinclude.h +++ b/src/dusk/script/module/script/moduleinclude.h @@ -10,9 +10,7 @@ #include "script/scriptmanager.h" moduleBaseFunction(moduleIncludeInclude) { - if(argc < 1 || !jerry_value_is_string(args[0])) { - return moduleBaseThrow("Expected string filename"); - } + moduleBaseRequireArgs(1); moduleBaseRequireString(0); char_t filename[1024]; moduleBaseToString(args[0], filename, sizeof(filename)); diff --git a/src/dusk/script/module/story/modulestory.h b/src/dusk/script/module/story/modulestory.h index 0a72d2c2..edee4f5d 100644 --- a/src/dusk/script/module/story/modulestory.h +++ b/src/dusk/script/module/story/modulestory.h @@ -13,9 +13,8 @@ static scriptproto_t MODULE_STORY_FLAG_PROTO; moduleBaseFunction(moduleStoryFlagGet) { - if(argc < 1) return moduleBaseThrow("Expected flagId"); - moduleBaseRequireNumber(0); - storyflag_t flag = (storyflag_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + storyflag_t flag = (storyflag_t)moduleBaseArgInt(0); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { return moduleBaseThrow("StoryFlag.get: invalid flag ID"); } @@ -23,14 +22,12 @@ moduleBaseFunction(moduleStoryFlagGet) { } moduleBaseFunction(moduleStoryFlagSet) { - if(argc < 2) return moduleBaseThrow("Expected (flagId, value)"); - moduleBaseRequireNumber(0); - moduleBaseRequireNumber(1); - storyflag_t flag = (storyflag_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(2); moduleBaseRequireNumber(0); moduleBaseRequireNumber(1); + storyflag_t flag = (storyflag_t)moduleBaseArgInt(0); if(flag <= STORY_FLAG_NULL || flag >= STORY_FLAG_COUNT) { return moduleBaseThrow("StoryFlag.set: invalid flag ID"); } - storyFlagSet(flag, (storyflagvalue_t)jerry_value_as_number(args[1])); + storyFlagSet(flag, (storyflagvalue_t)moduleBaseArgInt(1)); return jerry_undefined(); } diff --git a/src/dusk/script/module/ui/modulefullbox.h b/src/dusk/script/module/ui/modulefullbox.h index 29574378..07d99996 100644 --- a/src/dusk/script/module/ui/modulefullbox.h +++ b/src/dusk/script/module/ui/modulefullbox.h @@ -9,7 +9,6 @@ #include "script/module/display/modulecolor.h" #include "script/module/event/moduleEvent.h" #include "ui/uifullbox.h" -#include "animation/easing.h" static scriptproto_t MODULE_FULLBOX_UNDER_PROTO; static scriptproto_t MODULE_FULLBOX_OVER_PROTO; @@ -18,65 +17,29 @@ static scriptproto_t MODULE_FULLBOX_OVER_PROTO; static jerry_value_t MODULE_FULLBOX_UNDER_CALLBACK = 0; static jerry_value_t MODULE_FULLBOX_OVER_CALLBACK = 0; -static easingtype_t moduleFullboxReadEasing(jerry_value_t val) { - if(jerry_value_is_number(val)) { - return (easingtype_t)(int32_t)jerry_value_as_number(val); - } - jerry_value_t typeKey = jerry_string_sz("type"); - jerry_value_t typeVal = jerry_object_get(val, typeKey); - jerry_value_free(typeKey); - easingtype_t type = EASING_LINEAR; - if(jerry_value_is_number(typeVal)) { - type = (easingtype_t)(int32_t)jerry_value_as_number(typeVal); - } - jerry_value_free(typeVal); - return type; -} moduleBaseFunction(moduleFullboxUnderTransition) { - if(argc < 4) { - return moduleBaseThrow("FullboxUnder.transition: expected 4 arguments"); - } - + moduleBaseRequireArgs(4); moduleBaseRequireNumber(2); color_t *from = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[0]); if(!from) return moduleBaseThrow("FullboxUnder.transition: arg 0 must be a Color"); - color_t *to = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[1]); if(!to) return moduleBaseThrow("FullboxUnder.transition: arg 1 must be a Color"); - - if(!jerry_value_is_number(args[2])) { - return moduleBaseThrow("FullboxUnder.transition: arg 2 must be a number"); - } - uiFullboxTransition( - &UI_FULLBOX_UNDER, - *from, *to, - (float_t)jerry_value_as_number(args[2]), - moduleFullboxReadEasing(args[3]) + &UI_FULLBOX_UNDER, *from, *to, + moduleBaseArgFloat(2), moduleReadEasing(args[3]) ); return jerry_undefined(); } moduleBaseFunction(moduleFullboxOverTransition) { - if(argc < 4) { - return moduleBaseThrow("FullboxOver.transition: expected 4 arguments"); - } - + moduleBaseRequireArgs(4); moduleBaseRequireNumber(2); color_t *from = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[0]); if(!from) return moduleBaseThrow("FullboxOver.transition: arg 0 must be a Color"); - color_t *to = (color_t*)scriptProtoGetValue(&MODULE_COLOR_PROTO, args[1]); if(!to) return moduleBaseThrow("FullboxOver.transition: arg 1 must be a Color"); - - if(!jerry_value_is_number(args[2])) { - return moduleBaseThrow("FullboxOver.transition: arg 2 must be a number"); - } - uiFullboxTransition( - &UI_FULLBOX_OVER, - *from, *to, - (float_t)jerry_value_as_number(args[2]), - moduleFullboxReadEasing(args[3]) + &UI_FULLBOX_OVER, *from, *to, + moduleBaseArgFloat(2), moduleReadEasing(args[3]) ); return jerry_undefined(); } @@ -89,17 +52,11 @@ moduleBaseFunction(moduleFullboxUnderGetOnTransitionEnd) { moduleBaseFunction(moduleFullboxUnderSetOnTransitionEnd) { (void)callInfo; - if(MODULE_FULLBOX_UNDER_CALLBACK) { - moduleEventJsUnsubscribe( - &UI_FULLBOX_UNDER.onTransitionEnd, MODULE_FULLBOX_UNDER_CALLBACK - ); - jerry_value_free(MODULE_FULLBOX_UNDER_CALLBACK); - MODULE_FULLBOX_UNDER_CALLBACK = 0; - } - if(argc >= 1 && jerry_value_is_function(args[0])) { - MODULE_FULLBOX_UNDER_CALLBACK = jerry_value_copy(args[0]); - moduleEventJsSubscribe(&UI_FULLBOX_UNDER.onTransitionEnd, args[0]); - } + moduleEventSetCallback( + &MODULE_FULLBOX_UNDER_CALLBACK, + &UI_FULLBOX_UNDER.onTransitionEnd, + argc >= 1 ? args[0] : jerry_undefined() + ); return jerry_undefined(); } @@ -111,17 +68,11 @@ moduleBaseFunction(moduleFullboxOverGetOnTransitionEnd) { moduleBaseFunction(moduleFullboxOverSetOnTransitionEnd) { (void)callInfo; - if(MODULE_FULLBOX_OVER_CALLBACK) { - moduleEventJsUnsubscribe( - &UI_FULLBOX_OVER.onTransitionEnd, MODULE_FULLBOX_OVER_CALLBACK - ); - jerry_value_free(MODULE_FULLBOX_OVER_CALLBACK); - MODULE_FULLBOX_OVER_CALLBACK = 0; - } - if(argc >= 1 && jerry_value_is_function(args[0])) { - MODULE_FULLBOX_OVER_CALLBACK = jerry_value_copy(args[0]); - moduleEventJsSubscribe(&UI_FULLBOX_OVER.onTransitionEnd, args[0]); - } + moduleEventSetCallback( + &MODULE_FULLBOX_OVER_CALLBACK, + &UI_FULLBOX_OVER.onTransitionEnd, + argc >= 1 ? args[0] : jerry_undefined() + ); return jerry_undefined(); } diff --git a/src/dusk/script/module/ui/moduletextbox.h b/src/dusk/script/module/ui/moduletextbox.h index 946a753e..a2c27365 100644 --- a/src/dusk/script/module/ui/moduletextbox.h +++ b/src/dusk/script/module/ui/moduletextbox.h @@ -15,9 +15,7 @@ static jerry_value_t MODULE_TEXTBOX_LAST_PAGE_CALLBACK = 0; static scriptproto_t MODULE_TEXTBOX_PROTO; moduleBaseFunction(moduleTextboxSetText) { - if(argc < 1 || !jerry_value_is_string(args[0])) { - return moduleBaseThrow("Textbox.setText: expected string"); - } + moduleBaseRequireArgs(1); moduleBaseRequireString(0); char_t buf[UI_TEXTBOX_TEXT_MAX]; moduleBaseToString(args[0], buf, sizeof(buf)); uiTextboxSetText(buf); @@ -44,10 +42,8 @@ moduleBaseFunction(moduleTextboxGetScroll) { } moduleBaseFunction(moduleTextboxSetScroll) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Textbox.scroll: expected number"); - } - UI_TEXTBOX.scroll = (int32_t)jerry_value_as_number(args[0]); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + UI_TEXTBOX.scroll = moduleBaseArgInt(0); return jerry_undefined(); } @@ -56,12 +52,8 @@ moduleBaseFunction(moduleTextboxGetAdvanceAction) { } moduleBaseFunction(moduleTextboxSetAdvanceAction) { - if(argc < 1 || !jerry_value_is_number(args[0])) { - return moduleBaseThrow("Textbox.advanceAction: expected number"); - } - UI_TEXTBOX.advanceAction = (inputaction_t)( - (int32_t)jerry_value_as_number(args[0]) - ); + moduleBaseRequireArgs(1); moduleBaseRequireNumber(0); + UI_TEXTBOX.advanceAction = (inputaction_t)moduleBaseArgInt(0); return jerry_undefined(); } @@ -89,17 +81,11 @@ moduleBaseFunction(moduleTextboxGetOnPageComplete) { moduleBaseFunction(moduleTextboxSetOnPageComplete) { (void)callInfo; - if(MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK) { - moduleEventJsUnsubscribe( - &UI_TEXTBOX.onPageComplete, MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK - ); - jerry_value_free(MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK); - MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK = 0; - } - if(argc >= 1 && jerry_value_is_function(args[0])) { - MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK = jerry_value_copy(args[0]); - moduleEventJsSubscribe(&UI_TEXTBOX.onPageComplete, args[0]); - } + moduleEventSetCallback( + &MODULE_TEXTBOX_PAGE_COMPLETE_CALLBACK, + &UI_TEXTBOX.onPageComplete, + argc >= 1 ? args[0] : jerry_undefined() + ); return jerry_undefined(); } @@ -111,17 +97,11 @@ moduleBaseFunction(moduleTextboxGetOnLastPage) { moduleBaseFunction(moduleTextboxSetOnLastPage) { (void)callInfo; - if(MODULE_TEXTBOX_LAST_PAGE_CALLBACK) { - moduleEventJsUnsubscribe( - &UI_TEXTBOX.onLastPage, MODULE_TEXTBOX_LAST_PAGE_CALLBACK - ); - jerry_value_free(MODULE_TEXTBOX_LAST_PAGE_CALLBACK); - MODULE_TEXTBOX_LAST_PAGE_CALLBACK = 0; - } - if(argc >= 1 && jerry_value_is_function(args[0])) { - MODULE_TEXTBOX_LAST_PAGE_CALLBACK = jerry_value_copy(args[0]); - moduleEventJsSubscribe(&UI_TEXTBOX.onLastPage, args[0]); - } + moduleEventSetCallback( + &MODULE_TEXTBOX_LAST_PAGE_CALLBACK, + &UI_TEXTBOX.onLastPage, + argc >= 1 ? args[0] : jerry_undefined() + ); return jerry_undefined(); }