From d1dc02435354b2bc208ab1cc6c8a2626fa2008aa Mon Sep 17 00:00:00 2001 From: Sergey Lapin Date: Mon, 19 Aug 2024 18:30:02 +0300 Subject: [PATCH] Added camera mode to c++ --- .vscode/launch.json | 15 ++++-- debug.py | 5 ++ godot/main/editor.gd | 73 +++++++++++++++++++++++++---- godot/main/editor.tscn | 67 ++++++++++++++++++++------ src/modules/stream/stream.cpp | 27 ++++++++++- src/modules/stream/world_editor.cpp | 19 ++++++++ src/modules/stream/world_editor.h | 3 ++ 7 files changed, 179 insertions(+), 30 deletions(-) create mode 100644 debug.py diff --git a/.vscode/launch.json b/.vscode/launch.json index a8679be..ce4da59 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,13 +5,22 @@ "version": "0.2.0", "configurations": [ { - "name": "Run Gym", + "name": "Run Editor", "type": "cppdbg", "request": "launch", "program": "${workspaceRoot}/src/godot/bin/godot.x11.opt.tools.64", - "args": ["addons/astream/stream_view.tscn"], + "args": ["main/editor.tscn"], + "cwd": "${workspaceRoot}/godot", + "setupCommands": [{"text": "source ${workspaceRoot}/debug.py"}] + }, + { + "name": "Run Game", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceRoot}/src/godot/bin/godot.x11.opt.tools.64", + "args": ["main/main.tscn"], "cwd": "${workspaceRoot}/godot", "setupCommands": [{"text": "source ${workspaceRoot}/debug.py"}] } ] -} \ No newline at end of file +} diff --git a/debug.py b/debug.py new file mode 100644 index 0000000..b3725f4 --- /dev/null +++ b/debug.py @@ -0,0 +1,5 @@ +def release_mouse (event): + gdb.write("GDB/godot: Releasing mouse\n") + gdb.execute("call OS::get_singleton()->set_mouse_mode(0)") +gdb.events.stop.connect(release_mouse) +gdb.write("GDB/godot: installed release mouse for godot\n") diff --git a/godot/main/editor.gd b/godot/main/editor.gd index 1d64b63..e280213 100644 --- a/godot/main/editor.gd +++ b/godot/main/editor.gd @@ -1,6 +1,6 @@ extends Spatial -var camera_mode = -1 +#var camera_mode = -1 onready var vmode = { 2: $"%v_buildings", @@ -10,6 +10,10 @@ onready var vmode = { 7: $"%v_npc", } +func change_building_type(index): + var item = $"%building_type".get_item_text(index) + $WorldEditor.editor_command("change_building_type", [selected_building, item]) + func _ready(): for b in [ $"%select_buildings", @@ -24,6 +28,7 @@ func _ready(): for k in vmode.keys(): vmode[k].hide() $building_cursor.hide() + $"%building_type".connect("item_selected", self, "change_building_type") func editor_event(evname: String, args: Array): print(evname, args) @@ -40,6 +45,8 @@ func editor_event(evname: String, args: Array): vmode[mode_next].show() if mode_next == 2: $WorldEditor.editor_command("get_building_types", []) + elif mode_next == 6: + $WorldEditor.editor_command("get_lines_list", []) elif evname == "result:get_closest_building": print(evname, args) select_building(args[0], args[3], args[4]) @@ -72,6 +79,14 @@ func _process(delta): setup_cam2() if Input.is_action_just_pressed("editor_cam3"): setup_cam3() + var mode = $"%buildings_edit_mode".selected + if mode == 2: + $building_rot_cursor.global_transform = selected_building_xform + if !$building_rot_cursor.visible: + $building_rot_cursor.show() + else: + if $building_rot_cursor.visible: + $building_rot_cursor.hide() if dragging: if !Input.is_action_pressed("mouse1"): dragging = false @@ -86,7 +101,8 @@ func _process(delta): var result = space_state.intersect_ray(start, end, [], 1 << 15, false, true) if result.has("collider"): var proj = result.position - if $"%buildings_edit_mode".selected == 1: + if mode == 1: + # move print(proj) var newpos = proj newpos.x = stepify(newpos.x, 2.0) @@ -97,6 +113,25 @@ func _process(delta): $WorldEditor.editor_command("update_building_transform", [selected_building, Transform(selected_building_xform.basis, newpos)]) selected_building_xform = Transform(selected_building_xform.basis, newpos) $building_cursor.global_transform.origin = newpos + elif mode == 2: + # rotate + var m = proj + m.y = selected_building_xform.origin.y + var xform = selected_building_xform.looking_at(m, Vector3.UP) + $WorldEditor.editor_command("update_building_transform", [selected_building, xform]) + $building_rot_cursor.global_transform = xform + selected_building_xform = xform +# var o = selected_building_xform.origin +# var m = proj +# o.y = 0 +# m.y = 0 +# var d = m - o +# var rot: float = -0.01 * d.x * delta +# var basis: Basis = selected_building_xform.basis +# var pos: Vector3 = selected_building_xform.origin +# var xform = Transform(basis.rotated(Vector3.UP, rot), pos) +# $WorldEditor.editor_command("update_building_transform", [selected_building, xform]) +# selected_building_xform = xform var motion = Vector2() var old_mouse_pos = Vector2(-1, -1) var rotation_y = 0 @@ -105,6 +140,7 @@ var drag_delay = 0.2 var drag_start = Vector3() func _unhandled_input(event): var editor_mode = $WorldEditor.get_current_mode() + var camera_mode = $WorldEditor.get_camera_mode() if camera_mode in [2, 3]: if event is InputEventMouseMotion: motion = event.relative @@ -113,6 +149,7 @@ func _unhandled_input(event): 2: check_edit_building() func check_edit_building(): + var mode = $"%buildings_edit_mode".selected if Input.is_action_just_pressed("mouse1"): var position = get_viewport().get_mouse_position() # var proj = get_viewport().get_camera().project_position(position, $cam.global_transform.origin.y + position.y * 0.5) @@ -130,13 +167,20 @@ func check_edit_building(): var result = space_state.intersect_ray(start, end, [], 1 << 15, false, true) if result.has("collider"): var proj = result.position - if $"%buildings_edit_mode".selected == 0: + if mode == 0: print("get closest building") $WorldEditor.editor_command("get_closest_building", [Transform(Basis(), proj)]) + elif mode == 2: + var m = proj + m.y = selected_building_xform.origin.y + var xform = selected_building_xform.looking_at(m, Vector3.UP) + $WorldEditor.editor_command("update_building_transform", [selected_building, xform]) + $building_rot_cursor.global_transform = xform + selected_building_xform = xform elif Input.is_action_pressed("mouse1"): - # Moving buildings - if $"%buildings_edit_mode".selected == 1: - if drag_delay < 0.0 && !dragging: + # Moving/rotating buildings + if mode in [1, 2]: + if ((mode == 1 && drag_delay < 0.0) || mode == 2) && !dragging: dragging = true var position = get_viewport().get_mouse_position() var camera = get_viewport().get_camera() @@ -148,7 +192,14 @@ func check_edit_building(): if result.has("collider"): var proj = result.position drag_start = proj - $WorldEditor.editor_command("buildings_checkpoint", []) + if mode == 2: + var m = proj + m.y = selected_building_xform.origin.y + var xform = selected_building_xform.looking_at(m, Vector3.UP) + $WorldEditor.editor_command("update_building_transform", [selected_building, xform]) + $building_rot_cursor.global_transform = xform + selected_building_xform = xform + $WorldEditor.editor_command("buildings_checkpoint", []) else: drag_delay -= get_process_delta_time() else: @@ -159,6 +210,7 @@ func check_edit_building(): drag_delay = 0.2 func _physics_process(delta): var editor_mode = $WorldEditor.get_current_mode() + var camera_mode = $WorldEditor.get_camera_mode() if camera_mode == 1: var mouse_pos = get_viewport().get_mouse_position() if old_mouse_pos.x < 0: @@ -203,16 +255,17 @@ func _physics_process(delta): $Area.global_transform.origin.z = $Camera.global_transform.origin.z func setup_cam1(): Input.mouse_mode = Input.MOUSE_MODE_CAPTURED - camera_mode = 1 + var camera_mode = $WorldEditor.get_camera_mode() if camera_mode == -1: $Camera.global_transform.origin.y = 80.0 $Camera.global_transform.basis = Basis().rotated(Vector3(1, 0, 0), -PI / 2.0) func setup_cam2(): - camera_mode = 2 + var camera_mode = $WorldEditor.get_camera_mode() Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if camera_mode == -1: $Camera.global_transform.origin.y = 80.0 + $WorldEditor.set_camera_mode(2) $Camera.global_transform.basis = Basis().rotated(Vector3(1, 0, 0), -PI / 4.0) func setup_cam3(): - camera_mode = 3 Input.mouse_mode = Input.MOUSE_MODE_VISIBLE + $WorldEditor.set_camera_mode(3) diff --git a/godot/main/editor.tscn b/godot/main/editor.tscn index d046a49..850f985 100644 --- a/godot/main/editor.tscn +++ b/godot/main/editor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=14 format=2] +[gd_scene load_steps=15 format=2] [ext_resource path="res://main/editor.gd" type="Script" id=1] [ext_resource path="res://terrain/terrain_draw.png" type="Image" id=2] @@ -41,6 +41,9 @@ emission_on_uv2 = false [sub_resource type="BoxShape" id=12] extents = Vector3( 50, 1, 50 ) +[sub_resource type="CubeMesh" id=13] +size = Vector3( 4, 4, 120 ) + [node name="editor" type="Spatial"] script = ExtResource( 1 ) @@ -110,7 +113,7 @@ text = "NPC Mode" unique_name_in_owner = true margin_top = 154.0 margin_right = 160.0 -margin_bottom = 248.0 +margin_bottom = 274.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_buildings"] margin_right = 160.0 @@ -131,25 +134,36 @@ text = "Select" items = [ "Select", null, false, 0, null, "Move", null, false, 1, null, "Rotate", null, false, 2, null ] selected = 0 -[node name="building_type" type="OptionButton" parent="VBoxContainer/v_buildings"] -unique_name_in_owner = true +[node name="Label2" type="Label" parent="VBoxContainer/v_buildings"] margin_top = 50.0 margin_right = 160.0 -margin_bottom = 70.0 +margin_bottom = 64.0 +text = "Building type" + +[node name="building_type" type="OptionButton" parent="VBoxContainer/v_buildings"] +unique_name_in_owner = true +margin_top = 68.0 +margin_right = 160.0 +margin_bottom = 88.0 text = "Building Type" +[node name="HSeparator2" type="HSeparator" parent="VBoxContainer/v_buildings"] +margin_top = 92.0 +margin_right = 160.0 +margin_bottom = 96.0 + [node name="buildings_save" type="Button" parent="VBoxContainer/v_buildings"] unique_name_in_owner = true -margin_top = 74.0 +margin_top = 100.0 margin_right = 160.0 -margin_bottom = 94.0 +margin_bottom = 120.0 text = "Save Buildings" [node name="v_navigation" type="VBoxContainer" parent="VBoxContainer"] unique_name_in_owner = true -margin_top = 252.0 +margin_top = 278.0 margin_right = 160.0 -margin_bottom = 274.0 +margin_bottom = 300.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_navigation"] margin_right = 160.0 @@ -163,9 +177,9 @@ text = "Navigation mode" [node name="v_poi" type="VBoxContainer" parent="VBoxContainer"] unique_name_in_owner = true -margin_top = 278.0 +margin_top = 304.0 margin_right = 160.0 -margin_bottom = 300.0 +margin_bottom = 326.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_poi"] margin_right = 160.0 @@ -179,9 +193,9 @@ text = "POI mode" [node name="v_road_lines" type="VBoxContainer" parent="VBoxContainer"] unique_name_in_owner = true -margin_top = 304.0 +margin_top = 330.0 margin_right = 160.0 -margin_bottom = 326.0 +margin_bottom = 356.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_road_lines"] margin_right = 160.0 @@ -193,11 +207,17 @@ margin_right = 160.0 margin_bottom = 22.0 text = "Road Lines mode" +[node name="lines_list" type="ItemList" parent="VBoxContainer/v_road_lines"] +unique_name_in_owner = true +margin_top = 26.0 +margin_right = 160.0 +margin_bottom = 26.0 + [node name="v_npc" type="VBoxContainer" parent="VBoxContainer"] unique_name_in_owner = true -margin_top = 330.0 +margin_top = 360.0 margin_right = 160.0 -margin_bottom = 352.0 +margin_bottom = 382.0 [node name="HSeparator" type="HSeparator" parent="VBoxContainer/v_npc"] margin_right = 160.0 @@ -249,3 +269,20 @@ monitoring = false [node name="CollisionShape" type="CollisionShape" parent="building_cursor/Area"] transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0 ) shape = SubResource( 12 ) + +[node name="building_rot_cursor" type="Spatial" parent="."] + +[node name="building_rot_cursor" type="MeshInstance" parent="building_rot_cursor"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -60 ) +mesh = SubResource( 13 ) +skeleton = NodePath("../..") +material/0 = SubResource( 11 ) + +[node name="Area" type="Area" parent="building_rot_cursor/building_rot_cursor"] +collision_layer = 32768 +collision_mask = 32768 +monitoring = false + +[node name="CollisionShape" type="CollisionShape" parent="building_rot_cursor/building_rot_cursor/Area"] +transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0 ) +shape = SubResource( 12 ) diff --git a/src/modules/stream/stream.cpp b/src/modules/stream/stream.cpp index 8e8e193..a13fc64 100644 --- a/src/modules/stream/stream.cpp +++ b/src/modules/stream/stream.cpp @@ -436,8 +436,11 @@ void StreamWorld::run_command(const String &command, const Array &args) return; String key = buildings[id].key; buildings[id].xform == args[1]; - Spatial *bnode = Object::cast_to(item_nodes[id]); - bnode->set_global_transform(args[1]); + if (item_nodes.has(id)) { + Spatial *bnode = + Object::cast_to(item_nodes[id]); + bnode->set_global_transform(args[1]); + } VariantWriter::write_to_string(buildings[id].xform, key); buildings[id].key = key; } else if (command == "buildings_checkpoint") { @@ -454,6 +457,26 @@ void StreamWorld::run_command(const String &command, const Array &args) Array ret_data; ret_data.push_back(buildings_data); emit_signal("command_result", command, ret_data); + } else if (command == "change_building_type") { + if (args.size() == 0) { + print_error("bad command: not enough args: " + command); + return; + } + int id = args[0]; + String new_type = args[1]; + Dictionary buildings_data = + config.get_value("buildings", "building_data"); + if (!building_data.has(new_type)) { + print_error("unknown building type: " + new_type); + return; + } + String old_type = buildings[id].id; + unload_building(id); + buildings[id].id = new_type; + load_building(id); + update_items(); + print_line("changed building: " + itos(id) + + " from: " + old_type + " to: " + new_type); } else print_error("No command " + command); } diff --git a/src/modules/stream/world_editor.cpp b/src/modules/stream/world_editor.cpp index 5e54792..6dc85b0 100644 --- a/src/modules/stream/world_editor.cpp +++ b/src/modules/stream/world_editor.cpp @@ -11,6 +11,7 @@ WorldEditor::WorldEditor() , stream_world(nullptr) , editor_menu(nullptr) , current_mode(-1) + , current_camera_mode(-1) { } @@ -18,6 +19,16 @@ WorldEditor::~WorldEditor() { } +void WorldEditor::set_camera_mode(int mode) +{ + current_camera_mode = mode; +} + +int WorldEditor::get_camera_mode() const +{ + return current_camera_mode; +} + void WorldEditor::disable_all() { } @@ -136,6 +147,10 @@ void WorldEditor::editor_command(const String &command, const Array &args) if (stream_world) { stream_world->run_command(command, args); } + } else if (command == "change_building_type") { + if (stream_world) { + stream_world->run_command(command, args); + } } } @@ -198,6 +213,10 @@ void WorldEditor::_bind_methods() &WorldEditor::world_exited); ClassDB::bind_method(D_METHOD("world_command_result", "what", "data"), &WorldEditor::world_command_result); + ClassDB::bind_method(D_METHOD("set_camera_mode", "mode"), + &WorldEditor::set_camera_mode); + ClassDB::bind_method(D_METHOD("get_camera_mode"), + &WorldEditor::get_camera_mode); ADD_SIGNAL(MethodInfo("editor_event", PropertyInfo(Variant::STRING, "event_name"), PropertyInfo(Variant::ARRAY, "args"))); diff --git a/src/modules/stream/world_editor.h b/src/modules/stream/world_editor.h index 123c3db..178b0e7 100644 --- a/src/modules/stream/world_editor.h +++ b/src/modules/stream/world_editor.h @@ -7,6 +7,8 @@ class WorldEditor : public Spatial { protected: StreamWorld *stream_world; Control *editor_menu; + void set_camera_mode(int mode); + int get_camera_mode() const; void disable_all(); void mode_buildings(); void mode_navigation(); @@ -24,6 +26,7 @@ protected: private: void world_exited(); int current_mode; + int current_camera_mode; public: WorldEditor();