initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,420 @@
|
||||
/**************************************************************************/
|
||||
/* audio_stream_interactive_editor_plugin.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "audio_stream_interactive_editor_plugin.h"
|
||||
|
||||
#include "../audio_stream_interactive.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "editor/themes/editor_scale.h"
|
||||
#include "scene/gui/check_box.h"
|
||||
#include "scene/gui/option_button.h"
|
||||
#include "scene/gui/spin_box.h"
|
||||
#include "scene/gui/split_container.h"
|
||||
#include "scene/gui/tree.h"
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_THEME_CHANGED) {
|
||||
fade_mode->clear();
|
||||
fade_mode->add_icon_item(get_editor_theme_icon(SNAME("FadeDisabled")), TTR("Disabled"), AudioStreamInteractive::FADE_DISABLED);
|
||||
fade_mode->add_icon_item(get_editor_theme_icon(SNAME("FadeIn")), TTR("Fade-In"), AudioStreamInteractive::FADE_IN);
|
||||
fade_mode->add_icon_item(get_editor_theme_icon(SNAME("FadeOut")), TTR("Fade-Out"), AudioStreamInteractive::FADE_OUT);
|
||||
fade_mode->add_icon_item(get_editor_theme_icon(SNAME("FadeCross")), TTR("Cross-Fade"), AudioStreamInteractive::FADE_CROSS);
|
||||
fade_mode->add_icon_item(get_editor_theme_icon(SNAME("AutoPlay")), TTR("Automatic"), AudioStreamInteractive::FADE_AUTOMATIC);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_bind_methods() {
|
||||
ClassDB::bind_method("_update_transitions", &AudioStreamInteractiveTransitionEditor::_update_transitions);
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_edited() {
|
||||
if (updating) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled = transition_enabled->is_pressed();
|
||||
AudioStreamInteractive::TransitionFromTime from = AudioStreamInteractive::TransitionFromTime(transition_from->get_selected());
|
||||
AudioStreamInteractive::TransitionToTime to = AudioStreamInteractive::TransitionToTime(transition_to->get_selected());
|
||||
AudioStreamInteractive::FadeMode fade = AudioStreamInteractive::FadeMode(fade_mode->get_selected());
|
||||
float beats = fade_beats->get_value();
|
||||
bool use_filler = filler_clip->get_selected() > 0;
|
||||
int filler = use_filler ? filler_clip->get_selected() - 1 : 0;
|
||||
bool hold = hold_previous->is_pressed();
|
||||
|
||||
EditorUndoRedoManager::get_singleton()->create_action(TTR("Edit Transitions"));
|
||||
for (int i = 0; i < selected.size(); i++) {
|
||||
if (!enabled) {
|
||||
if (audio_stream_interactive->has_transition(selected[i].x, selected[i].y)) {
|
||||
EditorUndoRedoManager::get_singleton()->add_do_method(audio_stream_interactive, "erase_transition", selected[i].x, selected[i].y);
|
||||
}
|
||||
} else {
|
||||
EditorUndoRedoManager::get_singleton()->add_do_method(audio_stream_interactive, "add_transition", selected[i].x, selected[i].y, from, to, fade, beats, use_filler, filler, hold);
|
||||
}
|
||||
}
|
||||
EditorUndoRedoManager::get_singleton()->add_undo_property(audio_stream_interactive, "_transitions", audio_stream_interactive->get("_transitions"));
|
||||
EditorUndoRedoManager::get_singleton()->add_do_method(this, "_update_transitions");
|
||||
EditorUndoRedoManager::get_singleton()->add_undo_method(this, "_update_transitions");
|
||||
EditorUndoRedoManager::get_singleton()->commit_action();
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_update_selection() {
|
||||
updating_selection = false;
|
||||
int clip_count = audio_stream_interactive->get_clip_count();
|
||||
selected.clear();
|
||||
Vector2i editing;
|
||||
int editing_order = -1;
|
||||
for (int i = 0; i <= clip_count; i++) {
|
||||
for (int j = 0; j <= clip_count; j++) {
|
||||
if (rows[i]->is_selected(j)) {
|
||||
Vector2i meta = rows[i]->get_metadata(j);
|
||||
if (selection_order.has(meta)) {
|
||||
int order = selection_order[meta];
|
||||
if (order > editing_order) {
|
||||
editing = meta;
|
||||
}
|
||||
}
|
||||
selected.push_back(meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transition_enabled->set_disabled(selected.is_empty());
|
||||
transition_from->set_disabled(selected.is_empty());
|
||||
transition_to->set_disabled(selected.is_empty());
|
||||
fade_mode->set_disabled(selected.is_empty());
|
||||
fade_beats->set_editable(!selected.is_empty());
|
||||
filler_clip->set_disabled(selected.is_empty());
|
||||
hold_previous->set_disabled(selected.is_empty());
|
||||
|
||||
if (selected.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
updating = true;
|
||||
if (!audio_stream_interactive->has_transition(editing.x, editing.y)) {
|
||||
transition_enabled->set_pressed(false);
|
||||
transition_from->select(0);
|
||||
transition_to->select(0);
|
||||
fade_mode->select(AudioStreamInteractive::FADE_AUTOMATIC);
|
||||
fade_beats->set_value(1.0);
|
||||
filler_clip->select(0);
|
||||
hold_previous->set_pressed(false);
|
||||
} else {
|
||||
transition_enabled->set_pressed(true);
|
||||
transition_from->select(audio_stream_interactive->get_transition_from_time(editing.x, editing.y));
|
||||
transition_to->select(audio_stream_interactive->get_transition_to_time(editing.x, editing.y));
|
||||
fade_mode->select(audio_stream_interactive->get_transition_fade_mode(editing.x, editing.y));
|
||||
fade_beats->set_value(audio_stream_interactive->get_transition_fade_beats(editing.x, editing.y));
|
||||
if (audio_stream_interactive->is_transition_using_filler_clip(editing.x, editing.y)) {
|
||||
filler_clip->select(audio_stream_interactive->get_transition_filler_clip(editing.x, editing.y) + 1);
|
||||
} else {
|
||||
filler_clip->select(0);
|
||||
}
|
||||
hold_previous->set_pressed(audio_stream_interactive->is_transition_holding_previous(editing.x, editing.y));
|
||||
}
|
||||
updating = false;
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_cell_selected(TreeItem *p_item, int p_column, bool p_selected) {
|
||||
int to = p_item->get_meta("to");
|
||||
int from = p_column == audio_stream_interactive->get_clip_count() ? AudioStreamInteractive::CLIP_ANY : p_column;
|
||||
if (p_selected) {
|
||||
selection_order[Vector2i(from, to)] = order_counter++;
|
||||
}
|
||||
|
||||
if (!updating_selection) {
|
||||
MessageQueue::get_singleton()->push_callable(callable_mp(this, &AudioStreamInteractiveTransitionEditor::_update_selection));
|
||||
updating_selection = true;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::_update_transitions() {
|
||||
if (!is_visible()) {
|
||||
return;
|
||||
}
|
||||
int clip_count = audio_stream_interactive->get_clip_count();
|
||||
Color font_color = tree->get_theme_color(SceneStringName(font_color), "Tree");
|
||||
Color font_color_default = font_color;
|
||||
font_color_default.a *= 0.5;
|
||||
Ref<Texture> fade_icons[5] = {
|
||||
get_editor_theme_icon(SNAME("FadeDisabled")),
|
||||
get_editor_theme_icon(SNAME("FadeIn")),
|
||||
get_editor_theme_icon(SNAME("FadeOut")),
|
||||
get_editor_theme_icon(SNAME("FadeCross")),
|
||||
get_editor_theme_icon(SNAME("AutoPlay"))
|
||||
};
|
||||
for (int i = 0; i <= clip_count; i++) {
|
||||
for (int j = 0; j <= clip_count; j++) {
|
||||
int from = i == clip_count ? AudioStreamInteractive::CLIP_ANY : i;
|
||||
int to = j == clip_count ? AudioStreamInteractive::CLIP_ANY : j;
|
||||
|
||||
bool exists = audio_stream_interactive->has_transition(from, to);
|
||||
String tooltip;
|
||||
Ref<Texture> icon;
|
||||
if (!exists) {
|
||||
if (audio_stream_interactive->has_transition(AudioStreamInteractive::CLIP_ANY, to)) {
|
||||
from = AudioStreamInteractive::CLIP_ANY;
|
||||
tooltip = vformat(TTR("Using Any Clip -> %s."), audio_stream_interactive->get_clip_name(to));
|
||||
} else if (audio_stream_interactive->has_transition(from, AudioStreamInteractive::CLIP_ANY)) {
|
||||
to = AudioStreamInteractive::CLIP_ANY;
|
||||
tooltip = vformat(TTR("Using %s -> Any Clip."), audio_stream_interactive->get_clip_name(from));
|
||||
} else if (audio_stream_interactive->has_transition(AudioStreamInteractive::CLIP_ANY, AudioStreamInteractive::CLIP_ANY)) {
|
||||
from = to = AudioStreamInteractive::CLIP_ANY;
|
||||
tooltip = TTR("Using All Clips -> Any Clip.");
|
||||
} else {
|
||||
tooltip = TTR("No transition available.");
|
||||
}
|
||||
}
|
||||
|
||||
String from_time;
|
||||
String to_time;
|
||||
if (audio_stream_interactive->has_transition(from, to)) {
|
||||
icon = fade_icons[audio_stream_interactive->get_transition_fade_mode(from, to)];
|
||||
switch (audio_stream_interactive->get_transition_from_time(from, to)) {
|
||||
case AudioStreamInteractive::TRANSITION_FROM_TIME_IMMEDIATE: {
|
||||
from_time = TTR("Immediate");
|
||||
} break;
|
||||
case AudioStreamInteractive::TRANSITION_FROM_TIME_NEXT_BEAT: {
|
||||
from_time = TTR("Next Beat");
|
||||
} break;
|
||||
case AudioStreamInteractive::TRANSITION_FROM_TIME_NEXT_BAR: {
|
||||
from_time = TTR("Next Bar");
|
||||
} break;
|
||||
case AudioStreamInteractive::TRANSITION_FROM_TIME_END: {
|
||||
from_time = TTR("Clip End");
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
switch (audio_stream_interactive->get_transition_to_time(from, to)) {
|
||||
case AudioStreamInteractive::TRANSITION_TO_TIME_SAME_POSITION: {
|
||||
to_time = TTR("Same", "Transition Time Position");
|
||||
} break;
|
||||
case AudioStreamInteractive::TRANSITION_TO_TIME_START: {
|
||||
to_time = TTR("Start", "Transition Time Position");
|
||||
} break;
|
||||
case AudioStreamInteractive::TRANSITION_TO_TIME_PREVIOUS_POSITION: {
|
||||
to_time = TTR("Prev", "Transition Time Position");
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rows[j]->set_icon(i, icon);
|
||||
rows[j]->set_text(i, to_time.is_empty() ? from_time : vformat(U"%s ⮕ %s", from_time, to_time));
|
||||
rows[j]->set_tooltip_text(i, tooltip);
|
||||
if (exists) {
|
||||
rows[j]->set_custom_color(i, font_color);
|
||||
rows[j]->set_icon_modulate(i, Color(1, 1, 1, 1));
|
||||
} else {
|
||||
rows[j]->set_custom_color(i, font_color_default);
|
||||
rows[j]->set_icon_modulate(i, Color(1, 1, 1, 0.5));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamInteractiveTransitionEditor::edit(Object *p_obj) {
|
||||
audio_stream_interactive = Object::cast_to<AudioStreamInteractive>(p_obj);
|
||||
if (!audio_stream_interactive) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<Font> header_font = get_theme_font("bold", EditorStringName(EditorFonts));
|
||||
int header_font_size = get_theme_font_size("bold_size", EditorStringName(EditorFonts));
|
||||
|
||||
tree->clear();
|
||||
rows.clear();
|
||||
selection_order.clear();
|
||||
selected.clear();
|
||||
|
||||
int clip_count = audio_stream_interactive->get_clip_count();
|
||||
tree->set_columns(clip_count + 2);
|
||||
TreeItem *root = tree->create_item();
|
||||
TreeItem *header = tree->create_item(root); // Header
|
||||
int header_index = clip_count + 1;
|
||||
header->set_text(header_index, TTR("From / To"));
|
||||
header->set_selectable(header_index, false);
|
||||
|
||||
filler_clip->clear();
|
||||
filler_clip->add_item(TTR("Disabled"), -1);
|
||||
|
||||
Color header_color = get_theme_color(SNAME("prop_subsection"), EditorStringName(Editor));
|
||||
|
||||
int max_w = 0;
|
||||
|
||||
updating = true;
|
||||
for (int i = 0; i <= clip_count; i++) {
|
||||
int cell_index = i;
|
||||
int clip_i = i == clip_count ? AudioStreamInteractive::CLIP_ANY : i;
|
||||
header->set_selectable(cell_index, false);
|
||||
header->set_custom_font(cell_index, header_font);
|
||||
header->set_custom_font_size(cell_index, header_font_size);
|
||||
header->set_custom_bg_color(cell_index, header_color);
|
||||
|
||||
String name;
|
||||
if (i == clip_count) {
|
||||
name = TTR("Any Clip");
|
||||
} else {
|
||||
name = audio_stream_interactive->get_clip_name(i);
|
||||
}
|
||||
|
||||
int min_w = header_font->get_string_size(name + "XX").width;
|
||||
tree->set_column_custom_minimum_width(cell_index, min_w);
|
||||
max_w = MAX(max_w, min_w);
|
||||
|
||||
header->set_text(cell_index, name);
|
||||
|
||||
TreeItem *row = tree->create_item(root);
|
||||
row->set_text(header_index, name);
|
||||
row->set_selectable(header_index, false);
|
||||
row->set_custom_font(header_index, header_font);
|
||||
row->set_custom_font_size(header_index, header_font_size);
|
||||
row->set_custom_bg_color(header_index, header_color);
|
||||
row->set_meta("to", clip_i);
|
||||
for (int j = 0; j <= clip_count; j++) {
|
||||
int clip_j = j == clip_count ? AudioStreamInteractive::CLIP_ANY : j;
|
||||
row->set_metadata(j, Vector2i(clip_j, clip_i));
|
||||
}
|
||||
rows.push_back(row);
|
||||
|
||||
if (i < clip_count) {
|
||||
filler_clip->add_item(name, i);
|
||||
}
|
||||
}
|
||||
|
||||
tree->set_column_custom_minimum_width(header_index, max_w);
|
||||
selection_order.clear();
|
||||
_update_selection();
|
||||
popup_centered_clamped(Size2(900, 450) * EDSCALE);
|
||||
updating = false;
|
||||
_update_transitions();
|
||||
}
|
||||
|
||||
AudioStreamInteractiveTransitionEditor::AudioStreamInteractiveTransitionEditor() {
|
||||
set_title(TTR("AudioStreamInteractive Transition Editor"));
|
||||
split = memnew(HSplitContainer);
|
||||
add_child(split);
|
||||
tree = memnew(Tree);
|
||||
tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
|
||||
tree->set_hide_root(true);
|
||||
tree->add_theme_constant_override("draw_guides", 1);
|
||||
tree->set_select_mode(Tree::SELECT_MULTI);
|
||||
tree->set_custom_minimum_size(Size2(400, 0) * EDSCALE);
|
||||
split->add_child(tree);
|
||||
|
||||
tree->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
tree->connect("multi_selected", callable_mp(this, &AudioStreamInteractiveTransitionEditor::_cell_selected));
|
||||
VBoxContainer *edit_vb = memnew(VBoxContainer);
|
||||
split->add_child(edit_vb);
|
||||
|
||||
transition_enabled = memnew(CheckBox);
|
||||
transition_enabled->set_text(TTR("Enabled"));
|
||||
transition_enabled->set_accessibility_name(TTRC("Use Transition:"));
|
||||
edit_vb->add_margin_child(TTR("Use Transition:"), transition_enabled);
|
||||
transition_enabled->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited));
|
||||
|
||||
transition_from = memnew(OptionButton);
|
||||
edit_vb->add_margin_child(TTR("Transition From:"), transition_from);
|
||||
transition_from->add_item(TTR("Immediate"), AudioStreamInteractive::TRANSITION_FROM_TIME_IMMEDIATE);
|
||||
transition_from->add_item(TTR("Next Beat"), AudioStreamInteractive::TRANSITION_FROM_TIME_NEXT_BEAT);
|
||||
transition_from->add_item(TTR("Next Bar"), AudioStreamInteractive::TRANSITION_FROM_TIME_NEXT_BAR);
|
||||
transition_from->add_item(TTR("Clip End"), AudioStreamInteractive::TRANSITION_FROM_TIME_END);
|
||||
transition_from->set_accessibility_name(TTRC("Transition From:"));
|
||||
|
||||
transition_from->connect(SceneStringName(item_selected), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited).unbind(1));
|
||||
|
||||
transition_to = memnew(OptionButton);
|
||||
edit_vb->add_margin_child(TTR("Transition To:"), transition_to);
|
||||
transition_to->add_item(TTR("Same Position"), AudioStreamInteractive::TRANSITION_TO_TIME_SAME_POSITION);
|
||||
transition_to->add_item(TTR("Clip Start"), AudioStreamInteractive::TRANSITION_TO_TIME_START);
|
||||
transition_to->add_item(TTR("Prev Position"), AudioStreamInteractive::TRANSITION_TO_TIME_PREVIOUS_POSITION);
|
||||
transition_to->set_accessibility_name(TTRC("Transition To:"));
|
||||
transition_to->connect(SceneStringName(item_selected), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited).unbind(1));
|
||||
|
||||
fade_mode = memnew(OptionButton);
|
||||
edit_vb->add_margin_child(TTR("Fade Mode:"), fade_mode);
|
||||
fade_mode->connect(SceneStringName(item_selected), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited).unbind(1));
|
||||
fade_mode->set_accessibility_name(TTRC("Fade Mode:"));
|
||||
|
||||
fade_beats = memnew(SpinBox);
|
||||
edit_vb->add_margin_child(TTR("Fade Beats:"), fade_beats);
|
||||
fade_beats->set_max(16);
|
||||
fade_beats->set_step(0.1);
|
||||
fade_beats->connect(SceneStringName(value_changed), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited).unbind(1));
|
||||
fade_beats->set_accessibility_name(TTRC("Fade Beats:"));
|
||||
|
||||
filler_clip = memnew(OptionButton);
|
||||
edit_vb->add_margin_child(TTR("Filler Clip:"), filler_clip);
|
||||
filler_clip->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
|
||||
filler_clip->connect(SceneStringName(item_selected), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited).unbind(1));
|
||||
filler_clip->set_accessibility_name(TTRC("Filler Clip:"));
|
||||
|
||||
hold_previous = memnew(CheckBox);
|
||||
hold_previous->set_text(TTR("Enabled"));
|
||||
hold_previous->set_accessibility_name(TTRC("Hold Previous:"));
|
||||
hold_previous->connect(SceneStringName(pressed), callable_mp(this, &AudioStreamInteractiveTransitionEditor::_edited));
|
||||
edit_vb->add_margin_child(TTR("Hold Previous:"), hold_previous);
|
||||
|
||||
set_exclusive(true);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
|
||||
bool EditorInspectorPluginAudioStreamInteractive::can_handle(Object *p_object) {
|
||||
return Object::cast_to<AudioStreamInteractive>(p_object);
|
||||
}
|
||||
|
||||
void EditorInspectorPluginAudioStreamInteractive::_edit(Object *p_object) {
|
||||
audio_stream_interactive_transition_editor->edit(p_object);
|
||||
}
|
||||
|
||||
void EditorInspectorPluginAudioStreamInteractive::parse_end(Object *p_object) {
|
||||
if (Object::cast_to<AudioStreamInteractive>(p_object)) {
|
||||
Button *button = memnew(EditorInspectorActionButton(TTRC("Edit Transitions"), SNAME("Blend")));
|
||||
button->connect(SceneStringName(pressed), callable_mp(this, &EditorInspectorPluginAudioStreamInteractive::_edit).bind(p_object));
|
||||
add_custom_control(button);
|
||||
}
|
||||
}
|
||||
|
||||
EditorInspectorPluginAudioStreamInteractive::EditorInspectorPluginAudioStreamInteractive() {
|
||||
audio_stream_interactive_transition_editor = memnew(AudioStreamInteractiveTransitionEditor);
|
||||
EditorNode::get_singleton()->get_gui_base()->add_child(audio_stream_interactive_transition_editor);
|
||||
}
|
||||
|
||||
AudioStreamInteractiveEditorPlugin::AudioStreamInteractiveEditorPlugin() {
|
||||
Ref<EditorInspectorPluginAudioStreamInteractive> inspector_plugin;
|
||||
inspector_plugin.instantiate();
|
||||
add_inspector_plugin(inspector_plugin);
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/**************************************************************************/
|
||||
/* audio_stream_interactive_editor_plugin.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "editor/inspector/editor_inspector.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
|
||||
class CheckBox;
|
||||
class HSplitContainer;
|
||||
class VSplitContainer;
|
||||
class Tree;
|
||||
class TreeItem;
|
||||
class AudioStreamInteractive;
|
||||
|
||||
class AudioStreamInteractiveTransitionEditor : public AcceptDialog {
|
||||
GDCLASS(AudioStreamInteractiveTransitionEditor, AcceptDialog);
|
||||
|
||||
AudioStreamInteractive *audio_stream_interactive = nullptr;
|
||||
|
||||
HSplitContainer *split = nullptr;
|
||||
Tree *tree = nullptr;
|
||||
|
||||
Vector<TreeItem *> rows;
|
||||
|
||||
CheckBox *transition_enabled = nullptr;
|
||||
OptionButton *transition_from = nullptr;
|
||||
OptionButton *transition_to = nullptr;
|
||||
OptionButton *fade_mode = nullptr;
|
||||
SpinBox *fade_beats = nullptr;
|
||||
OptionButton *filler_clip = nullptr;
|
||||
CheckBox *hold_previous = nullptr;
|
||||
|
||||
bool updating_selection = false;
|
||||
int order_counter = 0;
|
||||
HashMap<Vector2i, int> selection_order;
|
||||
|
||||
Vector<Vector2i> selected;
|
||||
bool updating = false;
|
||||
void _cell_selected(TreeItem *p_item, int p_column, bool p_selected);
|
||||
void _update_transitions();
|
||||
|
||||
void _update_selection();
|
||||
void _edited();
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
void edit(Object *p_obj);
|
||||
|
||||
AudioStreamInteractiveTransitionEditor();
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
class EditorInspectorPluginAudioStreamInteractive : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginAudioStreamInteractive, EditorInspectorPlugin);
|
||||
|
||||
AudioStreamInteractiveTransitionEditor *audio_stream_interactive_transition_editor = nullptr;
|
||||
|
||||
void _edit(Object *p_object);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual void parse_end(Object *p_object) override;
|
||||
|
||||
EditorInspectorPluginAudioStreamInteractive();
|
||||
};
|
||||
|
||||
class AudioStreamInteractiveEditorPlugin : public EditorPlugin {
|
||||
GDCLASS(AudioStreamInteractiveEditorPlugin, EditorPlugin);
|
||||
|
||||
public:
|
||||
virtual String get_plugin_name() const override { return "AudioStreamInteractive"; }
|
||||
|
||||
AudioStreamInteractiveEditorPlugin();
|
||||
};
|
Reference in New Issue
Block a user