Get animation working with cutscenes and get switch object workings
This commit is contained in:
parent
7f965d28f3
commit
8d0be1c12a
Binary file not shown.
|
@ -53,6 +53,12 @@ local function raw(value)
|
|||
return setmetatable({ value = value}, RawType)
|
||||
end
|
||||
|
||||
RawType.__index = RawType;
|
||||
|
||||
function RawType.__tostring(raw)
|
||||
return 'raw(' .. raw.value .. ')'
|
||||
end
|
||||
|
||||
--- renders a string directly in the ouptut instead of wrapping the output in quotes
|
||||
---@function raw
|
||||
---@tparam string value
|
||||
|
|
|
@ -42,6 +42,24 @@ local function quaternion(x, y, z, w)
|
|||
return setmetatable({ x = x, y = y, z = z, w = w }, Quaternion)
|
||||
end
|
||||
|
||||
--- creates a new quaternion with an axis and an angle in radians
|
||||
--- @function quaternion
|
||||
--- @tparam Vector3 axis
|
||||
--- @tparam number angle
|
||||
--- @treturn Quaternion
|
||||
local function axis_angle(axis, angle)
|
||||
local normalized_axis = axis:normalized()
|
||||
local cos_angle = math.cos(angle * 0.5)
|
||||
local sin_angle = math.sin(angle * 0.5)
|
||||
|
||||
return quaternion(
|
||||
normalized_axis.x * sin_angle,
|
||||
normalized_axis.y * sin_angle,
|
||||
normalized_axis.z * sin_angle,
|
||||
cos_angle
|
||||
)
|
||||
end
|
||||
|
||||
--- determines if the input is a Quaternion
|
||||
--- @function isQuaternion
|
||||
--- @tparam any obj
|
||||
|
@ -406,5 +424,6 @@ return {
|
|||
Box3 = Box3,
|
||||
Quaternion = Quaternion,
|
||||
quaternion = quaternion,
|
||||
axis_angle = axis_angle,
|
||||
isQuaternion = isQuaternion,
|
||||
}
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#define COLLISION_OBJECT_HAS_CONTACTS (1 << 0)
|
||||
#define COLLISION_OBJECT_PLAYER_STANDING (1 << 1)
|
||||
#define COLLISION_OBJECT_INTERACTED (1 << 2)
|
||||
|
||||
typedef void (*TriggerCallback)(void* data, struct CollisionObject* objectEnteringTrigger);
|
||||
|
||||
|
|
|
@ -197,13 +197,17 @@ void playerUpdateGrabbedObject(struct Player* player) {
|
|||
|
||||
player->collisionObject.collisionLayers = 0;
|
||||
|
||||
if (collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_GRABBABLE | COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, &hit) && hit.object->body && (hit.object->body->flags & RigidBodyFlagsGrabbable)) {
|
||||
player->grabbing = hit.object;
|
||||
if (collisionSceneRaycast(&gCollisionScene, player->body.currentRoom, &ray, COLLISION_LAYERS_GRABBABLE | COLLISION_LAYERS_TANGIBLE, GRAB_RAYCAST_DISTANCE, 1, &hit)) {
|
||||
hit.object->flags |= COLLISION_OBJECT_INTERACTED;
|
||||
|
||||
if (hit.throughPortal) {
|
||||
player->grabbingThroughPortal = hit.throughPortal == gCollisionScene.portalTransforms[0] ? 0 : 1;
|
||||
} else {
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
if (hit.object->body && (hit.object->body->flags & RigidBodyFlagsGrabbable)) {
|
||||
player->grabbing = hit.object;
|
||||
|
||||
if (hit.throughPortal) {
|
||||
player->grabbingThroughPortal = hit.throughPortal == gCollisionScene.portalTransforms[0] ? 0 : 1;
|
||||
} else {
|
||||
player->grabbingThroughPortal = PLAYER_GRABBING_THROUGH_NOTHING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ struct Vector2 gButtonCylinderEdgeVectors[] = {
|
|||
struct CollisionQuad gButtonCylinderFaces[8];
|
||||
|
||||
struct CollisionCylinder gButtonCylinder = {
|
||||
0.1f,
|
||||
0.5f,
|
||||
0.3f,
|
||||
gButtonCylinderEdgeVectors,
|
||||
sizeof(gButtonCylinderEdgeVectors) / sizeof(*gButtonCylinderEdgeVectors),
|
||||
|
|
|
@ -55,7 +55,7 @@ void signalsSend(unsigned signalIndex) {
|
|||
return;
|
||||
}
|
||||
|
||||
gSignals[bin] = (gSignals[bin] & ~mask) | (gDefaultSignals[bin] ^ mask);
|
||||
gSignals[bin] = (gSignals[bin] & ~mask) | ((gDefaultSignals[bin] ^ mask) & mask);
|
||||
}
|
||||
|
||||
void signalsSetDefault(unsigned signalIndex, int value) {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include "../util/time.h"
|
||||
|
||||
#define COLLIDER_HEIGHT 7.0f
|
||||
#define COLLIDER_HEIGHT 0.7f
|
||||
|
||||
struct Vector2 gSwitchCylinderEdgeVectors[] = {
|
||||
{0.0f, 1.0f},
|
||||
|
@ -22,7 +22,7 @@ struct Vector2 gSwitchCylinderEdgeVectors[] = {
|
|||
struct CollisionQuad gSwitchCylinderFaces[8];
|
||||
|
||||
struct CollisionCylinder gSwitchCylinder = {
|
||||
0.5f,
|
||||
0.1f,
|
||||
COLLIDER_HEIGHT * 0.5f,
|
||||
gSwitchCylinderEdgeVectors,
|
||||
sizeof(gSwitchCylinderEdgeVectors) / sizeof(*gSwitchCylinderEdgeVectors),
|
||||
|
@ -94,7 +94,25 @@ void switchInit(struct Switch* switchObj, struct SwitchDefinition* definition) {
|
|||
switchObj->timeLeft = 0.0f;
|
||||
}
|
||||
|
||||
void switchActivate(struct Switch* switchObj) {
|
||||
if (switchObj->timeLeft > 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
switchObj->flags |= SwitchFlagsDepressed;
|
||||
switchObj->timeLeft = switchObj->duration;
|
||||
signalsSend(switchObj->signalIndex);
|
||||
skAnimatorRunClip(&switchObj->animator, &props_switch001_Armature_down_clip, 0.0f, 0);
|
||||
}
|
||||
|
||||
void switchUpdate(struct Switch* switchObj) {
|
||||
skAnimatorUpdate(&switchObj->animator, switchObj->armature.pose, FIXED_DELTA_TIME);
|
||||
|
||||
if (switchObj->collisionObject.flags & COLLISION_OBJECT_INTERACTED) {
|
||||
switchActivate(switchObj);
|
||||
switchObj->collisionObject.flags &= ~COLLISION_OBJECT_INTERACTED;
|
||||
}
|
||||
|
||||
if (switchObj->timeLeft <= 0.0f) {
|
||||
if ((switchObj->flags & SwitchFlagsDepressed) != 0 &&
|
||||
!skAnimatorIsRunning(&switchObj->animator)) {
|
||||
|
@ -112,15 +130,4 @@ void switchUpdate(struct Switch* switchObj) {
|
|||
} else {
|
||||
signalsSend(switchObj->signalIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void switchActivate(struct Switch* switchObj) {
|
||||
if (switchObj->timeLeft > 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
switchObj->flags |= SwitchFlagsDepressed;
|
||||
switchObj->timeLeft = switchObj->duration;
|
||||
signalsSend(switchObj->signalIndex);
|
||||
skAnimatorRunClip(&switchObj->animator, &props_switch001_Armature_down_clip, 0.0f, 0);
|
||||
}
|
|
@ -58,6 +58,10 @@ void skAnimatorRequestFrame(struct SKAnimator* animator, int nextFrame) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (nextFrame < 0 || nextFrame >= currentClip->nFrames) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (animator->nextFrameStateIndex == -1) {
|
||||
animator->nextFrameStateIndex = 0;
|
||||
}
|
||||
|
@ -163,6 +167,18 @@ int skAnimatorBoneStateIndexOfFrame(struct SKAnimator* animator, int frame) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
int skAnimatorClampFrame(struct SKAnimator* animator, int frame) {
|
||||
if (frame < animator->currentClip->nFrames) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
if (animator->flags & SKAnimatorFlagsLoop) {
|
||||
return frame - animator->currentClip->nFrames;
|
||||
}
|
||||
|
||||
return animator->currentClip->nFrames - 1;
|
||||
}
|
||||
|
||||
void skAnimatorStep(struct SKAnimator* animator, float deltaTime) {
|
||||
struct SKAnimationClip* currentClip = animator->currentClip;
|
||||
|
||||
|
@ -175,7 +191,12 @@ void skAnimatorStep(struct SKAnimator* animator, float deltaTime) {
|
|||
float duration = currentClip->nFrames / currentClip->fps;
|
||||
|
||||
if (animator->currentTime >= duration || animator->currentTime < 0.0f) {
|
||||
animator->currentTime = mathfMod(animator->currentTime, duration);
|
||||
if (animator->flags & SKAnimatorFlagsLoop) {
|
||||
animator->currentTime = mathfMod(animator->currentTime, duration);
|
||||
} else {
|
||||
animator->currentTime = minf(duration, maxf(0.0f, animator->currentTime));
|
||||
animator->flags |= SKAnimatorFlagsDone;
|
||||
}
|
||||
}
|
||||
|
||||
float currentFrameFractional = animator->currentTime * currentClip->fps;
|
||||
|
@ -183,9 +204,8 @@ void skAnimatorStep(struct SKAnimator* animator, float deltaTime) {
|
|||
int nextFrame = (int)ceilf(currentFrameFractional);
|
||||
float lerpValue = currentFrameFractional - prevFrame;
|
||||
|
||||
if (nextFrame >= currentClip->nFrames) {
|
||||
nextFrame -= currentClip->nFrames;
|
||||
}
|
||||
prevFrame = skAnimatorClampFrame(animator, prevFrame);
|
||||
nextFrame = skAnimatorClampFrame(animator, nextFrame);
|
||||
|
||||
if (nextFrame == prevFrame) {
|
||||
lerpValue = 1.0f;
|
||||
|
@ -244,6 +264,11 @@ void skAnimatorUpdate(struct SKAnimator* animator, struct Transform* transforms,
|
|||
|
||||
skAnimatorReadTransform(animator, transforms);
|
||||
|
||||
if (animator->flags & SKAnimatorFlagsDone) {
|
||||
animator->currentClip = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
skAnimatorStep(animator, deltaTime);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
enum SKAnimatorFlags {
|
||||
SKAnimatorFlagsLoop = (1 << 0),
|
||||
SKAnimatorFlagsDone = (1 << 1),
|
||||
};
|
||||
|
||||
struct SKAnimator {
|
||||
|
|
|
@ -49,4 +49,6 @@ sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
|
|||
signalOperatorCount = #signals.operators,
|
||||
animations = sk_definition_writer.reference_to(animation.animated_nodes, 1),
|
||||
animationInfoCount = #animation.animated_nodes,
|
||||
switches = sk_definition_writer.reference_to(entities.switches, 1),
|
||||
switchCount = #entities.switches,
|
||||
})
|
|
@ -33,6 +33,16 @@ table.sort(armatures, function(a, b)
|
|||
return a.name < b.name
|
||||
end)
|
||||
|
||||
local function parse_animation_name(name)
|
||||
local _, str_end = string.find(name, '|')
|
||||
|
||||
if str_end then
|
||||
return string.sub(name, str_end + 1)
|
||||
end
|
||||
|
||||
return name
|
||||
end
|
||||
|
||||
local animated_nodes = {}
|
||||
|
||||
for index, armature in pairs(armatures) do
|
||||
|
@ -58,7 +68,7 @@ for index, armature in pairs(armatures) do
|
|||
sk_definition_writer.add_macro(armature.name .. '_' .. animation.name, tostring(#animation_clips))
|
||||
table.insert(animation_clips, clip)
|
||||
|
||||
animation_names[animation.name] = sk_definition_writer.raw(sk_definition_writer.add_macro(armature.name .. '_ANIMATION_' .. animation.name, animation_index - 1))
|
||||
animation_names[parse_animation_name(animation.name)] = sk_definition_writer.raw(sk_definition_writer.add_macro(armature.name .. '_ANIMATION_' .. animation.name, animation_index - 1))
|
||||
end
|
||||
|
||||
sk_definition_writer.add_definition(armature.name .. '_clips', 'struct SKAnimationClip[]', '_geo', animation_clips)
|
||||
|
@ -87,7 +97,7 @@ end
|
|||
|
||||
local function get_animation_with_name(armature_name, animation_name)
|
||||
local armature = animation_indices_by_name[armature_name]
|
||||
|
||||
|
||||
if not armature then
|
||||
return nil
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
local sk_definition_writer = require('sk_definition_writer')
|
||||
local sk_scene = require('sk_scene')
|
||||
local sk_math = require('sk_math')
|
||||
local room_export = require('tools.level_scripts.room_export')
|
||||
local trigger = require('tools.level_scripts.trigger')
|
||||
local world = require('tools.level_scripts.world')
|
||||
|
@ -154,6 +155,25 @@ end
|
|||
|
||||
sk_definition_writer.add_definition('signage', 'struct SignageDefinition[]', '_geo', signage)
|
||||
|
||||
|
||||
local switches = {}
|
||||
|
||||
for _, switch_element in pairs(sk_scene.nodes_for_type('@switch')) do
|
||||
local position, rotation = switch_element.node.full_transformation:decompose()
|
||||
|
||||
local room_index = room_export.node_nearest_room_index(switch_element.node)
|
||||
|
||||
table.insert(switches, {
|
||||
position,
|
||||
rotation * sk_math.axis_angle(sk_math.vector3(1, 0, 0), math.pi * 0.5),
|
||||
room_index,
|
||||
signals.signal_index_for_name(switch_element.arguments[1]),
|
||||
switch_element.arguments[2] and tonumber(switch_element.arguments[2]) or 0,
|
||||
})
|
||||
end
|
||||
|
||||
sk_definition_writer.add_definition('switches', 'struct SwitchDefinition[]', '_geo', switches)
|
||||
|
||||
return {
|
||||
box_droppers = box_droppers,
|
||||
buttons = buttons,
|
||||
|
@ -163,4 +183,5 @@ return {
|
|||
fizzlers = fizzlers,
|
||||
pedestals = pedestals,
|
||||
signage = signage,
|
||||
switches = switches,
|
||||
}
|
|
@ -159,7 +159,7 @@ local function generate_cutscene_step(step, step_index, label_locations, cutscen
|
|||
elseif step.command == "goto" and #step.args >= 1 then
|
||||
result.type = sk_definition_writer.raw('CutsceneStepTypeGoto')
|
||||
result.gotoStep = {
|
||||
label_locations[step.args[1]] - step_index - 1,
|
||||
label_locations[step.args[1]] - step_index,
|
||||
}
|
||||
elseif step.command == "start_cutscene" and #step.args >= 1 then
|
||||
result.type = sk_definition_writer.raw('CutsceneStepTypeStartCutscene')
|
||||
|
|
Loading…
Reference in a new issue