progress
0
addons/cutscene_editor/CHANGES.md
Normal file → Executable file
19
addons/cutscene_editor/CutsceneEditorPlugin.gd
Normal file → Executable file
@@ -59,9 +59,6 @@ func _create_dock_panel() -> Control:
|
||||
graph_edit = _create_graph_edit()
|
||||
main_vbox.add_child(graph_edit)
|
||||
|
||||
# Set up preview system
|
||||
_setup_preview_system()
|
||||
|
||||
# Set up undo/redo system
|
||||
_setup_undo_redo_system()
|
||||
|
||||
@@ -113,13 +110,7 @@ func _create_toolbar() -> Control:
|
||||
# Separator
|
||||
var separator2 = VSeparator.new()
|
||||
toolbar.add_child(separator2)
|
||||
|
||||
# Preview button
|
||||
var preview_button = Button.new()
|
||||
preview_button.text = "Preview"
|
||||
preview_button.icon = get_editor_interface().get_base_control().get_theme_icon("Play", "EditorIcons")
|
||||
preview_button.connect("pressed", _on_preview_pressed)
|
||||
toolbar.add_child(preview_button)
|
||||
|
||||
|
||||
return toolbar
|
||||
|
||||
@@ -149,10 +140,6 @@ func _create_graph_edit() -> GraphEdit:
|
||||
|
||||
return graph
|
||||
|
||||
func _setup_preview_system() -> void:
|
||||
# Set up the preview system
|
||||
if graph_edit:
|
||||
graph_edit.setup_preview()
|
||||
|
||||
func _setup_undo_redo_system() -> void:
|
||||
# Set up the undo/redo system
|
||||
@@ -209,7 +196,3 @@ func _on_undo_pressed() -> void:
|
||||
func _on_redo_pressed() -> void:
|
||||
if graph_edit:
|
||||
graph_edit.redo()
|
||||
|
||||
func _on_preview_pressed() -> void:
|
||||
if graph_edit:
|
||||
graph_edit.start_preview()
|
||||
|
||||
0
addons/cutscene_editor/README.md
Normal file → Executable file
63
addons/cutscene_editor/editor/CutsceneGenerator.gd
Normal file → Executable file
@@ -9,7 +9,7 @@ var graph_nodes: Dictionary = {} # Map of node IDs to node data
|
||||
var connections: Array = [] # List of connection data
|
||||
|
||||
# Generate a cutscene from graph data
|
||||
func generate_cutscene(cutscene_resource: CutsceneResource) -> CutsceneManager:
|
||||
func generate_cutscene(scene: Node, cutscene_resource: CutsceneResource) -> CutsceneManager:
|
||||
# Clear previous data
|
||||
graph_nodes.clear()
|
||||
connections.clear()
|
||||
@@ -30,7 +30,7 @@ func generate_cutscene(cutscene_resource: CutsceneResource) -> CutsceneManager:
|
||||
return cutscene_manager
|
||||
|
||||
# Build action sequence starting from entry node
|
||||
_build_action_sequence(entry_node, cutscene_manager)
|
||||
_build_action_sequence(scene, entry_node, cutscene_manager)
|
||||
|
||||
return cutscene_manager
|
||||
|
||||
@@ -43,45 +43,42 @@ func _find_entry_node() -> Dictionary:
|
||||
return {}
|
||||
|
||||
# Build action sequence from graph data
|
||||
func _build_action_sequence(start_node: Dictionary, cutscene_manager: CutsceneManager) -> void:
|
||||
# Use a queue-based traversal to process nodes in order
|
||||
var node_queue = []
|
||||
var processed_nodes = {}
|
||||
var next_connections = _get_outgoing_connections(start_node["id"])
|
||||
func _build_action_sequence(scene: Node, start_node: Dictionary, cutscene_manager: CutsceneManager) -> void:
|
||||
# First pass: Create all actions
|
||||
var action_map = {} # Map of node IDs to action instances
|
||||
|
||||
# Add initial connections to queue
|
||||
for conn in next_connections:
|
||||
node_queue.append(conn["to_node"])
|
||||
|
||||
# Process nodes in order
|
||||
while not node_queue.is_empty():
|
||||
var current_node_id = node_queue.pop_front()
|
||||
for node_id in graph_nodes:
|
||||
var node_data = graph_nodes[node_id]
|
||||
|
||||
# Skip if already processed
|
||||
if processed_nodes.has(current_node_id):
|
||||
continue
|
||||
|
||||
# Mark as processed
|
||||
processed_nodes[current_node_id] = true
|
||||
|
||||
# Get node data
|
||||
var node_data = graph_nodes.get(current_node_id, {})
|
||||
if node_data.is_empty():
|
||||
# Skip entry and exit nodes as they don't create actions
|
||||
if node_data["type"] == "entry" or node_data["type"] == "exit":
|
||||
continue
|
||||
|
||||
# Create action for regular nodes
|
||||
var action = _create_action_from_node(node_data)
|
||||
var action = _create_action_from_node(scene, node_data)
|
||||
if action:
|
||||
cutscene_manager.add_action(action)
|
||||
action_map[node_id] = action
|
||||
|
||||
# Second pass: Add actions with their dependencies
|
||||
for node_id in action_map:
|
||||
print("setting up", node_id)
|
||||
var action = action_map[node_id]
|
||||
|
||||
# Add next nodes to queue
|
||||
var outgoing_connections = _get_outgoing_connections(current_node_id)
|
||||
for conn in outgoing_connections:
|
||||
if not processed_nodes.has(conn["to_node"]):
|
||||
node_queue.append(conn["to_node"])
|
||||
# Get dependencies (incoming connections)
|
||||
var deps = []
|
||||
var incoming_connections = _get_incoming_connections(node_id)
|
||||
|
||||
for conn in incoming_connections:
|
||||
# Only add as dependency if the source node creates an action
|
||||
var from_node_data = graph_nodes.get(conn["from_node"], {})
|
||||
if not from_node_data.is_empty() and from_node_data["type"] != "entry":
|
||||
deps.append(conn["from_node"])
|
||||
|
||||
# Add action with dependencies
|
||||
cutscene_manager.add_action(node_id, action, deps)
|
||||
|
||||
# Create an action instance from node data
|
||||
func _create_action_from_node(node_data: Dictionary):
|
||||
func _create_action_from_node(scene: Node, node_data: Dictionary):
|
||||
var parameters = node_data["parameters"]
|
||||
|
||||
match node_data["type"]:
|
||||
@@ -93,7 +90,7 @@ func _create_action_from_node(node_data: Dictionary):
|
||||
|
||||
# In a real implementation, we would resolve the character path to an actual node
|
||||
# For now, we'll create a placeholder
|
||||
var character_node = null # This would be resolved at runtime
|
||||
var character_node = scene.find_child(character_path) # This would be resolved at runtime
|
||||
var target_position = Vector2(target_x, target_y)
|
||||
|
||||
return MoveAction.new(character_node, target_position, speed)
|
||||
|
||||
50
addons/cutscene_editor/editor/CutsceneGraphEdit.gd
Normal file → Executable file
@@ -16,9 +16,6 @@ var node_counter: int = 0 # For generating unique node IDs
|
||||
var current_cutscene: CutsceneResource # The cutscene being edited
|
||||
|
||||
# Preview properties
|
||||
var preview_manager: PreviewManager
|
||||
var preview_panel: PreviewPanel
|
||||
|
||||
# Undo/Redo properties
|
||||
var undo_redo_manager: UndoRedoManager
|
||||
|
||||
@@ -289,7 +286,7 @@ func _on_graph_node_deleted(node: BaseGraphNode) -> void:
|
||||
# Remove all connections to/from this node
|
||||
var connections = get_connection_list()
|
||||
for connection in connections:
|
||||
if connection["from_node"] == node.node_id or connection["to_node"] == node.node_id:
|
||||
if connection["from_node"] == node.name or connection["to_node"] == node.name:
|
||||
disconnect_node(connection["from_node"], connection["from_port"], connection["to_node"], connection["to_port"])
|
||||
|
||||
|
||||
@@ -332,6 +329,9 @@ func clear_graph() -> void:
|
||||
# Emit signal
|
||||
emit_signal("graph_changed")
|
||||
|
||||
func get_graph_node_by_id(id: String):
|
||||
return find_child(id)
|
||||
|
||||
# Load graph from cutscene resource
|
||||
func load_from_cutscene(cutscene: CutsceneResource) -> void:
|
||||
# Clear existing graph
|
||||
@@ -343,14 +343,16 @@ func load_from_cutscene(cutscene: CutsceneResource) -> void:
|
||||
# Create nodes from cutscene data
|
||||
for node_data in cutscene.nodes:
|
||||
var node = add_node(node_data["type"], Vector2(node_data["position"]["x"], node_data["position"]["y"]))
|
||||
node.owner=self
|
||||
if node:
|
||||
node.node_id = node_data["id"]
|
||||
node.name = node_data["id"]
|
||||
# Set node parameters
|
||||
for param_name in node_data["parameters"]:
|
||||
node.set_parameter(param_name, node_data["parameters"][param_name])
|
||||
|
||||
# Create connections from cutscene data
|
||||
for connection_data in cutscene.connections:
|
||||
print(get_graph_node_by_id(connection_data["from_node"]))
|
||||
connect_node(connection_data["from_node"], connection_data["from_port"],
|
||||
connection_data["to_node"], connection_data["to_port"])
|
||||
|
||||
@@ -370,7 +372,7 @@ func save_to_cutscene() -> CutsceneResource:
|
||||
for child in get_children():
|
||||
if child is BaseGraphNode:
|
||||
var node_data = {
|
||||
"id": child.node_id,
|
||||
"id": str(child.name),
|
||||
"type": child.node_type,
|
||||
"position": {
|
||||
"x": child.position_offset.x,
|
||||
@@ -384,9 +386,9 @@ func save_to_cutscene() -> CutsceneResource:
|
||||
for connection in get_connection_list():
|
||||
var connection_data = {
|
||||
"id": _generate_unique_connection_id(),
|
||||
"from_node": connection["from_node"],
|
||||
"from_node": str(connection["from_node"]),
|
||||
"from_port": connection["from_port"],
|
||||
"to_node": connection["to_node"],
|
||||
"to_node": str(connection["to_node"]),
|
||||
"to_port": connection["to_port"]
|
||||
}
|
||||
current_cutscene.connections.append(connection_data)
|
||||
@@ -398,39 +400,7 @@ func _generate_unique_connection_id() -> String:
|
||||
return "conn_" + str(Time.get_ticks_msec())
|
||||
|
||||
|
||||
# Set up preview system
|
||||
func setup_preview() -> void:
|
||||
# Create preview manager
|
||||
preview_manager = PreviewManager.new()
|
||||
add_child(preview_manager)
|
||||
|
||||
# Create preview panel
|
||||
preview_panel = PreviewPanel.new()
|
||||
preview_panel.set_preview_manager(preview_manager)
|
||||
preview_panel.set_graph_edit(self)
|
||||
|
||||
# Add to editor interface (this would be added to the editor UI)
|
||||
# For now, we'll just keep a reference to it
|
||||
|
||||
# Start preview
|
||||
func start_preview() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.start_preview()
|
||||
|
||||
# Stop preview
|
||||
func stop_preview() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.stop_preview()
|
||||
|
||||
# Pause preview
|
||||
func pause_preview() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.pause_preview()
|
||||
|
||||
# Resume preview
|
||||
func resume_preview() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.resume_preview()
|
||||
|
||||
# Set up undo/redo system
|
||||
func _setup_undo_redo() -> void:
|
||||
|
||||
@@ -1,274 +0,0 @@
|
||||
@tool
|
||||
class_name PreviewManager
|
||||
extends Node
|
||||
|
||||
# Manager for real-time cutscene preview
|
||||
|
||||
# Signals
|
||||
signal preview_started()
|
||||
signal preview_stopped()
|
||||
signal preview_paused()
|
||||
signal preview_resumed()
|
||||
signal preview_progress(progress: float)
|
||||
signal node_activated(node_name: String)
|
||||
signal node_completed(node_name: String)
|
||||
|
||||
# Properties
|
||||
var is_previewing: bool = false
|
||||
var is_paused: bool = false
|
||||
var current_cutscene: CutsceneManager
|
||||
var preview_scene: Node2D # The scene being previewed
|
||||
var preview_characters: Dictionary = {} # Map of character names to nodes
|
||||
var graph_edit: CutsceneGraphEdit # Reference to the graph editor
|
||||
|
||||
# Preview settings
|
||||
var preview_speed: float = 1.0
|
||||
var show_debug_info: bool = true
|
||||
|
||||
# Initialize the preview manager
|
||||
func _init() -> void:
|
||||
name = "PreviewManager"
|
||||
|
||||
# Set up the preview with a graph editor
|
||||
func setup_preview(graph: CutsceneGraphEdit) -> void:
|
||||
graph_edit = graph
|
||||
|
||||
# Connect to graph change signals
|
||||
if graph_edit:
|
||||
graph_edit.connect("graph_changed", _on_graph_changed)
|
||||
|
||||
# Start the preview
|
||||
func start_preview() -> void:
|
||||
if is_previewing:
|
||||
return
|
||||
|
||||
# Create preview scene
|
||||
_setup_preview_scene()
|
||||
|
||||
# Generate cutscene from current graph
|
||||
var cutscene_resource = graph_edit.save_to_cutscene()
|
||||
var generator = CutsceneGenerator.new()
|
||||
current_cutscene = generator.generate_cutscene(cutscene_resource)
|
||||
|
||||
# Add cutscene to preview scene
|
||||
if preview_scene and current_cutscene:
|
||||
preview_scene.add_child(current_cutscene)
|
||||
|
||||
# Connect to cutscene signals for feedback
|
||||
_connect_cutscene_signals()
|
||||
|
||||
# Start the cutscene
|
||||
current_cutscene.start()
|
||||
|
||||
# Update state
|
||||
is_previewing = true
|
||||
is_paused = false
|
||||
emit_signal("preview_started")
|
||||
|
||||
# Stop the preview
|
||||
func stop_preview() -> void:
|
||||
if not is_previewing:
|
||||
return
|
||||
|
||||
# Stop the cutscene
|
||||
if current_cutscene:
|
||||
current_cutscene.stop()
|
||||
_disconnect_cutscene_signals()
|
||||
|
||||
# Remove from preview scene
|
||||
if current_cutscene.get_parent() == preview_scene:
|
||||
preview_scene.remove_child(current_cutscene)
|
||||
current_cutscene.queue_free()
|
||||
|
||||
# Clean up preview scene
|
||||
_cleanup_preview_scene()
|
||||
|
||||
# Update state
|
||||
is_previewing = false
|
||||
is_paused = false
|
||||
emit_signal("preview_stopped")
|
||||
|
||||
# Pause the preview
|
||||
func pause_preview() -> void:
|
||||
if not is_previewing or is_paused:
|
||||
return
|
||||
|
||||
if current_cutscene:
|
||||
current_cutscene.pause()
|
||||
is_paused = true
|
||||
emit_signal("preview_paused")
|
||||
|
||||
# Resume the preview
|
||||
func resume_preview() -> void:
|
||||
if not is_previewing or not is_paused:
|
||||
return
|
||||
|
||||
if current_cutscene:
|
||||
current_cutscene.resume()
|
||||
is_paused = false
|
||||
emit_signal("preview_resumed")
|
||||
|
||||
# Set preview speed
|
||||
func set_preview_speed(speed: float) -> void:
|
||||
preview_speed = speed
|
||||
# In a real implementation, this would affect the time scale
|
||||
# of the preview scene
|
||||
|
||||
# Set up the preview scene
|
||||
func _setup_preview_scene() -> void:
|
||||
# Create or reuse preview scene
|
||||
if not preview_scene:
|
||||
preview_scene = Node2D.new()
|
||||
preview_scene.name = "PreviewScene"
|
||||
add_child(preview_scene)
|
||||
|
||||
# Set up characters for preview
|
||||
_setup_preview_characters()
|
||||
|
||||
# Set up characters for preview
|
||||
func _setup_preview_characters() -> void:
|
||||
# Clear existing characters
|
||||
preview_characters.clear()
|
||||
|
||||
# Create placeholder characters for preview
|
||||
# In a real implementation, this would load actual character scenes
|
||||
var character1 = _create_preview_character("Character1", Vector2(100, 100))
|
||||
var character2 = _create_preview_character("Character2", Vector2(200, 100))
|
||||
|
||||
preview_characters["Character1"] = character1
|
||||
preview_characters["Character2"] = character2
|
||||
|
||||
# Add to preview scene
|
||||
if preview_scene:
|
||||
preview_scene.add_child(character1)
|
||||
preview_scene.add_child(character2)
|
||||
|
||||
# Create a preview character
|
||||
func _create_preview_character(name: String, position: Vector2) -> Node2D:
|
||||
var character = Node2D.new()
|
||||
character.name = name
|
||||
character.position = position
|
||||
|
||||
# Add a visual representation
|
||||
var sprite = Polygon2D.new()
|
||||
sprite.polygon = PackedVector2Array([
|
||||
Vector2(-10, -20),
|
||||
Vector2(-30, 0),
|
||||
Vector2(-10, 20),
|
||||
Vector2(10, 20),
|
||||
Vector2(30, 0),
|
||||
Vector2(10, -20)
|
||||
])
|
||||
sprite.color = Color(0.5, 0.7, 1.0)
|
||||
character.add_child(sprite)
|
||||
|
||||
return character
|
||||
|
||||
# Clean up the preview scene
|
||||
func _cleanup_preview_scene() -> void:
|
||||
# Remove characters
|
||||
for char_name in preview_characters:
|
||||
var character = preview_characters[char_name]
|
||||
if character.get_parent() == preview_scene:
|
||||
preview_scene.remove_child(character)
|
||||
character.queue_free()
|
||||
|
||||
preview_characters.clear()
|
||||
|
||||
# Connect to cutscene signals for feedback
|
||||
func _connect_cutscene_signals() -> void:
|
||||
if not current_cutscene:
|
||||
return
|
||||
|
||||
# Disconnect existing connections
|
||||
_disconnect_cutscene_signals()
|
||||
|
||||
# Connect to signals
|
||||
current_cutscene.connect("cutscene_started", _on_cutscene_started)
|
||||
current_cutscene.connect("cutscene_completed", _on_cutscene_completed)
|
||||
current_cutscene.connect("cutscene_paused", _on_cutscene_paused)
|
||||
current_cutscene.connect("cutscene_resumed", _on_cutscene_resumed)
|
||||
current_cutscene.connect("action_started", _on_action_started)
|
||||
current_cutscene.connect("action_completed", _on_action_completed)
|
||||
|
||||
# Disconnect from cutscene signals
|
||||
func _disconnect_cutscene_signals() -> void:
|
||||
if not current_cutscene:
|
||||
return
|
||||
|
||||
if current_cutscene.is_connected("cutscene_started", _on_cutscene_started):
|
||||
current_cutscene.disconnect("cutscene_started", _on_cutscene_started)
|
||||
if current_cutscene.is_connected("cutscene_completed", _on_cutscene_completed):
|
||||
current_cutscene.disconnect("cutscene_completed", _on_cutscene_completed)
|
||||
if current_cutscene.is_connected("cutscene_paused", _on_cutscene_paused):
|
||||
current_cutscene.disconnect("cutscene_paused", _on_cutscene_paused)
|
||||
if current_cutscene.is_connected("cutscene_resumed", _on_cutscene_resumed):
|
||||
current_cutscene.disconnect("cutscene_resumed", _on_cutscene_resumed)
|
||||
if current_cutscene.is_connected("action_started", _on_action_started):
|
||||
current_cutscene.disconnect("action_started", _on_action_started)
|
||||
if current_cutscene.is_connected("action_completed", _on_action_completed):
|
||||
current_cutscene.disconnect("action_completed", _on_action_completed)
|
||||
|
||||
# Handle graph changes
|
||||
func _on_graph_changed() -> void:
|
||||
# If we're previewing, restart the preview to reflect changes
|
||||
if is_previewing:
|
||||
stop_preview()
|
||||
start_preview()
|
||||
|
||||
# Handle cutscene started
|
||||
func _on_cutscene_started() -> void:
|
||||
emit_signal("preview_started")
|
||||
|
||||
# Handle cutscene completed
|
||||
func _on_cutscene_completed() -> void:
|
||||
emit_signal("preview_stopped")
|
||||
is_previewing = false
|
||||
is_paused = false
|
||||
|
||||
# Handle cutscene paused
|
||||
func _on_cutscene_paused() -> void:
|
||||
emit_signal("preview_paused")
|
||||
is_paused = true
|
||||
|
||||
# Handle cutscene resumed
|
||||
func _on_cutscene_resumed() -> void:
|
||||
emit_signal("preview_resumed")
|
||||
is_paused = false
|
||||
|
||||
# Handle action started
|
||||
func _on_action_started(action: Action) -> void:
|
||||
# Find the corresponding node in the graph and highlight it
|
||||
var node_name = _find_node_for_action(action)
|
||||
if node_name:
|
||||
emit_signal("node_activated", node_name)
|
||||
|
||||
# Update graph editor visualization
|
||||
if graph_edit:
|
||||
var node = graph_edit.get_node_or_null(node_name)
|
||||
if node and node.has_method("set_state"):
|
||||
node.set_state(BaseGraphNode.NodeState.ACTIVE)
|
||||
|
||||
# Handle action completed
|
||||
func _on_action_completed(action: Action) -> void:
|
||||
# Find the corresponding node in the graph and mark as completed
|
||||
var node_name = _find_node_for_action(action)
|
||||
if node_name:
|
||||
emit_signal("node_completed", node_name)
|
||||
|
||||
# Update graph editor visualization
|
||||
if graph_edit:
|
||||
var node = graph_edit.get_node_or_null(node_name)
|
||||
if node and node.has_method("set_state"):
|
||||
node.set_state(BaseGraphNode.NodeState.COMPLETED)
|
||||
|
||||
# Find node corresponding to an action
|
||||
func _find_node_for_action(action: Action) -> String:
|
||||
# This would need to map actions to nodes
|
||||
# In a real implementation, we would store this mapping when generating the cutscene
|
||||
# For now, we'll return a placeholder
|
||||
return ""
|
||||
|
||||
# Get the preview scene for display
|
||||
func get_preview_scene() -> Node2D:
|
||||
return preview_scene
|
||||
@@ -1,186 +0,0 @@
|
||||
@tool
|
||||
class_name PreviewPanel
|
||||
extends PanelContainer
|
||||
|
||||
# UI panel for displaying the preview
|
||||
|
||||
# UI elements
|
||||
var preview_viewport: SubViewport
|
||||
var preview_texture: TextureRect
|
||||
var controls_container: HBoxContainer
|
||||
var play_button: Button
|
||||
var pause_button: Button
|
||||
var stop_button: Button
|
||||
var speed_slider: HSlider
|
||||
var progress_bar: ProgressBar
|
||||
var debug_label: Label
|
||||
|
||||
# Properties
|
||||
var preview_manager: PreviewManager
|
||||
var is_playing: bool = false
|
||||
|
||||
# Initialize the preview panel
|
||||
func _ready() -> void:
|
||||
_setup_ui()
|
||||
_setup_signals()
|
||||
|
||||
# Set up the UI
|
||||
func _setup_ui() -> void:
|
||||
# Main container
|
||||
var main_vbox = VBoxContainer.new()
|
||||
main_vbox.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
main_vbox.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
add_child(main_vbox)
|
||||
|
||||
# Preview viewport
|
||||
var viewport_container = AspectRatioContainer.new()
|
||||
viewport_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
viewport_container.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
viewport_container.ratio = 16.0/9.0
|
||||
main_vbox.add_child(viewport_container)
|
||||
|
||||
preview_viewport = SubViewport.new()
|
||||
preview_viewport.size = Vector2i(800, 450)
|
||||
preview_viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
|
||||
viewport_container.add_child(preview_viewport)
|
||||
|
||||
preview_texture = TextureRect.new()
|
||||
preview_texture.expand = true
|
||||
preview_texture.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
preview_texture.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
preview_texture.texture = preview_viewport.get_texture()
|
||||
viewport_container.add_child(preview_texture)
|
||||
|
||||
# Controls
|
||||
controls_container = HBoxContainer.new()
|
||||
controls_container.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
main_vbox.add_child(controls_container)
|
||||
|
||||
play_button = Button.new()
|
||||
play_button.text = "▶"
|
||||
play_button.flat = true
|
||||
controls_container.add_child(play_button)
|
||||
|
||||
pause_button = Button.new()
|
||||
pause_button.text = "⏸"
|
||||
pause_button.flat = true
|
||||
controls_container.add_child(pause_button)
|
||||
|
||||
stop_button = Button.new()
|
||||
stop_button.text = "⏹"
|
||||
stop_button.flat = true
|
||||
controls_container.add_child(stop_button)
|
||||
|
||||
var speed_label = Label.new()
|
||||
speed_label.text = "Speed:"
|
||||
controls_container.add_child(speed_label)
|
||||
|
||||
speed_slider = HSlider.new()
|
||||
speed_slider.min = 0.1
|
||||
speed_slider.max = 2.0
|
||||
speed_slider.step = 0.1
|
||||
speed_slider.value = 1.0
|
||||
speed_slider.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
controls_container.add_child(speed_slider)
|
||||
|
||||
# Progress bar
|
||||
progress_bar = ProgressBar.new()
|
||||
progress_bar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
progress_bar.percent_visible = true
|
||||
main_vbox.add_child(progress_bar)
|
||||
|
||||
# Debug info
|
||||
debug_label = Label.new()
|
||||
debug_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
main_vbox.add_child(debug_label)
|
||||
|
||||
# Set up signal connections
|
||||
func _setup_signals() -> void:
|
||||
play_button.connect("pressed", _on_play_pressed)
|
||||
pause_button.connect("pressed", _on_pause_pressed)
|
||||
stop_button.connect("pressed", _on_stop_pressed)
|
||||
speed_slider.connect("value_changed", _on_speed_changed)
|
||||
|
||||
# Set the preview manager
|
||||
func set_preview_manager(manager: PreviewManager) -> void:
|
||||
preview_manager = manager
|
||||
|
||||
# Connect to preview manager signals
|
||||
if preview_manager:
|
||||
preview_manager.connect("preview_started", _on_preview_started)
|
||||
preview_manager.connect("preview_stopped", _on_preview_stopped)
|
||||
preview_manager.connect("preview_paused", _on_preview_paused)
|
||||
preview_manager.connect("preview_resumed", _on_preview_resumed)
|
||||
preview_manager.connect("preview_progress", _on_preview_progress)
|
||||
preview_manager.connect("node_activated", _on_node_activated)
|
||||
preview_manager.connect("node_completed", _on_node_completed)
|
||||
|
||||
# Set the graph editor
|
||||
func set_graph_edit(graph_edit: CutsceneGraphEdit) -> void:
|
||||
if preview_manager:
|
||||
preview_manager.setup_preview(graph_edit)
|
||||
|
||||
# Add preview scene to viewport
|
||||
var preview_scene = preview_manager.get_preview_scene()
|
||||
if preview_scene and preview_scene.get_parent() != preview_viewport:
|
||||
preview_viewport.add_child(preview_scene)
|
||||
|
||||
# Handle play button press
|
||||
func _on_play_pressed() -> void:
|
||||
if preview_manager:
|
||||
if is_playing:
|
||||
preview_manager.resume_preview()
|
||||
else:
|
||||
preview_manager.start_preview()
|
||||
|
||||
# Handle pause button press
|
||||
func _on_pause_pressed() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.pause_preview()
|
||||
|
||||
# Handle stop button press
|
||||
func _on_stop_pressed() -> void:
|
||||
if preview_manager:
|
||||
preview_manager.stop_preview()
|
||||
|
||||
# Handle speed slider change
|
||||
func _on_speed_changed(value: float) -> void:
|
||||
if preview_manager:
|
||||
preview_manager.set_preview_speed(value)
|
||||
|
||||
# Handle preview started
|
||||
func _on_preview_started() -> void:
|
||||
is_playing = true
|
||||
play_button.text = "⏸"
|
||||
debug_label.text = "Preview started"
|
||||
|
||||
# Handle preview stopped
|
||||
func _on_preview_stopped() -> void:
|
||||
is_playing = false
|
||||
play_button.text = "▶"
|
||||
progress_bar.value = 0
|
||||
debug_label.text = "Preview stopped"
|
||||
|
||||
# Handle preview paused
|
||||
func _on_preview_paused() -> void:
|
||||
is_playing = false
|
||||
play_button.text = "▶"
|
||||
debug_label.text = "Preview paused"
|
||||
|
||||
# Handle preview resumed
|
||||
func _on_preview_resumed() -> void:
|
||||
is_playing = true
|
||||
play_button.text = "⏸"
|
||||
debug_label.text = "Preview resumed"
|
||||
|
||||
# Handle preview progress
|
||||
func _on_preview_progress(progress: float) -> void:
|
||||
progress_bar.value = progress * 100
|
||||
|
||||
# Handle node activated
|
||||
func _on_node_activated(node_name: String) -> void:
|
||||
debug_label.text = "Executing: %s" % node_name
|
||||
|
||||
# Handle node completed
|
||||
func _on_node_completed(node_name: String) -> void:
|
||||
debug_label.text = "Completed: %s" % node_name
|
||||
0
addons/cutscene_editor/editor/UndoRedoManager.gd
Normal file → Executable file
2
addons/cutscene_editor/editor/nodes/AnimationActionNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "animation"
|
||||
node_id = "animation_" + str(randi())
|
||||
name = "animation_" + str(randi())
|
||||
title = "Animation"
|
||||
modulate = Color(0.8, 0.4, 0.8) # Purple
|
||||
|
||||
|
||||
0
addons/cutscene_editor/editor/nodes/AnimationActionNode.tscn
Normal file → Executable file
2
addons/cutscene_editor/editor/nodes/BaseGraphNode.gd
Normal file → Executable file
@@ -20,7 +20,7 @@ enum NodeState {
|
||||
|
||||
# Properties
|
||||
var node_type: String = "base"
|
||||
var node_id: String # Unique identifier for the node
|
||||
|
||||
var action_parameters: Dictionary = {} # Stores parameter values
|
||||
var current_state: int = NodeState.IDLE
|
||||
var error_message: String = ""
|
||||
|
||||
2
addons/cutscene_editor/editor/nodes/DialogueActionNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "dialogue"
|
||||
node_id = "dialogue_" + str(randi())
|
||||
name = "dialogue_" + str(randi())
|
||||
title = "Dialogue"
|
||||
modulate = Color(1.0, 1.0, 0.5) # Yellow
|
||||
resizable=true
|
||||
|
||||
0
addons/cutscene_editor/editor/nodes/DialogueActionNode.tscn
Normal file → Executable file
2
addons/cutscene_editor/editor/nodes/EntryNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "entry"
|
||||
node_id = "entry_" + str(randi())
|
||||
name = "entry_" + str(randi())
|
||||
title = "Start"
|
||||
modulate = Color(0.5, 1.0, 0.5) # Light green
|
||||
|
||||
|
||||
14
addons/cutscene_editor/editor/nodes/EntryNode.tscn
Normal file → Executable file
@@ -1,15 +1,23 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://entrynodetscn"]
|
||||
[gd_scene load_steps=2 format=3 uid="uid://sfwelq3tmwkv"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cutscene_editor/editor/nodes/EntryNode.gd" id="1_entry"]
|
||||
|
||||
[node name="EntryNode" type="GraphNode"]
|
||||
modulate = Color(0.5, 1.0, 0.5, 1)
|
||||
modulate = Color(0.5, 1, 0.5, 1)
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
title = "Start"
|
||||
slot/0/left_enabled = false
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color(0, 0, 0, 0)
|
||||
slot/0/left_icon = null
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color(0, 0, 0, 1)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
script = ExtResource("1_entry")
|
||||
script = ExtResource("1_entry")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
text = "completed
|
||||
"
|
||||
|
||||
2
addons/cutscene_editor/editor/nodes/ExitNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "exit"
|
||||
node_id = "exit_" + str(randi())
|
||||
name = "exit_" + str(randi())
|
||||
title = "End"
|
||||
modulate = Color(1.0, 0.5, 0.5) # Light red
|
||||
|
||||
|
||||
12
addons/cutscene_editor/editor/nodes/ExitNode.tscn
Normal file → Executable file
@@ -1,14 +1,22 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://exitnodetscn"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/cutscene_editor/editor/nodes/ExitNode.gd" id="1_exit"]
|
||||
|
||||
[node name="ExitNode" type="GraphNode"]
|
||||
modulate = Color(1.0, 0.5, 0.5, 1)
|
||||
modulate = Color(1, 0.5, 0.5, 1)
|
||||
custom_minimum_size = Vector2(100, 0)
|
||||
title = "End"
|
||||
slot/0/left_enabled = true
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color(0, 0, 0, 1)
|
||||
slot/0/left_icon = null
|
||||
slot/0/right_enabled = false
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color(0, 0, 0, 0)
|
||||
slot/0/right_icon = null
|
||||
slot/0/draw_stylebox = true
|
||||
script = ExtResource("1_exit")
|
||||
script = ExtResource("1_exit")
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
layout_mode = 2
|
||||
text = "Dependency"
|
||||
|
||||
12
addons/cutscene_editor/editor/nodes/MoveActionNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "move"
|
||||
node_id = "move_" + str(randi())
|
||||
name = "move_" + str(randi())
|
||||
title = "Move"
|
||||
modulate = Color(0.4, 0.6, 1.0) # Blue
|
||||
|
||||
@@ -22,6 +22,16 @@ func _ready() -> void:
|
||||
action_parameters["target_y"] = 0.0
|
||||
action_parameters["speed"] = 100.0
|
||||
|
||||
func set_parameter(pname, value) -> void:
|
||||
super.set_parameter(name, value)
|
||||
if pname == "character":
|
||||
$VBoxContainer/CharacterEDit.text = value
|
||||
elif pname == "target_x":
|
||||
$VBoxContainer/HBoxContainer/x.text = value
|
||||
elif pname == "target_y":
|
||||
$VBoxContainer/HBoxContainer/y.text = value
|
||||
elif pname == "speed":
|
||||
$VBoxContainer/speed.text = value
|
||||
func _on_character_changed(new_text: String) -> void:
|
||||
set_parameter("character", new_text)
|
||||
|
||||
|
||||
4
addons/cutscene_editor/editor/nodes/MoveActionNode.tscn
Normal file → Executable file
@@ -23,7 +23,7 @@ layout_mode = 2
|
||||
[node name="Character" type="Label" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[node name="TextEdit" type="LineEdit" parent="VBoxContainer"]
|
||||
[node name="CharacterEDit" type="LineEdit" parent="VBoxContainer"]
|
||||
custom_minimum_size = Vector2(0, 32.865)
|
||||
layout_mode = 2
|
||||
text = "aoeu"
|
||||
@@ -49,7 +49,7 @@ text = "Speed"
|
||||
[node name="speed" type="LineEdit" parent="VBoxContainer"]
|
||||
layout_mode = 2
|
||||
|
||||
[connection signal="text_changed" from="VBoxContainer/TextEdit" to="." method="_on_character_changed"]
|
||||
[connection signal="text_changed" from="VBoxContainer/CharacterEDit" to="." method="_on_character_changed"]
|
||||
[connection signal="text_changed" from="VBoxContainer/HBoxContainer/x" to="." method="_on_target_x_changed"]
|
||||
[connection signal="text_changed" from="VBoxContainer/HBoxContainer/y" to="." method="_on_target_y_changed"]
|
||||
[connection signal="text_change_rejected" from="VBoxContainer/speed" to="." method="_on_speed_text_change_rejected"]
|
||||
|
||||
2
addons/cutscene_editor/editor/nodes/ParallelGroupNode.gd
Normal file → Executable file
@@ -14,7 +14,7 @@ var container_rect: PanelContainer # Visual container for child nodes
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "parallel"
|
||||
node_id = "parallel_" + str(randi())
|
||||
name = "parallel_" + str(randi())
|
||||
title = "Parallel Group"
|
||||
modulate = Color(1.0, 0.6, 0.2) # Orange
|
||||
|
||||
|
||||
2
addons/cutscene_editor/editor/nodes/TurnActionNode.gd
Normal file → Executable file
@@ -6,7 +6,7 @@ extends "res://addons/cutscene_editor/editor/nodes/BaseGraphNode.gd"
|
||||
|
||||
func _init() -> void:
|
||||
node_type = "turn"
|
||||
node_id = "turn_" + str(randi())
|
||||
name = "turn_" + str(randi())
|
||||
title = "Turn"
|
||||
modulate = Color(0.5, 1.0, 0.5) # Green
|
||||
|
||||
|
||||
0
addons/cutscene_editor/editor/nodes/TurnActionNode.tscn
Normal file → Executable file
0
addons/cutscene_editor/editor/nodes/WaitActionNode.gd
Normal file → Executable file
0
addons/cutscene_editor/editor/nodes/WaitActionNode.tscn
Normal file → Executable file
0
addons/cutscene_editor/editor/resources/CutsceneResource.gd
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_animation.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 357 B |
0
addons/cutscene_editor/icons/icon_animation.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_dialogue.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
0
addons/cutscene_editor/icons/icon_dialogue.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_entry.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 222 B After Width: | Height: | Size: 222 B |
0
addons/cutscene_editor/icons/icon_entry.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_exit.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 244 B |
0
addons/cutscene_editor/icons/icon_exit.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_move.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
0
addons/cutscene_editor/icons/icon_move.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_parallel.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 428 B After Width: | Height: | Size: 428 B |
0
addons/cutscene_editor/icons/icon_parallel.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_turn.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 335 B After Width: | Height: | Size: 335 B |
0
addons/cutscene_editor/icons/icon_turn.svg.import
Normal file → Executable file
0
addons/cutscene_editor/icons/icon_wait.svg
Normal file → Executable file
|
Before Width: | Height: | Size: 407 B After Width: | Height: | Size: 407 B |