init
This commit is contained in:
commit
b99855351d
434 changed files with 50357 additions and 0 deletions
366
addons/inkgd/editor/panel/preview/ink_preview_panel.gd
Normal file
366
addons/inkgd/editor/panel/preview/ink_preview_panel.gd
Normal file
|
@ -0,0 +1,366 @@
|
|||
@tool
|
||||
# ############################################################################ #
|
||||
# Copyright © 2018-2022 Paul Joannon
|
||||
# Copyright © 2019-2022 Frédéric Maquin <fred@ephread.com>
|
||||
# Licensed under the MIT License.
|
||||
# See LICENSE in the project root for license information.
|
||||
# ############################################################################ #
|
||||
|
||||
extends Control
|
||||
|
||||
# Hiding this type to prevent registration of "private" nodes.
|
||||
# See https://github.com/godotengine/godot-proposals/issues/1047
|
||||
# class_name InkPreviewPanel
|
||||
|
||||
# ############################################################################ #
|
||||
# Imports
|
||||
# ############################################################################ #
|
||||
|
||||
var InkPlayerFactory := preload("res://addons/inkgd/ink_player_factory.gd") as GDScript
|
||||
|
||||
# ############################################################################ #
|
||||
# Enums
|
||||
# ############################################################################ #
|
||||
|
||||
enum StoryOrigin {
|
||||
CONFIGURATION,
|
||||
FILE
|
||||
}
|
||||
|
||||
# ############################################################################ #
|
||||
# Constants
|
||||
# ############################################################################ #
|
||||
|
||||
const NAME = "name"
|
||||
const STORY_ORIGIN = "story_origin"
|
||||
const FILE_PATH = "file_path"
|
||||
|
||||
# ############################################################################ #
|
||||
# Public Properties
|
||||
# ############################################################################ #
|
||||
|
||||
var editor_interface: InkEditorInterface
|
||||
var configuration: InkConfiguration
|
||||
var progress_texture: AnimatedTexture
|
||||
|
||||
# ############################################################################ #
|
||||
# Private Properties
|
||||
# ############################################################################ #
|
||||
|
||||
var _scrollbar_max_value = -1
|
||||
var _current_story_index = -1
|
||||
|
||||
var _custom_stories: Array = []
|
||||
var _available_stories: Array = []
|
||||
|
||||
var _file_dialog = EditorFileDialog.new()
|
||||
|
||||
var _ink_player = InkPlayerFactory.create()
|
||||
|
||||
# ############################################################################ #
|
||||
# On Ready | Private Properties
|
||||
# ############################################################################ #
|
||||
|
||||
@onready var _play_icon = get_theme_icon("Play", "EditorIcons")
|
||||
|
||||
# ############################################################################ #
|
||||
# On Ready | Private Nodes
|
||||
# ############################################################################
|
||||
|
||||
@onready var _command_strip = find_child("CommandStripHBoxContainer")
|
||||
|
||||
@onready var _pick_story_button = _command_strip.get_node("PickStoryOptionButton")
|
||||
@onready var _load_story_button = _command_strip.get_node("LoadStoryButton")
|
||||
@onready var _start_button = _command_strip.get_node("StartButton")
|
||||
@onready var _stop_button = _command_strip.get_node("StopButton")
|
||||
@onready var _clear_button = _command_strip.get_node("ClearButton")
|
||||
|
||||
@onready var _scroll_container = find_child("ScrollContainer")
|
||||
@onready var _story_container = _scroll_container.get_node("MarginContainer/StoryVBoxContainer")
|
||||
|
||||
@onready var _choice_area_container = find_child("ChoicesAreaVBoxContainer")
|
||||
@onready var _choices_container = _choice_area_container.get_node("ChoicesVBoxContainer")
|
||||
|
||||
# ############################################################################ #
|
||||
# Overrides
|
||||
# ############################################################################ #
|
||||
|
||||
func _ready():
|
||||
# FIXME: This needs investigating.
|
||||
# Sanity check. It seems the editor instantiates tools script on their
|
||||
# own, probably to add them to its tree. In that case, they won't have
|
||||
# their dependencies injected, so we're not doing anything.
|
||||
if editor_interface == null || configuration == null || progress_texture == null:
|
||||
print("[inkgd] [INFO] Ink Preview Tab: dependencies not met, ignoring.")
|
||||
return
|
||||
|
||||
add_child(_ink_player)
|
||||
|
||||
_connect_signals()
|
||||
_apply_configuration()
|
||||
_update_story_picker()
|
||||
|
||||
var load_icon = get_theme_icon("Load", "EditorIcons")
|
||||
var stop_icon = get_theme_icon("Stop", "EditorIcons")
|
||||
var clear_icon = get_theme_icon("Clear", "EditorIcons")
|
||||
|
||||
_start_button.icon = _play_icon
|
||||
_load_story_button.icon = load_icon
|
||||
_stop_button.icon = stop_icon
|
||||
_clear_button.icon = clear_icon
|
||||
|
||||
_stop_button.visible = false
|
||||
|
||||
_choice_area_container.custom_minimum_size = Vector2(200, 0) * editor_interface.scale
|
||||
_choice_area_container.visible = false
|
||||
|
||||
_file_dialog.connect("file_selected", Callable(self, "_on_file_selected"))
|
||||
add_child(_file_dialog)
|
||||
|
||||
# ############################################################################ #
|
||||
# Signal Receivers
|
||||
# ############################################################################ #
|
||||
|
||||
func _start_button_pressed():
|
||||
var file_path = _get_current_story_file_path()
|
||||
if file_path == null:
|
||||
return
|
||||
|
||||
print("[inkgd] [INFO] Previewing %s" % file_path)
|
||||
_clear_content()
|
||||
|
||||
_ink_player.destroy()
|
||||
_ink_player.ink_file = load(file_path)
|
||||
|
||||
_start_button.icon = progress_texture
|
||||
_disable_command_strip(true)
|
||||
|
||||
_ink_player.create_story()
|
||||
|
||||
|
||||
func _stop_button_pressed():
|
||||
_start_button.visible = true
|
||||
_stop_button.visible = false
|
||||
_choice_area_container.visible = false
|
||||
|
||||
_ink_player.destroy()
|
||||
|
||||
_clear_choices()
|
||||
_clear_content()
|
||||
|
||||
|
||||
func _story_loaded(successfully: bool):
|
||||
_disable_command_strip(false)
|
||||
_start_button.icon = _play_icon
|
||||
|
||||
if !successfully:
|
||||
return
|
||||
|
||||
_start_button.visible = false
|
||||
_stop_button.visible = true
|
||||
|
||||
_ink_player.allow_external_function_fallbacks = true
|
||||
_continue_story()
|
||||
|
||||
func _pick_story_button_selected(index):
|
||||
if _current_story_index != index:
|
||||
_stop_button_pressed()
|
||||
|
||||
_current_story_index = index
|
||||
|
||||
|
||||
func _load_story_button_pressed():
|
||||
_file_dialog.file_mode = FileDialog.FILE_MODE_OPEN_FILE
|
||||
_file_dialog.access = FileDialog.ACCESS_RESOURCES
|
||||
_file_dialog.add_filter("*.json;Compiled Ink story")
|
||||
_file_dialog.popup_centered(Vector2(1280, 800) * editor_interface.scale)
|
||||
|
||||
|
||||
func _choice_button_pressed(index):
|
||||
_clear_choices()
|
||||
|
||||
_ink_player.choose_choice_index(index)
|
||||
_continue_story()
|
||||
|
||||
|
||||
func _on_file_selected(path: String):
|
||||
if _custom_stories.has(path):
|
||||
return
|
||||
|
||||
for story_configuration in self.configuration.stories:
|
||||
var target_file_path = self.configuration.get_target_file_path(story_configuration)
|
||||
if target_file_path == path:
|
||||
return
|
||||
|
||||
_custom_stories.append(path)
|
||||
_apply_configuration()
|
||||
_update_story_picker(path)
|
||||
|
||||
|
||||
func _scrollbar_changed():
|
||||
var max_value = _scroll_container.get_v_scroll_bar().max_value
|
||||
|
||||
if _scrollbar_max_value == max_value && _scrollbar_max_value != -1:
|
||||
return
|
||||
|
||||
_scrollbar_max_value = max_value
|
||||
_scroll_container.scroll_vertical = max_value
|
||||
|
||||
|
||||
func _configuration_changed():
|
||||
# Cleaning everything on configuration change may end up being frustrating.
|
||||
# But for now, it's going to make everybody's life easier.
|
||||
_stop_button_pressed()
|
||||
_apply_configuration()
|
||||
_update_story_picker()
|
||||
|
||||
|
||||
# ############################################################################ #
|
||||
# Private Methods
|
||||
# ############################################################################ #
|
||||
|
||||
func _apply_configuration():
|
||||
_available_stories.clear()
|
||||
|
||||
_current_story_index = -1
|
||||
_pick_story_button.selected = _current_story_index
|
||||
|
||||
var i = 0
|
||||
for story_configuration in self.configuration.stories:
|
||||
var target_file_path = self.configuration.get_target_file_path(story_configuration)
|
||||
if target_file_path != null && !target_file_path.is_empty():
|
||||
_available_stories.append({
|
||||
NAME: "Story %d - %s" % [i + 1, target_file_path.get_file()],
|
||||
FILE_PATH: target_file_path,
|
||||
STORY_ORIGIN: StoryOrigin.CONFIGURATION
|
||||
})
|
||||
i += 1
|
||||
|
||||
var j = 0
|
||||
for custom_story_path in _custom_stories:
|
||||
if custom_story_path != null && !custom_story_path.is_empty():
|
||||
_available_stories.append({
|
||||
NAME: custom_story_path.get_file(),
|
||||
FILE_PATH: ProjectSettings.localize_path(custom_story_path),
|
||||
STORY_ORIGIN: StoryOrigin.FILE
|
||||
})
|
||||
j += 1
|
||||
|
||||
|
||||
func _update_story_picker(selected_path = null):
|
||||
_pick_story_button.clear()
|
||||
|
||||
var i = 0
|
||||
for story in _available_stories:
|
||||
_pick_story_button.add_item(story[NAME], i)
|
||||
if selected_path != null && story[FILE_PATH] == selected_path:
|
||||
_current_story_index = i
|
||||
_pick_story_button.selected = _current_story_index
|
||||
i += 1
|
||||
|
||||
if _available_stories.size() > 0:
|
||||
if _current_story_index == -1:
|
||||
_current_story_index = 0
|
||||
_pick_story_button.selected = _current_story_index
|
||||
|
||||
_pick_story_button.visible = true
|
||||
else:
|
||||
_current_story_index = -1
|
||||
_pick_story_button.selected = _current_story_index
|
||||
|
||||
_pick_story_button.visible = false
|
||||
|
||||
|
||||
func _continue_story():
|
||||
while _ink_player.can_continue:
|
||||
var text = _ink_player.continue_story()
|
||||
|
||||
if text.right(text.length() - 1) == "\n":
|
||||
text.erase(text.length() - 1, 1)
|
||||
|
||||
var text_label = Label.new()
|
||||
text_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
text_label.text = text
|
||||
|
||||
_story_container.add_child(text_label)
|
||||
|
||||
var tags = _ink_player.current_tags
|
||||
if !tags.is_empty():
|
||||
var tag_label = Label.new()
|
||||
tag_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
tag_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
tag_label.text = "# " + ", ".join(PackedStringArray(tags))
|
||||
tag_label.add_theme_color_override("font_color", Color(1, 1, 1, 0.4))
|
||||
|
||||
_story_container.add_child(tag_label)
|
||||
|
||||
var separator = HSeparator.new()
|
||||
_story_container.add_child(separator)
|
||||
|
||||
if _ink_player.current_choices.size() > 0:
|
||||
var i = 0
|
||||
for choice in _ink_player.current_choices:
|
||||
var button = Button.new()
|
||||
button.text = choice.text
|
||||
button.connect("pressed", Callable(self, "_choice_button_pressed").bind(i))
|
||||
|
||||
_choices_container.add_child(button)
|
||||
i += 1
|
||||
|
||||
_choice_area_container.visible = true
|
||||
else:
|
||||
var label = Label.new()
|
||||
label.text = "End of the story."
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
|
||||
|
||||
_story_container.add_child(label)
|
||||
|
||||
_choice_area_container.visible = false
|
||||
|
||||
|
||||
func _get_current_story_file_path():
|
||||
if _current_story_index >= 0 && _current_story_index < _available_stories.size():
|
||||
return _available_stories[_current_story_index][FILE_PATH]
|
||||
else:
|
||||
return null
|
||||
|
||||
|
||||
func _clear_content():
|
||||
for child in _story_container.get_children():
|
||||
_story_container.remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
|
||||
func _clear_choices():
|
||||
for child in _choices_container.get_children():
|
||||
_choices_container.remove_child(child)
|
||||
child.queue_free()
|
||||
|
||||
func _disable_command_strip(disabled: bool):
|
||||
_pick_story_button.disabled = disabled
|
||||
_load_story_button.disabled = disabled
|
||||
_start_button.disabled = disabled
|
||||
_stop_button.disabled = disabled
|
||||
_clear_button.disabled = disabled
|
||||
|
||||
func _connect_signals():
|
||||
if configuration != null:
|
||||
var is_signal_connected := configuration.is_connected(
|
||||
"story_configuration_changed",
|
||||
Callable(self, "_configuration_changed")
|
||||
)
|
||||
|
||||
if !is_signal_connected:
|
||||
configuration.connect(
|
||||
"story_configuration_changed",
|
||||
Callable(self, "_configuration_changed")
|
||||
)
|
||||
|
||||
_ink_player.connect("loaded", Callable(self, "_story_loaded"))
|
||||
_pick_story_button.connect("item_selected", Callable(self, "_pick_story_button_selected"))
|
||||
_load_story_button.connect("pressed", Callable(self, "_load_story_button_pressed"))
|
||||
_start_button.connect("pressed", Callable(self, "_start_button_pressed"))
|
||||
_stop_button.connect("pressed", Callable(self, "_stop_button_pressed"))
|
||||
_clear_button.connect("pressed", Callable(self, "_clear_content"))
|
||||
|
||||
_scroll_container.get_v_scroll_bar().connect("changed", Callable(self, "_scrollbar_changed"))
|
119
addons/inkgd/editor/panel/preview/ink_preview_panel.tscn
Normal file
119
addons/inkgd/editor/panel/preview/ink_preview_panel.tscn
Normal file
|
@ -0,0 +1,119 @@
|
|||
[gd_scene load_steps=4 format=3 uid="uid://0do8xgmkscjn"]
|
||||
|
||||
[ext_resource type="Script" path="res://addons/inkgd/editor/panel/preview/ink_preview_panel.gd" id="2"]
|
||||
|
||||
[sub_resource type="Image" id="Image_nl482"]
|
||||
data = {
|
||||
"data": PackedByteArray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
"format": "LumAlpha8",
|
||||
"height": 16,
|
||||
"mipmaps": false,
|
||||
"width": 16
|
||||
}
|
||||
|
||||
[sub_resource type="ImageTexture" id="2"]
|
||||
image = SubResource("Image_nl482")
|
||||
|
||||
[node name="Preview" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
script = ExtResource("2")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
layout_mode = 0
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="HSplitContainer" type="HSplitContainer" parent="MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="StoryVBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
theme_override_constants/separation = 5
|
||||
|
||||
[node name="CommandStripHBoxContainer" type="HBoxContainer" parent="MarginContainer/HSplitContainer/StoryVBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/separation = 10
|
||||
|
||||
[node name="LoadStoryButton" type="Button" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 8
|
||||
text = "Load new…"
|
||||
icon = SubResource("2")
|
||||
|
||||
[node name="PickStoryOptionButton" type="OptionButton" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 0
|
||||
|
||||
[node name="Control" type="Control" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="StartButton" type="Button" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 8
|
||||
text = "Start"
|
||||
icon = SubResource("2")
|
||||
|
||||
[node name="StopButton" type="Button" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
visible = false
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 10
|
||||
text = "Stop"
|
||||
icon = SubResource("2")
|
||||
|
||||
[node name="ClearButton" type="Button" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/CommandStripHBoxContainer"]
|
||||
layout_mode = 2
|
||||
theme_override_constants/h_separation = 8
|
||||
text = "Clear"
|
||||
icon = SubResource("2")
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/HSplitContainer/StoryVBoxContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="Panel" type="Panel" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/MarginContainer/ScrollContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
theme_override_constants/margin_left = 10
|
||||
theme_override_constants/margin_top = 10
|
||||
theme_override_constants/margin_right = 10
|
||||
theme_override_constants/margin_bottom = 10
|
||||
|
||||
[node name="StoryVBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer/StoryVBoxContainer/MarginContainer/ScrollContainer/MarginContainer"]
|
||||
layout_mode = 2
|
||||
size_flags_horizontal = 3
|
||||
|
||||
[node name="ChoicesAreaVBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer"]
|
||||
custom_minimum_size = Vector2(300, 0)
|
||||
layout_mode = 2
|
||||
theme_override_constants/separation = 5
|
||||
|
||||
[node name="Button" type="Button" parent="MarginContainer/HSplitContainer/ChoicesAreaVBoxContainer"]
|
||||
layout_mode = 2
|
||||
mouse_filter = 2
|
||||
text = "Choices"
|
||||
flat = true
|
||||
|
||||
[node name="ChoicesVBoxContainer" type="VBoxContainer" parent="MarginContainer/HSplitContainer/ChoicesAreaVBoxContainer"]
|
||||
layout_mode = 2
|
Loading…
Add table
Add a link
Reference in a new issue