first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
@tool
|
||||
extends EditorNode3DGizmo
|
||||
|
||||
#var pcam_3d: PhantomCamera3D
|
||||
|
||||
func _redraw() -> void:
|
||||
clear()
|
||||
|
||||
var icon: Material = get_plugin().get_material(get_plugin().get_name(), self)
|
||||
add_unscaled_billboard(icon, 0.035)
|
||||
|
||||
var pcam_3d: PhantomCamera3D = get_node_3d()
|
||||
|
||||
# if pcam_3d.is_following():
|
||||
# _draw_target(pcam_3d, pcam_3d.get_follow_target_position(), "follow_target")
|
||||
# if pcam_3d.is_looking_at():
|
||||
# _draw_target(pcam_3d, pcam_3d.get_look_at_target_position(), "look_at_target")
|
||||
|
||||
if pcam_3d.is_active(): return
|
||||
|
||||
var frustum_lines: PackedVector3Array = PackedVector3Array()
|
||||
var height: float = 0.25
|
||||
var width: float = height * 1.25
|
||||
var forward: float = height * -1.5
|
||||
|
||||
# Trapezoid
|
||||
frustum_lines.push_back(Vector3.ZERO)
|
||||
frustum_lines.push_back(Vector3(-width, height, forward))
|
||||
|
||||
frustum_lines.push_back(Vector3.ZERO)
|
||||
frustum_lines.push_back(Vector3(width, height, forward))
|
||||
|
||||
frustum_lines.push_back(Vector3.ZERO)
|
||||
frustum_lines.push_back(Vector3(-width, -height, forward))
|
||||
|
||||
frustum_lines.push_back(Vector3.ZERO)
|
||||
frustum_lines.push_back(Vector3(width, -height, forward))
|
||||
|
||||
#######
|
||||
# Frame
|
||||
#######
|
||||
## Left
|
||||
frustum_lines.push_back(Vector3(-width, height, forward))
|
||||
frustum_lines.push_back(Vector3(-width, -height, forward))
|
||||
|
||||
## Bottom
|
||||
frustum_lines.push_back(Vector3(-width, -height, forward))
|
||||
frustum_lines.push_back(Vector3(width, -height, forward))
|
||||
|
||||
## Right
|
||||
frustum_lines.push_back(Vector3(width, -height, forward))
|
||||
frustum_lines.push_back(Vector3(width, height, forward))
|
||||
|
||||
## Top
|
||||
frustum_lines.push_back(Vector3(width, height, forward))
|
||||
frustum_lines.push_back(Vector3(-width, height, forward))
|
||||
|
||||
##############
|
||||
# Up Direction
|
||||
##############
|
||||
var up_height: float = height + 0.15
|
||||
var up_width: float = width / 3
|
||||
|
||||
## Left
|
||||
frustum_lines.push_back(Vector3(0, up_height, forward))
|
||||
frustum_lines.push_back(Vector3(-up_width, height, forward))
|
||||
|
||||
## Right
|
||||
frustum_lines.push_back(Vector3(0, up_height, forward))
|
||||
frustum_lines.push_back(Vector3(up_width, height, forward))
|
||||
|
||||
var frustum_material: StandardMaterial3D = get_plugin().get_material("frustum", self)
|
||||
add_lines(frustum_lines, frustum_material, false)
|
||||
|
||||
|
||||
func _draw_target(pcam_3d: Node3D, target_position: Vector3, type: String) -> void:
|
||||
var target_lines: PackedVector3Array = PackedVector3Array()
|
||||
var direction: Vector3 = target_position - pcam_3d.global_position
|
||||
var end_position: Vector3 = pcam_3d.global_basis.z * direction
|
||||
|
||||
target_lines.push_back(Vector3.ZERO)
|
||||
target_lines.push_back(end_position)
|
||||
var target_material: StandardMaterial3D = get_plugin().get_material(type, self)
|
||||
add_lines(target_lines, target_material, false)
|
||||
@@ -0,0 +1 @@
|
||||
uid://cyr6fgximfw6q
|
||||
@@ -0,0 +1,37 @@
|
||||
@tool
|
||||
extends EditorNode3DGizmoPlugin
|
||||
|
||||
const PhantomCamera3DNode: Script = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd")
|
||||
const PhantomCamera3DGizmo: Script = preload("res://addons/phantom_camera/scripts/gizmos/phantom_camera_3d_gizmo.gd")
|
||||
const _icon_texture: Texture2D = preload("res://addons/phantom_camera/icons/phantom_camera_gizmo.svg")
|
||||
var _gizmo_name: String = "PhantomCamera3D"
|
||||
|
||||
var gizmo_name: String: set = set_gizmo_name
|
||||
var _gizmo_icon: Texture2D
|
||||
var _gizmo_spatial_script: Script = PhantomCamera3DNode
|
||||
|
||||
|
||||
func set_gizmo_name(name: String) -> void:
|
||||
_gizmo_name = name
|
||||
|
||||
|
||||
func _get_gizmo_name() -> String:
|
||||
return _gizmo_name
|
||||
|
||||
|
||||
func _has_gizmo(spatial: Node3D) -> bool:
|
||||
return spatial is PhantomCamera3D
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
create_icon_material(gizmo_name, _icon_texture, false, Color.WHITE)
|
||||
create_material("frustum", Color8(252, 127, 127, 255))
|
||||
create_material("follow_target", Color8(185, 58, 89))
|
||||
create_material("look_at_target", Color8(61, 207, 225))
|
||||
|
||||
|
||||
func _create_gizmo(for_node_3d: Node3D) -> EditorNode3DGizmo:
|
||||
if for_node_3d is PhantomCamera3DNode:
|
||||
return PhantomCamera3DGizmo.new()
|
||||
else:
|
||||
return null
|
||||
@@ -0,0 +1 @@
|
||||
uid://bkevga3bx4rfj
|
||||
@@ -0,0 +1,29 @@
|
||||
extends EditorNode3DGizmoPlugin
|
||||
|
||||
var _spatial_script: Script = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_noise_emitter_3d.gd")
|
||||
var _gizmo_icon: Texture2D = preload("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_gizmo.svg")
|
||||
|
||||
var _gizmo_name: StringName = "PhantomCameraNoiseEmitter"
|
||||
|
||||
func _init() -> void:
|
||||
create_material("main", Color8(252, 127, 127, 255))
|
||||
create_handle_material("handles")
|
||||
create_icon_material(_gizmo_name, _gizmo_icon, false, Color.WHITE)
|
||||
|
||||
|
||||
func _has_gizmo(node: Node3D):
|
||||
return node.get_script() == _spatial_script
|
||||
|
||||
|
||||
func _get_gizmo_name() -> String:
|
||||
return _gizmo_name
|
||||
|
||||
|
||||
func _redraw(gizmo: EditorNode3DGizmo):
|
||||
gizmo.clear()
|
||||
|
||||
var icon: Material = get_material(_gizmo_name, gizmo)
|
||||
gizmo.add_unscaled_billboard(icon, 0.035)
|
||||
|
||||
#var material = get_material("main", gizmo)
|
||||
#gizmo.add_lines(_draw_frustum(), material)
|
||||
@@ -0,0 +1 @@
|
||||
uid://dddokcd2ug05i
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace PhantomCamera.Manager;
|
||||
|
||||
public static class PhantomCameraManager
|
||||
{
|
||||
private static GodotObject? _instance;
|
||||
|
||||
public static GodotObject Instance => _instance ??= Engine.GetSingleton("PhantomCameraManager");
|
||||
|
||||
public static PhantomCamera2D[] PhantomCamera2Ds =>
|
||||
Instance.Call(MethodName.GetPhantomCamera2Ds).AsGodotArray<Node2D>()
|
||||
.Select(node => new PhantomCamera2D(node)).ToArray();
|
||||
|
||||
public static PhantomCamera3D[] PhantomCamera3Ds =>
|
||||
Instance.Call(MethodName.GetPhantomCamera3Ds).AsGodotArray<Node3D>()
|
||||
.Select(node => new PhantomCamera3D(node)).ToArray();
|
||||
|
||||
public static PhantomCameraHost[] PhantomCameraHosts =>
|
||||
Instance.Call(MethodName.GetPhantomCameraHosts).AsGodotArray<Node>()
|
||||
.Select(node => new PhantomCameraHost(node)).ToArray();
|
||||
|
||||
public static PhantomCamera2D[] GetPhantomCamera2Ds() => PhantomCamera2Ds;
|
||||
public static PhantomCamera3D[] GetPhantomCamera3Ds() => PhantomCamera3Ds;
|
||||
public static PhantomCameraHost[] GetPhantomCameraHosts() => PhantomCameraHosts;
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetPhantomCamera2Ds = "get_phantom_camera_2ds";
|
||||
public const string GetPhantomCamera3Ds = "get_phantom_camera_3ds";
|
||||
public const string GetPhantomCameraHosts = "get_phantom_camera_hosts";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://vtj8iqx4bp43
|
||||
149
addons/phantom_camera/scripts/managers/phantom_camera_manager.gd
Normal file
149
addons/phantom_camera/scripts/managers/phantom_camera_manager.gd
Normal file
@@ -0,0 +1,149 @@
|
||||
@tool
|
||||
extends Node
|
||||
|
||||
const _CONSTANTS = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
|
||||
#region Signals
|
||||
|
||||
# Noise
|
||||
signal noise_2d_emitted(noise_output: Transform2D, emitter_layer: int)
|
||||
signal noise_3d_emitted(noise_output: Transform3D, emitter_layer: int)
|
||||
|
||||
# PCam Host
|
||||
signal pcam_host_added_to_scene(pcam_host: PhantomCameraHost)
|
||||
signal pcam_host_removed_from_scene(pcam_host: PhantomCameraHost)
|
||||
|
||||
# PCam
|
||||
signal pcam_added_to_scene(pcam: Node)
|
||||
signal pcam_removed_from_scene(pcam: Node)
|
||||
|
||||
# Priority
|
||||
signal pcam_priority_changed(pcam: Node)
|
||||
signal pcam_visibility_changed(pcam: Node)
|
||||
|
||||
signal pcam_teleport(pcam: Node)
|
||||
|
||||
# Limit (2D)
|
||||
signal limit_2d_changed(side: int, limit: int)
|
||||
signal draw_limit_2d(enabled: bool)
|
||||
|
||||
# Camera3DResource (3D)
|
||||
signal camera_3d_resource_changed(property: String, value: Variant)
|
||||
|
||||
# Viewfinder Signals
|
||||
signal viewfinder_pcam_host_switch(pcam_host: PhantomCameraHost)
|
||||
signal pcam_priority_override(pcam: Node, shouldOverride: bool)
|
||||
signal pcam_dead_zone_changed(pcam: Node)
|
||||
signal pcam_host_layer_changed(pcam: Node)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _phantom_camera_host_list: Array[PhantomCameraHost]
|
||||
var _phantom_camera_2d_list: Array[PhantomCamera2D]
|
||||
var _phantom_camera_3d_list: Array[Node] ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Variables
|
||||
|
||||
var phantom_camera_hosts: Array[PhantomCameraHost]:
|
||||
get:
|
||||
return _phantom_camera_host_list
|
||||
|
||||
var phantom_camera_2ds: Array[PhantomCamera2D]:
|
||||
get:
|
||||
return _phantom_camera_2d_list
|
||||
|
||||
var phantom_camera_3ds: Array[Node]: ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
|
||||
get:
|
||||
return _phantom_camera_3d_list
|
||||
|
||||
var screen_size: Vector2i
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _enter_tree() -> void:
|
||||
if not Engine.has_singleton(_CONSTANTS.PCAM_MANAGER_NODE_NAME):
|
||||
Engine.register_singleton(_CONSTANTS.PCAM_MANAGER_NODE_NAME, self)
|
||||
Engine.physics_jitter_fix = 0
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# Setting default screensize
|
||||
screen_size = Vector2i(
|
||||
ProjectSettings.get_setting("display/window/size/viewport_width"),
|
||||
ProjectSettings.get_setting("display/window/size/viewport_height")
|
||||
)
|
||||
|
||||
# For editor
|
||||
if Engine.is_editor_hint():
|
||||
ProjectSettings.settings_changed.connect(func():
|
||||
screen_size = Vector2i(
|
||||
ProjectSettings.get_setting("display/window/size/viewport_width"),
|
||||
ProjectSettings.get_setting("display/window/size/viewport_height")
|
||||
)
|
||||
)
|
||||
# For runtime
|
||||
else:
|
||||
get_tree().get_root().size_changed.connect(func():
|
||||
screen_size = get_viewport().get_visible_rect().size
|
||||
)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func pcam_host_added(caller: Node) -> void:
|
||||
if is_instance_of(caller, PhantomCameraHost):
|
||||
_phantom_camera_host_list.append(caller)
|
||||
pcam_host_added_to_scene.emit(caller)
|
||||
else:
|
||||
printerr("This method can only be called from a PhantomCameraHost node")
|
||||
|
||||
func pcam_host_removed(caller: Node) -> void:
|
||||
if is_instance_of(caller, PhantomCameraHost):
|
||||
_phantom_camera_host_list.erase(caller)
|
||||
pcam_host_removed_from_scene.emit(caller)
|
||||
else:
|
||||
printerr("This method can only be called from a PhantomCameraHost node")
|
||||
|
||||
|
||||
func pcam_added(caller) -> void:
|
||||
if is_instance_of(caller, PhantomCamera2D):
|
||||
_phantom_camera_2d_list.append(caller)
|
||||
pcam_added_to_scene.emit(caller)
|
||||
elif caller.is_class("PhantomCamera3D"): ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
|
||||
_phantom_camera_3d_list.append(caller)
|
||||
pcam_added_to_scene.emit(caller)
|
||||
|
||||
func pcam_removed(caller) -> void:
|
||||
if is_instance_of(caller, PhantomCamera2D):
|
||||
_phantom_camera_2d_list.erase(caller)
|
||||
pcam_removed_from_scene.emit(caller)
|
||||
elif caller.is_class("PhantomCamera3D"): ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
|
||||
_phantom_camera_3d_list.erase(caller)
|
||||
pcam_removed_from_scene.emit(caller)
|
||||
else:
|
||||
printerr("This method can only be called from a PhantomCamera node")
|
||||
|
||||
|
||||
func get_phantom_camera_hosts() -> Array[PhantomCameraHost]:
|
||||
return _phantom_camera_host_list
|
||||
|
||||
func get_phantom_camera_2ds() -> Array[PhantomCamera2D]:
|
||||
return _phantom_camera_2d_list
|
||||
|
||||
func get_phantom_camera_3ds() -> Array: ## Note: To support disable_3d export templates for 2D projects, this is purposely not strongly typed.
|
||||
return _phantom_camera_3d_list
|
||||
|
||||
|
||||
func scene_changed() -> void:
|
||||
_phantom_camera_2d_list.clear()
|
||||
_phantom_camera_3d_list.clear()
|
||||
_phantom_camera_host_list.clear()
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://duq6jhf6unyis
|
||||
23
addons/phantom_camera/scripts/panel/editor.gd
Normal file
23
addons/phantom_camera/scripts/panel/editor.gd
Normal file
@@ -0,0 +1,23 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
#region Onready
|
||||
|
||||
@onready var updater: Control = %UpdateButton
|
||||
@onready var viewfinder: Control = %ViewfinderPanel
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Variables
|
||||
|
||||
var editor_plugin: EditorPlugin
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _ready():
|
||||
updater.editor_plugin = editor_plugin
|
||||
|
||||
#endregion
|
||||
1
addons/phantom_camera/scripts/panel/editor.gd.uid
Normal file
1
addons/phantom_camera/scripts/panel/editor.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://cgfwg3paxkj2x
|
||||
@@ -0,0 +1,162 @@
|
||||
#######################################################################
|
||||
# Credit goes to the Dialogue Manager plugin for this script
|
||||
# Check it out at: https://github.com/nathanhoad/godot_dialogue_manager
|
||||
#######################################################################
|
||||
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
#region Constants
|
||||
|
||||
const TEMP_FILE_NAME = "user://temp.zip"
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Signals
|
||||
|
||||
signal failed()
|
||||
signal updated(updated_to_version: String)
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region @onready
|
||||
|
||||
#@onready var logo: TextureRect = %Logo
|
||||
@onready var _download_verion: Label = %DownloadVersionLabel
|
||||
@onready var _download_http_request: HTTPRequest = %DownloadHTTPRequest
|
||||
@onready var _download_button: Button = %DownloadButton
|
||||
@onready var _download_button_bg: NinePatchRect = %DownloadButtonBG
|
||||
@onready var _download_label: Label = %UpdateLabel
|
||||
|
||||
@onready var _breaking_label: Label = %BreakingLabel
|
||||
@onready var _breaking_margin_container: MarginContainer = %BreakingMarginContainer
|
||||
@onready var _breaking_options_button: OptionButton = %BreakingOptionButton
|
||||
#@onready var current_version_label: Label = %CurrentVersionLabel
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Variables
|
||||
|
||||
# Todo - For 4.2 upgrade - Shows current version
|
||||
var _download_dialogue: AcceptDialog
|
||||
var _button_texture_default: Texture2D = load("res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryDefault.png")
|
||||
var _button_texture_hover: Texture2D = load("res://addons/phantom_camera/assets/PhantomCameraBtnPrimaryHover.png")
|
||||
|
||||
var next_version_release: Dictionary:
|
||||
set(value):
|
||||
next_version_release = value
|
||||
_download_verion.text = "%s update is available for download" % value.tag_name.substr(1)
|
||||
# Todo - For 4.2 upgrade
|
||||
#current_version_label.text = "Current version is " + editor_plugin.get_version()
|
||||
get:
|
||||
return next_version_release
|
||||
|
||||
var _breaking_window_height: float = 520
|
||||
var _breaking_window_height_update: float = 600
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _ready() -> void:
|
||||
_download_http_request.request_completed.connect(_on_http_request_request_completed)
|
||||
_download_button.pressed.connect(_on_download_button_pressed)
|
||||
_download_button.mouse_entered.connect(_on_mouse_entered)
|
||||
_download_button.mouse_exited.connect(_on_mouse_exited)
|
||||
|
||||
_breaking_label.hide()
|
||||
_breaking_margin_container.hide()
|
||||
_breaking_options_button.hide()
|
||||
|
||||
_breaking_options_button.item_selected.connect(_on_item_selected)
|
||||
|
||||
|
||||
func _on_item_selected(index: int) -> void:
|
||||
if index == 1:
|
||||
_download_button.show()
|
||||
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height_update)
|
||||
else:
|
||||
_download_button.hide()
|
||||
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height)
|
||||
|
||||
|
||||
func _on_download_button_pressed() -> void:
|
||||
_download_http_request.request(next_version_release.zipball_url)
|
||||
_download_button.disabled = true
|
||||
_download_label.text = "Downloading..."
|
||||
_download_button_bg.hide()
|
||||
|
||||
|
||||
func _on_mouse_entered() -> void:
|
||||
_download_button_bg.set_texture(_button_texture_hover)
|
||||
|
||||
|
||||
func _on_mouse_exited() -> void:
|
||||
_download_button_bg.set_texture(_button_texture_default)
|
||||
|
||||
|
||||
func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||
if result != HTTPRequest.RESULT_SUCCESS:
|
||||
failed.emit()
|
||||
return
|
||||
|
||||
# Save the downloaded zip
|
||||
var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
|
||||
zip_file.store_buffer(body)
|
||||
zip_file.close()
|
||||
|
||||
OS.move_to_trash(ProjectSettings.globalize_path("res://addons/phantom_camera"))
|
||||
|
||||
var zip_reader: ZIPReader = ZIPReader.new()
|
||||
zip_reader.open(TEMP_FILE_NAME)
|
||||
var files: PackedStringArray = zip_reader.get_files()
|
||||
|
||||
var base_path = files[1]
|
||||
# Remove archive folder
|
||||
files.remove_at(0)
|
||||
# Remove assets folder
|
||||
files.remove_at(0)
|
||||
|
||||
for path in files:
|
||||
var new_file_path: String = path.replace(base_path, "")
|
||||
if path.ends_with("/"):
|
||||
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
|
||||
else:
|
||||
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
|
||||
file.store_buffer(zip_reader.read_file(path))
|
||||
|
||||
zip_reader.close()
|
||||
DirAccess.remove_absolute(TEMP_FILE_NAME)
|
||||
|
||||
updated.emit(next_version_release.tag_name.substr(1))
|
||||
|
||||
|
||||
func _on_notes_button_pressed() -> void:
|
||||
OS.shell_open(next_version_release.html_url)
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func show_updater_warning(next_version_number: Array, current_version_number: Array) -> void:
|
||||
var current_version_number_0: int = current_version_number[0] as int
|
||||
var current_version_number_1: int = current_version_number[1] as int
|
||||
|
||||
var next_version_number_0: int = next_version_number[0] as int # Major release number in the new release
|
||||
var next_version_number_1: int = next_version_number[1] as int # Minor release number in the new release
|
||||
|
||||
if next_version_number_0 > current_version_number_0 or \
|
||||
next_version_number_1 > current_version_number_1:
|
||||
_breaking_label.show()
|
||||
_breaking_margin_container.show()
|
||||
_breaking_options_button.show()
|
||||
_download_button.hide()
|
||||
|
||||
_download_dialogue = get_parent()
|
||||
_download_dialogue.size = Vector2(_download_dialogue.size.x, _breaking_window_height)
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://cjblcocen12r3
|
||||
177
addons/phantom_camera/scripts/panel/updater/update_button.gd
Normal file
177
addons/phantom_camera/scripts/panel/updater/update_button.gd
Normal file
@@ -0,0 +1,177 @@
|
||||
#######################################################################
|
||||
# Credit goes to the Dialogue Manager plugin for this script
|
||||
# Check it out at: https://github.com/nathanhoad/godot_dialogue_manager
|
||||
#######################################################################
|
||||
|
||||
@tool
|
||||
extends Button
|
||||
|
||||
#region Constants
|
||||
|
||||
const REMOTE_RELEASE_URL: StringName = "https://api.github.com/repos/ramokz/phantom-camera/releases"
|
||||
const UPDATER_CONSTANTS := preload("res://addons/phantom_camera/scripts/panel/updater/updater_constants.gd")
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region @onready
|
||||
|
||||
@onready var http_request: HTTPRequest = %HTTPRequest
|
||||
@onready var download_dialog: AcceptDialog = %DownloadDialog
|
||||
@onready var download_update_panel: Control = %DownloadUpdatePanel
|
||||
@onready var needs_reload_dialog: AcceptDialog = %NeedsReloadDialog
|
||||
@onready var update_failed_dialog: AcceptDialog = %UpdateFailedDialog
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Variables
|
||||
|
||||
# The main editor plugin
|
||||
var editor_plugin: EditorPlugin
|
||||
|
||||
var needs_reload: bool = false
|
||||
|
||||
# A lambda that gets called just before refreshing the plugin. Return false to stop the reload.
|
||||
var on_before_refresh: Callable = func(): return true
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _ready() -> void:
|
||||
hide()
|
||||
|
||||
# Check for updates on GitHub Releases
|
||||
check_for_update()
|
||||
|
||||
pressed.connect(_on_update_button_pressed)
|
||||
http_request.request_completed.connect(_request_request_completed)
|
||||
download_update_panel.updated.connect(_on_download_update_panel_updated)
|
||||
needs_reload_dialog.confirmed.connect(_on_needs_reload_dialog_confirmed)
|
||||
|
||||
|
||||
func _request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||
if result != HTTPRequest.RESULT_SUCCESS: return
|
||||
|
||||
if not editor_plugin: return
|
||||
var current_version: String = editor_plugin.get_version()
|
||||
|
||||
# Work out the next version from the releases information on GitHub
|
||||
var response: Array = JSON.parse_string(body.get_string_from_utf8())
|
||||
if typeof(response) != TYPE_ARRAY: return
|
||||
|
||||
# GitHub releases are in order of creation, not order of version
|
||||
var versions: Array = response.filter(func(release):
|
||||
var version: String = release.tag_name.substr(1)
|
||||
return version_to_number(version) > version_to_number(current_version)
|
||||
)
|
||||
|
||||
if versions.size() > 0:
|
||||
if ProjectSettings.get_setting(UPDATER_CONSTANTS.setting_updater_mode) == 1: ## For console output mode
|
||||
|
||||
print_rich("
|
||||
[color=#3AB99A] ********[/color]
|
||||
[color=#3AB99A] ************[/color]
|
||||
[color=#3AB99A]**************[/color]
|
||||
[color=#3AB99A]****** *** *[/color]
|
||||
[color=#3AB99A]****** ***[/color]
|
||||
[color=#3AB99A]********** *****[/color]
|
||||
[color=#3AB99A]******** ***********[/color]
|
||||
[color=#3AB99A]******** *********** **[/color]
|
||||
[color=#3AB99A]********* **************[/color]
|
||||
[color=#3AB99A]********** *************[/color]
|
||||
[color=#3AB99A]** ** ** ******* **[/color]
|
||||
[font_size=18][b]New Phantom Camera version is available[/b][/font_size]")
|
||||
|
||||
if FileAccess.file_exists("res://dev_scenes/3d/dev_scene_3d.tscn"):
|
||||
print_rich("[font_size=14][color=#EAA15E][b]As you're using a fork of the project, you will need to update it manually[/b][/color][/font_size]")
|
||||
|
||||
print_rich("[font_size=12]If you don't want to see this message, then it can be disabled inside:\n[code]Project Settings/Phantom Camera/Updater/Show New Release Info on Editor Launch in Output[/code]")
|
||||
|
||||
return
|
||||
|
||||
download_update_panel.next_version_release = versions[0]
|
||||
download_update_panel.show_updater_warning(
|
||||
versions[0].tag_name.substr(1).split("."),
|
||||
current_version.split(".")
|
||||
)
|
||||
_set_scale()
|
||||
editor_plugin.panel_button.add_theme_color_override("font_color", Color("#3AB99A"))
|
||||
editor_plugin.panel_button.icon = load("res://addons/phantom_camera/icons/phantom_camera_updater_panel_icon.svg")
|
||||
editor_plugin.panel_button.add_theme_color_override("icon_normal_color", Color("#3AB99A"))
|
||||
show()
|
||||
|
||||
|
||||
func _on_update_button_pressed() -> void:
|
||||
if needs_reload:
|
||||
var will_refresh = on_before_refresh.call()
|
||||
if will_refresh:
|
||||
EditorInterface.restart_editor(true)
|
||||
else:
|
||||
_set_scale()
|
||||
download_dialog.popup_centered()
|
||||
|
||||
|
||||
func _set_scale() -> void:
|
||||
var scale: float = EditorInterface.get_editor_scale()
|
||||
download_dialog.min_size = Vector2(300, 250) * scale
|
||||
|
||||
|
||||
func _on_download_dialog_close_requested() -> void:
|
||||
download_dialog.hide()
|
||||
|
||||
|
||||
func _on_download_update_panel_updated(updated_to_version: String) -> void:
|
||||
download_dialog.hide()
|
||||
|
||||
needs_reload_dialog.dialog_text = "Reload to finish update"
|
||||
needs_reload_dialog.ok_button_text = "Reload"
|
||||
needs_reload_dialog.cancel_button_text = "Cancel"
|
||||
needs_reload_dialog.popup_centered()
|
||||
|
||||
needs_reload = true
|
||||
text = "Reload Project"
|
||||
|
||||
|
||||
func _on_download_update_panel_failed() -> void:
|
||||
download_dialog.hide()
|
||||
update_failed_dialog.dialog_text = "Updated Failed"
|
||||
update_failed_dialog.popup_centered()
|
||||
|
||||
|
||||
func _on_needs_reload_dialog_confirmed() -> void:
|
||||
EditorInterface.restart_editor(true)
|
||||
|
||||
|
||||
func _on_timer_timeout() -> void:
|
||||
if not needs_reload:
|
||||
check_for_update()
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Functions
|
||||
|
||||
# Convert a version number to an actually comparable number
|
||||
func version_to_number(version: String) -> int:
|
||||
var regex = RegEx.new()
|
||||
regex.compile("[a-zA-Z]+")
|
||||
if regex.search(str(version)): return 0
|
||||
|
||||
var bits = version.split(".")
|
||||
var version_bit: int
|
||||
var multiplier: int = 10000
|
||||
for i in bits.size():
|
||||
version_bit += bits[i].to_int() * multiplier / (10 ** (i))
|
||||
|
||||
return version_bit
|
||||
|
||||
|
||||
func check_for_update() -> void:
|
||||
if ProjectSettings.get_setting(UPDATER_CONSTANTS.setting_updater_mode) == 0: return
|
||||
|
||||
http_request.request(REMOTE_RELEASE_URL)
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://bwc42i46603qn
|
||||
@@ -0,0 +1,8 @@
|
||||
extends RefCounted
|
||||
|
||||
# Plugin Project Settings Sections
|
||||
const setting_phantom_camera: StringName = "phantom_camera/"
|
||||
const setting_updater_name: StringName = setting_phantom_camera + "updater/"
|
||||
|
||||
# Updater Settings
|
||||
const setting_updater_mode: StringName = setting_updater_name + "updater_mode"
|
||||
@@ -0,0 +1 @@
|
||||
uid://c8qkbc38waor2
|
||||
112
addons/phantom_camera/scripts/panel/viewfinder/host_list.gd
Normal file
112
addons/phantom_camera/scripts/panel/viewfinder/host_list.gd
Normal file
@@ -0,0 +1,112 @@
|
||||
@tool
|
||||
extends VBoxContainer
|
||||
|
||||
#region Constants
|
||||
|
||||
const _constants := preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
const _host_list_item: PackedScene = preload("res://addons/phantom_camera/panel/viewfinder/host_list/host_list_item.tscn")
|
||||
|
||||
#endregion
|
||||
|
||||
signal pcam_host_removed(pcam_host: PhantomCameraHost)
|
||||
|
||||
@onready var _host_list_button: Button = %HostListButton
|
||||
@onready var _host_list_scroll_container: ScrollContainer = %ScrollContainer
|
||||
@onready var _host_list_item_container: VBoxContainer = %HostListContainer
|
||||
|
||||
var _host_list_open: bool = false
|
||||
|
||||
var _bottom_offset_value: float
|
||||
|
||||
var _pcam_host_list: Array[PhantomCameraHost]
|
||||
var _pcam_manager: Node
|
||||
|
||||
var _viewfinder_panel: Control
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _ready() -> void:
|
||||
_host_list_button.pressed.connect(_host_list_button_pressed)
|
||||
if Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME):
|
||||
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
|
||||
_pcam_manager.pcam_host_removed_from_scene.connect(_remove_pcam_host)
|
||||
|
||||
if not get_parent() is Control: return # To prevent errors when opening the scene on its own
|
||||
_viewfinder_panel = get_parent()
|
||||
_viewfinder_panel.resized.connect(_set_offset_top)
|
||||
|
||||
_host_list_item_container.resized.connect(_set_offset_top)
|
||||
|
||||
|
||||
func _set_offset_top() -> void:
|
||||
offset_top = _set_host_list_size()
|
||||
|
||||
|
||||
func _host_list_button_pressed() -> void:
|
||||
_host_list_open = !_host_list_open
|
||||
|
||||
var tween: Tween = create_tween()
|
||||
var max_duration: float = 0.6
|
||||
|
||||
# 300 being the minimum size of the viewfinder's height
|
||||
var duration: float = clampf(
|
||||
max_duration / (300 / _host_list_item_container.size.y),
|
||||
0.3,
|
||||
max_duration)
|
||||
|
||||
tween.tween_property(self, "offset_top", _set_host_list_size(), duration)\
|
||||
.set_ease(Tween.EASE_OUT)\
|
||||
.set_trans(Tween.TRANS_QUINT)
|
||||
|
||||
|
||||
func _set_host_list_size() -> float:
|
||||
if not _host_list_open:
|
||||
return clampf(
|
||||
_viewfinder_panel.size.y - \
|
||||
_host_list_item_container.size.y - \
|
||||
_host_list_button.size.y - 20,
|
||||
0,
|
||||
INF
|
||||
)
|
||||
else:
|
||||
return (_viewfinder_panel.size.y - _host_list_button.size.y / 2)
|
||||
|
||||
|
||||
func _remove_pcam_host(pcam_host: PhantomCameraHost) -> void:
|
||||
if _pcam_host_list.has(pcam_host):
|
||||
_pcam_host_list.erase(pcam_host)
|
||||
|
||||
var freed_pcam_host: Control
|
||||
for host_list_item_instance in _host_list_item_container.get_children():
|
||||
if not host_list_item_instance.pcam_host == pcam_host: continue
|
||||
freed_pcam_host = host_list_item_instance
|
||||
host_list_item_instance.queue_free()
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func add_pcam_host(pcam_host: PhantomCameraHost, is_default: bool) -> void:
|
||||
if _pcam_host_list.has(pcam_host): return
|
||||
|
||||
_pcam_host_list.append(pcam_host)
|
||||
|
||||
var host_list_item_instance: PanelContainer = _host_list_item.instantiate()
|
||||
var switch_pcam_host_button: Button = host_list_item_instance.get_node("%SwitchPCamHost")
|
||||
if is_default: switch_pcam_host_button.button_pressed = true
|
||||
|
||||
if not pcam_host.tree_exiting.is_connected(_remove_pcam_host):
|
||||
pcam_host.tree_exiting.connect(_remove_pcam_host.bind(pcam_host))
|
||||
|
||||
host_list_item_instance.pcam_host = pcam_host
|
||||
|
||||
_host_list_item_container.add_child(host_list_item_instance)
|
||||
|
||||
|
||||
func clear_pcam_host_list() -> void:
|
||||
_pcam_host_list.clear()
|
||||
|
||||
for host_list_item_instance in _host_list_item_container.get_children():
|
||||
host_list_item_instance.queue_free()
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://c84cxry3t35ny
|
||||
@@ -0,0 +1,58 @@
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
const button_group_resource: ButtonGroup = preload("res://addons/phantom_camera/panel/viewfinder/host_list/host_list_item_group.tres")
|
||||
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
|
||||
@onready var select_pcam_host: Button = %SelectPCamHost
|
||||
@onready var switch_pcam_host: Button = %SwitchPCamHost
|
||||
|
||||
var pcam_host: PhantomCameraHost:
|
||||
set(value):
|
||||
pcam_host = value
|
||||
if not is_instance_valid(value): return
|
||||
if not pcam_host.renamed.is_connected(_rename_pcam_host):
|
||||
pcam_host.renamed.connect(_rename_pcam_host)
|
||||
pcam_host.has_error.connect(_pcam_host_has_error)
|
||||
get:
|
||||
return pcam_host
|
||||
|
||||
var _pcam_manager: Node
|
||||
|
||||
#region Private fucntions
|
||||
|
||||
func _ready() -> void:
|
||||
switch_pcam_host.button_group = button_group_resource
|
||||
select_pcam_host.pressed.connect(_select_pcam)
|
||||
switch_pcam_host.pressed.connect(_switch_pcam_host)
|
||||
|
||||
if not is_instance_valid(pcam_host): return
|
||||
switch_pcam_host.text = pcam_host.name
|
||||
|
||||
_pcam_host_has_error()
|
||||
|
||||
|
||||
func _pcam_host_has_error() -> void:
|
||||
if pcam_host.show_warning:
|
||||
%ErrorPCamHost.visible = true
|
||||
else:
|
||||
%ErrorPCamHost.visible = false
|
||||
|
||||
|
||||
func _rename_pcam_host() -> void:
|
||||
switch_pcam_host.text = pcam_host.name
|
||||
|
||||
|
||||
func _select_pcam() -> void:
|
||||
EditorInterface.get_selection().clear()
|
||||
EditorInterface.get_selection().add_node(pcam_host)
|
||||
|
||||
|
||||
func _switch_pcam_host() -> void:
|
||||
if not Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME): return
|
||||
if not is_instance_valid(_pcam_manager):
|
||||
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
|
||||
|
||||
_pcam_manager.viewfinder_pcam_host_switch.emit(pcam_host)
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://bv24ubx8mutw7
|
||||
605
addons/phantom_camera/scripts/panel/viewfinder/viewfinder.gd
Normal file
605
addons/phantom_camera/scripts/panel/viewfinder/viewfinder.gd
Normal file
@@ -0,0 +1,605 @@
|
||||
@tool
|
||||
extends Control
|
||||
|
||||
#region Constants
|
||||
|
||||
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
|
||||
# TODO - Should be in a central location
|
||||
const _camera_2d_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/Camera2DIcon.svg")
|
||||
const _camera_3d_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/Camera3DIcon.svg")
|
||||
const _pcam_host_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_host.svg")
|
||||
const _pcam_2D_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_2d.svg")
|
||||
const _pcam_3D_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/phantom_camera_3d.svg")
|
||||
|
||||
const _overlay_color_alpha: float = 0.3
|
||||
|
||||
#endregion
|
||||
|
||||
#region @onready
|
||||
|
||||
@onready var dead_zone_center_hbox: VBoxContainer = %DeadZoneCenterHBoxContainer
|
||||
@onready var dead_zone_center_center_panel: Panel = %DeadZoneCenterCenterPanel
|
||||
@onready var dead_zone_left_center_panel: Panel = %DeadZoneLeftCenterPanel
|
||||
@onready var dead_zone_right_center_panel: Panel = %DeadZoneRightCenterPanel
|
||||
@onready var target_point: Panel = %TargetPoint
|
||||
|
||||
@onready var aspect_ratio_container: AspectRatioContainer = %AspectRatioContainer
|
||||
@onready var camera_viewport_panel: Panel = aspect_ratio_container.get_child(0)
|
||||
@onready var _viewfinder: Control = %Viewfinder
|
||||
@onready var _dead_zone_h_box_container: Control = %DeadZoneHBoxContainer
|
||||
@onready var sub_viewport: SubViewport = %SubViewport
|
||||
|
||||
@onready var _empty_state_control: Control = %EmptyStateControl
|
||||
@onready var _empty_state_icon: TextureRect = %EmptyStateIcon
|
||||
@onready var _empty_state_text: RichTextLabel = %EmptyStateText
|
||||
@onready var _add_node_button: Button = %AddNodeButton
|
||||
@onready var _add_node_button_text: RichTextLabel = %AddNodeTypeText
|
||||
|
||||
@onready var _priority_override_button: Button = %PriorityOverrideButton
|
||||
@onready var _priority_override_name_label: Label = %PriorityOverrideNameLabel
|
||||
|
||||
@onready var _camera_2d: Camera2D = %Camera2D
|
||||
|
||||
@onready var _pcam_host_list: VBoxContainer = %PCamHostList
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _no_open_scene_icon: CompressedTexture2D = preload("res://addons/phantom_camera/icons/viewfinder/SceneTypesIcon.svg")
|
||||
var _no_open_scene_string: String = "[b]2D[/b] or [b]3D[/b] scene open"
|
||||
|
||||
var _selected_camera: Node
|
||||
var _active_pcam: Node
|
||||
|
||||
var _is_2d: bool
|
||||
|
||||
var _pcam_manager: Node
|
||||
|
||||
var _root_node: Node
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Variables
|
||||
|
||||
var pcam_host_group: Array[PhantomCameraHost]
|
||||
|
||||
var is_scene: bool
|
||||
|
||||
var viewfinder_visible: bool
|
||||
|
||||
var min_horizontal: float
|
||||
var max_horizontal: float
|
||||
var min_vertical: float
|
||||
var max_vertical: float
|
||||
|
||||
var pcam_host: PhantomCameraHost
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _ready() -> void:
|
||||
if not Engine.is_editor_hint():
|
||||
set_process(true)
|
||||
camera_viewport_panel.self_modulate.a = 0
|
||||
|
||||
_root_node = get_tree().current_scene
|
||||
|
||||
if _root_node is Node2D || _root_node is Node3D:
|
||||
%SubViewportContainer.visible = false
|
||||
if _root_node is Node2D:
|
||||
_is_2d = true
|
||||
else:
|
||||
_is_2d = false
|
||||
|
||||
_set_viewfinder(_root_node, false)
|
||||
|
||||
if not Engine.is_editor_hint():
|
||||
_empty_state_control.visible = false
|
||||
|
||||
_priority_override_button.visible = false
|
||||
|
||||
# Triggered when viewport size is changed in Project Settings
|
||||
ProjectSettings.settings_changed.connect(_settings_changed)
|
||||
|
||||
# PCam Host List
|
||||
_pcam_host_list.visible = false
|
||||
_assign_manager()
|
||||
_visibility_check()
|
||||
|
||||
|
||||
func _pcam_host_switch(new_pcam_host: PhantomCameraHost) -> void:
|
||||
_set_viewfinder_camera(new_pcam_host, true)
|
||||
|
||||
|
||||
func _exit_tree() -> void:
|
||||
if aspect_ratio_container.resized.is_connected(_resized):
|
||||
aspect_ratio_container.resized.disconnect(_resized)
|
||||
|
||||
if _add_node_button.pressed.is_connected(_visibility_check):
|
||||
_add_node_button.pressed.disconnect(_visibility_check)
|
||||
|
||||
if is_instance_valid(_active_pcam):
|
||||
if _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
|
||||
_active_pcam.dead_zone_changed.disconnect(_on_dead_zone_changed)
|
||||
|
||||
if _priority_override_button.pressed.is_connected(_select_override_pcam):
|
||||
_priority_override_button.pressed.disconnect(_select_override_pcam)
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if Engine.is_editor_hint() and not viewfinder_visible: return
|
||||
if not is_instance_valid(_active_pcam): return
|
||||
|
||||
var unprojected_position_clamped: Vector2 = Vector2(
|
||||
clamp(_active_pcam.viewport_position.x, min_horizontal, max_horizontal),
|
||||
clamp(_active_pcam.viewport_position.y, min_vertical, max_vertical)
|
||||
)
|
||||
|
||||
if not Engine.is_editor_hint():
|
||||
target_point.position = camera_viewport_panel.size * unprojected_position_clamped - target_point.size / 2
|
||||
|
||||
if not _is_2d: return
|
||||
if not is_instance_valid(pcam_host): return
|
||||
if not is_instance_valid(pcam_host.camera_2d): return
|
||||
|
||||
var window_size_height: float = ProjectSettings.get_setting("display/window/size/viewport_height")
|
||||
sub_viewport.size_2d_override = sub_viewport.size * (window_size_height / sub_viewport.size.y)
|
||||
|
||||
_camera_2d.global_transform = pcam_host.camera_2d.global_transform
|
||||
_camera_2d.offset = pcam_host.camera_2d.offset
|
||||
_camera_2d.zoom = pcam_host.camera_2d.zoom
|
||||
_camera_2d.ignore_rotation = pcam_host.camera_2d.ignore_rotation
|
||||
_camera_2d.anchor_mode = pcam_host.camera_2d.anchor_mode
|
||||
_camera_2d.limit_left = pcam_host.camera_2d.limit_left
|
||||
_camera_2d.limit_top = pcam_host.camera_2d.limit_top
|
||||
_camera_2d.limit_right = pcam_host.camera_2d.limit_right
|
||||
_camera_2d.limit_bottom = pcam_host.camera_2d.limit_bottom
|
||||
|
||||
|
||||
func _settings_changed() -> void:
|
||||
var viewport_width: float = ProjectSettings.get_setting("display/window/size/viewport_width")
|
||||
var viewport_height: float = ProjectSettings.get_setting("display/window/size/viewport_height")
|
||||
var ratio: float = viewport_width / viewport_height
|
||||
aspect_ratio_container.set_ratio(ratio)
|
||||
camera_viewport_panel.size.x = viewport_width / (viewport_height / sub_viewport.size.y)
|
||||
|
||||
# Applies Project Settings to Viewport
|
||||
sub_viewport.canvas_item_default_texture_filter = ProjectSettings.get_setting("rendering/textures/canvas_textures/default_texture_filter")
|
||||
|
||||
# TODO - Add resizer for Framed Viewfinder
|
||||
|
||||
|
||||
func _visibility_check() -> void:
|
||||
if not viewfinder_visible: return
|
||||
|
||||
var pcam_host: PhantomCameraHost
|
||||
var has_camera: bool = false
|
||||
if not Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME): return
|
||||
|
||||
if not Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts().is_empty():
|
||||
has_camera = true
|
||||
pcam_host = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts()[0]
|
||||
|
||||
var root: Node = EditorInterface.get_edited_scene_root()
|
||||
if root is Node2D:
|
||||
var camera_2d: Camera2D
|
||||
|
||||
if has_camera:
|
||||
camera_2d = pcam_host.camera_2d
|
||||
else:
|
||||
camera_2d = _get_camera_2d()
|
||||
|
||||
_is_2d = true
|
||||
is_scene = true
|
||||
_add_node_button.visible = true
|
||||
_check_camera(root, camera_2d)
|
||||
elif root is Node3D:
|
||||
var camera_3d: Camera3D
|
||||
if has_camera:
|
||||
camera_3d = pcam_host.camera_3d
|
||||
elif root.get_viewport() != null:
|
||||
if root.get_viewport().get_camera_3d() != null:
|
||||
camera_3d = root.get_viewport().get_camera_3d()
|
||||
|
||||
_is_2d = false
|
||||
is_scene = true
|
||||
_add_node_button.visible = true
|
||||
_check_camera(root, camera_3d)
|
||||
else:
|
||||
# Is not a 2D or 3D scene
|
||||
is_scene = false
|
||||
_set_empty_viewfinder_state(_no_open_scene_string, _no_open_scene_icon)
|
||||
_add_node_button.visible = false
|
||||
|
||||
# Checks if a new scene is created and changes viewfinder accordingly
|
||||
if not get_tree().node_added.is_connected(_node_added_to_scene):
|
||||
get_tree().node_added.connect(_node_added_to_scene)
|
||||
|
||||
if not _priority_override_button.pressed.is_connected(_select_override_pcam):
|
||||
_priority_override_button.pressed.connect(_select_override_pcam)
|
||||
|
||||
|
||||
func _node_added_to_scene(node: Node) -> void:
|
||||
if node is Node2D or node is Node3D:
|
||||
get_tree().node_added.disconnect(_node_added_to_scene)
|
||||
_visibility_check()
|
||||
|
||||
|
||||
func _get_camera_2d() -> Camera2D:
|
||||
var edited_scene_root: Node = EditorInterface.get_edited_scene_root()
|
||||
|
||||
if edited_scene_root == null: return null
|
||||
|
||||
var viewport: Viewport = edited_scene_root.get_viewport()
|
||||
if viewport == null: return null
|
||||
|
||||
var viewport_rid: RID = viewport.get_viewport_rid()
|
||||
if viewport_rid == null: return null
|
||||
|
||||
var camerasGroupName: String = "__cameras_%d" % viewport_rid.get_id()
|
||||
var cameras: Array[Node] = get_tree().get_nodes_in_group(camerasGroupName)
|
||||
|
||||
for camera in cameras:
|
||||
if camera is Camera2D and camera.is_current:
|
||||
return camera
|
||||
|
||||
return null
|
||||
|
||||
|
||||
func _check_camera(root: Node, camera: Node) -> void:
|
||||
var camera_string: String
|
||||
var pcam_string: String
|
||||
var color: Color
|
||||
var camera_icon: CompressedTexture2D
|
||||
var pcam_icon: CompressedTexture2D
|
||||
|
||||
if _is_2d:
|
||||
camera_string = _constants.CAMERA_2D_NODE_NAME
|
||||
pcam_string = _constants.PCAM_2D_NODE_NAME
|
||||
color = _constants.COLOR_2D
|
||||
camera_icon = _camera_2d_icon
|
||||
pcam_icon = _pcam_2D_icon
|
||||
else:
|
||||
camera_string = _constants.CAMERA_3D_NODE_NAME
|
||||
pcam_string = _constants.PCAM_3D_NODE_NAME
|
||||
color = _constants.COLOR_3D
|
||||
camera_icon = _camera_3d_icon
|
||||
pcam_icon = _pcam_3D_icon
|
||||
|
||||
if camera:
|
||||
# Has Camera
|
||||
if camera.get_children().size() > 0:
|
||||
for cam_child in camera.get_children():
|
||||
if cam_child is PhantomCameraHost:
|
||||
pcam_host = cam_child
|
||||
|
||||
if pcam_host:
|
||||
if get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_2ds() or \
|
||||
get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_3ds():
|
||||
# Pcam exists in tree
|
||||
_set_viewfinder(root, true)
|
||||
_set_viewfinder_state()
|
||||
%NoSupportMsg.visible = false
|
||||
else:
|
||||
# No PCam in scene
|
||||
_update_button(pcam_string, pcam_icon, color)
|
||||
_set_empty_viewfinder_state(pcam_string, pcam_icon)
|
||||
else:
|
||||
# No PCamHost in scene
|
||||
_update_button(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon, _constants.PCAM_HOST_COLOR)
|
||||
_set_empty_viewfinder_state(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon)
|
||||
else:
|
||||
# No PCamHost in scene
|
||||
_update_button(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon, _constants.PCAM_HOST_COLOR)
|
||||
_set_empty_viewfinder_state(_constants.PCAM_HOST_NODE_NAME, _pcam_host_icon)
|
||||
else:
|
||||
# No Camera
|
||||
_update_button(camera_string, camera_icon, color)
|
||||
_set_empty_viewfinder_state(camera_string, camera_icon)
|
||||
|
||||
|
||||
func _update_button(text: String, icon: CompressedTexture2D, color: Color) -> void:
|
||||
_add_node_button_text.set_text("[center]Add [img=32]" + icon.resource_path + "[/img] [b]"+ text + "[/b][/center]");
|
||||
var button_theme_hover: StyleBoxFlat = _add_node_button.get_theme_stylebox("hover")
|
||||
button_theme_hover.border_color = color
|
||||
_add_node_button.add_theme_stylebox_override("hover", button_theme_hover)
|
||||
|
||||
|
||||
func _set_viewfinder_state() -> void:
|
||||
_empty_state_control.visible = false
|
||||
_viewfinder.visible = true
|
||||
|
||||
if is_instance_valid(_active_pcam):
|
||||
if _active_pcam.get_follow_mode() == _active_pcam.FollowMode.FRAMED:
|
||||
_dead_zone_h_box_container.visible = true
|
||||
target_point.visible = true
|
||||
else:
|
||||
_dead_zone_h_box_container.visible = false
|
||||
target_point.visible = false
|
||||
|
||||
|
||||
func _set_empty_viewfinder_state(text: String, icon: CompressedTexture2D) -> void:
|
||||
_viewfinder.visible = false
|
||||
_framed_view_visible(false)
|
||||
|
||||
_empty_state_control.visible = true
|
||||
_empty_state_icon.texture = icon
|
||||
if icon == _no_open_scene_icon:
|
||||
_empty_state_text.set_text("[center]No " + text + "[/center]")
|
||||
else:
|
||||
_empty_state_text.set_text("[center]No [b]" + text + "[/b] in scene[/center]")
|
||||
|
||||
if _add_node_button.pressed.is_connected(_add_node):
|
||||
_add_node_button.pressed.disconnect(_add_node)
|
||||
|
||||
_add_node_button.pressed.connect(_add_node.bind(text))
|
||||
|
||||
|
||||
func _add_node(node_type: String) -> void:
|
||||
var scene_root: Node = EditorInterface.get_edited_scene_root()
|
||||
|
||||
match node_type:
|
||||
_no_open_scene_string:
|
||||
pass
|
||||
_constants.CAMERA_2D_NODE_NAME:
|
||||
var camera: Camera2D = Camera2D.new()
|
||||
_instantiate_node(scene_root, camera, _constants.CAMERA_2D_NODE_NAME)
|
||||
_constants.CAMERA_3D_NODE_NAME:
|
||||
var camera: Camera3D = Camera3D.new()
|
||||
_instantiate_node(scene_root, camera, _constants.CAMERA_3D_NODE_NAME)
|
||||
_constants.PCAM_HOST_NODE_NAME:
|
||||
var pcam_host: PhantomCameraHost = PhantomCameraHost.new()
|
||||
var camera_owner: Node
|
||||
if _is_2d:
|
||||
camera_owner = _get_camera_2d()
|
||||
else:
|
||||
camera_owner = get_tree().get_edited_scene_root().get_viewport().get_camera_3d()
|
||||
_instantiate_node(
|
||||
scene_root,
|
||||
pcam_host,
|
||||
_constants.PCAM_HOST_NODE_NAME,
|
||||
camera_owner
|
||||
)
|
||||
_constants.PCAM_2D_NODE_NAME:
|
||||
var pcam_2D: PhantomCamera2D = PhantomCamera2D.new()
|
||||
_instantiate_node(scene_root, pcam_2D, _constants.PCAM_2D_NODE_NAME)
|
||||
_constants.PCAM_3D_NODE_NAME:
|
||||
var pcam_3D: PhantomCamera3D = PhantomCamera3D.new()
|
||||
_instantiate_node(scene_root, pcam_3D, _constants.PCAM_3D_NODE_NAME)
|
||||
|
||||
_visibility_check()
|
||||
|
||||
|
||||
func _instantiate_node(scene_root: Node, node: Node, name: String, parent: Node = scene_root) -> void:
|
||||
node.set_name(name)
|
||||
parent.add_child(node)
|
||||
node.owner = scene_root
|
||||
|
||||
|
||||
func _set_viewfinder(root: Node, editor: bool) -> void:
|
||||
pcam_host_group = get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME).get_phantom_camera_hosts()
|
||||
if pcam_host_group.size() != 0:
|
||||
if pcam_host_group.size() == 1:
|
||||
_pcam_host_list.visible = false
|
||||
_set_viewfinder_camera(pcam_host_group[0], editor)
|
||||
else:
|
||||
_pcam_host_list.visible = true
|
||||
_set_viewfinder_camera(pcam_host_group[0], editor)
|
||||
for i in pcam_host_group.size():
|
||||
var is_default: bool = false
|
||||
if i == 0:
|
||||
is_default = true
|
||||
_pcam_host_list.add_pcam_host(pcam_host_group[i], is_default)
|
||||
|
||||
|
||||
func _set_viewfinder_camera(new_pcam_host: PhantomCameraHost, editor: bool) -> void:
|
||||
pcam_host = new_pcam_host
|
||||
|
||||
if _is_2d:
|
||||
_selected_camera = pcam_host.camera_2d
|
||||
|
||||
if editor:
|
||||
sub_viewport.disable_3d = true
|
||||
pcam_host = pcam_host
|
||||
_camera_2d.zoom = pcam_host.camera_2d.zoom
|
||||
_camera_2d.offset = pcam_host.camera_2d.offset
|
||||
_camera_2d.ignore_rotation = pcam_host.camera_2d.ignore_rotation
|
||||
|
||||
sub_viewport.world_2d = pcam_host.camera_2d.get_world_2d()
|
||||
sub_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||
sub_viewport.render_target_clear_mode = SubViewport.CLEAR_MODE_ALWAYS
|
||||
sub_viewport.size_2d_override_stretch = true
|
||||
else:
|
||||
_selected_camera = pcam_host.camera_3d
|
||||
if editor:
|
||||
var camera_3d_rid: RID = _selected_camera.get_camera_rid()
|
||||
sub_viewport.disable_3d = false
|
||||
sub_viewport.world_3d = pcam_host.camera_3d.get_world_3d()
|
||||
RenderingServer.viewport_attach_camera(sub_viewport.get_viewport_rid(), camera_3d_rid)
|
||||
|
||||
if _selected_camera.keep_aspect == Camera3D.KeepAspect.KEEP_HEIGHT:
|
||||
aspect_ratio_container.set_stretch_mode(AspectRatioContainer.STRETCH_HEIGHT_CONTROLS_WIDTH)
|
||||
else:
|
||||
aspect_ratio_container.set_stretch_mode(AspectRatioContainer.STRETCH_WIDTH_CONTROLS_HEIGHT)
|
||||
|
||||
set_process(true)
|
||||
|
||||
if not pcam_host.viewfinder_update.is_connected(_on_update_editor_viewfinder):
|
||||
pcam_host.viewfinder_update.connect(_on_update_editor_viewfinder)
|
||||
|
||||
if not pcam_host.viewfinder_disable_dead_zone.is_connected(_disconnect_dead_zone):
|
||||
pcam_host.viewfinder_disable_dead_zone.connect(_disconnect_dead_zone)
|
||||
|
||||
if not aspect_ratio_container.resized.is_connected(_resized):
|
||||
aspect_ratio_container.resized.connect(_resized)
|
||||
|
||||
if is_instance_valid(pcam_host.get_active_pcam()):
|
||||
_active_pcam = pcam_host.get_active_pcam()
|
||||
else:
|
||||
_framed_view_visible(false)
|
||||
_active_pcam = null
|
||||
return
|
||||
|
||||
if not _active_pcam.follow_mode == PhantomCamera2D.FollowMode.FRAMED: return
|
||||
|
||||
_framed_view_visible(true)
|
||||
_on_dead_zone_changed()
|
||||
_connect_dead_zone()
|
||||
|
||||
|
||||
func _connect_dead_zone() -> void:
|
||||
if not _active_pcam and is_instance_valid(pcam_host.get_active_pcam()):
|
||||
_active_pcam = pcam_host.get_active_pcam()
|
||||
|
||||
if not _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
|
||||
_active_pcam.dead_zone_changed.connect(_on_dead_zone_changed)
|
||||
|
||||
_framed_view_visible(true)
|
||||
_viewfinder.visible = true
|
||||
_on_dead_zone_changed()
|
||||
|
||||
func _disconnect_dead_zone() -> void:
|
||||
if not is_instance_valid(_active_pcam): return
|
||||
_framed_view_visible(_is_framed_pcam())
|
||||
|
||||
if _active_pcam.follow_mode_changed.is_connected(_check_follow_mode):
|
||||
_active_pcam.follow_mode_changed.disconnect(_check_follow_mode)
|
||||
|
||||
if _active_pcam.dead_zone_changed.is_connected(_on_dead_zone_changed):
|
||||
_active_pcam.dead_zone_changed.disconnect(_on_dead_zone_changed)
|
||||
|
||||
|
||||
func _resized() -> void:
|
||||
_on_dead_zone_changed()
|
||||
|
||||
|
||||
func _is_framed_pcam() -> bool:
|
||||
if not is_instance_valid(pcam_host): return false
|
||||
_active_pcam = pcam_host.get_active_pcam()
|
||||
if not is_instance_valid(_active_pcam): return false
|
||||
if not _active_pcam.follow_mode == PhantomCamera2D.FollowMode.FRAMED: return false
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func _framed_view_visible(should_show: bool) -> void:
|
||||
if should_show:
|
||||
target_point.visible = true
|
||||
_dead_zone_h_box_container.visible = true
|
||||
else:
|
||||
target_point.visible = false
|
||||
_dead_zone_h_box_container.visible = false
|
||||
|
||||
|
||||
func _on_dead_zone_changed() -> void:
|
||||
if not is_instance_valid(_active_pcam): return
|
||||
if not _active_pcam.follow_mode == _active_pcam.FollowMode.FRAMED: return
|
||||
|
||||
# Waits until the camera_viewport_panel has been resized when launching the game
|
||||
if camera_viewport_panel.size.x == 0:
|
||||
await camera_viewport_panel.resized
|
||||
|
||||
if not _active_pcam == pcam_host.get_active_pcam():
|
||||
_active_pcam == pcam_host.get_active_pcam()
|
||||
|
||||
var dead_zone_width: float = _active_pcam.dead_zone_width * camera_viewport_panel.size.x
|
||||
var dead_zone_height: float = _active_pcam.dead_zone_height * camera_viewport_panel.size.y
|
||||
dead_zone_center_hbox.set_custom_minimum_size(Vector2(dead_zone_width, 0))
|
||||
dead_zone_center_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
|
||||
dead_zone_left_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
|
||||
dead_zone_right_center_panel.set_custom_minimum_size(Vector2(0, dead_zone_height))
|
||||
|
||||
min_horizontal = 0.5 - _active_pcam.dead_zone_width / 2
|
||||
max_horizontal = 0.5 + _active_pcam.dead_zone_width / 2
|
||||
min_vertical = 0.5 - _active_pcam.dead_zone_height / 2
|
||||
max_vertical = 0.5 + _active_pcam.dead_zone_height / 2
|
||||
|
||||
|
||||
func _check_follow_mode() -> void:
|
||||
_framed_view_visible(_is_framed_pcam())
|
||||
|
||||
|
||||
func _on_update_editor_viewfinder(check_framed_view: bool = false) -> void:
|
||||
_active_pcam = pcam_host.get_active_pcam()
|
||||
|
||||
if not is_instance_valid(_active_pcam): return
|
||||
|
||||
if not _active_pcam.follow_mode_changed.is_connected(_check_follow_mode):
|
||||
_active_pcam.follow_mode_changed.connect(_check_follow_mode)
|
||||
|
||||
if _active_pcam.priority_override:
|
||||
_priority_override_button.visible = true
|
||||
_priority_override_name_label.set_text(_active_pcam.name)
|
||||
_priority_override_button.set_tooltip_text(_active_pcam.name)
|
||||
else:
|
||||
_priority_override_button.visible = false
|
||||
|
||||
_framed_view_visible(false)
|
||||
if not check_framed_view: return
|
||||
if _is_framed_pcam(): _connect_dead_zone()
|
||||
|
||||
|
||||
func _select_override_pcam() -> void:
|
||||
EditorInterface.get_selection().clear()
|
||||
EditorInterface.get_selection().add_node(_active_pcam)
|
||||
|
||||
|
||||
func _assign_manager() -> void:
|
||||
if not is_instance_valid(_pcam_manager):
|
||||
if Engine.has_singleton(_constants.PCAM_MANAGER_NODE_NAME):
|
||||
_pcam_manager = Engine.get_singleton(_constants.PCAM_MANAGER_NODE_NAME)
|
||||
_pcam_manager.pcam_host_added_to_scene.connect(_pcam_changed)
|
||||
_pcam_manager.pcam_host_removed_from_scene.connect(_pcam_host_removed_from_scene)
|
||||
|
||||
_pcam_manager.pcam_added_to_scene.connect(_pcam_changed)
|
||||
_pcam_manager.pcam_removed_from_scene.connect(_pcam_changed)
|
||||
|
||||
_pcam_manager.viewfinder_pcam_host_switch.connect(_pcam_host_switch)
|
||||
|
||||
|
||||
func _pcam_host_removed_from_scene(pcam_host: PhantomCameraHost) -> void:
|
||||
if _pcam_manager.phantom_camera_hosts.size() < 2:
|
||||
_pcam_host_list.visible = false
|
||||
|
||||
_visibility_check()
|
||||
|
||||
|
||||
func _pcam_changed(pcam: Node) -> void:
|
||||
_visibility_check()
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func set_visibility(visible: bool) -> void:
|
||||
if visible:
|
||||
viewfinder_visible = true
|
||||
_visibility_check()
|
||||
else:
|
||||
viewfinder_visible = false
|
||||
|
||||
|
||||
func update_dead_zone() -> void:
|
||||
_set_viewfinder(_root_node, true)
|
||||
|
||||
|
||||
## TODO - Signal can be added directly to this file with the changes in Godot 4.5 (https://github.com/godotengine/godot/pull/102986)
|
||||
func scene_changed(scene_root: Node) -> void:
|
||||
_assign_manager()
|
||||
_priority_override_button.visible = false
|
||||
_pcam_host_list.clear_pcam_host_list()
|
||||
|
||||
if not scene_root is Node2D and not scene_root is Node3D:
|
||||
is_scene = false
|
||||
_pcam_host_list.visible = false
|
||||
_set_empty_viewfinder_state(_no_open_scene_string, _no_open_scene_icon)
|
||||
_add_node_button.visible = false
|
||||
else:
|
||||
_visibility_check()
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://drmv3363t8amc
|
||||
253
addons/phantom_camera/scripts/phantom_camera/PhantomCamera.cs
Normal file
253
addons/phantom_camera/scripts/phantom_camera/PhantomCamera.cs
Normal file
@@ -0,0 +1,253 @@
|
||||
using Godot;
|
||||
using PhantomCamera.Noise;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum InactiveUpdateMode
|
||||
{
|
||||
Always,
|
||||
Never
|
||||
}
|
||||
|
||||
public abstract class PhantomCamera
|
||||
{
|
||||
protected readonly GodotObject Node;
|
||||
|
||||
public delegate void BecameActiveEventHandler();
|
||||
public delegate void BecameInactiveEventHandler();
|
||||
public delegate void FollowTargetChangedEventHandler();
|
||||
public delegate void DeadZoneChangedEventHandler();
|
||||
public delegate void TweenStartedEventHandler();
|
||||
public delegate void IsTweeningEventHandler();
|
||||
public delegate void TweenCompletedEventHandler();
|
||||
|
||||
public event BecameActiveEventHandler? BecameActive;
|
||||
public event BecameInactiveEventHandler? BecameInactive;
|
||||
public event FollowTargetChangedEventHandler? FollowTargetChanged;
|
||||
public event DeadZoneChangedEventHandler? DeadZoneChanged;
|
||||
public event TweenStartedEventHandler? TweenStarted;
|
||||
public event IsTweeningEventHandler? IsTweening;
|
||||
public event TweenCompletedEventHandler? TweenCompleted;
|
||||
|
||||
private readonly Callable _callableBecameActive;
|
||||
private readonly Callable _callableBecameInactive;
|
||||
private readonly Callable _callableFollowTargetChanged;
|
||||
private readonly Callable _callableDeadZoneChanged;
|
||||
private readonly Callable _callableTweenStarted;
|
||||
private readonly Callable _callableIsTweening;
|
||||
private readonly Callable _callableTweenCompleted;
|
||||
|
||||
public int Priority
|
||||
{
|
||||
get => (int)Node.Call(MethodName.GetPriority);
|
||||
set => Node.Call(MethodName.SetPriority, value);
|
||||
}
|
||||
|
||||
public bool IsActive => (bool)Node.Call(MethodName.IsActive);
|
||||
|
||||
public bool FollowDamping
|
||||
{
|
||||
get => (bool)Node.Call(MethodName.GetFollowDamping);
|
||||
set => Node.Call(MethodName.SetFollowDamping, value);
|
||||
}
|
||||
|
||||
public bool IsFollowing => (bool)Node.Call(PhantomCamera.MethodName.IsFollowing);
|
||||
|
||||
public float DeadZoneWidth
|
||||
{
|
||||
get => (float)Node.Get(PropertyName.DeadZoneWidth);
|
||||
set => Node.Set(PropertyName.DeadZoneWidth, value);
|
||||
}
|
||||
|
||||
public float DeadZoneHeight
|
||||
{
|
||||
get => (float)Node.Get(PropertyName.DeadZoneHeight);
|
||||
set => Node.Set(PropertyName.DeadZoneHeight, value);
|
||||
}
|
||||
|
||||
public PhantomCameraTween TweenResource
|
||||
{
|
||||
get => new((Resource)Node.Call(MethodName.GetTweenResource));
|
||||
set => Node.Call(MethodName.SetTweenResource, (GodotObject)value.Resource);
|
||||
}
|
||||
|
||||
public bool TweenSkip
|
||||
{
|
||||
get => (bool)Node.Call(MethodName.GetTweenSkip);
|
||||
set => Node.Call(MethodName.SetTweenSkip, value);
|
||||
}
|
||||
|
||||
public float TweenDuration
|
||||
{
|
||||
get => (float)Node.Call(MethodName.GetTweenDuration);
|
||||
set => Node.Call(MethodName.SetTweenDuration, value);
|
||||
}
|
||||
|
||||
public TransitionType TweenTransition
|
||||
{
|
||||
get => (TransitionType)(int)Node.Call(MethodName.GetTweenTransition);
|
||||
set => Node.Call(MethodName.SetTweenTransition, (int)value);
|
||||
}
|
||||
|
||||
public EaseType TweenEase
|
||||
{
|
||||
get => (EaseType)(int)Node.Call(MethodName.GetTweenEase);
|
||||
set => Node.Call(MethodName.SetTweenEase, (int)value);
|
||||
}
|
||||
|
||||
public bool TweenOnLoad
|
||||
{
|
||||
get => (bool)Node.Call(MethodName.GetTweenOnLoad);
|
||||
set => Node.Call(MethodName.SetTweenOnLoad, value);
|
||||
}
|
||||
|
||||
public InactiveUpdateMode InactiveUpdateMode
|
||||
{
|
||||
get => (InactiveUpdateMode)(int)Node.Call(MethodName.GetInactiveUpdateMode);
|
||||
set => Node.Call(MethodName.SetInactiveUpdateMode, (int)value);
|
||||
}
|
||||
|
||||
public int HostLayers
|
||||
{
|
||||
get => (int)Node.Call(MethodName.GetHostLayers);
|
||||
set => Node.Call(MethodName.SetHostLayers, value);
|
||||
}
|
||||
|
||||
public int NoiseEmitterLayer
|
||||
{
|
||||
get => (int)Node.Call(MethodName.GetNoiseEmitterLayer);
|
||||
set => Node.Call(MethodName.SetNoiseEmitterLayer, value);
|
||||
}
|
||||
|
||||
public void TeleportPosition()
|
||||
{
|
||||
Node.Call(MethodName.TeleportPosition);
|
||||
}
|
||||
|
||||
public void SetHostLayersValue(int layer, bool enabled)
|
||||
{
|
||||
Node.Call(MethodName.SetHostLayersValue, layer, enabled);
|
||||
}
|
||||
|
||||
protected PhantomCamera(GodotObject phantomCameraNode)
|
||||
{
|
||||
Node = phantomCameraNode;
|
||||
|
||||
_callableBecameActive = Callable.From(() => BecameActive?.Invoke());
|
||||
_callableBecameInactive = Callable.From(() => BecameInactive?.Invoke());
|
||||
_callableFollowTargetChanged = Callable.From(() => FollowTargetChanged?.Invoke());
|
||||
_callableDeadZoneChanged = Callable.From(() => DeadZoneChanged?.Invoke());
|
||||
_callableTweenStarted = Callable.From(() => TweenStarted?.Invoke());
|
||||
_callableIsTweening = Callable.From(() => IsTweening?.Invoke());
|
||||
_callableTweenCompleted = Callable.From(() => TweenCompleted?.Invoke());
|
||||
|
||||
Node.Connect(SignalName.BecameActive, _callableBecameActive);
|
||||
Node.Connect(SignalName.BecameInactive, _callableBecameInactive);
|
||||
Node.Connect(SignalName.FollowTargetChanged, _callableFollowTargetChanged);
|
||||
Node.Connect(SignalName.DeadZoneChanged, _callableDeadZoneChanged);
|
||||
Node.Connect(SignalName.TweenStarted, _callableTweenStarted);
|
||||
Node.Connect(SignalName.IsTweening, _callableIsTweening);
|
||||
Node.Connect(SignalName.TweenCompleted, _callableTweenCompleted);
|
||||
}
|
||||
|
||||
~PhantomCamera()
|
||||
{
|
||||
Node.Disconnect(SignalName.BecameActive, _callableBecameActive);
|
||||
Node.Disconnect(SignalName.BecameInactive, _callableBecameInactive);
|
||||
Node.Disconnect(SignalName.FollowTargetChanged, _callableFollowTargetChanged);
|
||||
Node.Disconnect(SignalName.DeadZoneChanged, _callableDeadZoneChanged);
|
||||
Node.Disconnect(SignalName.TweenStarted, _callableTweenStarted);
|
||||
Node.Disconnect(SignalName.IsTweening, _callableIsTweening);
|
||||
Node.Disconnect(SignalName.TweenCompleted, _callableTweenCompleted);
|
||||
}
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetFollowMode = "get_follow_mode";
|
||||
public const string IsActive = "is_active";
|
||||
|
||||
public const string GetPriority = "get_priority";
|
||||
public const string SetPriority = "set_priority";
|
||||
|
||||
public const string IsFollowing = "is_following";
|
||||
|
||||
public const string GetFollowTarget = "get_follow_target";
|
||||
public const string SetFollowTarget = "set_follow_target";
|
||||
|
||||
public const string GetFollowTargets = "get_follow_targets";
|
||||
public const string SetFollowTargets = "set_follow_targets";
|
||||
|
||||
public const string TeleportPosition = "teleport_position";
|
||||
|
||||
public const string AppendFollowTargets = "append_follow_targets";
|
||||
public const string AppendFollowTargetsArray = "append_follow_targets_array";
|
||||
public const string EraseFollowTargets = "erase_follow_targets";
|
||||
|
||||
public const string GetFollowPath = "get_follow_path";
|
||||
public const string SetFollowPath = "set_follow_path";
|
||||
|
||||
public const string GetFollowOffset = "get_follow_offset";
|
||||
public const string SetFollowOffset = "set_follow_offset";
|
||||
|
||||
public const string GetFollowDamping = "get_follow_damping";
|
||||
public const string SetFollowDamping = "set_follow_damping";
|
||||
|
||||
public const string GetFollowDampingValue = "get_follow_damping_value";
|
||||
public const string SetFollowDampingValue = "set_follow_damping_value";
|
||||
|
||||
public const string GetFollowAxisLock = "get_follow_axis_lock";
|
||||
public const string SetFollowAxisLock = "set_follow_axis_lock";
|
||||
|
||||
public const string GetTweenResource = "get_tween_resource";
|
||||
public const string SetTweenResource = "set_tween_resource";
|
||||
|
||||
public const string GetTweenSkip = "get_tween_skip";
|
||||
public const string SetTweenSkip = "set_tween_skip";
|
||||
|
||||
public const string GetTweenDuration = "get_tween_duration";
|
||||
public const string SetTweenDuration = "set_tween_duration";
|
||||
|
||||
public const string GetTweenTransition = "get_tween_transition";
|
||||
public const string SetTweenTransition = "set_tween_transition";
|
||||
|
||||
public const string GetTweenEase = "get_tween_ease";
|
||||
public const string SetTweenEase = "set_tween_ease";
|
||||
|
||||
public const string GetTweenOnLoad = "get_tween_on_load";
|
||||
public const string SetTweenOnLoad = "set_tween_on_load";
|
||||
|
||||
public const string GetInactiveUpdateMode = "get_inactive_update_mode";
|
||||
public const string SetInactiveUpdateMode = "set_inactive_update_mode";
|
||||
|
||||
public const string GetHostLayers = "get_host_layers";
|
||||
public const string SetHostLayers = "set_host_layers";
|
||||
public const string SetHostLayersValue = "set_host_layers_value";
|
||||
|
||||
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
|
||||
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
|
||||
|
||||
public const string EmitNoise = "emit_noise";
|
||||
}
|
||||
|
||||
public static class PropertyName
|
||||
{
|
||||
public const string DeadZoneWidth = "dead_zone_width";
|
||||
public const string DeadZoneHeight = "dead_zone_height";
|
||||
}
|
||||
|
||||
public static class SignalName
|
||||
{
|
||||
public const string BecameActive = "became_active";
|
||||
public const string BecameInactive = "became_inactive";
|
||||
public const string FollowTargetChanged = "follow_target_changed";
|
||||
public const string DeadZoneChanged = "dead_zone_changed";
|
||||
public const string DeadZoneReached = "dead_zone_reached";
|
||||
public const string TweenStarted = "tween_started";
|
||||
public const string IsTweening = "is_tweening";
|
||||
public const string TweenCompleted = "tween_completed";
|
||||
public const string TweenInterrupted = "tween_interrupted";
|
||||
public const string NoiseEmitted = "noise_emitted";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://d3wh0457i0i3
|
||||
351
addons/phantom_camera/scripts/phantom_camera/PhantomCamera2D.cs
Normal file
351
addons/phantom_camera/scripts/phantom_camera/PhantomCamera2D.cs
Normal file
@@ -0,0 +1,351 @@
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using PhantomCamera.Noise;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum FollowMode2D
|
||||
{
|
||||
None,
|
||||
Glued,
|
||||
Simple,
|
||||
Group,
|
||||
Path,
|
||||
Framed
|
||||
}
|
||||
|
||||
public enum FollowLockAxis2D
|
||||
{
|
||||
None,
|
||||
X,
|
||||
Y,
|
||||
XY
|
||||
}
|
||||
|
||||
public static class PhantomCamera2DExtensions
|
||||
{
|
||||
public static PhantomCamera2D AsPhantomCamera2D(this Node2D node2D)
|
||||
{
|
||||
return new PhantomCamera2D(node2D);
|
||||
}
|
||||
|
||||
public static PhantomCameraNoiseEmitter2D AsPhantomCameraNoiseEmitter2D(this Node2D node2D)
|
||||
{
|
||||
return new PhantomCameraNoiseEmitter2D(node2D);
|
||||
}
|
||||
|
||||
public static PhantomCameraNoise2D AsPhantomCameraNoise2D(this Resource resource)
|
||||
{
|
||||
return new PhantomCameraNoise2D(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public class PhantomCamera2D : PhantomCamera
|
||||
{
|
||||
public Node2D Node2D => (Node2D)Node;
|
||||
|
||||
public delegate void TweenInterruptedEventHandler(Node2D pCam);
|
||||
public delegate void DeadZoneReachedEventHandler(Vector2 side);
|
||||
public delegate void NoiseEmittedEventHandler(Transform2D output);
|
||||
|
||||
public event TweenInterruptedEventHandler? TweenInterrupted;
|
||||
public event DeadZoneReachedEventHandler? DeadZoneReached;
|
||||
public event NoiseEmittedEventHandler? NoiseEmitted;
|
||||
|
||||
private readonly Callable _callableTweenInterrupted;
|
||||
private readonly Callable _callableDeadZoneReached;
|
||||
private readonly Callable _callableNoiseEmitted;
|
||||
|
||||
public Node2D FollowTarget
|
||||
{
|
||||
get => (Node2D)Node2D.Call(PhantomCamera.MethodName.GetFollowTarget);
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowTarget, value);
|
||||
}
|
||||
|
||||
public Node2D[] FollowTargets
|
||||
{
|
||||
get => Node2D.Call(PhantomCamera.MethodName.GetFollowTargets).AsGodotArray<Node2D>().ToArray();
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowTargets, new Array<Node2D>(value));
|
||||
}
|
||||
|
||||
public void AppendFollowTargets(Node2D target) => Node2D.Call(PhantomCamera.MethodName.AppendFollowTargets, target);
|
||||
public void AppendFollowTargetsArray(Node2D[] targets) => Node2D.Call(PhantomCamera.MethodName.AppendFollowTargetsArray, targets);
|
||||
public void EraseFollowTargets(Node2D target) => Node2D.Call(PhantomCamera.MethodName.EraseFollowTargets, target);
|
||||
|
||||
public FollowMode2D FollowMode => (FollowMode2D)(int)Node.Call(PhantomCamera.MethodName.GetFollowMode);
|
||||
|
||||
public Path2D FollowPath
|
||||
{
|
||||
get => (Path2D)Node2D.Call(PhantomCamera.MethodName.GetFollowPath);
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowPath, value);
|
||||
}
|
||||
|
||||
public Vector2 FollowOffset
|
||||
{
|
||||
get => (Vector2)Node2D.Call(PhantomCamera.MethodName.GetFollowOffset);
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowOffset, value);
|
||||
}
|
||||
|
||||
public Vector2 FollowDampingValue
|
||||
{
|
||||
get => (Vector2)Node2D.Call(PhantomCamera.MethodName.GetFollowDampingValue);
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowDampingValue, value);
|
||||
}
|
||||
|
||||
public FollowLockAxis2D FollowAxisLock
|
||||
{
|
||||
get => (FollowLockAxis2D)(int)Node2D.Call(PhantomCamera.MethodName.GetFollowAxisLock);
|
||||
set => Node2D.Call(PhantomCamera.MethodName.SetFollowAxisLock, (int)value);
|
||||
}
|
||||
|
||||
public Vector2 Zoom
|
||||
{
|
||||
get => (Vector2)Node2D.Call(MethodName.GetZoom);
|
||||
set => Node2D.Call(MethodName.SetZoom, value);
|
||||
}
|
||||
|
||||
public bool SnapToPixel
|
||||
{
|
||||
get => (bool)Node2D.Call(MethodName.GetSnapToPixel);
|
||||
set => Node2D.Call(MethodName.SetSnapToPixel, value);
|
||||
}
|
||||
|
||||
public bool RotateWithTarget
|
||||
{
|
||||
get => (bool)Node2D.Call(MethodName.GetRotateWithTarget);
|
||||
set => Node2D.Call(MethodName.SetRotateWithTarget, value);
|
||||
}
|
||||
|
||||
public float RotationOffset
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetRotationOffset);
|
||||
set => Node2D.Call(MethodName.SetRotationOffset, value);
|
||||
}
|
||||
|
||||
public bool RotationDamping
|
||||
{
|
||||
get => (bool)Node2D.Call(MethodName.GetRotationDamping);
|
||||
set => Node2D.Call(MethodName.SetRotationDamping, value);
|
||||
}
|
||||
|
||||
public float RotationDampingValue
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetRotationDampingValue);
|
||||
set => Node2D.Call(MethodName.SetRotationDampingValue, value);
|
||||
}
|
||||
|
||||
public int LimitLeft
|
||||
{
|
||||
get => (int)Node2D.Call(MethodName.GetLimitLeft);
|
||||
set => Node2D.Call(MethodName.SetLimitLeft, value);
|
||||
}
|
||||
|
||||
public int LimitTop
|
||||
{
|
||||
get => (int)Node2D.Call(MethodName.GetLimitTop);
|
||||
set => Node2D.Call(MethodName.SetLimitTop, value);
|
||||
}
|
||||
|
||||
public int LimitRight
|
||||
{
|
||||
get => (int)Node2D.Call(MethodName.GetLimitRight);
|
||||
set => Node2D.Call(MethodName.SetLimitRight, value);
|
||||
}
|
||||
|
||||
public int LimitBottom
|
||||
{
|
||||
get => (int)Node2D.Call(MethodName.GetLimitBottom);
|
||||
set => Node2D.Call(MethodName.SetLimitBottom, value);
|
||||
}
|
||||
|
||||
public Vector4I LimitMargin
|
||||
{
|
||||
get => (Vector4I)Node2D.Call(MethodName.GetLimitMargin);
|
||||
set => Node2D.Call(MethodName.SetLimitMargin, value);
|
||||
}
|
||||
|
||||
public bool AutoZoom
|
||||
{
|
||||
get => (bool)Node2D.Call(MethodName.GetAutoZoom);
|
||||
set => Node2D.Call(MethodName.SetAutoZoom, value);
|
||||
}
|
||||
|
||||
public float AutoZoomMin
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetAutoZoomMin);
|
||||
set => Node2D.Call(MethodName.SetAutoZoomMin, value);
|
||||
}
|
||||
|
||||
public float AutoZoomMax
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetAutoZoomMax);
|
||||
set => Node2D.Call(MethodName.SetAutoZoomMax, value);
|
||||
}
|
||||
|
||||
public Vector4 AutoZoomMargin
|
||||
{
|
||||
get => (Vector4)Node2D.Call(MethodName.GetAutoZoomMargin);
|
||||
set => Node2D.Call(MethodName.SetAutoZoomMargin, value);
|
||||
}
|
||||
|
||||
public bool DrawLimits
|
||||
{
|
||||
get => (bool)Node2D.Get(PropertyName.DrawLimits);
|
||||
set => Node2D.Set(PropertyName.DrawLimits, value);
|
||||
}
|
||||
|
||||
public PhantomCameraNoise2D Noise
|
||||
{
|
||||
get => new((Resource)Node2D.Call(MethodName.GetNoise));
|
||||
set => Node2D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
|
||||
}
|
||||
|
||||
public void EmitNoise(Transform2D transform) => Node2D.Call(PhantomCamera.MethodName.EmitNoise, transform);
|
||||
|
||||
public NodePath LimitTarget
|
||||
{
|
||||
get => (NodePath)Node2D.Call(MethodName.GetLimitTarget);
|
||||
set => Node2D.Call(MethodName.SetLimitTarget, value);
|
||||
}
|
||||
|
||||
public static PhantomCamera2D FromScript(string path) => new(GD.Load<GDScript>(path).New().AsGodotObject());
|
||||
public static PhantomCamera2D FromScript(GDScript script) => new(script.New().AsGodotObject());
|
||||
|
||||
public PhantomCamera2D(GodotObject phantomCameraNode) : base(phantomCameraNode)
|
||||
{
|
||||
_callableTweenInterrupted = Callable.From<Node2D>(pCam => TweenInterrupted?.Invoke(pCam));
|
||||
_callableDeadZoneReached = Callable.From((Vector2 side) => DeadZoneReached?.Invoke(side));
|
||||
_callableNoiseEmitted = Callable.From((Transform2D output) => NoiseEmitted?.Invoke(output));
|
||||
|
||||
Node2D.Connect(SignalName.TweenInterrupted, _callableTweenInterrupted);
|
||||
Node2D.Connect(SignalName.DeadZoneReached, _callableDeadZoneReached);
|
||||
Node2D.Connect(SignalName.NoiseEmitted, _callableNoiseEmitted);
|
||||
}
|
||||
|
||||
~PhantomCamera2D()
|
||||
{
|
||||
Node2D.Disconnect(SignalName.TweenInterrupted, _callableTweenInterrupted);
|
||||
Node2D.Disconnect(SignalName.DeadZoneReached, _callableDeadZoneReached);
|
||||
Node2D.Disconnect(SignalName.NoiseEmitted, _callableNoiseEmitted);
|
||||
}
|
||||
|
||||
public void SetLimitTarget(TileMap tileMap)
|
||||
{
|
||||
Node2D.Call(MethodName.SetLimitTarget, tileMap.GetPath());
|
||||
}
|
||||
|
||||
public void SetLimitTarget(TileMapLayer tileMapLayer)
|
||||
{
|
||||
Node2D.Call(MethodName.SetLimitTarget, tileMapLayer.GetPath());
|
||||
}
|
||||
|
||||
public void SetLimitTarget(CollisionShape2D shape2D)
|
||||
{
|
||||
Node2D.Call(MethodName.SetLimitTarget, shape2D.GetPath());
|
||||
}
|
||||
|
||||
public LimitTargetQueryResult? GetLimitTarget()
|
||||
{
|
||||
var result = (NodePath)Node2D.Call(MethodName.GetLimitTarget);
|
||||
return result.IsEmpty ? null : new LimitTargetQueryResult(Node2D.GetNode(result));
|
||||
}
|
||||
|
||||
public void SetLimit(Side side, int value)
|
||||
{
|
||||
Node2D.Call(MethodName.SetLimit, (int)side, value);
|
||||
}
|
||||
|
||||
public int GetLimit(Side side)
|
||||
{
|
||||
return (int)Node2D.Call(MethodName.GetLimit, (int)side);
|
||||
}
|
||||
|
||||
public new static class MethodName
|
||||
{
|
||||
public const string GetZoom = "get_zoom";
|
||||
public const string SetZoom = "set_zoom";
|
||||
|
||||
public const string GetSnapToPixel = "get_snap_to_pixel";
|
||||
public const string SetSnapToPixel = "set_snap_to_pixel";
|
||||
|
||||
public const string GetRotateWithTarget = "get_rotate_with_target";
|
||||
public const string SetRotateWithTarget = "set_rotate_with_target";
|
||||
|
||||
public const string GetRotationOffset = "get_rotation_offset";
|
||||
public const string SetRotationOffset = "set_rotation_offset";
|
||||
|
||||
public const string GetRotationDamping = "get_rotation_damping";
|
||||
public const string SetRotationDamping = "set_rotation_damping";
|
||||
|
||||
public const string GetRotationDampingValue = "get_rotation_damping_value";
|
||||
public const string SetRotationDampingValue = "set_rotation_damping_value";
|
||||
|
||||
public const string GetLimit = "get_limit";
|
||||
public const string SetLimit = "set_limit";
|
||||
|
||||
public const string GetLimitLeft = "get_limit_left";
|
||||
public const string SetLimitLeft = "set_limit_left";
|
||||
|
||||
public const string GetLimitTop = "get_limit_top";
|
||||
public const string SetLimitTop = "set_limit_top";
|
||||
|
||||
public const string GetLimitRight = "get_limit_right";
|
||||
public const string SetLimitRight = "set_limit_right";
|
||||
|
||||
public const string GetLimitBottom = "get_limit_bottom";
|
||||
public const string SetLimitBottom = "set_limit_bottom";
|
||||
|
||||
public const string GetLimitTarget = "get_limit_target";
|
||||
public const string SetLimitTarget = "set_limit_target";
|
||||
|
||||
public const string GetLimitMargin = "get_limit_margin";
|
||||
public const string SetLimitMargin = "set_limit_margin";
|
||||
|
||||
public const string GetAutoZoom = "get_auto_zoom";
|
||||
public const string SetAutoZoom = "set_auto_zoom";
|
||||
|
||||
public const string GetAutoZoomMin = "get_auto_zoom_min";
|
||||
public const string SetAutoZoomMin = "set_auto_zoom_min";
|
||||
|
||||
public const string GetAutoZoomMax = "get_auto_zoom_max";
|
||||
public const string SetAutoZoomMax = "set_auto_zoom_max";
|
||||
|
||||
public const string GetAutoZoomMargin = "get_auto_zoom_margin";
|
||||
public const string SetAutoZoomMargin = "set_auto_zoom_margin";
|
||||
|
||||
public const string GetNoise = "get_noise";
|
||||
public const string SetNoise = "set_noise";
|
||||
}
|
||||
|
||||
public new static class PropertyName
|
||||
{
|
||||
public const string DrawLimits = "draw_limits";
|
||||
}
|
||||
}
|
||||
|
||||
public class LimitTargetQueryResult(GodotObject godotObject)
|
||||
{
|
||||
public bool IsTileMap => godotObject.IsClass("TileMap");
|
||||
|
||||
public bool IsTileMapLayer => godotObject.IsClass("TileMapLayer");
|
||||
|
||||
public bool IsCollisionShape2D => godotObject.IsClass("CollisionShape2D");
|
||||
|
||||
public TileMap? AsTileMap()
|
||||
{
|
||||
return IsTileMap ? (TileMap)godotObject : null;
|
||||
}
|
||||
|
||||
public TileMapLayer? AsTileMapLayer()
|
||||
{
|
||||
return IsTileMapLayer ? (TileMapLayer)godotObject : null;
|
||||
}
|
||||
|
||||
public CollisionShape2D? AsCollisionShape2D()
|
||||
{
|
||||
return IsCollisionShape2D ? (CollisionShape2D)godotObject : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://c38e5qhsf3fk3
|
||||
493
addons/phantom_camera/scripts/phantom_camera/PhantomCamera3D.cs
Normal file
493
addons/phantom_camera/scripts/phantom_camera/PhantomCamera3D.cs
Normal file
@@ -0,0 +1,493 @@
|
||||
using System.Linq;
|
||||
using Godot;
|
||||
using Godot.Collections;
|
||||
using PhantomCamera.Noise;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum LookAtMode
|
||||
{
|
||||
None,
|
||||
Mimic,
|
||||
Simple,
|
||||
Group
|
||||
}
|
||||
|
||||
public enum FollowMode3D
|
||||
{
|
||||
None,
|
||||
Glued,
|
||||
Simple,
|
||||
Group,
|
||||
Path,
|
||||
Framed,
|
||||
ThirdPerson
|
||||
}
|
||||
|
||||
public enum FollowLockAxis3D
|
||||
{
|
||||
None,
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
XY,
|
||||
XZ,
|
||||
YZ,
|
||||
XYZ
|
||||
}
|
||||
|
||||
public static class PhantomCamera3DExtensions
|
||||
{
|
||||
public static PhantomCamera3D AsPhantomCamera3D(this Node3D node3D)
|
||||
{
|
||||
return new PhantomCamera3D(node3D);
|
||||
}
|
||||
|
||||
public static PhantomCameraNoiseEmitter3D AsPhantomCameraNoiseEmitter3D(this Node3D node3D)
|
||||
{
|
||||
return new PhantomCameraNoiseEmitter3D(node3D);
|
||||
}
|
||||
|
||||
public static PhantomCameraNoise3D AsPhantomCameraNoise3D(this Resource resource)
|
||||
{
|
||||
return new PhantomCameraNoise3D(resource);
|
||||
}
|
||||
|
||||
public static Camera3DResource AsCamera3DResource(this Resource resource)
|
||||
{
|
||||
return new Camera3DResource(resource);
|
||||
}
|
||||
|
||||
public static Vector3 GetThirdPersonRotation(this PhantomCamera3D pCam3D) =>
|
||||
(Vector3)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonRotation);
|
||||
|
||||
public static void SetThirdPersonRotation(this PhantomCamera3D pCam3D, Vector3 rotation) =>
|
||||
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonRotation, rotation);
|
||||
|
||||
public static Vector3 GetThirdPersonRotationDegrees(this PhantomCamera3D pCam3D) =>
|
||||
(Vector3)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonRotationDegrees);
|
||||
|
||||
public static void SetThirdPersonDegrees(this PhantomCamera3D pCam3D, Vector3 rotation) =>
|
||||
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonRotationDegrees, rotation);
|
||||
|
||||
public static Quaternion GetThirdPersonQuaternion(this PhantomCamera3D pCam3D) =>
|
||||
(Quaternion)pCam3D.Node3D.Call(PhantomCamera3D.MethodName.GetThirdPersonQuaternion);
|
||||
|
||||
public static void SetThirdPersonQuaternion(this PhantomCamera3D pCam3D, Quaternion quaternion) =>
|
||||
pCam3D.Node3D.Call(PhantomCamera3D.MethodName.SetThirdPersonQuaternion, quaternion);
|
||||
|
||||
}
|
||||
|
||||
public class PhantomCamera3D : PhantomCamera
|
||||
{
|
||||
public Node3D Node3D => (Node3D)Node;
|
||||
|
||||
public delegate void LookAtTargetChangedEventHandler();
|
||||
public delegate void DeadZoneReachedEventHandler();
|
||||
public delegate void Camera3DResourceChangedEventHandler();
|
||||
public delegate void Camera3DResourcePropertyChangedEventHandler(StringName property, Variant value);
|
||||
public delegate void TweenInterruptedEventHandler(Node3D pCam);
|
||||
public delegate void NoiseEmittedEventHandler(Transform3D output);
|
||||
|
||||
public event LookAtTargetChangedEventHandler? LookAtTargetChanged;
|
||||
public event DeadZoneReachedEventHandler? DeadZoneReached;
|
||||
public event Camera3DResourceChangedEventHandler? Camera3DResourceChanged;
|
||||
public event Camera3DResourcePropertyChangedEventHandler? Camera3DResourcePropertyChanged;
|
||||
public event TweenInterruptedEventHandler? TweenInterrupted;
|
||||
public event NoiseEmittedEventHandler? NoiseEmitted;
|
||||
|
||||
private readonly Callable _callableLookAtTargetChanged;
|
||||
private readonly Callable _callableDeadZoneReached;
|
||||
private readonly Callable _callableCamera3DResourceChanged;
|
||||
private readonly Callable _callableCamera3DResourcePropertyChanged;
|
||||
private readonly Callable _callableTweenInterrupted;
|
||||
private readonly Callable _callableNoiseEmitted;
|
||||
|
||||
public Node3D FollowTarget
|
||||
{
|
||||
get => (Node3D)Node3D.Call(PhantomCamera.MethodName.GetFollowTarget);
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowTarget, value);
|
||||
}
|
||||
|
||||
public Node3D[] FollowTargets
|
||||
{
|
||||
get => Node3D.Call(PhantomCamera.MethodName.GetFollowTargets).AsGodotArray<Node3D>().ToArray();
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowTargets, new Array<Node3D>(value));
|
||||
}
|
||||
|
||||
public void AppendFollowTarget(Node3D target) => Node3D.Call(PhantomCamera.MethodName.AppendFollowTargets, target);
|
||||
public void AppendFollowTargetArray(Node3D[] targets) => Node3D.Call(PhantomCamera.MethodName.AppendFollowTargetsArray, targets);
|
||||
public void EraseFollowTarget(Node3D target) => Node3D.Call(PhantomCamera.MethodName.EraseFollowTargets, target);
|
||||
|
||||
public FollowMode3D FollowMode => (FollowMode3D)(int)Node.Call(PhantomCamera.MethodName.GetFollowMode);
|
||||
|
||||
public Path3D FollowPath
|
||||
{
|
||||
get => (Path3D)Node3D.Call(PhantomCamera.MethodName.GetFollowPath);
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowPath, value);
|
||||
}
|
||||
|
||||
public Vector3 FollowOffset
|
||||
{
|
||||
get => (Vector3)Node3D.Call(PhantomCamera.MethodName.GetFollowOffset);
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowOffset, value);
|
||||
}
|
||||
|
||||
public Vector3 FollowDampingValue
|
||||
{
|
||||
get => (Vector3)Node3D.Call(PhantomCamera.MethodName.GetFollowDampingValue);
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowDampingValue, value);
|
||||
}
|
||||
|
||||
public FollowLockAxis3D FollowAxisLock
|
||||
{
|
||||
get => (FollowLockAxis3D)(int)Node3D.Call(PhantomCamera.MethodName.GetFollowAxisLock);
|
||||
set => Node3D.Call(PhantomCamera.MethodName.SetFollowAxisLock, (int)value);
|
||||
}
|
||||
|
||||
public LookAtMode LookAtMode => (LookAtMode)(int)Node3D.Call(MethodName.GetLookAtMode);
|
||||
|
||||
public Camera3DResource Camera3DResource
|
||||
{
|
||||
get => new((Resource)Node3D.Call(MethodName.GetCamera3DResource));
|
||||
set => Node3D.Call(MethodName.SetCamera3DResource, value.Resource);
|
||||
}
|
||||
|
||||
public float SpringLength
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetSpringLength);
|
||||
set => Node3D.Call(MethodName.SetSpringLength, value);
|
||||
}
|
||||
|
||||
public float VerticalRotationOffset
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetVerticalRotationOffset);
|
||||
set => Node3D.Call(MethodName.SetVerticalRotationOffset, value);
|
||||
}
|
||||
|
||||
public float HorizontalRotationOffset
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetHorizontalRotationOffset);
|
||||
set => Node3D.Call(MethodName.SetHorizontalRotationOffset, value);
|
||||
}
|
||||
|
||||
public float FollowDistance
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetFollowDistance);
|
||||
set => Node3D.Call(MethodName.SetFollowDistance, value);
|
||||
}
|
||||
|
||||
public bool AutoFollowDistance
|
||||
{
|
||||
get => (bool)Node3D.Call(MethodName.GetAutoFollowDistance);
|
||||
set => Node3D.Call(MethodName.SetAutoFollowDistance, value);
|
||||
}
|
||||
|
||||
public float AutoFollowDistanceMin
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceMin);
|
||||
set => Node3D.Call(MethodName.SetAutoFollowDistanceMin, value);
|
||||
}
|
||||
|
||||
public float AutoFollowDistanceMax
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceMax);
|
||||
set => Node3D.Call(MethodName.SetAutoFollowDistanceMax, value);
|
||||
}
|
||||
|
||||
public float AutoFollowDistanceDivisor
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetAutoFollowDistanceDivisor);
|
||||
set => Node3D.Call(MethodName.SetAutoFollowDistanceDivisor, value);
|
||||
}
|
||||
|
||||
public Node3D LookAtTarget
|
||||
{
|
||||
get => (Node3D)Node3D.Call(MethodName.GetLookAtTarget);
|
||||
set => Node3D.Call(MethodName.SetLookAtTarget, value);
|
||||
}
|
||||
|
||||
public Node3D[] LookAtTargets
|
||||
{
|
||||
get => Node3D.Call(MethodName.GetLookAtTargets).AsGodotArray<Node3D>().ToArray();
|
||||
set => Node3D.Call(MethodName.SetLookAtTargets, new Array<Node3D>(value));
|
||||
}
|
||||
|
||||
public bool IsLooking => (bool)Node3D.Call(MethodName.IsLooking);
|
||||
|
||||
public int CollisionMask
|
||||
{
|
||||
get => (int)Node3D.Call(MethodName.GetCollisionMask);
|
||||
set => Node3D.Call(MethodName.SetCollisionMask, value);
|
||||
}
|
||||
|
||||
public void SetCollisionMaskValue(int maskLayer, bool enable) =>
|
||||
Node3D.Call(MethodName.SetCollisionMaskValue, maskLayer, enable);
|
||||
|
||||
public Shape3D Shape
|
||||
{
|
||||
get => (Shape3D)Node3D.Call(MethodName.GetShape);
|
||||
set => Node3D.Call(MethodName.SetShape, value);
|
||||
}
|
||||
|
||||
public float Margin
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetMargin);
|
||||
set => Node3D.Call(MethodName.SetMargin, value);
|
||||
}
|
||||
|
||||
public Vector3 LookAtOffset
|
||||
{
|
||||
get => (Vector3)Node3D.Call(MethodName.GetLookAtOffset);
|
||||
set => Node3D.Call(MethodName.SetLookAtOffset, value);
|
||||
}
|
||||
|
||||
public bool LookAtDamping
|
||||
{
|
||||
get => (bool)Node3D.Call(MethodName.GetLookAtDamping);
|
||||
set => Node3D.Call(MethodName.SetLookAtDamping, value);
|
||||
}
|
||||
|
||||
public float LookAtDampingValue
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetLookAtDampingValue);
|
||||
set => Node3D.Call(MethodName.SetLookAtDampingValue, value);
|
||||
}
|
||||
|
||||
public Node3D Up
|
||||
{
|
||||
get => (Node3D)Node3D.Call(MethodName.GetUp);
|
||||
set => Node3D.Call(MethodName.SetUp, value);
|
||||
}
|
||||
|
||||
public Vector3 UpTarget
|
||||
{
|
||||
get => (Vector3)Node3D.Call(MethodName.GetUpTarget);
|
||||
set => Node3D.Call(MethodName.SetUpTarget, value);
|
||||
}
|
||||
|
||||
public int CullMask
|
||||
{
|
||||
get => (int)Node3D.Call(MethodName.GetCullMask);
|
||||
set => Node3D.Call(MethodName.SetCullMask, value);
|
||||
}
|
||||
|
||||
public float HOffset
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetHOffset);
|
||||
set => Node3D.Call(MethodName.SetHOffset, value);
|
||||
}
|
||||
|
||||
public float VOffset
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetVOffset);
|
||||
set => Node3D.Call(MethodName.SetVOffset, value);
|
||||
}
|
||||
|
||||
public ProjectionType Projection
|
||||
{
|
||||
get => (ProjectionType)(int)Node3D.Call(MethodName.GetProjection);
|
||||
set => Node3D.Call(MethodName.SetProjection, (int)value);
|
||||
}
|
||||
|
||||
public float Fov
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetFov);
|
||||
set => Node3D.Call(MethodName.SetFov, value);
|
||||
}
|
||||
|
||||
public float Size
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetSize);
|
||||
set => Node3D.Call(MethodName.SetSize, value);
|
||||
}
|
||||
|
||||
public Vector2 FrustumOffset
|
||||
{
|
||||
get => (Vector2)Node3D.Call(MethodName.GetFrustumOffset);
|
||||
set => Node3D.Call(MethodName.SetFrustumOffset, value);
|
||||
}
|
||||
|
||||
public float Far
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetFar);
|
||||
set => Node3D.Call(MethodName.SetFar, value);
|
||||
}
|
||||
|
||||
public float Near
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetNear);
|
||||
set => Node3D.Call(MethodName.SetNear, value);
|
||||
}
|
||||
|
||||
public Environment Environment
|
||||
{
|
||||
get => (Environment)Node3D.Call(MethodName.GetEnvironment);
|
||||
set => Node3D.Call(MethodName.SetEnvironment, value);
|
||||
}
|
||||
|
||||
public CameraAttributes Attributes
|
||||
{
|
||||
get => (CameraAttributes)Node3D.Call(MethodName.GetAttributes);
|
||||
set => Node3D.Call(MethodName.SetAttributes, value);
|
||||
}
|
||||
|
||||
public PhantomCameraNoise3D Noise
|
||||
{
|
||||
get => new((Resource)Node3D.Call(MethodName.GetNoise));
|
||||
set => Node3D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
|
||||
}
|
||||
|
||||
public void EmitNoise(Transform3D transform) => Node3D.Call(PhantomCamera.MethodName.EmitNoise, transform);
|
||||
|
||||
public static PhantomCamera3D FromScript(string path) => new(GD.Load<GDScript>(path).New().AsGodotObject());
|
||||
public static PhantomCamera3D FromScript(GDScript script) => new(script.New().AsGodotObject());
|
||||
|
||||
public PhantomCamera3D(GodotObject phantomCamera3DNode) : base(phantomCamera3DNode)
|
||||
{
|
||||
_callableLookAtTargetChanged = Callable.From(() => LookAtTargetChanged?.Invoke());
|
||||
_callableDeadZoneReached = Callable.From(() => DeadZoneReached?.Invoke());
|
||||
_callableCamera3DResourceChanged = Callable.From(() => Camera3DResourceChanged?.Invoke());
|
||||
_callableCamera3DResourcePropertyChanged = Callable.From((StringName property, Variant value) =>
|
||||
Camera3DResourcePropertyChanged?.Invoke(property, value));
|
||||
_callableTweenInterrupted = Callable.From<Node3D>(pCam => TweenInterrupted?.Invoke(pCam));
|
||||
_callableNoiseEmitted = Callable.From((Transform3D output) => NoiseEmitted?.Invoke(output));
|
||||
|
||||
Node3D.Connect(SignalName.LookAtTargetChanged, _callableLookAtTargetChanged);
|
||||
Node3D.Connect(PhantomCamera.SignalName.DeadZoneReached, _callableDeadZoneReached);
|
||||
Node3D.Connect(SignalName.Camera3DResourceChanged, _callableCamera3DResourceChanged);
|
||||
Node3D.Connect(SignalName.Camera3DResourcePropertyChanged, _callableCamera3DResourcePropertyChanged);
|
||||
Node3D.Connect(PhantomCamera.SignalName.TweenInterrupted, _callableTweenInterrupted);
|
||||
Node3D.Connect(PhantomCamera.SignalName.NoiseEmitted, _callableNoiseEmitted);
|
||||
}
|
||||
|
||||
~PhantomCamera3D()
|
||||
{
|
||||
Node3D.Disconnect(SignalName.LookAtTargetChanged, _callableLookAtTargetChanged);
|
||||
Node3D.Disconnect(PhantomCamera.SignalName.DeadZoneReached, _callableDeadZoneReached);
|
||||
Node3D.Disconnect(SignalName.Camera3DResourceChanged, _callableCamera3DResourceChanged);
|
||||
Node3D.Disconnect(SignalName.Camera3DResourcePropertyChanged, _callableCamera3DResourcePropertyChanged);
|
||||
Node3D.Disconnect(PhantomCamera.SignalName.TweenInterrupted, _callableTweenInterrupted);
|
||||
Node3D.Disconnect(PhantomCamera.SignalName.NoiseEmitted, _callableNoiseEmitted);
|
||||
}
|
||||
|
||||
public new static class MethodName
|
||||
{
|
||||
public const string GetLookAtMode = "get_look_at_mode";
|
||||
|
||||
public const string GetCamera3DResource = "get_camera_3d_resource";
|
||||
public const string SetCamera3DResource = "set_camera_3d_resource";
|
||||
|
||||
public const string GetThirdPersonRotation = "get_third_person_rotation";
|
||||
public const string SetThirdPersonRotation = "set_third_person_rotation";
|
||||
|
||||
public const string GetThirdPersonRotationDegrees = "get_third_person_rotation_degrees";
|
||||
public const string SetThirdPersonRotationDegrees = "set_third_person_rotation_degrees";
|
||||
|
||||
public const string GetThirdPersonQuaternion = "get_third_person_quaternion";
|
||||
public const string SetThirdPersonQuaternion = "set_third_person_quaternion";
|
||||
|
||||
public const string GetVerticalRotationOffset = "get_vertical_rotation_offset";
|
||||
public const string SetVerticalRotationOffset = "set_vertical_rotation_offset";
|
||||
|
||||
public const string GetHorizontalRotationOffset = "get_horizontal_rotation_offset";
|
||||
public const string SetHorizontalRotationOffset = "set_horizontal_rotation_offset";
|
||||
|
||||
public const string GetSpringLength = "get_spring_length";
|
||||
public const string SetSpringLength = "set_spring_length";
|
||||
|
||||
public const string GetFollowDistance = "get_follow_distance";
|
||||
public const string SetFollowDistance = "set_follow_distance";
|
||||
|
||||
public const string GetAutoFollowDistance = "get_auto_follow_distance";
|
||||
public const string SetAutoFollowDistance = "set_auto_follow_distance";
|
||||
|
||||
public const string GetAutoFollowDistanceMin = "get_auto_follow_distance_min";
|
||||
public const string SetAutoFollowDistanceMin = "set_auto_follow_distance_min";
|
||||
|
||||
public const string GetAutoFollowDistanceMax = "get_auto_follow_distance_max";
|
||||
public const string SetAutoFollowDistanceMax = "set_auto_follow_distance_max";
|
||||
|
||||
public const string GetAutoFollowDistanceDivisor = "get_auto_follow_distance_divisor";
|
||||
public const string SetAutoFollowDistanceDivisor = "set_auto_follow_distance_divisor";
|
||||
|
||||
public const string GetLookAtTarget = "get_look_at_target";
|
||||
public const string SetLookAtTarget = "set_look_at_target";
|
||||
|
||||
public const string GetLookAtTargets = "get_look_at_targets";
|
||||
public const string SetLookAtTargets = "set_look_at_targets";
|
||||
|
||||
public const string IsLooking = "is_looking";
|
||||
|
||||
public const string GetUp = "get_up";
|
||||
public const string SetUp = "set_up";
|
||||
|
||||
public const string GetUpTarget = "get_up_target";
|
||||
public const string SetUpTarget = "set_up_target";
|
||||
|
||||
public const string GetCollisionMask = "get_collision_mask";
|
||||
public const string SetCollisionMask = "set_collision_mask";
|
||||
|
||||
public const string SetCollisionMaskValue = "set_collision_mask_value";
|
||||
|
||||
public const string GetShape = "get_shape";
|
||||
public const string SetShape = "set_shape";
|
||||
|
||||
public const string GetMargin = "get_margin";
|
||||
public const string SetMargin = "set_margin";
|
||||
|
||||
public const string GetLookAtOffset = "get_look_at_offset";
|
||||
public const string SetLookAtOffset = "set_look_at_offset";
|
||||
|
||||
public const string GetLookAtDamping = "get_look_at_damping";
|
||||
public const string SetLookAtDamping = "set_look_at_damping";
|
||||
|
||||
public const string GetLookAtDampingValue = "get_look_at_damping_value";
|
||||
public const string SetLookAtDampingValue = "set_look_at_damping_value";
|
||||
|
||||
public const string GetCullMask = "get_cull_mask";
|
||||
public const string SetCullMask = "set_cull_mask";
|
||||
|
||||
public const string GetHOffset = "get_h_offset";
|
||||
public const string SetHOffset = "set_h_offset";
|
||||
|
||||
public const string GetVOffset = "get_v_offset";
|
||||
public const string SetVOffset = "set_v_offset";
|
||||
|
||||
public const string GetProjection = "get_projection";
|
||||
public const string SetProjection = "set_projection";
|
||||
|
||||
public const string GetFov = "get_fov";
|
||||
public const string SetFov = "set_fov";
|
||||
|
||||
public const string GetSize = "get_size";
|
||||
public const string SetSize = "set_size";
|
||||
|
||||
public const string GetFrustumOffset = "get_frustum_offset";
|
||||
public const string SetFrustumOffset = "set_frustum_offset";
|
||||
|
||||
public const string GetFar = "get_far";
|
||||
public const string SetFar = "set_far";
|
||||
|
||||
public const string GetNear = "get_near";
|
||||
public const string SetNear = "set_near";
|
||||
|
||||
public const string GetEnvironment = "get_environment";
|
||||
public const string SetEnvironment = "set_environment";
|
||||
|
||||
public const string GetAttributes = "get_attributes";
|
||||
public const string SetAttributes = "set_attributes";
|
||||
|
||||
public const string GetNoise = "get_noise";
|
||||
public const string SetNoise = "set_noise";
|
||||
}
|
||||
|
||||
public new static class SignalName
|
||||
{
|
||||
public const string LookAtTargetChanged = "look_at_target_changed";
|
||||
public const string Camera3DResourceChanged = "camera_3d_resource_changed";
|
||||
public const string Camera3DResourcePropertyChanged = "camera_3d_resource_property_changed";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bx3g7jxtwhi04
|
||||
@@ -0,0 +1,83 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera.Noise;
|
||||
|
||||
public class PhantomCameraNoiseEmitter2D(GodotObject node)
|
||||
{
|
||||
public Node2D Node2D = (Node2D)node;
|
||||
|
||||
public PhantomCameraNoise2D Noise
|
||||
{
|
||||
get => new((Resource)Node2D.Call(MethodName.GetNoise));
|
||||
set => Node2D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
|
||||
}
|
||||
|
||||
public bool Continuous
|
||||
{
|
||||
get => (bool)Node2D.Call(MethodName.GetContinuous);
|
||||
set => Node2D.Call(MethodName.SetContinuous, value);
|
||||
}
|
||||
|
||||
public float GrowthTime
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetGrowthTime);
|
||||
set => Node2D.Call(MethodName.SetGrowthTime, value);
|
||||
}
|
||||
|
||||
public float Duration
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetDuration);
|
||||
set => Node2D.Call(MethodName.SetDuration, value);
|
||||
}
|
||||
|
||||
public float DecayTime
|
||||
{
|
||||
get => (float)Node2D.Call(MethodName.GetDecayTime);
|
||||
set => Node2D.Call(MethodName.SetDecayTime, value);
|
||||
}
|
||||
|
||||
public int NoiseEmitterLayer
|
||||
{
|
||||
get => (int)Node2D.Call(MethodName.GetNoiseEmitterLayer);
|
||||
set => Node2D.Call(MethodName.SetNoiseEmitterLayer, value);
|
||||
}
|
||||
|
||||
public void SetNoiseEmitterLayerValue(int layer, bool value) =>
|
||||
Node2D.Call(MethodName.SetNoiseEmitterLayerValue, layer, value);
|
||||
|
||||
public void Emit() => Node2D.Call(MethodName.Emit);
|
||||
|
||||
public bool IsEmitting() => (bool)Node2D.Call(MethodName.IsEmitting);
|
||||
|
||||
public void Stop() => Node2D.Call(MethodName.Stop);
|
||||
|
||||
public void Toggle() => Node2D.Call(MethodName.Toggle);
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetNoise = "get_noise";
|
||||
public const string SetNoise = "set_noise";
|
||||
|
||||
public const string GetContinuous = "get_continuous";
|
||||
public const string SetContinuous = "set_continuous";
|
||||
|
||||
public const string GetGrowthTime = "get_growth_time";
|
||||
public const string SetGrowthTime = "set_growth_time";
|
||||
|
||||
public const string GetDuration = "get_duration";
|
||||
public const string SetDuration = "set_duration";
|
||||
|
||||
public const string GetDecayTime = "get_decay_time";
|
||||
public const string SetDecayTime = "set_decay_time";
|
||||
|
||||
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
|
||||
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
|
||||
|
||||
public const string SetNoiseEmitterLayerValue = "set_noise_emitter_layer_value";
|
||||
|
||||
public const string Emit = "emit";
|
||||
public const string IsEmitting = "is_emitting";
|
||||
public const string Stop = "stop";
|
||||
public const string Toggle = "toggle";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://btom8l3wlkn2j
|
||||
@@ -0,0 +1,83 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera.Noise;
|
||||
|
||||
public class PhantomCameraNoiseEmitter3D(GodotObject node)
|
||||
{
|
||||
public Node3D Node3D = (Node3D)node;
|
||||
|
||||
public PhantomCameraNoise3D Noise
|
||||
{
|
||||
get => new((Resource)Node3D.Call(MethodName.GetNoise));
|
||||
set => Node3D.Call(MethodName.SetNoise, (GodotObject)value.Resource);
|
||||
}
|
||||
|
||||
public bool Continuous
|
||||
{
|
||||
get => (bool)Node3D.Call(MethodName.GetContinuous);
|
||||
set => Node3D.Call(MethodName.SetContinuous, value);
|
||||
}
|
||||
|
||||
public float GrowthTime
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetGrowthTime);
|
||||
set => Node3D.Call(MethodName.SetGrowthTime, value);
|
||||
}
|
||||
|
||||
public float Duration
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetDuration);
|
||||
set => Node3D.Call(MethodName.SetDuration, value);
|
||||
}
|
||||
|
||||
public float DecayTime
|
||||
{
|
||||
get => (float)Node3D.Call(MethodName.GetDecayTime);
|
||||
set => Node3D.Call(MethodName.SetDecayTime, value);
|
||||
}
|
||||
|
||||
public int NoiseEmitterLayer
|
||||
{
|
||||
get => (int)Node3D.Call(MethodName.GetNoiseEmitterLayer);
|
||||
set => Node3D.Call(MethodName.SetNoiseEmitterLayer, value);
|
||||
}
|
||||
|
||||
public void SetNoiseEmitterLayerValue(int layer, bool value) =>
|
||||
Node3D.Call(MethodName.SetNoiseEmitterLayerValue, layer, value);
|
||||
|
||||
public void Emit() => Node3D.Call(MethodName.Emit);
|
||||
|
||||
public bool IsEmitting() => (bool)Node3D.Call(MethodName.IsEmitting);
|
||||
|
||||
public void Stop() => Node3D.Call(MethodName.Stop);
|
||||
|
||||
public void Toggle() => Node3D.Call(MethodName.Toggle);
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetNoise = "get_noise";
|
||||
public const string SetNoise = "set_noise";
|
||||
|
||||
public const string GetContinuous = "get_continuous";
|
||||
public const string SetContinuous = "set_continuous";
|
||||
|
||||
public const string GetGrowthTime = "get_growth_time";
|
||||
public const string SetGrowthTime = "set_growth_time";
|
||||
|
||||
public const string GetDuration = "get_duration";
|
||||
public const string SetDuration = "set_duration";
|
||||
|
||||
public const string GetDecayTime = "get_decay_time";
|
||||
public const string SetDecayTime = "set_decay_time";
|
||||
|
||||
public const string GetNoiseEmitterLayer = "get_noise_emitter_layer";
|
||||
public const string SetNoiseEmitterLayer = "set_noise_emitter_layer";
|
||||
|
||||
public const string SetNoiseEmitterLayerValue = "set_noise_emitter_layer_value";
|
||||
|
||||
public const string Emit = "emit";
|
||||
public const string IsEmitting = "is_emitting";
|
||||
public const string Stop = "stop";
|
||||
public const string Toggle = "toggle";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://buvda14filkjx
|
||||
1726
addons/phantom_camera/scripts/phantom_camera/phantom_camera_2d.gd
Normal file
1726
addons/phantom_camera/scripts/phantom_camera/phantom_camera_2d.gd
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
uid://bhexx6mj1xv3q
|
||||
2279
addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd
Normal file
2279
addons/phantom_camera/scripts/phantom_camera/phantom_camera_3d.gd
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
uid://csjccrhj5wnx7
|
||||
@@ -0,0 +1,29 @@
|
||||
@tool
|
||||
extends RefCounted
|
||||
|
||||
#region Constants
|
||||
|
||||
#const PhantomCameraHost: Script = preload("res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd")
|
||||
|
||||
const CAMERA_2D_NODE_NAME: StringName = "Camera2D"
|
||||
const CAMERA_3D_NODE_NAME: StringName = "Camera3D"
|
||||
const PCAM_HOST_NODE_NAME: StringName = "PhantomCameraHost"
|
||||
const PCAM_MANAGER_NODE_NAME: String = "PhantomCameraManager" # TODO - Convert to StringName once https://github.com/godotengine/godot/pull/72702 is merged
|
||||
const PCAM_2D_NODE_NAME: StringName = "PhantomCamera2D"
|
||||
const PCAM_3D_NODE_NAME: StringName = "PhantomCamera3D"
|
||||
const PCAM_HOST: StringName = "phantom_camera_host"
|
||||
|
||||
const COLOR_2D: Color = Color("8DA5F3")
|
||||
const COLOR_3D: Color = Color("FC7F7F")
|
||||
const COLOR_PCAM: Color = Color("3AB99A")
|
||||
const COLOR_PCAM_33: Color = Color("3ab99a33")
|
||||
const PCAM_HOST_COLOR: Color = Color("E0E0E0")
|
||||
|
||||
#endregion
|
||||
|
||||
#region Group Names
|
||||
|
||||
const PCAM_GROUP_NAME: StringName = "phantom_camera_group"
|
||||
const PCAM_HOST_GROUP_NAME: StringName = "phantom_camera_host_group"
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://dn74j5b5hdxu
|
||||
@@ -0,0 +1,264 @@
|
||||
@tool
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_2d.svg")
|
||||
class_name PhantomCameraNoiseEmitter2D
|
||||
extends Node2D
|
||||
|
||||
## Emits positional and rotational noise to active [PhantomCamera2D]s and its corresponding [Camera2D].
|
||||
##
|
||||
## Is a node meant to apply positional and rotational noise, also referred to as shake, to the [Camera2D].
|
||||
## It is designed for use cases such as when hitting or when being hit, earthquakes or to add a
|
||||
## bit of slight movement to the camera to make it feel less static.
|
||||
## The emitter can affect multiple [PhantomCamera2D] in a given scene based on which [member noise_emitter_layer]
|
||||
## are enabled by calling its [method emit] function. At least one corresponding layer has to be
|
||||
## set on the [PhantomCamera2D] and the emitter node.
|
||||
|
||||
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
|
||||
#region Exported Proerpties
|
||||
|
||||
## The [PhantomCameraNoise2D] resource that defines the noise pattern.
|
||||
@export var noise: PhantomCameraNoise2D = null:
|
||||
set = set_noise,
|
||||
get = get_noise
|
||||
|
||||
## If true, previews the noise in the editor - can be seen in the viewfinder.
|
||||
@export var preview: bool = false:
|
||||
set(value):
|
||||
preview = value
|
||||
_play = value
|
||||
get:
|
||||
return preview
|
||||
|
||||
## If true, repeats the noise indefinitely once started. Otherwise, it will only be triggered once. [br]
|
||||
@export var continuous: bool = false:
|
||||
set = set_continuous,
|
||||
get = get_continuous
|
||||
|
||||
## Determines how long the noise should take to reach full [member intensity] once started.[br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_exp_easing("positive_only", "suffix: s") var growth_time: float = 0:
|
||||
set = set_growth_time,
|
||||
get = get_growth_time
|
||||
|
||||
## Sets the duration for the camera noise if [member continuous] is set to [b]false[/b].[br][br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_range(0, 10, 0.001, "or_greater", "suffix: s") var duration: float = 1.0:
|
||||
set = set_duration,
|
||||
get = get_duration
|
||||
|
||||
## Determines how long the noise should take to come to a full stop.[br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_exp_easing("attenuation", "positive_only", "suffix: s") var decay_time: float = 0:
|
||||
set = set_decay_time,
|
||||
get = get_decay_time
|
||||
|
||||
## Enabled layers will affect [PhantomCamera2D] nodes with at least one corresponding layer enabled.[br]
|
||||
## Enabling multiple corresponding layers on the same [PhantomCamera2D] causes no additional effect.
|
||||
@export_flags_2d_render var noise_emitter_layer: int = 1:
|
||||
set = set_noise_emitter_layer,
|
||||
get = get_noise_emitter_layer
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _play: bool = false:
|
||||
set(value):
|
||||
_play = value
|
||||
if value:
|
||||
_elasped_play_time = 0
|
||||
_decay_countdown = 0
|
||||
_play = true
|
||||
_should_grow = true
|
||||
_start_duration_countdown = false
|
||||
_should_decay = false
|
||||
else:
|
||||
_should_decay = true
|
||||
if noise.randomize_noise_seed:
|
||||
noise.noise_seed = randi() & 1000
|
||||
else:
|
||||
noise.reset_noise_time()
|
||||
get:
|
||||
return _play
|
||||
|
||||
var _start_duration_countdown: bool = false
|
||||
|
||||
var _decay_countdown: float = 0
|
||||
|
||||
var _should_grow: bool = false
|
||||
|
||||
var _should_decay: bool = false
|
||||
|
||||
var _elasped_play_time: float = 0
|
||||
|
||||
var _noise_output: Transform2D = Transform2D()
|
||||
|
||||
# NOTE - Temp solution until Godot has better plugin autoload recognition out-of-the-box.
|
||||
var _phantom_camera_manager: Node
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
if noise == null:
|
||||
return ["Noise resource is required in order to trigger emitter."]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
func _validate_property(property) -> void:
|
||||
if property.name == "duration" and continuous:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
_phantom_camera_manager = get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not _play and not _should_decay: return
|
||||
if noise == null:
|
||||
printerr("Noise resource missing in ", name)
|
||||
_play = false
|
||||
return
|
||||
|
||||
_elasped_play_time += delta
|
||||
|
||||
if _should_grow:
|
||||
noise.set_trauma(minf(_elasped_play_time / growth_time, 1))
|
||||
if _elasped_play_time >= growth_time:
|
||||
_should_grow = false
|
||||
_start_duration_countdown = true
|
||||
noise.set_trauma(1)
|
||||
else:
|
||||
noise.set_trauma(1)
|
||||
|
||||
if not continuous:
|
||||
if _start_duration_countdown:
|
||||
if _elasped_play_time >= duration + growth_time:
|
||||
_should_decay = true
|
||||
_start_duration_countdown = false
|
||||
|
||||
if _should_decay:
|
||||
_decay_countdown += delta
|
||||
noise.set_trauma(maxf(1 - (_decay_countdown / decay_time), 0))
|
||||
if _decay_countdown >= decay_time:
|
||||
noise.set_trauma(0)
|
||||
_play = false
|
||||
preview = false
|
||||
_should_decay = false
|
||||
_elasped_play_time = 0
|
||||
_decay_countdown = 0
|
||||
|
||||
_noise_output = noise.get_noise_transform(delta)
|
||||
_phantom_camera_manager.noise_2d_emitted.emit(_noise_output, noise_emitter_layer)
|
||||
|
||||
|
||||
func _set_layer(current_layers: int, layer_number: int, value: bool) -> int:
|
||||
var mask: int = current_layers
|
||||
|
||||
# From https://github.com/godotengine/godot/blob/51991e20143a39e9ef0107163eaf283ca0a761ea/scene/3d/camera_3d.cpp#L638
|
||||
if layer_number < 1 or layer_number > 20:
|
||||
printerr("Layer must be between 1 and 20.")
|
||||
else:
|
||||
if value:
|
||||
mask |= 1 << (layer_number - 1)
|
||||
else:
|
||||
mask &= ~(1 << (layer_number - 1))
|
||||
|
||||
return mask
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Public Functions
|
||||
|
||||
## Emits noise to the [PhantomCamera2D]s that has at least one matching layers.
|
||||
func emit() -> void:
|
||||
if _play: _play = false
|
||||
_play = true
|
||||
|
||||
## Returns the state for the emitter. If true, the emitter is currently emitting.
|
||||
func is_emitting() -> bool:
|
||||
return _play
|
||||
|
||||
## Stops the emitter from emitting noise.
|
||||
func stop(should_decay: bool = true) -> void:
|
||||
if should_decay:
|
||||
_should_decay = true
|
||||
else:
|
||||
_play = false
|
||||
|
||||
## Toggles the emitter on and off.
|
||||
func toggle() -> void:
|
||||
_play = !_play
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Setter & Getter Functions
|
||||
|
||||
## Sets the [member noise] resource.
|
||||
func set_noise(value: PhantomCameraNoise2D) -> void:
|
||||
noise = value
|
||||
update_configuration_warnings()
|
||||
|
||||
## Returns the [member noise] resource.
|
||||
func get_noise() -> PhantomCameraNoise2D:
|
||||
return noise
|
||||
|
||||
|
||||
## Sets the [member continous] value.
|
||||
func set_continuous(value: bool) -> void:
|
||||
continuous = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Gets the [member continous] value.
|
||||
func get_continuous() -> bool:
|
||||
return continuous
|
||||
|
||||
|
||||
## Sets the [member growth_time] value.
|
||||
func set_growth_time(value: float) -> void:
|
||||
growth_time = value
|
||||
|
||||
## Returns the [member growth_time] value.
|
||||
func get_growth_time() -> float:
|
||||
return growth_time
|
||||
|
||||
|
||||
## Sets the [member duration] value.
|
||||
func set_duration(value: float) -> void:
|
||||
duration = value
|
||||
if duration == 0:
|
||||
duration = 0.001
|
||||
|
||||
## Returns the [member duration] value.
|
||||
func get_duration() -> float:
|
||||
return duration
|
||||
|
||||
|
||||
## Sets the [member decay_time] value.
|
||||
func set_decay_time(value: float) -> void:
|
||||
decay_time = value
|
||||
|
||||
## Returns the [member decay_time] value.
|
||||
func get_decay_time() -> float:
|
||||
return decay_time
|
||||
|
||||
|
||||
## Sets the [member noise_emitter_layer] value.
|
||||
func set_noise_emitter_layer(value: int) -> void:
|
||||
noise_emitter_layer = value
|
||||
|
||||
## Enables or disables a given layer of [member noise_emitter_layer].
|
||||
func set_noise_emitter_value(value: int, enabled: bool) -> void:
|
||||
noise_emitter_layer = _set_layer(noise_emitter_layer, value, enabled)
|
||||
|
||||
## Returns the [member noise_emitter_layer] value.
|
||||
func get_noise_emitter_layer() -> int:
|
||||
return noise_emitter_layer
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://bhd4nuiu23e7l
|
||||
@@ -0,0 +1,265 @@
|
||||
@tool
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_noise_emitter_3d.svg")
|
||||
class_name PhantomCameraNoiseEmitter3D
|
||||
extends Node3D
|
||||
|
||||
## Emits positional and rotational noise to active [PhantomCamera3D]s and its corresponding [Camera3D].
|
||||
##
|
||||
## Is a node meant to apply positional and rotational noise, also referred to as shake, to the [Camera3D].
|
||||
## It is designed for use cases such as when hitting or when being hit, earthquakes or to add a
|
||||
## bit of slight movement to the camera to make it feel less static.
|
||||
## The emitter can affect multiple [PhantomCamera3D] in a given scene based on which [member noise_emitter_layer]
|
||||
## are enabled by calling its [method emit] function. At least one corresponding layer has to be
|
||||
## set on the [PhantomCamera3D] and the emitter node.
|
||||
|
||||
const _constants = preload("res://addons/phantom_camera/scripts/phantom_camera/phantom_camera_constants.gd")
|
||||
|
||||
#region Exported Properties
|
||||
|
||||
## The [PhantomCameraNoise3D] resource that defines the noise pattern.
|
||||
@export var noise: PhantomCameraNoise3D = null:
|
||||
set = set_noise,
|
||||
get = get_noise
|
||||
|
||||
## If true, previews the noise in the Viewfinder.
|
||||
@export var preview: bool = false:
|
||||
set(value):
|
||||
preview = value
|
||||
_play = value
|
||||
get:
|
||||
return preview
|
||||
|
||||
## If true, repeats the noise indefinitely once started.Otherwise, it will only be triggered once. [br]
|
||||
## [b]Note:[/b] This will always be enabled if the resource is assigned the the [PhantomCamera3D]'s
|
||||
## [member PhantomCamera3D.noise] property.
|
||||
@export var continuous: bool = false:
|
||||
set = set_continuous,
|
||||
get = get_continuous
|
||||
|
||||
## Determines how long the noise should take to reach full [member intensity] once started.[br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_exp_easing("positive_only", "suffix: s") var growth_time: float = 0:
|
||||
set = set_growth_time,
|
||||
get = get_growth_time
|
||||
|
||||
## Sets the duration for the camera noise if [member loop] is set to false.[br]
|
||||
## If the duration is [param 0] then [member continous] becomes enabled.[br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_range(0, 10, 0.001, "or_greater", "suffix: s") var duration: float = 1.0:
|
||||
set = set_duration,
|
||||
get = get_duration
|
||||
|
||||
## Determines how long the noise should take to come to a full stop.[br]
|
||||
## The value is set in [b]seconds[/b].
|
||||
@export_exp_easing("attenuation", "positive_only", "suffix: s") var decay_time: float = 0:
|
||||
set = set_decay_time,
|
||||
get = get_decay_time
|
||||
|
||||
## Enabled layers will affect [PhantomCamera3D] nodes with at least one corresponding layer enabled.[br]
|
||||
## Enabling multiple corresponding layers on the same [PhantomCamera3D] causes no additional effect.
|
||||
@export_flags_3d_render var noise_emitter_layer: int = 1:
|
||||
set = set_noise_emitter_layer,
|
||||
get = get_noise_emitter_layer
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _play: bool = false:
|
||||
set(value):
|
||||
_play = value
|
||||
if value:
|
||||
_elasped_play_time = 0
|
||||
_decay_countdown = 0
|
||||
_play = true
|
||||
_should_grow = true
|
||||
_start_duration_countdown = false
|
||||
_should_decay = false
|
||||
else:
|
||||
_should_decay = true
|
||||
if noise.randomize_noise_seed:
|
||||
noise.noise_seed = randi() & 1000
|
||||
else:
|
||||
noise.reset_noise_time()
|
||||
get:
|
||||
return _play
|
||||
|
||||
var _start_duration_countdown: bool = false
|
||||
|
||||
var _decay_countdown: float = 0
|
||||
|
||||
var _should_grow: bool = false
|
||||
|
||||
var _should_decay: bool = false
|
||||
|
||||
var _elasped_play_time: float = 0
|
||||
|
||||
var _noise_output: Transform3D = Transform3D()
|
||||
|
||||
# NOTE - Temp solution until Godot has better plugin autoload recognition out-of-the-box.
|
||||
var _phantom_camera_manager: Node
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _get_configuration_warnings() -> PackedStringArray:
|
||||
if noise == null:
|
||||
return ["Noise resource is required in order to trigger emitter."]
|
||||
else:
|
||||
return []
|
||||
|
||||
|
||||
func _validate_property(property) -> void:
|
||||
if property.name == "duration" and continuous:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
|
||||
func _enter_tree() -> void:
|
||||
_phantom_camera_manager = get_tree().root.get_node(_constants.PCAM_MANAGER_NODE_NAME)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not _play and not _should_decay: return
|
||||
if noise == null:
|
||||
printerr("Noise resource missing in ", name)
|
||||
_play = false
|
||||
return
|
||||
|
||||
_elasped_play_time += delta
|
||||
|
||||
if _should_grow:
|
||||
noise.set_trauma(minf(_elasped_play_time / growth_time, 1))
|
||||
if _elasped_play_time >= growth_time:
|
||||
_should_grow = false
|
||||
_start_duration_countdown = true
|
||||
noise.set_trauma(1)
|
||||
|
||||
if not continuous:
|
||||
if _start_duration_countdown:
|
||||
if _elasped_play_time >= duration + growth_time:
|
||||
_should_decay = true
|
||||
_start_duration_countdown = false
|
||||
|
||||
if _should_decay:
|
||||
_decay_countdown += delta
|
||||
noise.set_trauma(maxf(1 - (_decay_countdown / decay_time), 0))
|
||||
if _decay_countdown >= decay_time:
|
||||
noise.set_trauma(0)
|
||||
_play = false
|
||||
preview = false
|
||||
_should_decay = false
|
||||
_elasped_play_time = 0
|
||||
_decay_countdown = 0
|
||||
|
||||
_noise_output = noise.get_noise_transform(delta)
|
||||
_phantom_camera_manager.noise_3d_emitted.emit(_noise_output, noise_emitter_layer)
|
||||
|
||||
|
||||
func _set_layer(current_layers: int, layer_number: int, value: bool) -> int:
|
||||
var mask: int = current_layers
|
||||
|
||||
# From https://github.com/godotengine/godot/blob/51991e20143a39e9ef0107163eaf283ca0a761ea/scene/3d/camera_3d.cpp#L638
|
||||
if layer_number < 1 or layer_number > 20:
|
||||
printerr("Layer must be between 1 and 20.")
|
||||
else:
|
||||
if value:
|
||||
mask |= 1 << (layer_number - 1)
|
||||
else:
|
||||
mask &= ~(1 << (layer_number - 1))
|
||||
|
||||
return mask
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
## Emits noise to the [PhantomCamera3D]s that has at least one matching layers.
|
||||
func emit() -> void:
|
||||
if _play: _play = false
|
||||
_play = true
|
||||
|
||||
|
||||
## Returns the state for the emitter. If true, the emitter is currently emitting.
|
||||
func is_emitting() -> bool:
|
||||
return _play
|
||||
|
||||
|
||||
## Stops the emitter from emitting noise.
|
||||
func stop(should_decay: bool = true) -> void:
|
||||
if should_decay:
|
||||
_should_decay = true
|
||||
else:
|
||||
_play = false
|
||||
|
||||
|
||||
## Toggles the emitter on and off.[br]
|
||||
func toggle() -> void:
|
||||
_play = !_play
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setter & Getter Functions
|
||||
|
||||
## Sets the [member noise] resource.
|
||||
func set_noise(value: PhantomCameraNoise3D) -> void:
|
||||
noise = value
|
||||
update_configuration_warnings()
|
||||
|
||||
## Returns the [member noise] resource.
|
||||
func get_noise() -> PhantomCameraNoise3D:
|
||||
return noise
|
||||
|
||||
|
||||
## Sets the [member continous] value.
|
||||
func set_continuous(value: bool) -> void:
|
||||
continuous = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Gets the [member continous] value.
|
||||
func get_continuous() -> bool:
|
||||
return continuous
|
||||
|
||||
|
||||
## Sets the [member growth_time] value.
|
||||
func set_growth_time(value: float) -> void:
|
||||
growth_time = value
|
||||
|
||||
## Returns the [member growth_time] value.
|
||||
func get_growth_time() -> float:
|
||||
return growth_time
|
||||
|
||||
|
||||
## Sets the [member duration] value.
|
||||
func set_duration(value: float) -> void:
|
||||
duration = value
|
||||
if duration == 0:
|
||||
duration = 0.001
|
||||
|
||||
## Returns the [member duration] value.
|
||||
func get_duration() -> float:
|
||||
return duration
|
||||
|
||||
|
||||
## Sets the [member decay_time] value.
|
||||
func set_decay_time(value: float) -> void:
|
||||
decay_time = value
|
||||
|
||||
## Returns the [member decay_time] value.
|
||||
func get_decay_time() -> float:
|
||||
return decay_time
|
||||
|
||||
|
||||
## Sets the [member noise_emitter_layer] value.
|
||||
func set_noise_emitter_layer(value: int) -> void:
|
||||
noise_emitter_layer = value
|
||||
|
||||
## Enables or disables a given layer of [member noise_emitter_layer].
|
||||
func set_noise_emitter_value(value: int, enabled: bool) -> void:
|
||||
noise_emitter_layer = _set_layer(noise_emitter_layer, value, enabled)
|
||||
|
||||
## Returns the [member noise_emitter_layer] value.
|
||||
func get_noise_emitter_layer() -> int:
|
||||
return noise_emitter_layer
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://ccmiitq0sdh7j
|
||||
@@ -0,0 +1,128 @@
|
||||
using Godot;
|
||||
|
||||
#nullable enable
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum InterpolationMode
|
||||
{
|
||||
Auto,
|
||||
Idle,
|
||||
Physics
|
||||
}
|
||||
|
||||
public static class PhantomCameraHostExtensions
|
||||
{
|
||||
public static PhantomCameraHost AsPhantomCameraHost(this Node node)
|
||||
{
|
||||
return new PhantomCameraHost(node);
|
||||
}
|
||||
}
|
||||
|
||||
public class PhantomCameraHost()
|
||||
{
|
||||
public Node Node { get; } = null!;
|
||||
|
||||
public PhantomCameraHost(Node node) : this()
|
||||
{
|
||||
Node = node;
|
||||
|
||||
_callablePCamBecameActive = Callable.From<Node>(pCam => PCamBecameActive?.Invoke(pCam));
|
||||
_callablePCamBecameInactive = Callable.From<Node>(pCam => PCamBecameInactive?.Invoke(pCam));
|
||||
|
||||
Node.Connect(SignalName.PCamBecameActive, _callablePCamBecameActive);
|
||||
Node.Connect(SignalName.PCamBecameInactive, _callablePCamBecameInactive);
|
||||
}
|
||||
|
||||
~PhantomCameraHost()
|
||||
{
|
||||
Node.Disconnect(SignalName.PCamBecameActive, _callablePCamBecameActive);
|
||||
Node.Disconnect(SignalName.PCamBecameInactive, _callablePCamBecameInactive);
|
||||
}
|
||||
|
||||
public delegate void PCamBecameActiveEventHandler(Node pCam);
|
||||
public delegate void PCamBecameInactiveEventHandler(Node pCam);
|
||||
|
||||
public event PCamBecameActiveEventHandler? PCamBecameActive;
|
||||
public event PCamBecameInactiveEventHandler? PCamBecameInactive;
|
||||
|
||||
|
||||
private readonly Callable _callablePCamBecameActive;
|
||||
private readonly Callable _callablePCamBecameInactive;
|
||||
// For when Godot becomes the minimum version
|
||||
// public InterpolationMode InterpolationMode
|
||||
// {
|
||||
// get => (InterpolationMode)(int)Node.Call(MethodName.GetInterpolationMode);
|
||||
// set => Node.Call(MethodName.SetInterpolationMode, (int)value);
|
||||
// }
|
||||
|
||||
public int HostLayers
|
||||
{
|
||||
get => (int)Node.Call(PhantomCamera.MethodName.GetHostLayers);
|
||||
set => Node.Call(PhantomCamera.MethodName.SetHostLayers, value);
|
||||
}
|
||||
|
||||
public void SetHostLayersValue(int layer, bool value) => Node.Call(MethodName.SetHostLayersValue, layer, value);
|
||||
|
||||
public Camera2D? Camera2D => (Camera2D?)Node.Get(PropertyName.Camera2D);
|
||||
|
||||
public Camera3D? Camera3D => (Camera3D?)Node.Get(PropertyName.Camera3D);
|
||||
|
||||
public InterpolationMode InterpolationMode
|
||||
{
|
||||
get => (InterpolationMode)(int)Node.Call(MethodName.GetInterpolationMode);
|
||||
set => Node.Call(MethodName.SetInterpolationMode, (int)value);
|
||||
}
|
||||
|
||||
public bool TriggerPhantomCameraTween => (bool)Node.Call(MethodName.GetTriggerPhantomCameraTween);
|
||||
|
||||
public ActivePhantomCameraQueryResult? GetActivePhantomCamera()
|
||||
{
|
||||
var result = Node.Call(MethodName.GetActivePhantomCamera);
|
||||
return result.VariantType == Variant.Type.Nil ? null : new ActivePhantomCameraQueryResult(result.AsGodotObject());
|
||||
}
|
||||
|
||||
public static class PropertyName
|
||||
{
|
||||
public const string Camera2D = "camera_2d";
|
||||
public const string Camera3D = "camera_3d";
|
||||
}
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetActivePhantomCamera = "get_active_pcam";
|
||||
public const string GetTriggerPhantomCameraTween = "get_trigger_pcam_tween";
|
||||
|
||||
public const string GetInterpolationMode = "get_interpolation_mode";
|
||||
public const string SetInterpolationMode = "set_interpolation_mode";
|
||||
|
||||
public const string SetHostLayersValue = "set_host_layers_value";
|
||||
}
|
||||
|
||||
public static class SignalName
|
||||
{
|
||||
public const string PCamBecameActive = "pcam_became_active";
|
||||
public const string PCamBecameInactive = "pcam_became_inactive";
|
||||
}
|
||||
}
|
||||
|
||||
public class ActivePhantomCameraQueryResult(GodotObject godotObject)
|
||||
{
|
||||
public bool Is2D => godotObject.IsClass("Node2D") || ((Node)godotObject).Name.ToString().Contains("PhantomCamera2D")
|
||||
|| ((Node)godotObject).Name.ToString().Contains("PCam2D")
|
||||
|| ((Node)godotObject).Name.ToString().Contains("2D");
|
||||
|
||||
public bool Is3D => godotObject.IsClass("Node3D") || ((Node)godotObject).Name.ToString().Contains("PhantomCamera3D")
|
||||
|| ((Node)godotObject).Name.ToString().Contains("PCam3D")
|
||||
|| ((Node)godotObject).Name.ToString().Contains("3D");
|
||||
|
||||
public PhantomCamera2D? AsPhantomCamera2D()
|
||||
{
|
||||
return Is2D ? new PhantomCamera2D(godotObject) : null;
|
||||
}
|
||||
|
||||
public PhantomCamera3D? AsPhantomCamera3D()
|
||||
{
|
||||
return Is3D ? new PhantomCamera3D(godotObject) : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://cr8brwrls2nn3
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
uid://bd046eokvcnu2
|
||||
117
addons/phantom_camera/scripts/resources/Camera3DResource.cs
Normal file
117
addons/phantom_camera/scripts/resources/Camera3DResource.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum KeepAspect
|
||||
{
|
||||
KeepWidth,
|
||||
KeepHeight
|
||||
}
|
||||
|
||||
public enum ProjectionType
|
||||
{
|
||||
Perspective,
|
||||
Orthogonal,
|
||||
Frustum
|
||||
}
|
||||
|
||||
public class Camera3DResource(Resource resource)
|
||||
{
|
||||
public readonly Resource Resource = resource;
|
||||
|
||||
public KeepAspect KeepAspect
|
||||
{
|
||||
get => (KeepAspect)(int)Resource.Call(MethodName.GetKeepAspect);
|
||||
set => Resource.Call(MethodName.SetKeepAspect, (int)value);
|
||||
}
|
||||
|
||||
public int CullMask
|
||||
{
|
||||
get => (int)Resource.Call(MethodName.GetCullMask);
|
||||
set => Resource.Call(MethodName.SetCullMask, value);
|
||||
}
|
||||
|
||||
public void SetCullMaskValue(int layer, bool value) => Resource.Call(MethodName.SetCullMaskValue, layer, value);
|
||||
|
||||
public float HOffset
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetHOffset);
|
||||
set => Resource.Call(MethodName.SetHOffset, value);
|
||||
}
|
||||
|
||||
public float VOffset
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetVOffset);
|
||||
set => Resource.Call(MethodName.SetVOffset, value);
|
||||
}
|
||||
|
||||
public ProjectionType Projection
|
||||
{
|
||||
get => (ProjectionType)(int)Resource.Call(MethodName.GetProjection);
|
||||
set => Resource.Call(MethodName.SetProjection, (int)value);
|
||||
}
|
||||
|
||||
public float Fov
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetFov);
|
||||
set => Resource.Call(MethodName.SetFov, Mathf.Clamp(value, 1, 179));
|
||||
}
|
||||
|
||||
public float Size
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetSize);
|
||||
set => Resource.Call(MethodName.SetSize, Mathf.Clamp(value, 0.001f, float.PositiveInfinity));
|
||||
}
|
||||
|
||||
public Vector2 FrustumOffset
|
||||
{
|
||||
get => (Vector2)Resource.Call(MethodName.GetFrustumOffset);
|
||||
set => Resource.Call(MethodName.SetFrustumOffset, value);
|
||||
}
|
||||
|
||||
public float Near
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetNear);
|
||||
set => Resource.Call(MethodName.SetNear, Mathf.Clamp(value, 0.001f, float.PositiveInfinity));
|
||||
}
|
||||
|
||||
public float Far
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetFar);
|
||||
set => Resource.Call(MethodName.SetFar, Mathf.Clamp(value, 0.01f, float.PositiveInfinity));
|
||||
}
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetKeepAspect = "get_keep_aspect";
|
||||
public const string SetKeepAspect = "set_keep_aspect";
|
||||
|
||||
public const string GetCullMask = "get_cull_mask";
|
||||
public const string SetCullMask = "set_cull_mask";
|
||||
public const string SetCullMaskValue = "set_cull_mask_value";
|
||||
|
||||
public const string GetHOffset = "get_h_offset";
|
||||
public const string SetHOffset = "set_h_offset";
|
||||
|
||||
public const string GetVOffset = "get_v_offset";
|
||||
public const string SetVOffset = "set_v_offset";
|
||||
|
||||
public const string GetProjection = "get_projection";
|
||||
public const string SetProjection = "set_projection";
|
||||
|
||||
public const string GetFov = "get_fov";
|
||||
public const string SetFov = "set_fov";
|
||||
|
||||
public const string GetSize = "get_size";
|
||||
public const string SetSize = "set_size";
|
||||
|
||||
public const string GetFrustumOffset = "get_frustum_offset";
|
||||
public const string SetFrustumOffset = "set_frustum_offset";
|
||||
|
||||
public const string GetNear = "get_near";
|
||||
public const string SetNear = "set_near";
|
||||
|
||||
public const string GetFar = "get_far";
|
||||
public const string SetFar = "set_far";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://jedyxlihuwbj
|
||||
@@ -0,0 +1,92 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera.Noise;
|
||||
|
||||
public class PhantomCameraNoise2D(Resource resource)
|
||||
{
|
||||
public readonly Resource Resource = resource;
|
||||
|
||||
public float Amplitude
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetAmplitude);
|
||||
set => Resource.Call(MethodName.SetAmplitude, value);
|
||||
}
|
||||
|
||||
public float Frequency
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetFrequency);
|
||||
set => Resource.Call(MethodName.SetFrequency, value);
|
||||
}
|
||||
|
||||
public bool RandomizeNoiseSeed
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetRandomizeNoiseSeed);
|
||||
set => Resource.Call(MethodName.SetRandomizeNoiseSeed, value);
|
||||
}
|
||||
|
||||
public int NoiseSeed
|
||||
{
|
||||
get => (int)Resource.Call(MethodName.GetNoiseSeed);
|
||||
set => Resource.Call(MethodName.SetNoiseSeed, value);
|
||||
}
|
||||
|
||||
public bool RotationalNoise
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetRotationalNoise);
|
||||
set => Resource.Call(MethodName.SetRotationalNoise, value);
|
||||
}
|
||||
|
||||
public bool PositionalNoise
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetPositionalNoise);
|
||||
set => Resource.Call(MethodName.SetPositionalNoise, value);
|
||||
}
|
||||
|
||||
public float RotationalMultiplier
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetRotationalMultiplier);
|
||||
set => Resource.Call(MethodName.SetRotationalMultiplier, value);
|
||||
}
|
||||
|
||||
public float PositionalMultiplierX
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetPositionalMultiplierX);
|
||||
set => Resource.Call(MethodName.SetPositionalMultiplierX, value);
|
||||
}
|
||||
|
||||
public float PositionalMultiplierY
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetPositionalMultiplierY);
|
||||
set => Resource.Call(MethodName.SetPositionalMultiplierY, value);
|
||||
}
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetAmplitude = "get_amplitude";
|
||||
public const string SetAmplitude = "set_amplitude";
|
||||
|
||||
public const string GetFrequency = "get_frequency";
|
||||
public const string SetFrequency = "set_frequency";
|
||||
|
||||
public const string GetRandomizeNoiseSeed = "get_randomize_noise_seed";
|
||||
public const string SetRandomizeNoiseSeed = "set_randomize_noise_seed";
|
||||
|
||||
public const string GetNoiseSeed = "get_noise_seed";
|
||||
public const string SetNoiseSeed = "set_noise_seed";
|
||||
|
||||
public const string GetRotationalNoise = "get_rotational_noise";
|
||||
public const string SetRotationalNoise = "set_rotational_noise";
|
||||
|
||||
public const string GetPositionalNoise = "get_positional_noise";
|
||||
public const string SetPositionalNoise = "set_positional_noise";
|
||||
|
||||
public const string GetRotationalMultiplier = "get_rotational_multiplier";
|
||||
public const string SetRotationalMultiplier = "set_rotational_multiplier";
|
||||
|
||||
public const string GetPositionalMultiplierX = "get_positional_multiplier_x";
|
||||
public const string SetPositionalMultiplierX = "set_positional_multiplier_x";
|
||||
|
||||
public const string GetPositionalMultiplierY = "get_positional_multiplier_y";
|
||||
public const string SetPositionalMultiplierY = "set_positional_multiplier_y";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://capjdoxs6gs6r
|
||||
119
addons/phantom_camera/scripts/resources/PhantomCameraNoise3D.cs
Normal file
119
addons/phantom_camera/scripts/resources/PhantomCameraNoise3D.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera.Noise;
|
||||
|
||||
public class PhantomCameraNoise3D(Resource resource)
|
||||
{
|
||||
public readonly Resource Resource = resource;
|
||||
|
||||
public float Amplitude
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetAmplitude);
|
||||
set => Resource.Call(MethodName.SetAmplitude, value);
|
||||
}
|
||||
|
||||
public float Frequency
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetFrequency);
|
||||
set => Resource.Call(MethodName.SetFrequency, value);
|
||||
}
|
||||
|
||||
public bool RandomizeNoiseSeed
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetRandomizeNoiseSeed);
|
||||
set => Resource.Call(MethodName.SetRandomizeNoiseSeed, value);
|
||||
}
|
||||
|
||||
public int NoiseSeed
|
||||
{
|
||||
get => (int)Resource.Call(MethodName.GetNoiseSeed);
|
||||
set => Resource.Call(MethodName.SetNoiseSeed, value);
|
||||
}
|
||||
|
||||
public bool RotationalNoise
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetRotationalNoise);
|
||||
set => Resource.Call(MethodName.SetRotationalNoise, value);
|
||||
}
|
||||
|
||||
public bool PositionalNoise
|
||||
{
|
||||
get => (bool)Resource.Call(MethodName.GetPositionalNoise);
|
||||
set => Resource.Call(MethodName.SetPositionalNoise, value);
|
||||
}
|
||||
|
||||
public float RotationalMultiplierX
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetRotationalMultiplierX);
|
||||
set => Resource.Call(MethodName.SetRotationalMultiplierX, value);
|
||||
}
|
||||
|
||||
public float RotationalMultiplierY
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetRotationalMultiplierY);
|
||||
set => Resource.Call(MethodName.SetRotationalMultiplierY, value);
|
||||
}
|
||||
|
||||
public float RotationalMultiplierZ
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetRotationalMultiplierZ);
|
||||
set => Resource.Call(MethodName.SetRotationalMultiplierZ, value);
|
||||
}
|
||||
|
||||
public float PositionalMultiplierX
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetPositionalMultiplierX);
|
||||
set => Resource.Call(MethodName.SetPositionalMultiplierX, value);
|
||||
}
|
||||
|
||||
public float PositionalMultiplierY
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetPositionalMultiplierY);
|
||||
set => Resource.Call(MethodName.SetPositionalMultiplierY, value);
|
||||
}
|
||||
|
||||
public float PositionalMultiplierZ
|
||||
{
|
||||
get => (float)Resource.Call(MethodName.GetPositionalMultiplierZ);
|
||||
set => Resource.Call(MethodName.SetPositionalMultiplierZ, value);
|
||||
}
|
||||
|
||||
public static class MethodName
|
||||
{
|
||||
public const string GetAmplitude = "get_amplitude";
|
||||
public const string SetAmplitude = "set_amplitude";
|
||||
|
||||
public const string GetFrequency = "get_frequency";
|
||||
public const string SetFrequency = "set_frequency";
|
||||
|
||||
public const string GetRandomizeNoiseSeed = "get_randomize_noise_seed";
|
||||
public const string SetRandomizeNoiseSeed = "set_randomize_noise_seed";
|
||||
|
||||
public const string GetNoiseSeed = "get_noise_seed";
|
||||
public const string SetNoiseSeed = "set_noise_seed";
|
||||
|
||||
public const string GetRotationalNoise = "get_rotational_noise";
|
||||
public const string SetRotationalNoise = "set_rotational_noise";
|
||||
|
||||
public const string GetPositionalNoise = "get_positional_noise";
|
||||
public const string SetPositionalNoise = "set_positional_noise";
|
||||
|
||||
public const string GetRotationalMultiplierX = "get_rotational_multiplier_x";
|
||||
public const string SetRotationalMultiplierX = "set_rotational_multiplier_x";
|
||||
|
||||
public const string GetRotationalMultiplierY = "get_rotational_multiplier_y";
|
||||
public const string SetRotationalMultiplierY = "set_rotational_multiplier_y";
|
||||
|
||||
public const string GetRotationalMultiplierZ = "get_rotational_multiplier_z";
|
||||
public const string SetRotationalMultiplierZ = "set_rotational_multiplier_z";
|
||||
|
||||
public const string GetPositionalMultiplierX = "get_positional_multiplier_x";
|
||||
public const string SetPositionalMultiplierX = "set_positional_multiplier_x";
|
||||
|
||||
public const string GetPositionalMultiplierY = "get_positional_multiplier_y";
|
||||
public const string SetPositionalMultiplierY = "set_positional_multiplier_y";
|
||||
|
||||
public const string GetPositionalMultiplierZ = "get_positional_multiplier_z";
|
||||
public const string SetPositionalMultiplierZ = "set_positional_multiplier_z";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://chk7643ynhe4f
|
||||
@@ -0,0 +1,64 @@
|
||||
using Godot;
|
||||
|
||||
namespace PhantomCamera;
|
||||
|
||||
public enum TransitionType
|
||||
{
|
||||
Linear,
|
||||
Sine,
|
||||
Quint,
|
||||
Quart,
|
||||
Quad,
|
||||
Expo,
|
||||
Elastic,
|
||||
Cubic,
|
||||
Circ,
|
||||
Bounce,
|
||||
Back
|
||||
}
|
||||
|
||||
public enum EaseType
|
||||
{
|
||||
EaseIn,
|
||||
EaseOut,
|
||||
EaseInOut,
|
||||
EaseOutIn
|
||||
}
|
||||
|
||||
public static class PhantomCameraTweenExtensions
|
||||
{
|
||||
public static PhantomCameraTween AsPhantomCameraTween(this Resource resource)
|
||||
{
|
||||
return new PhantomCameraTween(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public class PhantomCameraTween(Resource tweenResource)
|
||||
{
|
||||
public Resource Resource { get; } = tweenResource;
|
||||
|
||||
public float Duration
|
||||
{
|
||||
get => (float)Resource.Get(PropertyName.Duration);
|
||||
set => Resource.Set(PropertyName.Duration, value);
|
||||
}
|
||||
|
||||
public TransitionType Transition
|
||||
{
|
||||
get => (TransitionType)(int)Resource.Get(PropertyName.Transition);
|
||||
set => Resource.Set(PropertyName.Transition, (int)value);
|
||||
}
|
||||
|
||||
public EaseType Ease
|
||||
{
|
||||
get => (EaseType)(int)Resource.Get(PropertyName.Ease);
|
||||
set => Resource.Set(PropertyName.Ease, (int)value);
|
||||
}
|
||||
|
||||
public static class PropertyName
|
||||
{
|
||||
public const string Duration = "duration";
|
||||
public const string Transition = "transition";
|
||||
public const string Ease = "ease";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://ybr5c2s0tfvx
|
||||
110
addons/phantom_camera/scripts/resources/camera_3d_resource.gd
Normal file
110
addons/phantom_camera/scripts/resources/camera_3d_resource.gd
Normal file
@@ -0,0 +1,110 @@
|
||||
@tool
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_camera_3d_resource.svg")
|
||||
class_name Camera3DResource
|
||||
extends Resource
|
||||
|
||||
## Resource for [PhantomCamera3D] to override various [Camera3D] properties.
|
||||
##
|
||||
## The overrides defined here will be applied to the [Camera3D] upon the
|
||||
## [PhantomCamera3D] becoming active.
|
||||
|
||||
enum KeepAspect {
|
||||
KEEP_WIDTH = 0, ## Preserves the horizontal aspect ratio; also known as Vert- scaling. This is usually the best option for projects running in portrait mode, as taller aspect ratios will benefit from a wider vertical FOV.
|
||||
KEEP_HEIGHT = 1, ## Preserves the vertical aspect ratio; also known as Hor+ scaling. This is usually the best option for projects running in landscape mode, as wider aspect ratios will automatically benefit from a wider horizontal FOV.
|
||||
}
|
||||
|
||||
enum ProjectionType {
|
||||
PERSPECTIVE = 0, ## Perspective projection. Objects on the screen becomes smaller when they are far away.
|
||||
ORTHOGONAL = 1, ## Orthogonal projection, also known as orthographic projection. Objects remain the same size on the screen no matter how far away they are.
|
||||
FRUSTUM = 2, ## Frustum projection. This mode allows adjusting frustum_offset to create "tilted frustum" effects.
|
||||
}
|
||||
|
||||
## Overrides [member Camera3D.keep_aspect].
|
||||
@export var keep_aspect: KeepAspect = KeepAspect.KEEP_HEIGHT:
|
||||
set(value):
|
||||
keep_aspect = value
|
||||
emit_changed()
|
||||
get:
|
||||
return keep_aspect
|
||||
|
||||
## Overrides [member Camera3D.cull_mask].
|
||||
@export_flags_3d_render var cull_mask: int = 1048575:
|
||||
set(value):
|
||||
cull_mask = value
|
||||
emit_changed()
|
||||
get:
|
||||
return cull_mask
|
||||
|
||||
## Overrides [member Camera3D.h_offset].
|
||||
@export_range(0, 1, 0.001, "or_greater", "or_less", "hide_slider", "suffix:m") var h_offset: float = 0:
|
||||
set(value):
|
||||
h_offset = value
|
||||
emit_changed()
|
||||
get:
|
||||
return h_offset
|
||||
|
||||
## Overrides [member Camera3D.v_offset].
|
||||
@export_range(0, 1, 0.001, "or_greater", "or_less", "hide_slider", "suffix:m") var v_offset: float = 0:
|
||||
set(value):
|
||||
v_offset = value
|
||||
emit_changed()
|
||||
|
||||
## Overrides [member Camera3D.projection].
|
||||
@export var projection: ProjectionType = ProjectionType.PERSPECTIVE:
|
||||
set(value):
|
||||
projection = value
|
||||
notify_property_list_changed()
|
||||
emit_changed()
|
||||
get:
|
||||
return projection
|
||||
|
||||
## Overrides [member Camera3D.fov].
|
||||
@export_range(1, 179, 0.1, "degrees") var fov: float = 75:
|
||||
set(value):
|
||||
fov = value
|
||||
emit_changed()
|
||||
get:
|
||||
return fov
|
||||
|
||||
## Overrides [member Camera3D.size].
|
||||
@export_range(0.001, 100, 0.001, "suffix:m", "or_greater") var size: float = 1:
|
||||
set(value):
|
||||
size = value
|
||||
emit_changed()
|
||||
get:
|
||||
return size
|
||||
|
||||
## Overrides [member Camera3d.frustum_offset].
|
||||
@export var frustum_offset: Vector2 = Vector2.ZERO:
|
||||
set(value):
|
||||
frustum_offset = value
|
||||
emit_changed()
|
||||
get:
|
||||
return frustum_offset
|
||||
|
||||
## Overrides [member Camera3D.near].
|
||||
@export_range(0.001, 10, 0.001, "suffix:m", "or_greater") var near: float = 0.05:
|
||||
set(value):
|
||||
near = value
|
||||
emit_changed()
|
||||
get:
|
||||
return near
|
||||
|
||||
## Overrides [member Camera3D.far].
|
||||
@export_range(0.01, 4000, 0.001, "suffix:m","or_greater") var far: float = 4000:
|
||||
set(value):
|
||||
far = value
|
||||
emit_changed()
|
||||
get:
|
||||
return far
|
||||
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if property.name == "fov" and not projection == ProjectionType.PERSPECTIVE:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if property.name == "size" and projection == ProjectionType.PERSPECTIVE:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if property.name == "frustum_offset" and not projection == ProjectionType.FRUSTUM:
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
@@ -0,0 +1 @@
|
||||
uid://bc2tn187qiatpcheck
|
||||
@@ -0,0 +1,228 @@
|
||||
@tool
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_noise_resource.svg")
|
||||
class_name PhantomCameraNoise2D
|
||||
extends Resource
|
||||
|
||||
## A resource type used to apply noise, or shake, to [Camera2D]s that have a [PhantomCameraHost] as a child.
|
||||
##
|
||||
## Is a resource type that defines, calculates and outputs the noise values to a [Camera2D] through active
|
||||
## [PhantomCamera3D].[br]
|
||||
## It can be applied to either [PhantomCameraNoiseEmitter2D] or a [PhantomCamera2D] noise property directly
|
||||
|
||||
#region Exported Properties
|
||||
|
||||
## Defines the size of the noise pattern.[br]
|
||||
## Higher values will increase the range the noise can reach.
|
||||
@export_range(0, 1000, 0.001, "or_greater") var amplitude: float = 10:
|
||||
set = set_amplitude,
|
||||
get = get_amplitude
|
||||
|
||||
## Sets the density of the noise pattern.[br]
|
||||
## Higher values will result in more erratic noise.
|
||||
@export_range(0, 10, 0.001, "or_greater") var frequency: float = 0.5:
|
||||
set = set_frequency,
|
||||
get = get_frequency
|
||||
|
||||
## If true, randomizes the noise pattern every time the noise is run.[br]
|
||||
## If disabled, [member seed] can be used to define a fixed noise pattern.
|
||||
@export var randomize_noise_seed: bool = true:
|
||||
set = set_randomize_noise_seed,
|
||||
get = get_randomize_noise_seed
|
||||
|
||||
## Sets a predetermined seed noise value.[br]
|
||||
## Useful if wanting to achieve a persistent noise pattern every time the noise is emitted.
|
||||
@export var noise_seed: int = 0:
|
||||
set = set_noise_seed,
|
||||
get = get_noise_seed
|
||||
|
||||
## Enables noise changes to the [member Camera2D.offset] position.
|
||||
@export var positional_noise: bool = true:
|
||||
set = set_positional_noise,
|
||||
get = get_positional_noise
|
||||
|
||||
## Enables noise changes to the [Camera2D]'s rotation.
|
||||
@export var rotational_noise: bool = false:
|
||||
set = set_rotational_noise,
|
||||
get = get_rotational_noise
|
||||
|
||||
@export_group("Positional Multiplier")
|
||||
## Multiplies positional noise amount in the X-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.
|
||||
@export_range(0, 1, 0.001, "or_greater") var positional_multiplier_x: float = 1:
|
||||
set = set_positional_multiplier_x,
|
||||
get = get_positional_multiplier_x
|
||||
|
||||
## Multiplies positional noise amount in the Y-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.
|
||||
@export_range(0, 1, 0.001, "or_greater") var positional_multiplier_y: float = 1:
|
||||
set = set_positional_multiplier_y,
|
||||
get = get_positional_multiplier_y
|
||||
|
||||
@export_group("Rotational Multiplier")
|
||||
## Multiplies rotational noise amount.
|
||||
@export_range(0, 1, 0.001, "or_greater") var rotational_multiplier: float = 1:
|
||||
set = set_rotational_multiplier,
|
||||
get = get_rotational_multiplier
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _noise_algorithm: FastNoiseLite = FastNoiseLite.new()
|
||||
|
||||
var _noise_positional_multiplier: Vector2 = Vector2(
|
||||
positional_multiplier_x,
|
||||
positional_multiplier_y
|
||||
)
|
||||
|
||||
var _trauma: float = 0.0:
|
||||
set(value):
|
||||
_trauma = value
|
||||
|
||||
var _noise_time: float = 0.0
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _init():
|
||||
_noise_algorithm.noise_type = FastNoiseLite.TYPE_PERLIN
|
||||
if randomize_noise_seed: _noise_algorithm.seed = randi()
|
||||
_noise_algorithm.frequency = frequency
|
||||
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if randomize_noise_seed and property.name == "noise_seed":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if not rotational_noise and property.name == "rotational_multiplier":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if not positional_noise:
|
||||
match property.name:
|
||||
"positional_multiplier_x", \
|
||||
"positional_multiplier_y":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
|
||||
func _get_noise_from_seed(noise_seed: int) -> float:
|
||||
return _noise_algorithm.get_noise_2d(noise_seed, _noise_time) * amplitude
|
||||
|
||||
|
||||
func set_trauma(value: float) -> void:
|
||||
_trauma = value
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func get_noise_transform(delta: float) -> Transform2D:
|
||||
var output_position: Vector2 = Vector2.ZERO
|
||||
var output_rotation: float = 0.0
|
||||
_noise_time += delta
|
||||
_trauma = maxf(_trauma, 0.0)
|
||||
|
||||
if positional_noise:
|
||||
for i in 2:
|
||||
output_position[i] = _noise_positional_multiplier[i] * pow(_trauma, 2) * _get_noise_from_seed(i + noise_seed)
|
||||
if rotational_noise:
|
||||
output_rotation = rotational_multiplier / 100 * pow(_trauma, 2) * _get_noise_from_seed(noise_seed)
|
||||
|
||||
return Transform2D(output_rotation, output_position)
|
||||
|
||||
|
||||
func reset_noise_time() -> void:
|
||||
_noise_time = 0
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setters & Getters
|
||||
|
||||
## Sets the [member amplitude] value.
|
||||
func set_amplitude(value: float) -> void:
|
||||
amplitude =value
|
||||
|
||||
## Returns the [member amplitude] value.
|
||||
func get_amplitude() -> float:
|
||||
return amplitude
|
||||
|
||||
|
||||
## Sets the [member frequency] value.
|
||||
func set_frequency(value: float) -> void:
|
||||
frequency = value
|
||||
_noise_algorithm.frequency = value
|
||||
|
||||
## Returns the [member frequency] value.
|
||||
func get_frequency() -> float:
|
||||
return frequency
|
||||
|
||||
|
||||
## Sets the [member randomize_seed] value.
|
||||
func set_randomize_noise_seed(value: int) -> void:
|
||||
randomize_noise_seed = value
|
||||
if value: _noise_algorithm.seed = randi()
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member randomize_seed] value.
|
||||
func get_randomize_noise_seed() -> int:
|
||||
return randomize_noise_seed
|
||||
|
||||
|
||||
## Sets the [member randomize_seed] value.
|
||||
func set_noise_seed(value: int) -> void:
|
||||
noise_seed = value
|
||||
|
||||
## Returns the [member seed] value.
|
||||
func get_noise_seed() -> int:
|
||||
return noise_seed
|
||||
|
||||
|
||||
## Sets the [member positional_noise] value.
|
||||
func set_positional_noise(value: bool) -> void:
|
||||
positional_noise = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member positional_noise] value.
|
||||
func get_positional_noise() -> bool:
|
||||
return positional_noise
|
||||
|
||||
|
||||
## Sets the [member rotational_noise] value.
|
||||
func set_rotational_noise(value: bool) -> void:
|
||||
rotational_noise = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member rotational_noise] value.
|
||||
func get_rotational_noise() -> bool:
|
||||
return rotational_noise
|
||||
|
||||
|
||||
## Sets the [member positional_multiplier_x] value.
|
||||
func set_positional_multiplier_x(value: float) -> void:
|
||||
positional_multiplier_x = value
|
||||
_noise_positional_multiplier.x = value
|
||||
|
||||
## Returns the [member positional_multiplier_x] value.
|
||||
func get_positional_multiplier_x() -> float:
|
||||
return positional_multiplier_x
|
||||
|
||||
|
||||
## Sets the [member positional_multiplier_y] value.
|
||||
func set_positional_multiplier_y(value: float) -> void:
|
||||
positional_multiplier_y = value
|
||||
_noise_positional_multiplier.y = value
|
||||
|
||||
## Returns the [member positional_multiplier_y] value.
|
||||
func get_positional_multiplier_y() -> float:
|
||||
return positional_multiplier_y
|
||||
|
||||
|
||||
## Sets the [member rotational_multiplier] value.
|
||||
func set_rotational_multiplier(value: float) -> void:
|
||||
rotational_multiplier = value
|
||||
|
||||
## Returns the [member rotational_multiplier] value.
|
||||
func get_rotational_multiplier() -> float:
|
||||
return rotational_multiplier
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://dimvdouy8g0sv
|
||||
@@ -0,0 +1,301 @@
|
||||
@tool
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_noise_resource.svg")
|
||||
class_name PhantomCameraNoise3D
|
||||
extends Resource
|
||||
|
||||
## A resource type used to apply noise, or shake, to [Camera3D]s that have a [PhantomCameraHost] as a child.
|
||||
##
|
||||
## Is a resource type that defines, calculates and outputs the noise values to a [Camera3D] through active
|
||||
## [PhantomCamera3D].[br]
|
||||
## It can be applied to either [PhantomCameraNoiseEmitter3D] or a [PhantomCamera3D] noise property directly
|
||||
|
||||
#region Exported Properties
|
||||
|
||||
## Defines the size of the noise pattern.[br]
|
||||
## Higher values will increase the range the noise can reach.
|
||||
@export_range(0, 100, 0.001, "or_greater") var amplitude: float = 10:
|
||||
set = set_amplitude,
|
||||
get = get_amplitude
|
||||
|
||||
## Sets the density of the noise pattern.[br]
|
||||
## Higher values will result in more erratic noise.
|
||||
@export_range(0, 10, 0.001, "or_greater") var frequency: float = 0.2:
|
||||
set = set_frequency,
|
||||
get = get_frequency
|
||||
|
||||
## If true, randomizes the noise pattern every time the noise is run.[br]
|
||||
## If disabled, [member seed] can be used to define a fixed noise pattern.
|
||||
@export var randomize_noise_seed: bool = true:
|
||||
set = set_randomize_noise_seed,
|
||||
get = get_randomize_noise_seed
|
||||
|
||||
## Sets a predetermined seed noise value.[br]
|
||||
## Useful if wanting to achieve a persistent noise pattern every time the noise is emitted.
|
||||
@export var noise_seed: int = 0:
|
||||
set = set_noise_seed,
|
||||
get = get_noise_seed
|
||||
|
||||
## Enables noise changes to the [Camera3D]'s rotation.
|
||||
@export var rotational_noise: bool = true:
|
||||
set = set_rotational_noise,
|
||||
get = get_rotational_noise
|
||||
|
||||
## Enables noise changes to the camera's position.[br][br]
|
||||
## [b]Important[/b][br]This can cause geometry clipping if the camera gets too close while this is active.
|
||||
@export var positional_noise: bool = false:
|
||||
set = set_positional_noise,
|
||||
get = get_positional_noise
|
||||
|
||||
@export_group("Rotational Multiplier")
|
||||
## Multiplies rotational noise amount in the X-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.
|
||||
@export_range(0, 1, 0.001, "or_greater") var rotational_multiplier_x: float = 1:
|
||||
set = set_rotational_multiplier_x,
|
||||
get = get_rotational_multiplier_x
|
||||
|
||||
## Multiplies rotational noise amount in the Y-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.
|
||||
@export_range(0, 1, 0.001, "or_greater") var rotational_multiplier_y: float = 1:
|
||||
set = set_rotational_multiplier_y,
|
||||
get = get_rotational_multiplier_y
|
||||
|
||||
## Multiplies rotational noise amount in the Z-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.
|
||||
@export_range(0, 1, 0.001, "or_greater") var rotational_multiplier_z: float = 1:
|
||||
set = set_rotational_multiplier_z,
|
||||
get = get_rotational_multiplier_z
|
||||
|
||||
@export_group("Positional Multiplier")
|
||||
## Multiplies positional noise amount in the X-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.[br]
|
||||
## [b]Note:[/b] Rotational Offset is recommended to avoid potential camera clipping with the environment.
|
||||
@export_range(0, 1, 0.001, "or_greater") var positional_multiplier_x: float = 1:
|
||||
set = set_positional_multiplier_x,
|
||||
get = get_positional_multiplier_x
|
||||
|
||||
## Multiplies positional noise amount in the Y-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.[br]
|
||||
## [b]Note:[/b] Rotational Offset is recommended to avoid potential camera clipping with the environment.
|
||||
@export_range(0, 1, 0.001, "or_greater") var positional_multiplier_y: float = 1:
|
||||
set = set_positional_multiplier_y,
|
||||
get = get_positional_multiplier_y
|
||||
|
||||
## Multiplies positional noise amount in the Z-axis.[br]
|
||||
## Set the value to [param 0] to disable noise in the axis.[br]
|
||||
## [b]Note:[/b] Rotational Offset is recommended to avoid potential camera clipping with the environment.
|
||||
@export_range(0, 1, 0.001, "or_greater") var positional_multiplier_z: float = 1:
|
||||
set = set_positional_multiplier_z,
|
||||
get = get_positional_multiplier_z
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Variables
|
||||
|
||||
var _noise_algorithm: FastNoiseLite = FastNoiseLite.new()
|
||||
|
||||
var _noise_rotational_multiplier: Vector3 = Vector3(
|
||||
rotational_multiplier_x,
|
||||
rotational_multiplier_y,
|
||||
rotational_multiplier_z,
|
||||
)
|
||||
|
||||
var _noise_positional_multiplier: Vector3 = Vector3(
|
||||
positional_multiplier_x,
|
||||
positional_multiplier_y,
|
||||
positional_multiplier_z,
|
||||
)
|
||||
|
||||
var _trauma: float = 0.0:
|
||||
set(value):
|
||||
_trauma = value
|
||||
if _trauma == 0.0:
|
||||
_noise_time = 0.0
|
||||
|
||||
var _noise_time: float = 0.0
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Functions
|
||||
|
||||
func _init():
|
||||
_noise_algorithm.noise_type = FastNoiseLite.TYPE_PERLIN
|
||||
|
||||
if randomize_noise_seed: _noise_algorithm.seed = randi()
|
||||
_noise_algorithm.frequency = frequency
|
||||
|
||||
|
||||
func _validate_property(property: Dictionary) -> void:
|
||||
if randomize_noise_seed and property.name == "noise_seed":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if not rotational_noise:
|
||||
match property.name:
|
||||
"rotational_multiplier_x", \
|
||||
"rotational_multiplier_y", \
|
||||
"rotational_multiplier_z":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
if not positional_noise:
|
||||
match property.name:
|
||||
"positional_multiplier_x", \
|
||||
"positional_multiplier_y", \
|
||||
"positional_multiplier_z":
|
||||
property.usage = PROPERTY_USAGE_NO_EDITOR
|
||||
|
||||
|
||||
func _get_noise_from_seed(noise_seed: int) -> float:
|
||||
return _noise_algorithm.get_noise_2d(noise_seed, _noise_time) * amplitude
|
||||
|
||||
|
||||
func set_trauma(value: float) -> void:
|
||||
_trauma = value
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Functions
|
||||
|
||||
func get_noise_transform(delta: float) -> Transform3D:
|
||||
var output_rotation: Vector3 = Vector3.ZERO
|
||||
var output_position: Vector3 = Vector3.ZERO
|
||||
_noise_time += delta
|
||||
_trauma = maxf(_trauma, 0.0)
|
||||
|
||||
for i in 3:
|
||||
if rotational_noise:
|
||||
output_rotation[i] = deg_to_rad(
|
||||
_noise_rotational_multiplier[i] * pow(_trauma, 2) * _get_noise_from_seed(i + noise_seed)
|
||||
)
|
||||
|
||||
if positional_noise:
|
||||
output_position[i] += _noise_positional_multiplier[i] / 10 * \
|
||||
pow(_trauma, 2) * _get_noise_from_seed(i + noise_seed)
|
||||
|
||||
return Transform3D(Quaternion.from_euler(output_rotation), output_position)
|
||||
|
||||
|
||||
func reset_noise_time() -> void:
|
||||
_noise_time = 0
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setters & Getters
|
||||
|
||||
## Sets the [member amplitude] value.
|
||||
func set_amplitude(value: float) -> void:
|
||||
amplitude =value
|
||||
|
||||
## Returns the [member amplitude] value.
|
||||
func get_amplitude() -> float:
|
||||
return amplitude
|
||||
|
||||
|
||||
## Sets the [member frequency] value.
|
||||
func set_frequency(value: float) -> void:
|
||||
frequency = value
|
||||
_noise_algorithm.frequency = value
|
||||
|
||||
## Returns the [member frequency] value.
|
||||
func get_frequency() -> float:
|
||||
return frequency
|
||||
|
||||
|
||||
## Sets the [member randomize_seed] value.
|
||||
func set_randomize_noise_seed(value: int) -> void:
|
||||
randomize_noise_seed = value
|
||||
if value: _noise_algorithm.seed = randi()
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member randomize_seed] value.
|
||||
func get_randomize_noise_seed() -> int:
|
||||
return randomize_noise_seed
|
||||
|
||||
|
||||
## Sets the [member randomize_seed] value.
|
||||
func set_noise_seed(value: int) -> void:
|
||||
noise_seed = value
|
||||
|
||||
## Returns the [member seed] value.
|
||||
func get_noise_seed() -> int:
|
||||
return noise_seed
|
||||
|
||||
|
||||
## Sets the [member positional_noise] value.
|
||||
func set_positional_noise(value: bool) -> void:
|
||||
positional_noise = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member positional_noise] value.
|
||||
func get_positional_noise() -> bool:
|
||||
return positional_noise
|
||||
|
||||
|
||||
## Sets the [member rotational_noise] value.
|
||||
func set_rotational_noise(value: bool) -> void:
|
||||
rotational_noise = value
|
||||
notify_property_list_changed()
|
||||
|
||||
## Returns the [member rotational_noise] value.
|
||||
func get_rotational_noise() -> bool:
|
||||
return rotational_noise
|
||||
|
||||
|
||||
## Sets the [member positional_multiplier_x] value.
|
||||
func set_positional_multiplier_x(value: float) -> void:
|
||||
positional_multiplier_x = value
|
||||
_noise_positional_multiplier.x = value
|
||||
|
||||
## Returns the [member positional_multiplier_x] value.
|
||||
func get_positional_multiplier_x() -> float:
|
||||
return positional_multiplier_x
|
||||
|
||||
|
||||
## Sets the [member positional_multiplier_y] value.
|
||||
func set_positional_multiplier_y(value: float) -> void:
|
||||
positional_multiplier_y = value
|
||||
_noise_positional_multiplier.y = value
|
||||
|
||||
## Returns the [member positional_multiplier_y] value.
|
||||
func get_positional_multiplier_y() -> float:
|
||||
return positional_multiplier_y
|
||||
|
||||
|
||||
## Sets the [member positional_multiplier_z] value.
|
||||
func set_positional_multiplier_z(value: float) -> void:
|
||||
positional_multiplier_z = value
|
||||
_noise_positional_multiplier.z = value
|
||||
|
||||
## Returns the [member positional_multiplier_z] value.
|
||||
func get_positional_multiplier_z() -> float:
|
||||
return positional_multiplier_z
|
||||
|
||||
|
||||
## Sets the [member rotational_multiplier_x] value.
|
||||
func set_rotational_multiplier_x(value: float) -> void:
|
||||
rotational_multiplier_x = value
|
||||
_noise_rotational_multiplier.x = value
|
||||
|
||||
## Returns the [member rotational_multiplier_x] value.
|
||||
func get_rotational_multiplier_x() -> float:
|
||||
return rotational_multiplier_x
|
||||
|
||||
|
||||
## Sets the [member rotational_multiplier_y] value.
|
||||
func set_rotational_multiplier_y(value: float) -> void:
|
||||
rotational_multiplier_y = value
|
||||
_noise_rotational_multiplier.y = value
|
||||
|
||||
## Returns the [member rotational_multiplier_y] value.
|
||||
func get_rotational_multiplier_y() -> float:
|
||||
return rotational_multiplier_y
|
||||
|
||||
|
||||
## Sets the [member rotational_multiplier_z] value.
|
||||
func set_rotational_multiplier_z(value: float) -> void:
|
||||
rotational_multiplier_z = value
|
||||
_noise_rotational_multiplier.z = value
|
||||
|
||||
## Returns the [member rotational_multiplier_z] value.
|
||||
func get_rotational_multiplier_z() -> float:
|
||||
return rotational_multiplier_z
|
||||
|
||||
#endregion
|
||||
@@ -0,0 +1 @@
|
||||
uid://cuffvge5ad4aa
|
||||
41
addons/phantom_camera/scripts/resources/tween_resource.gd
Normal file
41
addons/phantom_camera/scripts/resources/tween_resource.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
@icon("res://addons/phantom_camera/icons/phantom_camera_tween.svg")
|
||||
class_name PhantomCameraTween
|
||||
extends Resource
|
||||
|
||||
## Tweening resource for [PhantomCamera2D] and [PhantomCamera3D].
|
||||
##
|
||||
## Defines how [param PhantomCameras] transition between one another.
|
||||
## Changing the tween values for a given [param PhantomCamera] determines how
|
||||
## transitioning to that instance will look like.
|
||||
|
||||
enum TransitionType {
|
||||
LINEAR = 0, ## The animation is interpolated linearly.
|
||||
SINE = 1, ## The animation is interpolated using a sine function.
|
||||
QUINT = 2, ## The animation is interpolated with a quintic (to the power of 5) function.
|
||||
QUART = 3, ## The animation is interpolated with a quartic (to the power of 4) function.
|
||||
QUAD = 4, ## The animation is interpolated with a quadratic (to the power of 2) function.
|
||||
EXPO = 5, ## The animation is interpolated with an exponential (to the power of x) function.
|
||||
ELASTIC = 6, ## The animation is interpolated with elasticity, wiggling around the edges.
|
||||
CUBIC = 7, ## The animation is interpolated with a cubic (to the power of 3) function.
|
||||
CIRC = 8, ## The animation is interpolated with a function using square roots.
|
||||
BOUNCE = 9, ## The animation is interpolated by bouncing at the end.
|
||||
BACK = 10, ## The animation is interpolated backing out at ends.
|
||||
# CUSTOM = 11,
|
||||
# NONE = 12,
|
||||
}
|
||||
|
||||
enum EaseType {
|
||||
EASE_IN = 0, ## The interpolation starts slowly and speeds up towards the end.
|
||||
EASE_OUT = 1, ## The interpolation starts quickly and slows down towards the end.
|
||||
EASE_IN_OUT = 2, ## A combination of EASE_IN and EASE_OUT. The interpolation is slowest at both ends.
|
||||
EASE_OUT_IN = 3, ## A combination of EASE_IN and EASE_OUT. The interpolation is fastest at both ends.
|
||||
}
|
||||
|
||||
## The time it takes to tween to this PhantomCamera in [param seconds].
|
||||
@export var duration: float = 1.0
|
||||
|
||||
## The transition bezier type for the tween. The options are defined in the [enum TransitionType].
|
||||
@export var transition: TransitionType = TransitionType.LINEAR
|
||||
|
||||
## The ease type for the tween. The options are defined in the [enum EaseType].
|
||||
@export var ease: EaseType = EaseType.EASE_IN_OUT
|
||||
@@ -0,0 +1 @@
|
||||
uid://8umksf8e80fw
|
||||
Reference in New Issue
Block a user