diff options
Diffstat (limited to 'editor/plugins/sprite_frames_editor_plugin.cpp')
| -rw-r--r-- | editor/plugins/sprite_frames_editor_plugin.cpp | 297 |
1 files changed, 281 insertions, 16 deletions
diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 5ba2fde763..c509202a88 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -38,23 +38,207 @@ void SpriteFramesEditor::_gui_input(Ref<InputEvent> p_event) { } -void SpriteFramesEditor::_notification(int p_what) { +void SpriteFramesEditor::_open_sprite_sheet() { + + file_split_sheet->clear_filters(); + List<String> extensions; + ResourceLoader::get_recognized_extensions_for_type("Texture", &extensions); + for (int i = 0; i < extensions.size(); i++) { + file_split_sheet->add_filter("*." + extensions[i]); + } + + file_split_sheet->popup_centered_ratio(); +} + +void SpriteFramesEditor::_sheet_preview_draw() { + + Size2i size = split_sheet_preview->get_size(); + int h = split_sheet_h->get_value(); + int v = split_sheet_v->get_value(); + int width = size.width / h; + int height = size.height / v; + const float a = 0.3; + for (int i = 1; i < h; i++) { + + int x = i * width; + split_sheet_preview->draw_line(Point2(x, 0), Point2(x, size.height), Color(1, 1, 1, a)); + split_sheet_preview->draw_line(Point2(x + 1, 0), Point2(x + 1, size.height), Color(0, 0, 0, a)); + + for (int j = 1; j < v; j++) { + + int y = j * height; + + split_sheet_preview->draw_line(Point2(0, y), Point2(size.width, y), Color(1, 1, 1, a)); + split_sheet_preview->draw_line(Point2(0, y + 1), Point2(size.width, y + 1), Color(0, 0, 0, a)); + } + } + + if (frames_selected.size() == 0) { + split_sheet_dialog->get_ok()->set_disabled(true); + split_sheet_dialog->get_ok()->set_text(TTR("No Frames Selected")); + return; + } + + Color accent = get_color("accent_color", "Editor"); + + for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { + int idx = E->get(); + int xp = idx % h; + int yp = (idx - xp) / h; + int x = xp * width; + int y = yp * height; + + split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 0.35), true); + split_sheet_preview->draw_rect(Rect2(x + 0, y + 0, width - 0, height - 0), Color(0, 0, 0, 1), false); + split_sheet_preview->draw_rect(Rect2(x + 1, y + 1, width - 2, height - 2), Color(0, 0, 0, 1), false); + split_sheet_preview->draw_rect(Rect2(x + 2, y + 2, width - 4, height - 4), accent, false); + split_sheet_preview->draw_rect(Rect2(x + 3, y + 3, width - 6, height - 6), accent, false); + split_sheet_preview->draw_rect(Rect2(x + 4, y + 4, width - 8, height - 8), Color(0, 0, 0, 1), false); + split_sheet_preview->draw_rect(Rect2(x + 5, y + 5, width - 10, height - 10), Color(0, 0, 0, 1), false); + } + + split_sheet_dialog->get_ok()->set_disabled(false); + split_sheet_dialog->get_ok()->set_text(vformat(TTR("Add %d Frame(s)"), frames_selected.size())); +} +void SpriteFramesEditor::_sheet_preview_input(const Ref<InputEvent> &p_event) { + + Ref<InputEventMouseButton> mb = p_event; + + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + Size2i size = split_sheet_preview->get_size(); + int h = split_sheet_h->get_value(); + int v = split_sheet_v->get_value(); + + int x = CLAMP(int(mb->get_position().x) * h / size.width, 0, h - 1); + int y = CLAMP(int(mb->get_position().y) * v / size.height, 0, v - 1); + + int idx = h * y + x; + + if (mb->get_shift() && last_frame_selected >= 0) { + //select multiple + int from = idx; + int to = last_frame_selected; + if (from > to) { + SWAP(from, to); + } + + for (int i = from; i <= to; i++) { + if (mb->get_control()) { + frames_selected.erase(i); + } else { + frames_selected.insert(i); + } + } + } else { + if (frames_selected.has(idx)) { + frames_selected.erase(idx); + } else { + frames_selected.insert(idx); + } + } + + last_frame_selected = idx; + split_sheet_preview->update(); + } +} - if (p_what == NOTIFICATION_ENTER_TREE) { +void SpriteFramesEditor::_sheet_add_frames() { - load->set_icon(get_icon("Load", "EditorIcons")); - copy->set_icon(get_icon("ActionCopy", "EditorIcons")); - paste->set_icon(get_icon("ActionPaste", "EditorIcons")); - empty->set_icon(get_icon("InsertBefore", "EditorIcons")); - empty2->set_icon(get_icon("InsertAfter", "EditorIcons")); - move_up->set_icon(get_icon("MoveLeft", "EditorIcons")); - move_down->set_icon(get_icon("MoveRight", "EditorIcons")); - _delete->set_icon(get_icon("Remove", "EditorIcons")); - new_anim->set_icon(get_icon("New", "EditorIcons")); - remove_anim->set_icon(get_icon("Remove", "EditorIcons")); - } else if (p_what == NOTIFICATION_READY) { + Size2i size = split_sheet_preview->get_size(); + int h = split_sheet_h->get_value(); + int v = split_sheet_v->get_value(); - add_constant_override("autohide", 1); // Fixes the dragger always showing up. + undo_redo->create_action(TTR("Add Frame")); + + int fc = frames->get_frame_count(edited_anim); + + for (Set<int>::Element *E = frames_selected.front(); E; E = E->next()) { + int idx = E->get(); + int width = size.width / h; + int height = size.height / v; + int xp = idx % h; + int yp = (idx - xp) / h; + int x = xp * width; + int y = yp * height; + + Ref<AtlasTexture> at; + at.instance(); + at->set_atlas(split_sheet_preview->get_texture()); + at->set_region(Rect2(x, y, width, height)); + + undo_redo->add_do_method(frames, "add_frame", edited_anim, at, -1); + undo_redo->add_undo_method(frames, "remove_frame", edited_anim, fc); + } + + undo_redo->add_do_method(this, "_update_library"); + undo_redo->add_undo_method(this, "_update_library"); + undo_redo->commit_action(); +} + +void SpriteFramesEditor::_sheet_select_clear_all_frames() { + + bool should_clear = true; + for (int i = 0; i < split_sheet_h->get_value() * split_sheet_v->get_value(); i++) { + if (!frames_selected.has(i)) { + frames_selected.insert(i); + should_clear = false; + } + } + if (should_clear) { + frames_selected.clear(); + } + + split_sheet_preview->update(); +} + +void SpriteFramesEditor::_sheet_spin_changed(double) { + + frames_selected.clear(); + last_frame_selected = -1; + split_sheet_preview->update(); +} + +void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) { + + Ref<Resource> texture = ResourceLoader::load(p_file); + if (!texture.is_valid()) { + EditorNode::get_singleton()->show_warning("Unable to load images"); + ERR_FAIL_COND(!texture.is_valid()); + } + if (texture != split_sheet_preview->get_texture()) { + //different texture, reset to 4x4 + split_sheet_h->set_value(4); + split_sheet_v->set_value(4); + } + frames_selected.clear(); + last_frame_selected = -1; + + split_sheet_preview->set_texture(texture); + split_sheet_dialog->popup_centered_ratio(0.65); +} + +void SpriteFramesEditor::_notification(int p_what) { + + switch (p_what) { + case NOTIFICATION_ENTER_TREE: { + load->set_icon(get_icon("Load", "EditorIcons")); + load_sheet->set_icon(get_icon("SpriteSheet", "EditorIcons")); + copy->set_icon(get_icon("ActionCopy", "EditorIcons")); + paste->set_icon(get_icon("ActionPaste", "EditorIcons")); + empty->set_icon(get_icon("InsertBefore", "EditorIcons")); + empty2->set_icon(get_icon("InsertAfter", "EditorIcons")); + move_up->set_icon(get_icon("MoveLeft", "EditorIcons")); + move_down->set_icon(get_icon("MoveRight", "EditorIcons")); + _delete->set_icon(get_icon("Remove", "EditorIcons")); + new_anim->set_icon(get_icon("New", "EditorIcons")); + remove_anim->set_icon(get_icon("Remove", "EditorIcons")); + } // Fallthrough. + case NOTIFICATION_THEME_CHANGED: { + splite_sheet_scroll->add_style_override("bg", get_stylebox("bg", "Tree")); + } break; + case NOTIFICATION_READY: { + add_constant_override("autohide", 1); // Fixes the dragger always showing up. + } break; } } @@ -72,6 +256,7 @@ void SpriteFramesEditor::_file_load_request(const PoolVector<String> &p_path, in if (resource.is_null()) { dialog->set_text(TTR("ERROR: Couldn't load frame resource!")); dialog->set_title(TTR("Error!")); + //dialog->get_cancel()->set_text("Close"); dialog->get_ok()->set_text(TTR("Close")); dialog->popup_centered_minsize(); @@ -278,6 +463,10 @@ void SpriteFramesEditor::_animation_select() { if (updating) return; + double value = anim_speed->get_line_edit()->get_text().to_double(); + if (!Math::is_equal_approx(value, frames->get_animation_speed(edited_anim))) + _animation_fps_changed(value); + TreeItem *selected = animations->get_selected(); ERR_FAIL_COND(!selected); edited_anim = selected->get_text(0); @@ -655,6 +844,13 @@ void SpriteFramesEditor::_bind_methods() { ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &SpriteFramesEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &SpriteFramesEditor::can_drop_data_fw); ClassDB::bind_method(D_METHOD("drop_data_fw"), &SpriteFramesEditor::drop_data_fw); + ClassDB::bind_method(D_METHOD("_prepare_sprite_sheet"), &SpriteFramesEditor::_prepare_sprite_sheet); + ClassDB::bind_method(D_METHOD("_open_sprite_sheet"), &SpriteFramesEditor::_open_sprite_sheet); + ClassDB::bind_method(D_METHOD("_sheet_preview_draw"), &SpriteFramesEditor::_sheet_preview_draw); + ClassDB::bind_method(D_METHOD("_sheet_preview_input"), &SpriteFramesEditor::_sheet_preview_input); + ClassDB::bind_method(D_METHOD("_sheet_spin_changed"), &SpriteFramesEditor::_sheet_spin_changed); + ClassDB::bind_method(D_METHOD("_sheet_add_frames"), &SpriteFramesEditor::_sheet_add_frames); + ClassDB::bind_method(D_METHOD("_sheet_select_clear_all_frames"), &SpriteFramesEditor::_sheet_select_clear_all_frames); } SpriteFramesEditor::SpriteFramesEditor() { @@ -712,9 +908,15 @@ SpriteFramesEditor::SpriteFramesEditor() { sub_vb->add_child(hbc); load = memnew(ToolButton); - load->set_tooltip(TTR("Load Resource")); + load->set_tooltip(TTR("Add a Texture from File")); hbc->add_child(load); + load_sheet = memnew(ToolButton); + load_sheet->set_tooltip(TTR("Add Frames from a Sprite Sheet")); + hbc->add_child(load_sheet); + + hbc->add_child(memnew(VSeparator)); + copy = memnew(ToolButton); copy->set_tooltip(TTR("Copy")); hbc->add_child(copy); @@ -723,6 +925,8 @@ SpriteFramesEditor::SpriteFramesEditor() { paste->set_tooltip(TTR("Paste")); hbc->add_child(paste); + hbc->add_spacer(false); + empty = memnew(ToolButton); empty->set_tooltip(TTR("Insert Empty (Before)")); hbc->add_child(empty); @@ -731,7 +935,7 @@ SpriteFramesEditor::SpriteFramesEditor() { empty2->set_tooltip(TTR("Insert Empty (After)")); hbc->add_child(empty2); - hbc->add_spacer(false); + hbc->add_child(memnew(VSeparator)); move_up = memnew(ToolButton); move_up->set_tooltip(TTR("Move (Before)")); @@ -766,6 +970,7 @@ SpriteFramesEditor::SpriteFramesEditor() { add_child(dialog); load->connect("pressed", this, "_load_pressed"); + load_sheet->connect("pressed", this, "_open_sprite_sheet"); _delete->connect("pressed", this, "_delete_pressed"); copy->connect("pressed", this, "_copy_pressed"); paste->connect("pressed", this, "_paste_pressed"); @@ -780,6 +985,66 @@ SpriteFramesEditor::SpriteFramesEditor() { updating = false; edited_anim = "default"; + + split_sheet_dialog = memnew(ConfirmationDialog); + add_child(split_sheet_dialog); + VBoxContainer *split_sheet_vb = memnew(VBoxContainer); + split_sheet_dialog->add_child(split_sheet_vb); + split_sheet_dialog->set_title(TTR("Select Frames")); + split_sheet_dialog->connect("confirmed", this, "_sheet_add_frames"); + + HBoxContainer *split_sheet_hb = memnew(HBoxContainer); + + Label *ss_label = memnew(Label(TTR("Horizontal:"))); + split_sheet_hb->add_child(ss_label); + split_sheet_h = memnew(SpinBox); + split_sheet_h->set_min(1); + split_sheet_h->set_max(128); + split_sheet_h->set_step(1); + split_sheet_hb->add_child(split_sheet_h); + split_sheet_h->connect("value_changed", this, "_sheet_spin_changed"); + + ss_label = memnew(Label(TTR("Vertical:"))); + split_sheet_hb->add_child(ss_label); + split_sheet_v = memnew(SpinBox); + split_sheet_v->set_min(1); + split_sheet_v->set_max(128); + split_sheet_v->set_step(1); + split_sheet_hb->add_child(split_sheet_v); + split_sheet_v->connect("value_changed", this, "_sheet_spin_changed"); + + split_sheet_hb->add_spacer(); + + Button *select_clear_all = memnew(Button); + select_clear_all->set_text(TTR("Select/Clear All Frames")); + select_clear_all->connect("pressed", this, "_sheet_select_clear_all_frames"); + split_sheet_hb->add_child(select_clear_all); + + split_sheet_vb->add_child(split_sheet_hb); + + split_sheet_preview = memnew(TextureRect); + split_sheet_preview->set_expand(false); + split_sheet_preview->set_mouse_filter(MOUSE_FILTER_PASS); + split_sheet_preview->connect("draw", this, "_sheet_preview_draw"); + split_sheet_preview->connect("gui_input", this, "_sheet_preview_input"); + + splite_sheet_scroll = memnew(ScrollContainer); + splite_sheet_scroll->set_enable_h_scroll(true); + splite_sheet_scroll->set_enable_v_scroll(true); + splite_sheet_scroll->set_v_size_flags(SIZE_EXPAND_FILL); + CenterContainer *cc = memnew(CenterContainer); + cc->add_child(split_sheet_preview); + cc->set_h_size_flags(SIZE_EXPAND_FILL); + cc->set_v_size_flags(SIZE_EXPAND_FILL); + splite_sheet_scroll->add_child(cc); + + split_sheet_vb->add_child(splite_sheet_scroll); + + file_split_sheet = memnew(EditorFileDialog); + file_split_sheet->set_title(TTR("Create Frames from Sprite Sheet")); + file_split_sheet->set_mode(EditorFileDialog::MODE_OPEN_FILE); + add_child(file_split_sheet); + file_split_sheet->connect("file_selected", this, "_prepare_sprite_sheet"); } void SpriteFramesEditorPlugin::edit(Object *p_object) { |
