void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { Ref<Curve3D> c = path->get_curve(); if (c.is_null()) return; UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); if (p_idx < c->get_point_count()) { if (p_cancel) { c->set_point_pos(p_idx, p_restore); return; } ur->create_action(TTR("Set Curve Point Pos")); ur->add_do_method(c.ptr(), "set_point_pos", p_idx, c->get_point_pos(p_idx)); ur->add_undo_method(c.ptr(), "set_point_pos", p_idx, p_restore); ur->commit_action(); return; } p_idx = p_idx - c->get_point_count() + 1; int idx = p_idx / 2; int t = p_idx % 2; Vector3 ofs; if (p_cancel) { return; } if (t == 0) { if (p_cancel) { c->set_point_in(p_idx, p_restore); return; } ur->create_action(TTR("Set Curve In Pos")); ur->add_do_method(c.ptr(), "set_point_in", idx, c->get_point_in(idx)); ur->add_undo_method(c.ptr(), "set_point_in", idx, p_restore); ur->commit_action(); } else { if (p_cancel) { c->set_point_out(idx, p_restore); return; } ur->create_action(TTR("Set Curve Out Pos")); ur->add_do_method(c.ptr(), "set_point_out", idx, c->get_point_out(idx)); ur->add_undo_method(c.ptr(), "set_point_out", idx, p_restore); ur->commit_action(); } }
void EditorAudioBus::_effect_edited() { if (updating_bus) return; TreeItem *effect = effects->get_edited(); if (!effect) return; if (effect->get_metadata(0) == Variant()) { Rect2 area = effects->get_item_rect(effect); effect_options->set_position(effects->get_global_position() + area.position + Vector2(0, area.size.y)); effect_options->popup(); //add effect } else { int index = effect->get_metadata(0); updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Select Audio Bus Send")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled", get_index(), index, effect->is_checked(0)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled", get_index(), index, AudioServer::get_singleton()->is_bus_effect_enabled(get_index(), index)); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); updating_bus = false; } }
void EditorAudioBuses::_delete_bus(Object *p_which) { EditorAudioBus *bus = Object::cast_to<EditorAudioBus>(p_which); int index = bus->get_index(); if (index == 0) { EditorNode::get_singleton()->show_warning(TTR("Master bus can't be deleted!")); return; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Delete Audio Bus")); ur->add_do_method(AudioServer::get_singleton(), "remove_bus", index); ur->add_undo_method(AudioServer::get_singleton(), "add_bus", index); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_name", index, AudioServer::get_singleton()->get_bus_name(index)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db", index, AudioServer::get_singleton()->get_bus_volume_db(index)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send", index, AudioServer::get_singleton()->get_bus_send(index)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_solo", index, AudioServer::get_singleton()->is_bus_solo(index)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_mute", index, AudioServer::get_singleton()->is_bus_mute(index)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_bypass_effects", index, AudioServer::get_singleton()->is_bus_bypassing_effects(index)); for (int i = 0; i < AudioServer::get_singleton()->get_bus_effect_count(index); i++) { ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect", index, AudioServer::get_singleton()->get_bus_effect(index, i)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled", index, i, AudioServer::get_singleton()->is_bus_effect_enabled(index, i)); } ur->add_do_method(this, "_update_buses"); ur->add_undo_method(this, "_update_buses"); ur->commit_action(); }
void EditorSettingsDialog::_press_a_key_confirm() { if (last_wait_for_key.type!=InputEvent::KEY) return; InputEvent ie; ie.type=InputEvent::KEY; ie.key.scancode=last_wait_for_key.key.scancode; ie.key.mod=last_wait_for_key.key.mod; Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Change Shortcut '"+shortcut_configured+"'"); ur->add_do_method(sc.ptr(),"set_shortcut",ie); ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut()); ur->add_do_method(this,"_update_shortcuts"); ur->add_undo_method(this,"_update_shortcuts"); ur->add_do_method(this,"_settings_changed"); ur->add_undo_method(this,"_settings_changed"); ur->commit_action(); }
void MeshInstanceEditor::_create_outline_mesh() { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text(TTR("MeshInstance lacks a Mesh!")); err_dialog->popup_centered_minsize(); return; } Ref<Mesh> mesho = mesh->create_outline(outline_size->get_val()); if (mesho.is_null()) { err_dialog->set_text(TTR("Could not create outline!")); err_dialog->popup_centered_minsize(); return; } MeshInstance *mi = memnew( MeshInstance ); mi->set_mesh(mesho); Node *owner=node->get_owner(); if (get_tree()->get_edited_scene_root()==node) { owner=node; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Create Outline")); ur->add_do_method(node,"add_child",mi); ur->add_do_method(mi,"set_owner",owner); ur->add_do_reference(mi); ur->add_undo_method(node,"remove_child",mi); ur->commit_action(); }
void EditorSettingsDialog::_press_a_key_confirm() { if (last_wait_for_key.is_null()) return; Ref<InputEventKey> ie; ie.instance(); ie->set_scancode(last_wait_for_key->get_scancode()); ie->set_shift(last_wait_for_key->get_shift()); ie->set_control(last_wait_for_key->get_control()); ie->set_alt(last_wait_for_key->get_alt()); ie->set_metakey(last_wait_for_key->get_metakey()); Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(shortcut_configured); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Change Shortcut '" + shortcut_configured + "'"); ur->add_do_method(sc.ptr(), "set_shortcut", ie); ur->add_undo_method(sc.ptr(), "set_shortcut", sc->get_shortcut()); ur->add_do_method(this, "_update_shortcuts"); ur->add_undo_method(this, "_update_shortcuts"); ur->add_do_method(this, "_settings_changed"); ur->add_undo_method(this, "_settings_changed"); ur->commit_action(); }
void EditorSettingsDialog::_shortcut_button_pressed(Object* p_item,int p_column,int p_idx) { TreeItem *ti=p_item->cast_to<TreeItem>(); ERR_FAIL_COND(!ti); String item = ti->get_metadata(0); Ref<ShortCut> sc = EditorSettings::get_singleton()->get_shortcut(item); if (p_idx==0) { press_a_key_label->set_text(TTR("Press a Key..")); last_wait_for_key=InputEvent(); press_a_key->popup_centered(Size2(250,80)*EDSCALE); press_a_key->grab_focus(); press_a_key->get_ok()->set_focus_mode(FOCUS_NONE); press_a_key->get_cancel()->set_focus_mode(FOCUS_NONE); shortcut_configured=item; } else if (p_idx==1) {//erase if (!sc.is_valid()) return; //pointless, there is nothing UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Erase Shortcut"); ur->add_do_method(sc.ptr(),"set_shortcut",InputEvent()); ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut()); ur->add_do_method(this,"_update_shortcuts"); ur->add_undo_method(this,"_update_shortcuts"); ur->add_do_method(this,"_settings_changed"); ur->add_undo_method(this,"_settings_changed"); ur->commit_action(); } else if (p_idx==2) {//revert to original if (!sc.is_valid()) return; //pointless, there is nothing InputEvent original = sc->get_meta("original"); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Restore Shortcut"); ur->add_do_method(sc.ptr(),"set_shortcut",original); ur->add_undo_method(sc.ptr(),"set_shortcut",sc->get_shortcut()); ur->add_do_method(this,"_update_shortcuts"); ur->add_undo_method(this,"_update_shortcuts"); ur->add_do_method(this,"_settings_changed"); ur->add_undo_method(this,"_settings_changed"); ur->commit_action(); } }
void EditorAudioBus::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { Dictionary d = p_data; TreeItem *item = effects->get_item_at_position(p_point); if (!item) return; int pos = effects->get_drop_section_at_position(p_point); Variant md = item->get_metadata(0); int paste_at; int bus = d["bus"]; int effect = d["effect"]; if (md.get_type() == Variant::INT) { paste_at = md; if (pos > 0) paste_at++; if (bus == get_index() && paste_at > effect) { paste_at--; } } else { paste_at = -1; } bool enabled = AudioServer::get_singleton()->is_bus_effect_enabled(bus, effect); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Move Bus Effect")); ur->add_do_method(AudioServer::get_singleton(), "remove_bus_effect", bus, effect); ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect", get_index(), AudioServer::get_singleton()->get_bus_effect(bus, effect), paste_at); if (paste_at == -1) { paste_at = AudioServer::get_singleton()->get_bus_effect_count(get_index()); if (bus == get_index()) { paste_at--; } } if (!enabled) { ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled", get_index(), paste_at, false); } ur->add_undo_method(AudioServer::get_singleton(), "remove_bus_effect", get_index(), paste_at); ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect", bus, AudioServer::get_singleton()->get_bus_effect(bus, effect), effect); if (!enabled) { ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled", bus, effect, false); } ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); if (get_index() != bus) { ur->add_do_method(buses, "_update_bus", bus); ur->add_undo_method(buses, "_update_bus", bus); } ur->commit_action(); }
void EditorAudioBuses::_add_bus() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); //need to simulate new name, so we can undi :( ur->create_action(TTR("Add Audio Bus")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_count", AudioServer::get_singleton()->get_bus_count() + 1); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_count", AudioServer::get_singleton()->get_bus_count()); ur->add_do_method(this, "_update_buses"); ur->add_undo_method(this, "_update_buses"); ur->commit_action(); }
void EditorAudioBus::_name_changed(const String &p_new_name) { if (p_new_name == AudioServer::get_singleton()->get_bus_name(get_index())) return; String attempt = p_new_name; int attempts = 1; while (true) { bool name_free = true; for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { if (AudioServer::get_singleton()->get_bus_name(i) == attempt) { name_free = false; break; } } if (name_free) { break; } attempts++; attempt = p_new_name + " " + itos(attempts); } updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); StringName current = AudioServer::get_singleton()->get_bus_name(get_index()); ur->create_action(TTR("Rename Audio Bus")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_name", get_index(), attempt); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_name", get_index(), current); for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) { if (AudioServer::get_singleton()->get_bus_send(i) == current) { ur->add_do_method(AudioServer::get_singleton(), "set_bus_send", i, attempt); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send", i, current); } } ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->add_do_method(buses, "_update_sends"); ur->add_undo_method(buses, "_update_sends"); ur->commit_action(); updating_bus = false; track_name->release_focus(); }
void EditorAudioBuses::_reset_bus_volume(Object *p_which) { EditorAudioBus *bus = Object::cast_to<EditorAudioBus>(p_which); int index = bus->get_index(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Reset Bus Volume")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db", index, 0.f); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db", index, AudioServer::get_singleton()->get_bus_volume_db(index)); ur->add_do_method(this, "_update_buses"); ur->add_undo_method(this, "_update_buses"); ur->commit_action(); }
void EditorAudioBus::_bypass_toggled() { updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Toggle Audio Bus Bypass Effects")); ur->add_do_method(AudioServer::get_singleton(), "set_bus_bypass_effects", get_index(), bypass->is_pressed()); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_bypass_effects", get_index(), AudioServer::get_singleton()->is_bus_bypassing_effects(get_index())); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); updating_bus = false; }
void SkeletonEditor::create_physical_skeleton() { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); Node *owner = skeleton == get_tree()->get_edited_scene_root() ? skeleton : skeleton->get_owner(); const int bc = skeleton->get_bone_count(); if (!bc) { return; } Vector<BoneInfo> bones_infos; bones_infos.resize(bc); for (int bone_id = 0; bc > bone_id; ++bone_id) { const int parent = skeleton->get_bone_parent(bone_id); const int parent_parent = skeleton->get_bone_parent(parent); if (parent < 0) { bones_infos.write[bone_id].relative_rest = skeleton->get_bone_rest(bone_id); } else { bones_infos.write[bone_id].relative_rest = bones_infos[parent].relative_rest * skeleton->get_bone_rest(bone_id); /// create physical bone on parent if (!bones_infos[parent].physical_bone) { bones_infos.write[parent].physical_bone = create_physical_bone(parent, bone_id, bones_infos); ur->create_action(TTR("Create physical bones")); ur->add_do_method(skeleton, "add_child", bones_infos[parent].physical_bone); ur->add_do_reference(bones_infos[parent].physical_bone); ur->add_undo_method(skeleton, "remove_child", bones_infos[parent].physical_bone); ur->commit_action(); bones_infos[parent].physical_bone->set_bone_name(skeleton->get_bone_name(parent)); bones_infos[parent].physical_bone->set_owner(owner); bones_infos[parent].physical_bone->get_child(0)->set_owner(owner); // set shape owner /// Create joint between parent of parent if (-1 != parent_parent) { bones_infos[parent].physical_bone->set_joint_type(PhysicalBone::JOINT_TYPE_PIN); } } } } }
void GradientEditorPlugin::_ramp_changed() { if (gradient_ref.is_valid()) { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); //Not sure if I should convert this data to PoolVector Vector<float> new_offsets = ramp_editor->get_offsets(); Vector<Color> new_colors = ramp_editor->get_colors(); Vector<float> old_offsets = gradient_ref->get_offsets(); Vector<Color> old_colors = gradient_ref->get_colors(); if (old_offsets.size() != new_offsets.size()) ur->create_action(TTR("Add/Remove Color Ramp Point")); else ur->create_action(TTR("Modify Color Ramp"), UndoRedo::MERGE_ENDS); ur->add_do_method(this, "undo_redo_gradient", new_offsets, new_colors); ur->add_undo_method(this, "undo_redo_gradient", old_offsets, old_colors); ur->commit_action(); //color_ramp_ref->set_points(ramp_editor->get_points()); } }
void EditorAudioBus::_send_selected(int p_which) { updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action("Select Audio Bus Send"); ur->add_do_method(AudioServer::get_singleton(), "set_bus_send", get_index(), send->get_item_text(p_which)); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_send", get_index(), AudioServer::get_singleton()->get_bus_send(get_index())); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); updating_bus = false; }
bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, const String &p_field) { Node *es = EditorNode::get_singleton()->get_edited_scene(); if (!es) return false; String name = p_name; if (name == "scripts") { // script set is intercepted at object level (check Variant Object::get() ) ,so use a different name name = "script"; } UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("MultiNode Set") + " " + String(name)); for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) { if (!es->has_node(E->get())) continue; Node *n = es->get_node(E->get()); if (!n) continue; if (p_value.get_type() == Variant::NODE_PATH) { Node *tonode = n->get_node(p_value); NodePath p_path = n->get_path_to(tonode); ur->add_do_property(n, name, p_path); } else { Variant new_value; if (p_field == "") { // whole value new_value = p_value; } else { // only one field new_value = fieldwise_assign(n->get(name), p_value, p_field); } ur->add_do_property(n, name, new_value); } ur->add_undo_property(n, name, n->get(name)); } ur->add_do_method(EditorNode::get_singleton()->get_inspector(), "refresh"); ur->add_undo_method(EditorNode::get_singleton()->get_inspector(), "refresh"); ur->commit_action(); return true; }
void EditorAudioBus::_volume_db_changed(float p_db) { if (updating_bus) return; updating_bus = true; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Audio Bus Volume"), UndoRedo::MERGE_ENDS); ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db", get_index(), p_db); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_volume_db", get_index(), AudioServer::get_singleton()->get_bus_volume_db(get_index())); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); updating_bus = false; }
void EditorAudioBus::_delete_effect_pressed(int p_option) { TreeItem *item = effects->get_selected(); if (!item) return; if (item->get_metadata(0).get_type() != Variant::INT) return; int index = item->get_metadata(0); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Delete Bus Effect")); ur->add_do_method(AudioServer::get_singleton(), "remove_bus_effect", get_index(), index); ur->add_undo_method(AudioServer::get_singleton(), "add_bus_effect", get_index(), AudioServer::get_singleton()->get_bus_effect(get_index(), index), index); ur->add_undo_method(AudioServer::get_singleton(), "set_bus_effect_enabled", get_index(), index, AudioServer::get_singleton()->is_bus_effect_enabled(get_index(), index)); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); }
void EditorAudioBuses::_duplicate_bus(int p_which) { int add_at_pos = p_which + 1; UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Duplicate Audio Bus")); ur->add_do_method(AudioServer::get_singleton(), "add_bus", add_at_pos); ur->add_do_method(AudioServer::get_singleton(), "set_bus_name", add_at_pos, AudioServer::get_singleton()->get_bus_name(p_which) + " Copy"); ur->add_do_method(AudioServer::get_singleton(), "set_bus_volume_db", add_at_pos, AudioServer::get_singleton()->get_bus_volume_db(p_which)); ur->add_do_method(AudioServer::get_singleton(), "set_bus_send", add_at_pos, AudioServer::get_singleton()->get_bus_send(p_which)); ur->add_do_method(AudioServer::get_singleton(), "set_bus_solo", add_at_pos, AudioServer::get_singleton()->is_bus_solo(p_which)); ur->add_do_method(AudioServer::get_singleton(), "set_bus_mute", add_at_pos, AudioServer::get_singleton()->is_bus_mute(p_which)); ur->add_do_method(AudioServer::get_singleton(), "set_bus_bypass_effects", add_at_pos, AudioServer::get_singleton()->is_bus_bypassing_effects(p_which)); for (int i = 0; i < AudioServer::get_singleton()->get_bus_effect_count(p_which); i++) { ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect", add_at_pos, AudioServer::get_singleton()->get_bus_effect(p_which, i)); ur->add_do_method(AudioServer::get_singleton(), "set_bus_effect_enabled", add_at_pos, i, AudioServer::get_singleton()->is_bus_effect_enabled(p_which, i)); } ur->add_undo_method(AudioServer::get_singleton(), "remove_bus", add_at_pos); ur->add_do_method(this, "_update_buses"); ur->add_undo_method(this, "_update_buses"); ur->commit_action(); }
void EditorAudioBuses::_drop_at_index(int p_bus, int p_index) { UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); //need to simulate new name, so we can undi :( ur->create_action(TTR("Move Audio Bus")); ur->add_do_method(AudioServer::get_singleton(), "move_bus", p_bus, p_index); int final_pos; if (p_index == p_bus) { final_pos = p_bus; } else if (p_index == -1) { final_pos = AudioServer::get_singleton()->get_bus_count() - 1; } else if (p_index < p_bus) { final_pos = p_index; } else { final_pos = p_index - 1; } ur->add_undo_method(AudioServer::get_singleton(), "move_bus", final_pos, p_bus); ur->add_do_method(this, "_update_buses"); ur->add_undo_method(this, "_update_buses"); ur->commit_action(); }
void EditorAudioBus::_effect_add(int p_which) { if (updating_bus) return; StringName name = effect_options->get_item_metadata(p_which); Object *fx = ClassDB::instance(name); ERR_FAIL_COND(!fx); AudioEffect *afx = Object::cast_to<AudioEffect>(fx); ERR_FAIL_COND(!afx); Ref<AudioEffect> afxr = Ref<AudioEffect>(afx); afxr->set_name(effect_options->get_item_text(p_which)); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Add Audio Bus Effect")); ur->add_do_method(AudioServer::get_singleton(), "add_bus_effect", get_index(), afxr, -1); ur->add_undo_method(AudioServer::get_singleton(), "remove_bus_effect", get_index(), AudioServer::get_singleton()->get_bus_effect_count(get_index())); ur->add_do_method(buses, "_update_bus", get_index()); ur->add_undo_method(buses, "_update_bus", get_index()); ur->commit_action(); }
bool PathEditorPlugin::forward_spatial_input_event(Camera *p_camera, const InputEvent &p_event) { if (!path) return false; Ref<Curve3D> c = path->get_curve(); if (c.is_null()) return false; Transform gt = path->get_global_transform(); Transform it = gt.affine_inverse(); static const int click_dist = 10; //should make global if (p_event.type == InputEvent::MOUSE_BUTTON) { const InputEventMouseButton &mb = p_event.mouse_button; Point2 mbpos(mb.x, mb.y); if (mb.pressed && mb.button_index == BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) { //click into curve, break it down Vector3Array v3a = c->tesselate(); int idx = 0; int rc = v3a.size(); int closest_seg = -1; Vector3 closest_seg_point; float closest_d = 1e20; if (rc >= 2) { Vector3Array::Read r = v3a.read(); if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos) < click_dist) return false; //nope, existing for (int i = 0; i < c->get_point_count() - 1; i++) { //find the offset and point index of the place to break up int j = idx; if (p_camera->unproject_position(gt.xform(c->get_point_pos(i + 1))).distance_to(mbpos) < click_dist) return false; //nope, existing while (j < rc && c->get_point_pos(i + 1) != r[j]) { Vector3 from = r[j]; Vector3 to = r[j + 1]; real_t cdist = from.distance_to(to); from = gt.xform(from); to = gt.xform(to); if (cdist > 0) { Vector2 s[2]; s[0] = p_camera->unproject_position(from); s[1] = p_camera->unproject_position(to); Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos, s); float d = inters.distance_to(mbpos); if (d < 10 && d < closest_d) { closest_d = d; closest_seg = i; Vector3 ray_from = p_camera->project_ray_origin(mbpos); Vector3 ray_dir = p_camera->project_ray_normal(mbpos); Vector3 ra, rb; Geometry::get_closest_points_between_segments(ray_from, ray_from + ray_dir * 4096, from, to, ra, rb); closest_seg_point = it.xform(rb); } } j++; } if (idx == j) idx++; //force next else idx = j; //swap if (j == rc) break; } } UndoRedo *ur = editor->get_undo_redo(); if (closest_seg != -1) { //subdivide ur->create_action(TTR("Split Path")); ur->add_do_method(c.ptr(), "add_point", closest_seg_point, Vector3(), Vector3(), closest_seg + 1); ur->add_undo_method(c.ptr(), "remove_point", closest_seg + 1); ur->commit_action(); return true; } else { Vector3 org; if (c->get_point_count() == 0) org = path->get_transform().get_origin(); else org = gt.xform(c->get_point_pos(c->get_point_count())); Plane p(org, p_camera->get_transform().basis.get_axis(2)); Vector3 ray_from = p_camera->project_ray_origin(mbpos); Vector3 ray_dir = p_camera->project_ray_normal(mbpos); Vector3 inters; if (p.intersects_ray(ray_from, ray_dir, &inters)) { ur->create_action(TTR("Add Point to Curve")); ur->add_do_method(c.ptr(), "add_point", it.xform(inters), Vector3(), Vector3(), -1); ur->add_undo_method(c.ptr(), "remove_point", c->get_point_count()); ur->commit_action(); return true; } //add new at pos } } else if (mb.pressed && ((mb.button_index == BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index == BUTTON_RIGHT && curve_edit->is_pressed()))) { int erase_idx = -1; for (int i = 0; i < c->get_point_count(); i++) { //find the offset and point index of the place to break up if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos) < click_dist) { erase_idx = i; break; } } if (erase_idx != -1) { UndoRedo *ur = editor->get_undo_redo(); ur->create_action(TTR("Remove Path Point")); ur->add_do_method(c.ptr(), "remove_point", erase_idx); ur->add_undo_method(c.ptr(), "add_point", c->get_point_pos(erase_idx), c->get_point_in(erase_idx), c->get_point_out(erase_idx), erase_idx); ur->commit_action(); return true; } } } return false; }
void MeshInstanceEditor::_menu_option(int p_option) { Ref<Mesh> mesh = node->get_mesh(); if (mesh.is_null()) { err_dialog->set_text(TTR("Mesh is empty!")); err_dialog->popup_centered_minsize(); return; } switch (p_option) { case MENU_OPTION_CREATE_STATIC_TRIMESH_BODY: case MENU_OPTION_CREATE_STATIC_CONVEX_BODY: { bool trimesh_shape = (p_option == MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); EditorSelection *editor_selection = EditorNode::get_singleton()->get_editor_selection(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); List<Node *> selection = editor_selection->get_selected_node_list(); if (selection.empty()) { Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape(); if (shape.is_null()) return; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); StaticBody *body = memnew(StaticBody); body->add_child(cshape); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); if (trimesh_shape) ur->create_action(TTR("Create Static Trimesh Body")); else ur->create_action(TTR("Create Static Convex Body")); ur->add_do_method(node, "add_child", body); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); ur->add_undo_method(node, "remove_child", body); ur->commit_action(); return; } if (trimesh_shape) ur->create_action(TTR("Create Static Trimesh Body")); else ur->create_action(TTR("Create Static Convex Body")); for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { MeshInstance *instance = E->get()->cast_to<MeshInstance>(); if (!instance) continue; Ref<Mesh> m = instance->get_mesh(); if (m.is_null()) continue; Ref<Shape> shape = trimesh_shape ? m->create_trimesh_shape() : m->create_convex_shape(); if (shape.is_null()) continue; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); StaticBody *body = memnew(StaticBody); body->add_child(cshape); Node *owner = instance == get_tree()->get_edited_scene_root() ? instance : instance->get_owner(); ur->add_do_method(instance, "add_child", body); ur->add_do_method(body, "set_owner", owner); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(body); ur->add_undo_method(instance, "remove_child", body); } ur->commit_action(); } break; case MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE: case MENU_OPTION_CREATE_CONVEX_COLLISION_SHAPE: { if (node == get_tree()->get_edited_scene_root()) { err_dialog->set_text(TTR("This doesn't work on scene root!")); err_dialog->popup_centered_minsize(); return; } bool trimesh_shape = (p_option == MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); Ref<Shape> shape = trimesh_shape ? mesh->create_trimesh_shape() : mesh->create_convex_shape(); if (shape.is_null()) return; CollisionShape *cshape = memnew(CollisionShape); cshape->set_shape(shape); Node *owner = node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); if (trimesh_shape) ur->create_action(TTR("Create Trimesh Shape")); else ur->create_action(TTR("Create Convex Shape")); ur->add_do_method(node->get_parent(), "add_child", cshape); ur->add_do_method(node->get_parent(), "move_child", cshape, node->get_index() + 1); ur->add_do_method(cshape, "set_owner", owner); ur->add_do_reference(cshape); ur->add_undo_method(node->get_parent(), "remove_child", cshape); ur->commit_action(); } break; case MENU_OPTION_CREATE_NAVMESH: { Ref<NavigationMesh> nmesh = memnew(NavigationMesh); if (nmesh.is_null()) return; nmesh->create_from_mesh(mesh); NavigationMeshInstance *nmi = memnew(NavigationMeshInstance); nmi->set_navigation_mesh(nmesh); Node *owner = node == get_tree()->get_edited_scene_root() ? node : node->get_owner(); UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); ur->create_action(TTR("Create Navigation Mesh")); ur->add_do_method(node, "add_child", nmi); ur->add_do_method(nmi, "set_owner", owner); ur->add_do_reference(nmi); ur->add_undo_method(node, "remove_child", nmi); ur->commit_action(); } break; case MENU_OPTION_CREATE_OUTLINE_MESH: { outline_dialog->popup_centered(Vector2(200, 90)); } break; } }
void CSGShapeSpatialGizmoPlugin::commit_handle(EditorSpatialGizmo *p_gizmo, int p_idx, const Variant &p_restore, bool p_cancel) { CSGShape *cs = Object::cast_to<CSGShape>(p_gizmo->get_spatial_node()); if (Object::cast_to<CSGSphere>(cs)) { CSGSphere *s = Object::cast_to<CSGSphere>(cs); if (p_cancel) { s->set_radius(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Sphere Shape Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); ur->add_undo_method(s, "set_radius", p_restore); ur->commit_action(); } if (Object::cast_to<CSGBox>(cs)) { CSGBox *s = Object::cast_to<CSGBox>(cs); if (p_cancel) { switch (p_idx) { case 0: s->set_width(p_restore); break; case 1: s->set_height(p_restore); break; case 2: s->set_depth(p_restore); break; } return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); ur->create_action(TTR("Change Box Shape Extents")); static const char *method[3] = { "set_width", "set_height", "set_depth" }; float current = 0; switch (p_idx) { case 0: current = s->get_width(); break; case 1: current = s->get_height(); break; case 2: current = s->get_depth(); break; } ur->add_do_method(s, method[p_idx], current); ur->add_undo_method(s, method[p_idx], p_restore); ur->commit_action(); } if (Object::cast_to<CSGCylinder>(cs)) { CSGCylinder *s = Object::cast_to<CSGCylinder>(cs); if (p_cancel) { if (p_idx == 0) s->set_radius(p_restore); else s->set_height(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Cylinder Radius")); ur->add_do_method(s, "set_radius", s->get_radius()); ur->add_undo_method(s, "set_radius", p_restore); } else { ur->create_action(TTR("Change Cylinder Height")); ur->add_do_method(s, "set_height", s->get_height()); ur->add_undo_method(s, "set_height", p_restore); } ur->commit_action(); } if (Object::cast_to<CSGTorus>(cs)) { CSGTorus *s = Object::cast_to<CSGTorus>(cs); if (p_cancel) { if (p_idx == 0) s->set_inner_radius(p_restore); else s->set_outer_radius(p_restore); return; } UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); if (p_idx == 0) { ur->create_action(TTR("Change Torus Inner Radius")); ur->add_do_method(s, "set_inner_radius", s->get_inner_radius()); ur->add_undo_method(s, "set_inner_radius", p_restore); } else { ur->create_action(TTR("Change Torus Outer Radius")); ur->add_do_method(s, "set_outer_radius", s->get_outer_radius()); ur->add_undo_method(s, "set_outer_radius", p_restore); } ur->commit_action(); } }
void PathSpatialGizmo::commit_handle(int p_idx, const Variant &p_restore, bool p_cancel) { Ref<Curve3D> c = path->get_curve(); if (c.is_null()) return; UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); if (p_idx < c->get_point_count()) { if (p_cancel) { c->set_point_position(p_idx, p_restore); return; } ur->create_action(TTR("Set Curve Point Position")); ur->add_do_method(c.ptr(), "set_point_position", p_idx, c->get_point_position(p_idx)); ur->add_undo_method(c.ptr(), "set_point_position", p_idx, p_restore); ur->commit_action(); return; } p_idx = p_idx - c->get_point_count() + 1; int idx = p_idx / 2; int t = p_idx % 2; if (t == 0) { if (p_cancel) { c->set_point_in(p_idx, p_restore); return; } ur->create_action(TTR("Set Curve In Position")); ur->add_do_method(c.ptr(), "set_point_in", idx, c->get_point_in(idx)); ur->add_undo_method(c.ptr(), "set_point_in", idx, p_restore); if (PathEditorPlugin::singleton->mirror_angle_enabled()) { ur->add_do_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_in(idx) : (-c->get_point_in(idx).normalized() * orig_out_length)); ur->add_undo_method(c.ptr(), "set_point_out", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_out_length)); } ur->commit_action(); } else { if (p_cancel) { c->set_point_out(idx, p_restore); return; } ur->create_action(TTR("Set Curve Out Position")); ur->add_do_method(c.ptr(), "set_point_out", idx, c->get_point_out(idx)); ur->add_undo_method(c.ptr(), "set_point_out", idx, p_restore); if (PathEditorPlugin::singleton->mirror_angle_enabled()) { ur->add_do_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -c->get_point_out(idx) : (-c->get_point_out(idx).normalized() * orig_in_length)); ur->add_undo_method(c.ptr(), "set_point_in", idx, PathEditorPlugin::singleton->mirror_length_enabled() ? -static_cast<Vector3>(p_restore) : (-static_cast<Vector3>(p_restore).normalized() * orig_in_length)); } ur->commit_action(); } }