From 562569a4eb227f47e4819e6faaf0973c3fe92f19 Mon Sep 17 00:00:00 2001 From: MrMiguel211 <60329473+MrMiguel211@users.noreply.github.com> Date: Thu, 6 Jun 2024 21:25:17 -0700 Subject: [PATCH 1/2] Reimplementation of CameraHint --- schema/randomprime.schema.json | 383 ++++++++++++++++++++---- src/add_modify_obj_patches.rs | 404 ++++++++++++++++++++++---- src/patch_config.rs | 116 ++++++-- src/patches.rs | 44 +-- structs/src/scly_props/camera_hint.rs | 22 +- 5 files changed, 793 insertions(+), 176 deletions(-) diff --git a/schema/randomprime.schema.json b/schema/randomprime.schema.json index 2ab99768..5f038008 100644 --- a/schema/randomprime.schema.json +++ b/schema/randomprime.schema.json @@ -3064,64 +3064,6 @@ "additionalProperties": false } }, - "cameraHints": { - "description": "Add camera hint + camera hint trigger pairs to this room. They are somewhat broken.", - "type": "array", - "items": { - "type": "object", - "properties": { - "layer": { - "description": "Layer of the pair of objects", - "type": "integer", - "default": 0, - "minimum": 0, - "maximum": 63 - }, - "triggerId": { - "description": "Instance ID of the trigger used. Defaults to next unused ID.", - "type": "integer", - "minimum": 0, - "maximum": 4294967295 - }, - "triggerPos": { - "description": "Position of the trigger.", - "$ref": "#/$defs/vector3" - }, - "triggerScale": { - "description": "Extent of the trigger.", - "$ref": "#/$defs/vector3Positive" - }, - "cameraId": { - "description": "Instance ID of the camera object. Defaults to next unused ID.", - "type": "integer", - "minimum": 0, - "maximum": 4294967295 - }, - "cameraPos": { - "description": "Position of the Camera Hint.", - "$ref": "#/$defs/vector3" - }, - "cameraRot": { - "description": "Facing angle of the Camera Hint.", - "$ref": "#/$defs/vector3" - }, - "behavior": { - "description": "- `0`: `Default`\n- `1`: `FreezeLookPosition`\n- `2`: `HintBallToCam`\n- `3`: `HintInitializePosition`\n- `4`: `HintFixedPosition`\n- `5`: `HintFixedTransform`\n- `6`: `PathCameraDesiredPos`\n- `7`: `PathCamera`\n- `8`: `SpindleCamer`\n", - "type": "integer", - "minimum": 0, - "maximum": 8 - } - }, - "required": [ - "triggerPos", - "triggerScale", - "cameraPos", - "cameraRot", - "behavior" - ], - "additionalProperties": false - } - }, "blocks": { "description": "Add blocks to this room. They are specifically the sandstone blocks found in Ruined nursery as they are the closest thing to a 1x1x1 perfect square as I could find.", "type": "array", @@ -4843,7 +4785,7 @@ "$ref": "#/$defs/addModifyLayer" }, "active": { - "description": "Default active state of the ControllerAction object.", + "description": "Default active state of the CameraFilterKeyframe object.", "type": "boolean", "default": true }, @@ -4929,6 +4871,329 @@ ], "additionalProperties": false } + }, + "cameraHints": { + "description": "Add CameraHint objects to this room. They are used to manipulate the Morph Ball camera in various ways.", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/addModifyId" + }, + "layer": { + "$ref": "#/$defs/addModifyLayer" + }, + "position": { + "description": "The position of the CameraHint.", + "$ref": "#/$defs/vector3" + }, + "rotation": { + "description": "The rotation of the CameraHint.", + "$ref": "#/$defs/vector3" + }, + "active": { + "description": "Default active state of the CameraHint.", + "type": "boolean", + "default": true + }, + "priority": { + "type": "integer", + "default": 10 + }, + "behaviour": { + "type": "string", + "enum": [ + "Default", + "FreezeLookPosition", + "HintBallToCam", + "HintInitializePosition", + "HintFixedPosition", + "HintFixedTransform", + "PathCameraDesiredPos", + "PathCamera", + "SpindleCamera" + ], + "default": "Default" + }, + "calculateCamPos": { + "type": "boolean", + "default": false + }, + "chaseAllowed": { + "type": "boolean", + "default": false + }, + "boostAllowed": { + "type": "boolean", + "default": false + }, + "obscureAvoidance": { + "type": "boolean", + "default": false + }, + "volumeCollider": { + "type": "boolean", + "default": false + }, + "applyImmediately": { + "type": "boolean", + "default": false + }, + "lookAtBall": { + "type": "boolean", + "default": false + }, + "hintDistanceSelection": { + "type": "boolean", + "default": false + }, + "hintDistanceSelfPos": { + "type": "boolean", + "default": false + }, + "sinusoidalInterpolation": { + "type": "boolean", + "default": false + }, + "sinusoidalInterpolationHintless": { + "type": "boolean", + "default": false + }, + "clampVelocity": { + "type": "boolean", + "default": false + }, + "skipCinematic": { + "type": "boolean", + "default": false + }, + "noElevationInterp": { + "type": "boolean", + "default": false + }, + "overrideLookDir": { + "type": "boolean", + "default": false + }, + "noElevationVelClamp": { + "type": "boolean", + "default": false + }, + "calculateTransformFromPrevCam": { + "type": "boolean", + "default": false + }, + "noSpline": { + "type": "boolean", + "default": false + }, + "unknown1": { + "type": "boolean", + "default": false + }, + "unknown2": { + "type": "boolean", + "default": false + }, + "overrideMinDist": { + "type": "boolean", + "default": false + }, + "minDist": { + "type": "number", + "minimum": 0.0, + "default": 8.0 + }, + "overrideMaxDist": { + "type": "boolean", + "default": false + }, + "maxDist": { + "type": "number", + "minimum": 0.0, + "default": 8.0 + }, + "overrideBackwardsDist": { + "type": "boolean", + "default": false + }, + "backwardsDist": { + "type": "number", + "minimum": 0.0, + "default": 8.0 + }, + "overrideLookAtOffset": { + "type": "boolean", + "default": false + }, + "lookAtOffset": { + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "overrideChaseLookAtOffset": { + "type": "boolean", + "default": false + }, + "chaseLookAtOffset": { + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ballToCam": { + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "overrideFov": { + "type": "boolean", + "default": false + }, + "fov": { + "description": "55.0 = Morph Ball Camera Fov", + "type": "number", + "minimum": 0.0, + "default": 55.0 + }, + "overrideAttitudeRange": { + "type": "boolean", + "default": false + }, + "attitudeRange": { + "type": "number", + "minimum": 0.0, + "default": 90.0 + }, + "overrideAzimuthRange": { + "type": "boolean", + "default": false + }, + "azimuthRange": { + "type": "number", + "minimum": 0.0, + "default": 90.0 + }, + "overrideAnglePerSecond": { + "type": "boolean", + "default": false + }, + "anglePerSecond": { + "type": "number", + "minimum": 0.0, + "default": 120.0 + }, + "clampVelRange": { + "type": "number", + "minimum": 0.0, + "default": 10.0 + }, + "clampRotRange": { + "type": "number", + "minimum": 0.0, + "default": 120.0 + }, + "overrideElevation": { + "type": "boolean", + "default": false + }, + "elevation": { + "type": "number", + "minimum": 0.0, + "default": 2.7 + }, + "interpolateTime": { + "type": "number", + "minimum": 0.0, + "default": 1.5 + }, + "clampVelTime": { + "type": "number", + "minimum": 0.0, + "default": 2.0 + }, + "controlInterpDur": { + "type": "number", + "minimum": 0.0, + "default": 1.0 + } + }, + "required": [ + "id", + "position", + "rotation", + "behaviour" + ], + "additionalProperties": false + } + }, + "cameraHintTriggers": { + "description": "Add CameraHintTrigger objects to this room. They behave like regular triggers but they can be rotated, and have less properties", + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "$ref": "#/$defs/addModifyId" + }, + "layer": { + "$ref": "#/$defs/addModifyLayer" + }, + "active": { + "description": "Default activate state of the trigger", + "type": "boolean", + "default": true + }, + "position": { + "description": "Position of the trigger.", + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "rotation": { + "description": "Rotation of the trigger.", + "$ref": "#/$defs/vector3", + "default": [ + 0.0, + 0.0, + 0.0 + ] + }, + "scale": { + "description": "Extent of the trigger.", + "$ref": "#/$defs/vector3Positive", + "default": [ + 5, + 5, + 5 + ] + }, + "deactivateOnEnter": { + "description": "Disable this trigger when entered.", + "type": "boolean", + "default": false + }, + "deactivateOnExit": { + "description": "Disable this trigger when exited.", + "type": "boolean", + "default": false + } + }, + "required": [], + "additionalProperties": false + } } }, "additionalProperties": false diff --git a/src/add_modify_obj_patches.rs b/src/add_modify_obj_patches.rs index 8a6d0b09..f2ec8c30 100644 --- a/src/add_modify_obj_patches.rs +++ b/src/add_modify_obj_patches.rs @@ -8,10 +8,10 @@ use crate::{ door_meta::DoorType, mlvl_wrapper, patch_config::{ - ActorKeyFrameConfig, ActorRotateConfig, BlockConfig, BombSlotConfig, CameraConfig, - CameraFilterKeyframeConfig, CameraWaypointConfig, ControllerActionConfig, CounterConfig, - DamageType, FogConfig, GenericTexture, HudmemoConfig, LockOnPoint, PlatformConfig, - PlatformType, PlayerActorConfig, PlayerHintConfig, RelayConfig, SpawnPointConfig, + ActorKeyFrameConfig, ActorRotateConfig, BlockConfig, BombSlotConfig, CameraConfig, CameraHintTriggerConfig, + CameraFilterKeyframeConfig, CameraHintConfig, CameraWaypointConfig, ControllerActionConfig, + CounterConfig, DamageType, FogConfig, GenericTexture, HudmemoConfig, LockOnPoint, + PlatformConfig, PlatformType, PlayerActorConfig, PlayerHintConfig, RelayConfig, SpawnPointConfig, SpecialFunctionConfig, StreamedAudioConfig, SwitchConfig, TimerConfig, TriggerConfig, WaterConfig, WaypointConfig, WorldLightFaderConfig, }, @@ -1911,6 +1911,338 @@ pub fn patch_add_camera_filter_keyframe( ); } +#[allow(clippy::too_many_arguments)] +pub fn patch_add_camera_hint( + _ps: &mut PatcherState, + area: &mut mlvl_wrapper::MlvlArea, + config: CameraHintConfig, +) -> Result<(), String> { + macro_rules! new { + () => { + structs::CameraHint { + name: b"my camerahint\0".as_cstr(), + position: config.position.unwrap_or([0.0, 0.0, 0.0]).into(), + rotation: config.rotation.unwrap_or([0.0, 0.0, 0.0]).into(), + active: config.active.unwrap_or(true) as u8, + priority: config.priority.unwrap_or(10) as u32, + behaviour: config.behaviour as u32, + + camera_hint_params: structs::CameraHintParameters { + calculate_cam_pos: config.calculate_cam_pos.unwrap_or(false) as u8, + chase_allowed: config.chase_allowed.unwrap_or(false) as u8, + boost_allowed: config.boost_allowed.unwrap_or(false) as u8, + obscure_avoidance: config.obscure_avoidance.unwrap_or(false) as u8, + volume_collider: config.volume_collider.unwrap_or(false) as u8, + apply_immediately: config.apply_immediately.unwrap_or(false) as u8, + look_at_ball: config.look_at_ball.unwrap_or(false) as u8, + hint_distance_selection: config.hint_distance_selection.unwrap_or(false) as u8, + hint_distance_self_pos: config.hint_distance_self_pos.unwrap_or(false) as u8, + control_interpolation: config.control_interpolation.unwrap_or(false) as u8, + sinusoidal_interpolation: config.sinusoidal_interpolation.unwrap_or(false) as u8, + sinusoidal_interpolation_hintless: config.sinusoidal_interpolation_hintless.unwrap_or(false) as u8, + clamp_velocity: config.clamp_velocity.unwrap_or(false) as u8, + skip_cinematic: config.skip_cinematic.unwrap_or(false) as u8, + no_elevation_interp: config.no_elevation_interp.unwrap_or(false) as u8, + direct_elevation: config.direct_elevation.unwrap_or(false) as u8, + override_look_dir: config.override_look_dir.unwrap_or(false) as u8, + no_elevation_vel_clamp: config.no_elevation_vel_clamp.unwrap_or(false) as u8, + calculate_transform_from_prev_cam: config.calculate_transform_from_prev_cam.unwrap_or(false) as u8, + no_spline: config.no_spline.unwrap_or(false) as u8, + unknown1: config.unknown1.unwrap_or(false) as u8, + unknown2: config.unknown2.unwrap_or(false) as u8, + } + .into(), + + min_dist: structs::BoolFloat { + override_flags: config.override_min_dist.unwrap_or(false) as u8, + value: config.min_dist.unwrap_or(8.0) as f32, + } + .into(), + max_dist: structs::BoolFloat { + override_flags: config.override_max_dist.unwrap_or(false) as u8, + value: config.max_dist.unwrap_or(8.0) as f32, + } + .into(), + backwards_dist: structs::BoolFloat { + override_flags: config.override_backwards_dist.unwrap_or(false) as u8, + value: config.backwards_dist.unwrap_or(8.0) as f32, + } + .into(), + look_at_offset: structs::BoolVec3 { + override_flags: config.override_look_at_offset.unwrap_or(false) as u8, + value: config.look_at_offset.unwrap_or([0.0, 0.0, 0.0]).into(), + } + .into(), + chase_look_at_offset: structs::BoolVec3 { + override_flags: config.override_chase_look_at_offset.unwrap_or(false) as u8, + value: config.chase_look_at_offset.unwrap_or([0.0, 0.0, 0.0]).into(), + } + .into(), + + ball_to_cam: config.ball_to_cam.unwrap_or([0.0, 0.0, 0.0]).into(), + + fov: structs::BoolFloat { + override_flags: config.override_fov.unwrap_or(false) as u8, + value: config.fov.unwrap_or(55.0) as f32, + } + .into(), + + attitude_range: structs::BoolFloat { + override_flags: config.override_attitude_range.unwrap_or(false) as u8, + value: config.attitude_range.unwrap_or(90.0) as f32, + } + .into(), + + azimuth_range: structs::BoolFloat { + override_flags: config.override_azimuth_range.unwrap_or(false) as u8, + value: config.azimuth_range.unwrap_or(90.0) as f32, + } + .into(), + + angle_per_second: structs::BoolFloat { + override_flags: config.override_angle_per_second.unwrap_or(false) as u8, + value: config.angle_per_second.unwrap_or(120.0) as f32, + } + .into(), + + clamp_vel_range: config.clamp_vel_range.unwrap_or(10.0) as f32, + clamp_rot_range: config.clamp_rot_range.unwrap_or(120.0) as f32, + + elevation: structs::BoolFloat { + override_flags: config.override_elevation.unwrap_or(false) as u8, + value: config.elevation.unwrap_or(2.7) as f32, + } + .into(), + + interpolate_time: config.interpolate_time.unwrap_or(1.5) as f32, + clamp_vel_time: config.clamp_vel_time.unwrap_or(2.0) as f32, + control_interp_dur: config.control_interp_dur.unwrap_or(1.0) as f32, + } + }; + } + + macro_rules! update { + ($obj:expr) => { + let property_data = $obj.property_data.as_camera_hint_mut().unwrap(); + + property_data.behaviour = config.behaviour as u32; + + if let Some(position) = config.position { + property_data.position = position.into() + } + if let Some(rotation) = config.rotation { + property_data.rotation = rotation.into() + } + if let Some(active) = config.active { + property_data.active = active as u8 + } + if let Some(priority) = config.priority { + property_data.priority = priority as u32 + } + if let Some(calculate_cam_pos) = config.calculate_cam_pos { + property_data.camera_hint_params.calculate_cam_pos = calculate_cam_pos as u8 + } + if let Some(chase_allowed) = config.chase_allowed { + property_data.camera_hint_params.chase_allowed = chase_allowed as u8 + } + if let Some(boost_allowed) = config.boost_allowed { + property_data.camera_hint_params.boost_allowed = boost_allowed as u8 + } + if let Some(obscure_avoidance) = config.obscure_avoidance { + property_data.camera_hint_params.obscure_avoidance = obscure_avoidance as u8 + } + if let Some(volume_collider) = config.volume_collider { + property_data.camera_hint_params.volume_collider = volume_collider as u8 + } + if let Some(apply_immediately) = config.apply_immediately { + property_data.camera_hint_params.apply_immediately = apply_immediately as u8 + } + if let Some(look_at_ball) = config.look_at_ball { + property_data.camera_hint_params.look_at_ball = look_at_ball as u8 + } + if let Some(hint_distance_selection) = config.hint_distance_selection { + property_data.camera_hint_params.hint_distance_selection = hint_distance_selection as u8 + } + if let Some(hint_distance_self_pos) = config.hint_distance_self_pos { + property_data.camera_hint_params.hint_distance_self_pos = hint_distance_self_pos as u8 + } + if let Some(control_interpolation) = config.control_interpolation { + property_data.camera_hint_params.control_interpolation = control_interpolation as u8 + } + if let Some(sinusoidal_interpolation) = config.sinusoidal_interpolation { + property_data.camera_hint_params.sinusoidal_interpolation = sinusoidal_interpolation as u8 + } + if let Some(sinusoidal_interpolation_hintless) = config.sinusoidal_interpolation_hintless { + property_data.camera_hint_params.sinusoidal_interpolation_hintless = sinusoidal_interpolation_hintless as u8 + } + if let Some(clamp_velocity) = config.clamp_velocity { + property_data.camera_hint_params.clamp_velocity = clamp_velocity as u8 + } + if let Some(skip_cinematic) = config.skip_cinematic { + property_data.camera_hint_params.skip_cinematic = skip_cinematic as u8 + } + if let Some(no_elevation_interp) = config.no_elevation_interp { + property_data.camera_hint_params.no_elevation_interp = no_elevation_interp as u8 + } + if let Some(direct_elevation) = config.direct_elevation { + property_data.camera_hint_params.direct_elevation = direct_elevation as u8 + } + if let Some(override_look_dir) = config.override_look_dir { + property_data.camera_hint_params.override_look_dir = override_look_dir as u8 + } + if let Some(no_elevation_vel_clamp) = config.no_elevation_vel_clamp { + property_data.camera_hint_params.no_elevation_vel_clamp = no_elevation_vel_clamp as u8 + } + if let Some(calculate_transform_from_prev_cam) = config.calculate_transform_from_prev_cam { + property_data.camera_hint_params.calculate_transform_from_prev_cam = calculate_transform_from_prev_cam as u8 + } + if let Some(no_spline) = config.no_spline { + property_data.camera_hint_params.no_spline = no_spline as u8 + } + if let Some(unknown1) = config.unknown1 { + property_data.camera_hint_params.unknown1 = unknown1 as u8 + } + if let Some(unknown2) = config.unknown2 { + property_data.camera_hint_params.unknown2 = unknown2 as u8 + } + if let Some(override_min_dist) = config.override_min_dist { + property_data.min_dist.override_flags = override_min_dist as u8 + } + if let Some(min_dist) = config.min_dist { + property_data.min_dist.value = min_dist as f32 + } + if let Some(override_max_dist) = config.override_max_dist { + property_data.max_dist.override_flags = override_max_dist as u8 + } + if let Some(max_dist) = config.max_dist { + property_data.max_dist.value = max_dist as f32 + } + if let Some(override_backwards_dist) = config.override_backwards_dist { + property_data.backwards_dist.override_flags = override_backwards_dist as u8 + } + if let Some(backwards_dist) = config.backwards_dist { + property_data.backwards_dist.value = backwards_dist as f32 + } + if let Some(override_look_at_offset) = config.override_look_at_offset { + property_data.look_at_offset.override_flags = override_look_at_offset as u8 + } + if let Some(look_at_offset) = config.look_at_offset { + property_data.look_at_offset.value = look_at_offset.into() + } + if let Some(override_chase_look_at_offset) = config.override_chase_look_at_offset { + property_data.chase_look_at_offset.override_flags = override_chase_look_at_offset as u8 + } + if let Some(chase_look_at_offset) = config.chase_look_at_offset { + property_data.chase_look_at_offset.value = chase_look_at_offset.into() + } + if let Some(ball_to_cam) = config.ball_to_cam { + property_data.ball_to_cam = ball_to_cam.into() + } + if let Some(override_fov) = config.override_fov { + property_data.fov.override_flags = override_fov as u8 + } + if let Some(fov) = config.fov { + property_data.fov.value = fov as f32 + } + if let Some(override_attitude_range) = config.override_attitude_range { + property_data.attitude_range.override_flags = override_attitude_range as u8 + } + if let Some(attitude_range) = config.attitude_range { + property_data.attitude_range.value = attitude_range as f32 + } + if let Some(override_azimuth_range) = config.override_azimuth_range { + property_data.azimuth_range.override_flags = override_azimuth_range as u8 + } + if let Some(azimuth_range) = config.azimuth_range { + property_data.azimuth_range.value = azimuth_range as f32 + } + if let Some(override_angle_per_second) = config.override_angle_per_second { + property_data.angle_per_second.override_flags = override_angle_per_second as u8 + } + if let Some(angle_per_second) = config.angle_per_second { + property_data.angle_per_second.value = angle_per_second as f32 + } + if let Some(clamp_vel_range) = config.clamp_vel_range { + property_data.clamp_vel_range = clamp_vel_range as f32 + } + if let Some(clamp_rot_range) = config.clamp_rot_range { + property_data.clamp_rot_range = clamp_rot_range as f32 + } + if let Some(override_elevation) = config.override_elevation { + property_data.elevation.override_flags = override_elevation as u8 + } + if let Some(elevation) = config.elevation { + property_data.elevation.value = elevation as f32 + } + if let Some(interpolate_time) = config.interpolate_time { + property_data.interpolate_time = interpolate_time as f32 + } + if let Some(clamp_vel_time) = config.clamp_vel_time { + property_data.clamp_vel_time = clamp_vel_time as f32 + } + if let Some(control_interp_dur) = config.control_interp_dur { + property_data.control_interp_dur = control_interp_dur as f32 + } + }; + } + + add_edit_obj_helper!( + area, + Some(config.id), + config.layer, + CameraHint, + new, + update + ); +} + +pub fn patch_add_camera_hint_trigger( + _ps: &mut PatcherState, + area: &mut mlvl_wrapper::MlvlArea, + config: CameraHintTriggerConfig, +) -> Result<(), String> { + macro_rules! new { + () => { + structs::CameraHintTrigger { + name: b"my camerahinttrigger\0".as_cstr(), + position: config.position.unwrap_or([0.0, 0.0, 0.0]).into(), + rotation: config.rotation.unwrap_or([0.0, 0.0, 0.0]).into(), + scale: config.scale.unwrap_or([5.0, 5.0, 5.0]).into(), + active: config.active.unwrap_or(true) as u8, + deactivate_on_enter: config.deactivate_on_enter.unwrap_or(false) as u8, + deactivate_on_exit: config.deactivate_on_exit.unwrap_or(false) as u8, + } + }; + } + + macro_rules! update { + ($obj:expr) => { + let property_data = $obj.property_data.as_camera_hint_trigger_mut().unwrap(); + + if let Some(position) = config.position { + property_data.position = position.into() + } + if let Some(rotation) = config.rotation { + property_data.rotation = rotation.into() + } + if let Some(scale) = config.scale { + property_data.scale = scale.into() + } + if let Some(active) = config.active { + property_data.active = active as u8 + } + if let Some(deactivate_on_enter) = config.deactivate_on_enter { + property_data.deactivate_on_enter = deactivate_on_enter as u8 + } + if let Some(deactivate_on_exit) = config.deactivate_on_exit { + property_data.deactivate_on_exit = deactivate_on_exit as u8 + } + }; + } + + add_edit_obj_helper!(area, config.id, config.layer, CameraHintTrigger, new, update); +} + pub fn patch_add_platform<'r>( _ps: &mut PatcherState, area: &mut mlvl_wrapper::MlvlArea<'r, '_, '_, '_>, @@ -3053,41 +3385,7 @@ pub fn patch_lock_on_point<'r>( Ok(()) } -#[allow(clippy::too_many_arguments)] -pub fn patch_add_camera_hint( - _ps: &mut PatcherState, - area: &mut mlvl_wrapper::MlvlArea, - trigger_pos: [f32; 3], - trigger_scale: [f32; 3], - camera_pos: [f32; 3], - camera_rot: [f32; 3], - behavior: u32, - layer: u32, - camera_id: Option, - trigger_id: Option, -) -> Result<(), String> { - let layer = layer as usize; - let camear_hint_id = camera_id.unwrap_or(area.new_object_id_from_layer_id(layer)); - let camera_hint_trigger_id = trigger_id.unwrap_or(area.new_object_id_from_layer_id(layer)); - - let camera_objs = add_camera_hint( - camear_hint_id, - camera_hint_trigger_id, - trigger_pos, - trigger_scale, - camera_pos, - camera_rot, - behavior, - ); - - area.mrea().scly_section_mut().layers.as_mut_vec()[layer] - .objects - .as_mut_vec() - .extend_from_slice(&camera_objs); - - Ok(()) -} - +// different camera hint thing for a separate arbitrary patch pub fn add_camera_hint<'r>( camear_hint_id: u32, camera_hint_trigger_id: u32, @@ -3095,7 +3393,7 @@ pub fn add_camera_hint<'r>( trigger_scale: [f32; 3], camera_pos: [f32; 3], camera_rot: [f32; 3], - behavior: u32, + behaviour: u32, ) -> Vec> { let objects = vec![ structs::SclyObject { @@ -3107,7 +3405,7 @@ pub fn add_camera_hint<'r>( rotation: camera_rot.into(), active: 1, priority: 8, - behavior, + behaviour, camera_hint_params: structs::CameraHintParameters { calculate_cam_pos: 0, chase_allowed: 0, @@ -3129,50 +3427,50 @@ pub fn add_camera_hint<'r>( no_elevation_vel_clamp: 0, calculate_transform_from_prev_cam: 1, no_spline: 1, - unknown21: 0, - unknown22: 0, + unknown1: 0, + unknown2: 0, }, min_dist: structs::BoolFloat { - active: 0, + override_flags: 0, value: 8.0, }, max_dist: structs::BoolFloat { - active: 0, + override_flags: 0, value: 50.0, }, backwards_dist: structs::BoolFloat { - active: 0, + override_flags: 0, value: 8.0, }, look_at_offset: structs::BoolVec3 { - active: 0, + override_flags: 0, value: [0.0, 1.0, 1.0].into(), }, chase_look_at_offset: structs::BoolVec3 { - active: 0, + override_flags: 0, value: [0.0, 1.0, 1.0].into(), }, ball_to_cam: [3.0, 3.0, 3.0].into(), fov: structs::BoolFloat { - active: 0, + override_flags: 0, value: 55.0, }, attitude_range: structs::BoolFloat { - active: 0, + override_flags: 0, value: 90.0, }, azimuth_range: structs::BoolFloat { - active: 0, + override_flags: 0, value: 90.0, }, angle_per_second: structs::BoolFloat { - active: 0, + override_flags: 0, value: 120.0, }, clamp_vel_range: 10.0, clamp_rot_range: 120.0, elevation: structs::BoolFloat { - active: 0, + override_flags: 0, value: 2.7, }, interpolate_time: 1.0, diff --git a/src/patch_config.rs b/src/patch_config.rs index eb79abef..b0c2129b 100644 --- a/src/patch_config.rs +++ b/src/patch_config.rs @@ -283,33 +283,6 @@ pub struct EscapeSequenceConfig { pub stop_trigger_scale: [f32; 3], } -#[derive(Serialize, Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct CameraHintConfig { - pub layer: Option, - pub trigger_id: Option, - pub trigger_pos: [f32; 3], - pub trigger_scale: [f32; 3], - pub camera_id: Option, - pub camera_pos: [f32; 3], - pub camera_rot: [f32; 3], - - /** - enum class EBallCameraBehaviour { - Default, - FreezeLookPosition, // Unused - HintBallToCam, - HintInitializePosition, - HintFixedPosition, - HintFixedTransform, - PathCameraDesiredPos, // Unused - PathCamera, - SpindleCamera - }; - */ - pub behavior: u32, -} - #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct LockOnPoint { @@ -826,6 +799,93 @@ pub struct CameraFilterKeyframeConfig { pub overlay_texture: Option, } +#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)] +#[serde(deny_unknown_fields)] +pub enum EBallCameraBehaviour { + Default, + FreezeLookPosition, // Unused + HintBallToCam, + HintInitializePosition, + HintFixedPosition, + HintFixedTransform, + PathCameraDesiredPos, // Unused + PathCamera, + SpindleCamera +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct CameraHintConfig { + pub id: u32, + pub layer: Option, + pub position: Option<[f32; 3]>, + pub rotation: Option<[f32; 3]>, + pub active: Option, + pub priority: Option, + pub behaviour: EBallCameraBehaviour, + pub calculate_cam_pos: Option, + pub chase_allowed: Option, + pub boost_allowed: Option, + pub obscure_avoidance: Option, + pub volume_collider: Option, + pub apply_immediately: Option, + pub look_at_ball: Option, + pub hint_distance_selection: Option, + pub hint_distance_self_pos: Option, + pub control_interpolation: Option, + pub sinusoidal_interpolation: Option, + pub sinusoidal_interpolation_hintless: Option, + pub clamp_velocity: Option, + pub skip_cinematic: Option, + pub no_elevation_interp: Option, + pub direct_elevation: Option, + pub override_look_dir: Option, + pub no_elevation_vel_clamp: Option, + pub calculate_transform_from_prev_cam: Option, + pub no_spline: Option, + pub unknown1: Option, + pub unknown2: Option, + pub override_min_dist: Option, + pub min_dist: Option, + pub override_max_dist: Option, + pub max_dist: Option, + pub override_backwards_dist: Option, + pub backwards_dist: Option, + pub override_look_at_offset: Option, + pub look_at_offset: Option<[f32; 3]>, + pub override_chase_look_at_offset: Option, + pub chase_look_at_offset: Option<[f32; 3]>, + pub ball_to_cam: Option<[f32; 3]>, + pub override_fov: Option, + pub fov: Option, + pub override_attitude_range: Option, + pub attitude_range: Option, + pub override_azimuth_range: Option, + pub azimuth_range: Option, + pub override_angle_per_second: Option, + pub angle_per_second: Option, + pub clamp_vel_range: Option, + pub clamp_rot_range: Option, + pub override_elevation: Option, + pub elevation: Option, + pub interpolate_time: Option, + pub clamp_vel_time: Option, + pub control_interp_dur: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct CameraHintTriggerConfig { + pub id: Option, + pub layer: Option, + pub active: Option, + pub position: Option<[f32; 3]>, + pub rotation: Option<[f32; 3]>, + pub scale: Option<[f32; 3]>, + pub deactivate_on_enter: Option, + pub deactivate_on_exit: Option, +} + #[allow(non_camel_case_types)] #[derive(Debug, Serialize, Deserialize, Copy, Clone, Eq, PartialEq)] #[repr(u32)] @@ -1041,6 +1101,7 @@ pub struct RoomConfig { pub cameras: Option>, pub camera_waypoints: Option>, pub camera_filter_keyframes: Option>, + pub camera_hint_triggers: Option>, // Don't forget to update merge_json when adding here } @@ -1932,6 +1993,7 @@ impl PatchConfigPrivate { extend_option_vec!(cameras, self_room_config, other_room_config); extend_option_vec!(camera_waypoints, self_room_config, other_room_config); extend_option_vec!(camera_filter_keyframes, self_room_config, other_room_config); + extend_option_vec!(camera_hint_triggers, self_room_config, other_room_config); if let Some(other_layers) = &other_room_config.layers { if self_room_config.layers.is_none() { diff --git a/src/patches.rs b/src/patches.rs index 0c27f40e..072f97d5 100644 --- a/src/patches.rs +++ b/src/patches.rs @@ -16350,6 +16350,28 @@ fn build_and_run_patches<'r>( } } + if let Some(camera_hints) = room.camera_hints.as_ref() { + for config in camera_hints { + patcher.add_scly_patch( + (pak_name.as_bytes(), room_info.room_id.to_u32()), + move |ps, area| { + patch_add_camera_hint(ps, area, config.clone()) + }, + ); + } + } + + if let Some(camera_hint_triggers) = room.camera_hint_triggers.as_ref() { + for config in camera_hint_triggers { + patcher.add_scly_patch( + (pak_name.as_bytes(), room_info.room_id.to_u32()), + move |ps, area| { + patch_add_camera_hint_trigger(ps, area, config.clone()) + }, + ); + } + } + if room.streamed_audios.is_some() { for config in room.streamed_audios.as_ref().unwrap() { patcher.add_scly_patch( @@ -16456,28 +16478,6 @@ fn build_and_run_patches<'r>( } } - if room.camera_hints.is_some() { - for camera_hint in room.camera_hints.as_ref().unwrap() { - patcher.add_scly_patch( - (pak_name.as_bytes(), room_info.room_id.to_u32()), - move |ps, area| { - patch_add_camera_hint( - ps, - area, - camera_hint.trigger_pos, - camera_hint.trigger_scale, - camera_hint.camera_pos, - camera_hint.camera_rot, - camera_hint.behavior, - camera_hint.layer.unwrap_or(0), - camera_hint.camera_id, - camera_hint.trigger_id, - ) - }, - ); - } - } - if room.fog.is_some() { patcher.add_scly_patch( (pak_name.as_bytes(), room_info.room_id.to_u32()), diff --git a/structs/src/scly_props/camera_hint.rs b/structs/src/scly_props/camera_hint.rs index 37c85303..d8ab09ca 100644 --- a/structs/src/scly_props/camera_hint.rs +++ b/structs/src/scly_props/camera_hint.rs @@ -6,7 +6,7 @@ use crate::SclyPropertyData; #[auto_struct(Readable, Writable, FixedSize)] #[derive(Debug, Clone)] pub struct CameraHintParameters { - #[auto_struct(expect = 15)] + #[auto_struct(expect = 22)] prop_count: u32, pub calculate_cam_pos: u8, pub chase_allowed: u8, @@ -28,28 +28,28 @@ pub struct CameraHintParameters { pub no_elevation_vel_clamp: u8, pub calculate_transform_from_prev_cam: u8, pub no_spline: u8, - pub unknown21: u8, - pub unknown22: u8, + pub unknown1: u8, + pub unknown2: u8, } #[auto_struct(Readable, Writable, FixedSize)] #[derive(Debug, Clone)] pub struct BoolFloat { - pub active: u8, + pub override_flags: u8, pub value: f32, } #[auto_struct(Readable, Writable, FixedSize)] #[derive(Debug, Clone)] pub struct BoolVec3 { - pub active: u8, + pub override_flags: u8, pub value: GenericArray, } #[auto_struct(Readable, Writable)] #[derive(Debug, Clone)] pub struct CameraHint<'r> { - #[auto_struct(expect = 9)] + #[auto_struct(expect = 23)] prop_count: u32, pub name: CStr<'r>, @@ -57,29 +57,21 @@ pub struct CameraHint<'r> { pub rotation: GenericArray, pub active: u8, pub priority: u32, - pub behavior: u32, - + pub behaviour: u32, pub camera_hint_params: CameraHintParameters, - pub min_dist: BoolFloat, pub max_dist: BoolFloat, pub backwards_dist: BoolFloat, - pub look_at_offset: BoolVec3, pub chase_look_at_offset: BoolVec3, - pub ball_to_cam: GenericArray, - pub fov: BoolFloat, pub attitude_range: BoolFloat, pub azimuth_range: BoolFloat, pub angle_per_second: BoolFloat, - pub clamp_vel_range: f32, pub clamp_rot_range: f32, - pub elevation: BoolFloat, - pub interpolate_time: f32, pub clamp_vel_time: f32, pub control_interp_dur: f32, From abd965f1ff46ea0034f83c7f00370527127b78e9 Mon Sep 17 00:00:00 2001 From: MrMiguel211 <60329473+MrMiguel211@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:44:34 -0700 Subject: [PATCH 2/2] id required --- schema/randomprime.schema.json | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/schema/randomprime.schema.json b/schema/randomprime.schema.json index 5f038008..75395477 100644 --- a/schema/randomprime.schema.json +++ b/schema/randomprime.schema.json @@ -5175,9 +5175,9 @@ "description": "Extent of the trigger.", "$ref": "#/$defs/vector3Positive", "default": [ - 5, - 5, - 5 + 5.0, + 5.0, + 5.0 ] }, "deactivateOnEnter": { @@ -5191,7 +5191,9 @@ "default": false } }, - "required": [], + "required": [ + "id" + ], "additionalProperties": false } }