2
0

runtime_node_select.cpp 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. /**************************************************************************/
  2. /* runtime_node_select.cpp */
  3. /**************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /**************************************************************************/
  8. /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
  9. /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /**************************************************************************/
  30. #ifdef DEBUG_ENABLED
  31. #include "runtime_node_select.h"
  32. #include "core/config/project_settings.h"
  33. #include "core/debugger/debugger_marshalls.h"
  34. #include "core/debugger/engine_debugger.h"
  35. #include "core/input/input.h"
  36. #include "core/math/geometry_3d.h"
  37. #include "scene/2d/camera_2d.h"
  38. #include "scene/debugger/scene_debugger_object.h"
  39. #include "scene/gui/popup_menu.h"
  40. #include "scene/main/canvas_layer.h"
  41. #include "scene/theme/theme_db.h"
  42. #ifndef PHYSICS_2D_DISABLED
  43. #include "scene/2d/physics/collision_object_2d.h"
  44. #include "scene/2d/physics/collision_polygon_2d.h"
  45. #include "scene/2d/physics/collision_shape_2d.h"
  46. #endif // PHYSICS_2D_DISABLED
  47. #ifndef _3D_DISABLED
  48. #include "scene/3d/camera_3d.h"
  49. #ifndef PHYSICS_3D_DISABLED
  50. #include "scene/3d/physics/collision_object_3d.h"
  51. #include "scene/3d/physics/collision_shape_3d.h"
  52. #endif // PHYSICS_3D_DISABLED
  53. #include "scene/3d/visual_instance_3d.h"
  54. #include "scene/resources/3d/convex_polygon_shape_3d.h"
  55. #include "scene/resources/surface_tool.h"
  56. #endif // _3D_DISABLED
  57. RuntimeNodeSelect *RuntimeNodeSelect::get_singleton() {
  58. return singleton;
  59. }
  60. RuntimeNodeSelect::~RuntimeNodeSelect() {
  61. if (selection_list && !selection_list->is_visible()) {
  62. memdelete(selection_list);
  63. }
  64. if (draw_canvas.is_valid()) {
  65. RS::get_singleton()->free_rid(sel_drag_ci);
  66. RS::get_singleton()->free_rid(sbox_2d_ci);
  67. RS::get_singleton()->free_rid(draw_canvas);
  68. }
  69. }
  70. void RuntimeNodeSelect::_setup(const Dictionary &p_settings) {
  71. Window *root = SceneTree::get_singleton()->get_root();
  72. ERR_FAIL_COND(root->is_connected(SceneStringName(window_input), callable_mp(this, &RuntimeNodeSelect::_root_window_input)));
  73. root->connect(SceneStringName(window_input), callable_mp(this, &RuntimeNodeSelect::_root_window_input));
  74. root->connect("size_changed", callable_mp(this, &RuntimeNodeSelect::_queue_selection_update), CONNECT_DEFERRED);
  75. max_selection = p_settings.get("debugger/max_node_selection", 1);
  76. panner.instantiate();
  77. panner->set_callbacks(callable_mp(this, &RuntimeNodeSelect::_pan_callback), callable_mp(this, &RuntimeNodeSelect::_zoom_callback));
  78. ViewPanner::ControlScheme panning_scheme = (ViewPanner::ControlScheme)p_settings.get("editors/panning/2d_editor_panning_scheme", 0).operator int();
  79. bool simple_panning = p_settings.get("editors/panning/simple_panning", false);
  80. int pan_speed = p_settings.get("editors/panning/2d_editor_pan_speed", 20);
  81. Array keys = p_settings.get("canvas_item_editor/pan_view", Array()).operator Array();
  82. panner->setup(panning_scheme, DebuggerMarshalls::deserialize_key_shortcut(keys), simple_panning);
  83. panner->setup_warped_panning(root, p_settings.get("editors/panning/warped_mouse_panning", true));
  84. panner->set_scroll_speed(pan_speed);
  85. sel_2d_grab_dist = p_settings.get("editors/polygon_editor/point_grab_radius", 0);
  86. sel_2d_scale = MAX(1, Math::ceil(2.0 / (float)GLOBAL_GET("display/window/stretch/scale")));
  87. selection_area_fill = p_settings.get("box_selection_fill_color", Color());
  88. selection_area_outline = p_settings.get("box_selection_stroke_color", Color());
  89. draw_canvas = RS::get_singleton()->canvas_create();
  90. sel_drag_ci = RS::get_singleton()->canvas_item_create();
  91. /// 2D Selection Box Generation
  92. sbox_2d_ci = RS::get_singleton()->canvas_item_create();
  93. RS::get_singleton()->viewport_attach_canvas(root->get_viewport_rid(), draw_canvas);
  94. RS::get_singleton()->canvas_item_set_parent(sel_drag_ci, draw_canvas);
  95. RS::get_singleton()->canvas_item_set_parent(sbox_2d_ci, draw_canvas);
  96. #ifndef _3D_DISABLED
  97. cursor = Cursor();
  98. camera_fov = p_settings.get("editors/3d/default_fov", 70);
  99. camera_znear = p_settings.get("editors/3d/default_z_near", 0.05);
  100. camera_zfar = p_settings.get("editors/3d/default_z_far", 4'000);
  101. invert_x_axis = p_settings.get("editors/3d/navigation/invert_x_axis", false);
  102. invert_y_axis = p_settings.get("editors/3d/navigation/invert_y_axis", false);
  103. warped_mouse_panning_3d = p_settings.get("editors/3d/navigation/warped_mouse_panning", true);
  104. freelook_base_speed = p_settings.get("editors/3d/freelook/freelook_base_speed", 5);
  105. freelook_sensitivity = Math::deg_to_rad((real_t)p_settings.get("editors/3d/freelook/freelook_sensitivity", 0.25));
  106. orbit_sensitivity = Math::deg_to_rad((real_t)p_settings.get("editors/3d/navigation_feel/orbit_sensitivity", 0.004));
  107. translation_sensitivity = p_settings.get("editors/3d/navigation_feel/translation_sensitivity", 1);
  108. /// 3D Selection Box Generation
  109. // Copied from the Node3DEditor implementation.
  110. sbox_3d_color = p_settings.get("editors/3d/selection_box_color", Color());
  111. // Use two AABBs to create the illusion of a slightly thicker line.
  112. AABB aabb(Vector3(), Vector3(1, 1, 1));
  113. // Create a x-ray (visible through solid surfaces) and standard version of the selection box.
  114. // Both will be drawn at the same position, but with different opacity.
  115. // This lets the user see where the selection is while still having a sense of depth.
  116. Ref<SurfaceTool> st = memnew(SurfaceTool);
  117. Ref<SurfaceTool> st_xray = memnew(SurfaceTool);
  118. st->begin(Mesh::PRIMITIVE_LINES);
  119. st_xray->begin(Mesh::PRIMITIVE_LINES);
  120. for (int i = 0; i < 12; i++) {
  121. Vector3 a, b;
  122. aabb.get_edge(i, a, b);
  123. st->add_vertex(a);
  124. st->add_vertex(b);
  125. st_xray->add_vertex(a);
  126. st_xray->add_vertex(b);
  127. }
  128. Ref<StandardMaterial3D> mat = memnew(StandardMaterial3D);
  129. mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
  130. mat->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
  131. mat->set_albedo(sbox_3d_color);
  132. mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
  133. st->set_material(mat);
  134. sbox_3d_mesh = st->commit();
  135. Ref<StandardMaterial3D> mat_xray = memnew(StandardMaterial3D);
  136. mat_xray->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED);
  137. mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_FOG, true);
  138. mat_xray->set_flag(StandardMaterial3D::FLAG_DISABLE_DEPTH_TEST, true);
  139. mat_xray->set_albedo(sbox_3d_color * Color(1, 1, 1, 0.15));
  140. mat_xray->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA);
  141. st_xray->set_material(mat_xray);
  142. sbox_3d_mesh_xray = st_xray->commit();
  143. #endif // _3D_DISABLED
  144. SceneTree::get_singleton()->connect("process_frame", callable_mp(this, &RuntimeNodeSelect::_process_frame));
  145. SceneTree::get_singleton()->connect("physics_frame", callable_mp(this, &RuntimeNodeSelect::_physics_frame));
  146. // This function will be called before the root enters the tree at first when the Game view is passing its settings to
  147. // the debugger, so queue the update for after it enters.
  148. root->connect(SceneStringName(tree_entered), callable_mp(this, &RuntimeNodeSelect::_update_input_state), Object::CONNECT_ONE_SHOT);
  149. }
  150. void RuntimeNodeSelect::_node_set_type(NodeType p_type) {
  151. node_select_type = p_type;
  152. _update_input_state();
  153. }
  154. void RuntimeNodeSelect::_select_set_mode(SelectMode p_mode) {
  155. node_select_mode = p_mode;
  156. }
  157. void RuntimeNodeSelect::_set_camera_override_enabled(bool p_enabled) {
  158. camera_override = p_enabled;
  159. if (camera_first_override) {
  160. _reset_camera_2d();
  161. #ifndef _3D_DISABLED
  162. _reset_camera_3d();
  163. #endif // _3D_DISABLED
  164. camera_first_override = false;
  165. } else if (p_enabled) {
  166. _update_view_2d();
  167. #ifndef _3D_DISABLED
  168. Window *root = SceneTree::get_singleton()->get_root();
  169. ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
  170. Camera3D *override_camera = root->get_override_camera_3d();
  171. override_camera->set_transform(_get_cursor_transform());
  172. override_camera->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
  173. #endif // _3D_DISABLED
  174. }
  175. }
  176. void RuntimeNodeSelect::_root_window_input(const Ref<InputEvent> &p_event) {
  177. Window *root = SceneTree::get_singleton()->get_root();
  178. if (node_select_type == NODE_TYPE_NONE || (selection_list && selection_list->is_visible())) {
  179. // Workaround for platforms that don't allow subwindows.
  180. if (selection_list && selection_list->is_visible() && selection_list->is_embedded()) {
  181. root->set_disable_input_override(false);
  182. selection_list->push_input(p_event);
  183. callable_mp(root->get_viewport(), &Viewport::set_disable_input_override).call_deferred(true);
  184. }
  185. return;
  186. }
  187. bool is_dragging_camera = false;
  188. if (camera_override) {
  189. if (node_select_type == NODE_TYPE_2D) {
  190. is_dragging_camera = panner->gui_input(p_event, Rect2(Vector2(), root->get_visible_rect().get_size()));
  191. #ifndef _3D_DISABLED
  192. } else if (node_select_type == NODE_TYPE_3D && selection_drag_state == SELECTION_DRAG_NONE) {
  193. if (_handle_3d_input(p_event)) {
  194. return;
  195. }
  196. #endif // _3D_DISABLED
  197. }
  198. }
  199. Ref<InputEventMouseButton> b = p_event;
  200. if (selection_drag_state == SELECTION_DRAG_MOVE) {
  201. Ref<InputEventMouseMotion> m = p_event;
  202. if (m.is_valid()) {
  203. _update_selection_drag(root->get_screen_transform().affine_inverse().xform(m->get_position()));
  204. return;
  205. } else if (b.is_valid()) {
  206. // Account for actions like zooming.
  207. _update_selection_drag(root->get_screen_transform().affine_inverse().xform(b->get_position()));
  208. }
  209. }
  210. if (b.is_null()) {
  211. return;
  212. }
  213. // Ignore mouse wheel inputs.
  214. if (b->get_button_index() != MouseButton::LEFT && b->get_button_index() != MouseButton::RIGHT) {
  215. return;
  216. }
  217. if (selection_drag_state == SELECTION_DRAG_MOVE && !b->is_pressed() && b->get_button_index() == MouseButton::LEFT) {
  218. selection_drag_state = SELECTION_DRAG_END;
  219. selection_drag_area = selection_drag_area.abs();
  220. _update_selection_drag();
  221. // Trigger a selection in the position on release.
  222. if (multi_shortcut_pressed) {
  223. selection_position = root->get_screen_transform().affine_inverse().xform(b->get_position());
  224. }
  225. }
  226. if (!is_dragging_camera && b->is_pressed()) {
  227. multi_shortcut_pressed = b->is_shift_pressed();
  228. list_shortcut_pressed = node_select_mode == SELECT_MODE_SINGLE && b->get_button_index() == MouseButton::RIGHT && b->is_alt_pressed();
  229. if (list_shortcut_pressed || b->get_button_index() == MouseButton::LEFT) {
  230. selection_position = root->get_screen_transform().affine_inverse().xform(b->get_position());
  231. }
  232. }
  233. }
  234. void RuntimeNodeSelect::_items_popup_index_pressed(int p_index, PopupMenu *p_popup) {
  235. Object *obj = p_popup->get_item_metadata(p_index).get_validated_object();
  236. if (obj) {
  237. Vector<Node *> node;
  238. node.append(Object::cast_to<Node>(obj));
  239. _send_ids(node);
  240. }
  241. }
  242. void RuntimeNodeSelect::_update_input_state() {
  243. SceneTree *scene_tree = SceneTree::get_singleton();
  244. // This function can be called at the very beginning, when the root hasn't entered the tree yet.
  245. // So check first to avoid a crash.
  246. if (!scene_tree->get_root()->is_inside_tree()) {
  247. return;
  248. }
  249. bool disable_input = scene_tree->is_suspended() || node_select_type != RuntimeNodeSelect::NODE_TYPE_NONE;
  250. Input::get_singleton()->set_disable_input(disable_input);
  251. Input::get_singleton()->set_mouse_mode_override_enabled(disable_input);
  252. scene_tree->get_root()->set_disable_input_override(disable_input);
  253. }
  254. void RuntimeNodeSelect::_process_frame() {
  255. #ifndef _3D_DISABLED
  256. if (camera_freelook) {
  257. Transform3D transform = _get_cursor_transform();
  258. Vector3 forward = transform.basis.xform(Vector3(0, 0, -1));
  259. const Vector3 right = transform.basis.xform(Vector3(1, 0, 0));
  260. Vector3 up = transform.basis.xform(Vector3(0, 1, 0));
  261. Vector3 direction;
  262. Input *input = Input::get_singleton();
  263. bool was_input_disabled = input->is_input_disabled();
  264. if (was_input_disabled) {
  265. input->set_disable_input(false);
  266. }
  267. if (input->is_physical_key_pressed(Key::A)) {
  268. direction -= right;
  269. }
  270. if (input->is_physical_key_pressed(Key::D)) {
  271. direction += right;
  272. }
  273. if (input->is_physical_key_pressed(Key::W)) {
  274. direction += forward;
  275. }
  276. if (input->is_physical_key_pressed(Key::S)) {
  277. direction -= forward;
  278. }
  279. if (input->is_physical_key_pressed(Key::E)) {
  280. direction += up;
  281. }
  282. if (input->is_physical_key_pressed(Key::Q)) {
  283. direction -= up;
  284. }
  285. real_t speed = freelook_base_speed;
  286. if (input->is_physical_key_pressed(Key::SHIFT)) {
  287. speed *= 3.0;
  288. }
  289. if (input->is_physical_key_pressed(Key::ALT)) {
  290. speed *= 0.333333;
  291. }
  292. if (was_input_disabled) {
  293. input->set_disable_input(true);
  294. }
  295. if (direction != Vector3()) {
  296. Window *root = SceneTree::get_singleton()->get_root();
  297. ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
  298. // Calculate the process time manually, as the time scale is frozen.
  299. const double process_time = (1.0 / Engine::get_singleton()->get_frames_per_second()) * Engine::get_singleton()->get_unfrozen_time_scale();
  300. const Vector3 motion = direction * speed * process_time;
  301. cursor.pos += motion;
  302. cursor.eye_pos += motion;
  303. root->get_override_camera_3d()->set_transform(_get_cursor_transform());
  304. }
  305. }
  306. #endif // _3D_DISABLED
  307. if (selection_update_queued || !SceneTree::get_singleton()->is_suspended()) {
  308. selection_update_queued = false;
  309. if (has_selection) {
  310. _update_selection();
  311. }
  312. }
  313. }
  314. void RuntimeNodeSelect::_physics_frame() {
  315. if (selection_drag_state != SELECTION_DRAG_END && (selection_drag_state == SELECTION_DRAG_MOVE || Math::is_inf(selection_position.x))) {
  316. return;
  317. }
  318. Window *root = SceneTree::get_singleton()->get_root();
  319. bool selection_drag_valid = selection_drag_state == SELECTION_DRAG_END && selection_drag_area.get_area() > SELECTION_MIN_AREA;
  320. Vector<SelectResult> items;
  321. if (node_select_type == NODE_TYPE_2D) {
  322. if (selection_drag_valid) {
  323. for (int i = 0; i < root->get_child_count(); i++) {
  324. _find_canvas_items_at_rect(selection_drag_area, root->get_child(i), items);
  325. }
  326. } else if (!Math::is_inf(selection_position.x)) {
  327. for (int i = 0; i < root->get_child_count(); i++) {
  328. _find_canvas_items_at_pos(selection_position, root->get_child(i), items);
  329. }
  330. }
  331. #ifndef _3D_DISABLED
  332. } else if (node_select_type == NODE_TYPE_3D) {
  333. if (selection_drag_valid) {
  334. _find_3d_items_at_rect(selection_drag_area, items);
  335. } else {
  336. _find_3d_items_at_pos(selection_position, items);
  337. }
  338. #endif // _3D_DISABLED
  339. }
  340. if ((prefer_group_selection || avoid_locked_nodes) && !list_shortcut_pressed && node_select_mode == SELECT_MODE_SINGLE) {
  341. for (int i = 0; i < items.size(); i++) {
  342. Node *node = items[i].item;
  343. Node *final_node = node;
  344. real_t order = items[i].order;
  345. // Replace the node by the group if grouped.
  346. if (prefer_group_selection) {
  347. while (node && node != root) {
  348. if (node->has_meta("_edit_group_")) {
  349. final_node = node;
  350. if (Object::cast_to<CanvasItem>(final_node)) {
  351. CanvasItem *ci_tmp = Object::cast_to<CanvasItem>(final_node);
  352. order = ci_tmp->get_effective_z_index() + ci_tmp->get_canvas_layer();
  353. #ifndef _3D_DISABLED
  354. } else if (Object::cast_to<Node3D>(final_node)) {
  355. Node3D *node3d_tmp = Object::cast_to<Node3D>(final_node);
  356. Camera3D *camera = root->get_camera_3d();
  357. Vector3 pos = camera->project_ray_origin(selection_position);
  358. order = -pos.distance_to(node3d_tmp->get_global_transform().origin);
  359. #endif // _3D_DISABLED
  360. }
  361. }
  362. node = node->get_parent();
  363. }
  364. }
  365. // Filter out locked nodes.
  366. if (avoid_locked_nodes && final_node->get_meta("_edit_lock_", false)) {
  367. items.remove_at(i);
  368. i--;
  369. continue;
  370. }
  371. items.write[i].item = final_node;
  372. items.write[i].order = order;
  373. }
  374. }
  375. // Remove possible duplicates.
  376. for (int i = 0; i < items.size(); i++) {
  377. Node *item = items[i].item;
  378. for (int j = 0; j < i; j++) {
  379. if (items[j].item == item) {
  380. items.remove_at(i);
  381. i--;
  382. break;
  383. }
  384. }
  385. }
  386. items.sort();
  387. switch (selection_drag_state) {
  388. case SELECTION_DRAG_END: {
  389. selection_position = Point2(Math::INF, Math::INF);
  390. selection_drag_state = SELECTION_DRAG_NONE;
  391. if (selection_drag_area.get_area() > SELECTION_MIN_AREA) {
  392. if (!items.is_empty()) {
  393. Vector<Node *> nodes;
  394. for (const SelectResult item : items) {
  395. nodes.append(item.item);
  396. }
  397. _send_ids(nodes, false);
  398. }
  399. _update_selection_drag();
  400. return;
  401. }
  402. _update_selection_drag();
  403. } break;
  404. case SELECTION_DRAG_NONE: {
  405. if (node_select_mode == SELECT_MODE_LIST) {
  406. break;
  407. }
  408. if (multi_shortcut_pressed) {
  409. // Allow forcing box selection when an item was clicked.
  410. selection_drag_state = SELECTION_DRAG_MOVE;
  411. } else if (items.is_empty()) {
  412. #ifdef _3D_DISABLED
  413. if (!selected_ci_nodes.is_empty()) {
  414. #else
  415. if (!selected_ci_nodes.is_empty() || !selected_3d_nodes.is_empty()) {
  416. #endif // _3D_DISABLED
  417. EngineDebugger::get_singleton()->send_message("remote_nothing_selected", Array());
  418. _clear_selection();
  419. }
  420. selection_drag_state = SELECTION_DRAG_MOVE;
  421. } else {
  422. break;
  423. }
  424. [[fallthrough]];
  425. }
  426. case SELECTION_DRAG_MOVE: {
  427. selection_drag_area.position = selection_position;
  428. // Stop selection on click, so it can happen on release if the selection area doesn't pass the threshold.
  429. if (multi_shortcut_pressed) {
  430. return;
  431. }
  432. }
  433. }
  434. if (items.is_empty()) {
  435. selection_position = Point2(Math::INF, Math::INF);
  436. return;
  437. }
  438. if ((!list_shortcut_pressed && node_select_mode == SELECT_MODE_SINGLE) || items.size() == 1) {
  439. selection_position = Point2(Math::INF, Math::INF);
  440. Vector<Node *> node;
  441. node.append(items[0].item);
  442. _send_ids(node);
  443. return;
  444. }
  445. if (!selection_list && (list_shortcut_pressed || node_select_mode == SELECT_MODE_LIST)) {
  446. _open_selection_list(items, selection_position);
  447. }
  448. selection_position = Point2(Math::INF, Math::INF);
  449. }
  450. void RuntimeNodeSelect::_send_ids(const Vector<Node *> &p_picked_nodes, bool p_invert_new_selections) {
  451. ERR_FAIL_COND(p_picked_nodes.is_empty());
  452. Vector<Node *> picked_nodes = p_picked_nodes;
  453. Array message;
  454. if (!multi_shortcut_pressed) {
  455. if (picked_nodes.size() > max_selection) {
  456. picked_nodes.resize(max_selection);
  457. EngineDebugger::get_singleton()->send_message("show_selection_limit_warning", Array());
  458. }
  459. for (const Node *node : picked_nodes) {
  460. SceneDebuggerObject obj(node->get_instance_id());
  461. Array arr;
  462. obj.serialize(arr);
  463. message.append(arr);
  464. }
  465. EngineDebugger::get_singleton()->send_message("remote_objects_selected", message);
  466. _set_selected_nodes(picked_nodes);
  467. return;
  468. }
  469. LocalVector<Node *> nodes;
  470. LocalVector<ObjectID> ids;
  471. for (Node *node : picked_nodes) {
  472. ObjectID id = node->get_instance_id();
  473. if (CanvasItem *ci = Object::cast_to<CanvasItem>(node)) {
  474. if (selected_ci_nodes.has(id)) {
  475. if (p_invert_new_selections) {
  476. selected_ci_nodes.erase(id);
  477. }
  478. } else {
  479. ids.push_back(id);
  480. nodes.push_back(ci);
  481. }
  482. } else {
  483. #ifndef _3D_DISABLED
  484. if (Node3D *node3d = Object::cast_to<Node3D>(node)) {
  485. if (selected_3d_nodes.has(id)) {
  486. if (p_invert_new_selections) {
  487. selected_3d_nodes.erase(id);
  488. }
  489. } else {
  490. ids.push_back(id);
  491. nodes.push_back(node3d);
  492. }
  493. }
  494. #endif // _3D_DISABLED
  495. }
  496. }
  497. uint32_t limit = max_selection - selected_ci_nodes.size();
  498. #ifndef _3D_DISABLED
  499. limit -= selected_3d_nodes.size();
  500. #endif // _3D_DISABLED
  501. if (ids.size() > limit) {
  502. ids.resize(limit);
  503. nodes.resize(limit);
  504. EngineDebugger::get_singleton()->send_message("show_selection_limit_warning", Array());
  505. }
  506. for (ObjectID id : selected_ci_nodes) {
  507. ids.push_back(id);
  508. nodes.push_back(ObjectDB::get_instance<Node>(id));
  509. }
  510. #ifndef _3D_DISABLED
  511. for (const KeyValue<ObjectID, Ref<SelectionBox3D>> &KV : selected_3d_nodes) {
  512. ids.push_back(KV.key);
  513. nodes.push_back(ObjectDB::get_instance<Node>(KV.key));
  514. }
  515. #endif // _3D_DISABLED
  516. if (ids.is_empty()) {
  517. EngineDebugger::get_singleton()->send_message("remote_nothing_selected", message);
  518. } else {
  519. for (const ObjectID &id : ids) {
  520. SceneDebuggerObject obj(id);
  521. Array arr;
  522. obj.serialize(arr);
  523. message.append(arr);
  524. }
  525. EngineDebugger::get_singleton()->send_message("remote_objects_selected", message);
  526. }
  527. _set_selected_nodes(Vector<Node *>(nodes));
  528. }
  529. void RuntimeNodeSelect::_set_selected_nodes(const Vector<Node *> &p_nodes) {
  530. if (p_nodes.is_empty()) {
  531. _clear_selection();
  532. return;
  533. }
  534. bool changed = false;
  535. LocalVector<ObjectID> nodes_ci;
  536. #ifndef _3D_DISABLED
  537. HashMap<ObjectID, Ref<SelectionBox3D>> nodes_3d;
  538. #endif // _3D_DISABLED
  539. for (Node *node : p_nodes) {
  540. ObjectID id = node->get_instance_id();
  541. if (Object::cast_to<CanvasItem>(node)) {
  542. if (!changed || !selected_ci_nodes.has(id)) {
  543. changed = true;
  544. }
  545. nodes_ci.push_back(id);
  546. } else {
  547. #ifndef _3D_DISABLED
  548. Node3D *node_3d = Object::cast_to<Node3D>(node);
  549. if (!node_3d || !node_3d->is_inside_world()) {
  550. continue;
  551. }
  552. if (!changed || !selected_3d_nodes.has(id)) {
  553. changed = true;
  554. }
  555. if (selected_3d_nodes.has(id)) {
  556. // Assign an already available visual instance.
  557. nodes_3d[id] = selected_3d_nodes.get(id);
  558. continue;
  559. }
  560. if (sbox_3d_mesh.is_null() || sbox_3d_mesh_xray.is_null()) {
  561. continue;
  562. }
  563. Ref<SelectionBox3D> sb;
  564. sb.instantiate();
  565. nodes_3d[id] = sb;
  566. RID scenario = node_3d->get_world_3d()->get_scenario();
  567. sb->instance = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), scenario);
  568. sb->instance_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh->get_rid(), scenario);
  569. RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance, RS::SHADOW_CASTING_SETTING_OFF);
  570. RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_ofs, RS::SHADOW_CASTING_SETTING_OFF);
  571. RS::get_singleton()->instance_geometry_set_flag(sb->instance, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
  572. RS::get_singleton()->instance_geometry_set_flag(sb->instance, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
  573. RS::get_singleton()->instance_geometry_set_flag(sb->instance_ofs, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
  574. RS::get_singleton()->instance_geometry_set_flag(sb->instance_ofs, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
  575. sb->instance_xray = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), scenario);
  576. sb->instance_xray_ofs = RS::get_singleton()->instance_create2(sbox_3d_mesh_xray->get_rid(), scenario);
  577. RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_xray, RS::SHADOW_CASTING_SETTING_OFF);
  578. RS::get_singleton()->instance_geometry_set_cast_shadows_setting(sb->instance_xray_ofs, RS::SHADOW_CASTING_SETTING_OFF);
  579. RS::get_singleton()->instance_geometry_set_flag(sb->instance_xray, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
  580. RS::get_singleton()->instance_geometry_set_flag(sb->instance_xray, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
  581. RS::get_singleton()->instance_geometry_set_flag(sb->instance_xray_ofs, RS::INSTANCE_FLAG_IGNORE_OCCLUSION_CULLING, true);
  582. RS::get_singleton()->instance_geometry_set_flag(sb->instance_xray_ofs, RS::INSTANCE_FLAG_USE_BAKED_LIGHT, false);
  583. #endif // _3D_DISABLED
  584. }
  585. }
  586. #ifdef _3D_DISABLED
  587. if (!changed && nodes_ci.size() == selected_ci_nodes.size()) {
  588. return;
  589. }
  590. #else
  591. if (!changed && nodes_ci.size() == selected_ci_nodes.size() && nodes_3d.size() == selected_3d_nodes.size()) {
  592. return;
  593. }
  594. #endif // _3D_DISABLED
  595. _clear_selection();
  596. selected_ci_nodes = nodes_ci;
  597. has_selection = !nodes_ci.is_empty();
  598. #ifndef _3D_DISABLED
  599. if (!nodes_3d.is_empty()) {
  600. selected_3d_nodes = nodes_3d;
  601. has_selection = true;
  602. }
  603. #endif // _3D_DISABLED
  604. _queue_selection_update();
  605. }
  606. void RuntimeNodeSelect::_queue_selection_update() {
  607. if (has_selection && selection_visible) {
  608. if (SceneTree::get_singleton()->is_suspended()) {
  609. _update_selection();
  610. } else {
  611. selection_update_queued = true;
  612. }
  613. }
  614. }
  615. void RuntimeNodeSelect::_update_selection() {
  616. RS::get_singleton()->canvas_item_clear(sbox_2d_ci);
  617. RS::get_singleton()->canvas_item_set_visible(sbox_2d_ci, selection_visible);
  618. for (LocalVector<ObjectID>::Iterator E = selected_ci_nodes.begin(); E != selected_ci_nodes.end(); ++E) {
  619. ObjectID id = *E;
  620. CanvasItem *ci = ObjectDB::get_instance<CanvasItem>(id);
  621. if (!ci) {
  622. selected_ci_nodes.erase(id);
  623. --E;
  624. continue;
  625. }
  626. if (!ci->is_inside_tree()) {
  627. continue;
  628. }
  629. Transform2D xform = ci->get_global_transform_with_canvas();
  630. // Fallback.
  631. Rect2 rect = Rect2(Vector2(), Vector2(10, 10));
  632. if (ci->_edit_use_rect()) {
  633. rect = ci->_edit_get_rect();
  634. } else {
  635. #ifndef PHYSICS_2D_DISABLED
  636. CollisionShape2D *collision_shape = Object::cast_to<CollisionShape2D>(ci);
  637. if (collision_shape) {
  638. Ref<Shape2D> shape = collision_shape->get_shape();
  639. if (shape.is_valid()) {
  640. rect = shape->get_rect();
  641. }
  642. }
  643. #endif // PHYSICS_2D_DISABLED
  644. }
  645. const Vector2 endpoints[4] = {
  646. xform.xform(rect.position),
  647. xform.xform(rect.position + Point2(rect.size.x, 0)),
  648. xform.xform(rect.position + rect.size),
  649. xform.xform(rect.position + Point2(0, rect.size.y))
  650. };
  651. const Color selection_color_2d = Color(1, 0.6, 0.4, 0.7);
  652. for (int i = 0; i < 4; i++) {
  653. RS::get_singleton()->canvas_item_add_line(sbox_2d_ci, endpoints[i], endpoints[(i + 1) % 4], selection_color_2d, sel_2d_scale);
  654. }
  655. }
  656. #ifndef _3D_DISABLED
  657. for (HashMap<ObjectID, Ref<SelectionBox3D>>::ConstIterator KV = selected_3d_nodes.begin(); KV != selected_3d_nodes.end(); ++KV) {
  658. ObjectID id = KV->key;
  659. Node3D *node_3d = ObjectDB::get_instance<Node3D>(id);
  660. if (!node_3d) {
  661. selected_3d_nodes.erase(id);
  662. --KV;
  663. continue;
  664. }
  665. if (!node_3d->is_inside_tree()) {
  666. continue;
  667. }
  668. // Fallback.
  669. AABB bounds(Vector3(-0.5, -0.5, -0.5), Vector3(1, 1, 1));
  670. VisualInstance3D *visual_instance = Object::cast_to<VisualInstance3D>(node_3d);
  671. if (visual_instance) {
  672. bounds = visual_instance->get_aabb();
  673. } else {
  674. #ifndef PHYSICS_3D_DISABLED
  675. CollisionShape3D *collision_shape = Object::cast_to<CollisionShape3D>(node_3d);
  676. if (collision_shape) {
  677. Ref<Shape3D> shape = collision_shape->get_shape();
  678. if (shape.is_valid()) {
  679. bounds = shape->get_debug_mesh()->get_aabb();
  680. }
  681. }
  682. #endif // PHYSICS_3D_DISABLED
  683. }
  684. Transform3D xform_to_top_level_parent_space = node_3d->get_global_transform().affine_inverse() * node_3d->get_global_transform();
  685. bounds = xform_to_top_level_parent_space.xform(bounds);
  686. Transform3D t = node_3d->get_global_transform();
  687. Ref<SelectionBox3D> sb = KV->value;
  688. if (t == sb->transform && bounds == sb->bounds) {
  689. continue; // Nothing changed.
  690. }
  691. sb->transform = t;
  692. sb->bounds = bounds;
  693. Transform3D t_offset = t;
  694. // Apply AABB scaling before item's global transform.
  695. {
  696. const Vector3 offset(0.005, 0.005, 0.005);
  697. Basis aabb_s;
  698. aabb_s.scale(bounds.size + offset);
  699. t.translate_local(bounds.position - offset / 2);
  700. t.basis = t.basis * aabb_s;
  701. }
  702. {
  703. const Vector3 offset(0.01, 0.01, 0.01);
  704. Basis aabb_s;
  705. aabb_s.scale(bounds.size + offset);
  706. t_offset.translate_local(bounds.position - offset / 2);
  707. t_offset.basis = t_offset.basis * aabb_s;
  708. }
  709. RS::get_singleton()->instance_set_visible(sb->instance, selection_visible);
  710. RS::get_singleton()->instance_set_visible(sb->instance_ofs, selection_visible);
  711. RS::get_singleton()->instance_set_visible(sb->instance_xray, selection_visible);
  712. RS::get_singleton()->instance_set_visible(sb->instance_xray_ofs, selection_visible);
  713. RS::get_singleton()->instance_set_transform(sb->instance, t);
  714. RS::get_singleton()->instance_set_transform(sb->instance_ofs, t_offset);
  715. RS::get_singleton()->instance_set_transform(sb->instance_xray, t);
  716. RS::get_singleton()->instance_set_transform(sb->instance_xray_ofs, t_offset);
  717. }
  718. #endif // _3D_DISABLED
  719. }
  720. void RuntimeNodeSelect::_clear_selection() {
  721. selected_ci_nodes.clear();
  722. if (draw_canvas.is_valid()) {
  723. RS::get_singleton()->canvas_item_clear(sbox_2d_ci);
  724. }
  725. #ifndef _3D_DISABLED
  726. selected_3d_nodes.clear();
  727. #endif // _3D_DISABLED
  728. has_selection = false;
  729. }
  730. void RuntimeNodeSelect::_update_selection_drag(const Point2 &p_end_pos) {
  731. RS::get_singleton()->canvas_item_clear(sel_drag_ci);
  732. if (selection_drag_state != SELECTION_DRAG_MOVE) {
  733. return;
  734. }
  735. selection_drag_area.size = p_end_pos - selection_drag_area.position;
  736. if (selection_drag_state == SELECTION_DRAG_END) {
  737. return;
  738. }
  739. Rect2 selection_drawing = selection_drag_area.abs();
  740. int thickness = 1;
  741. const Vector2 endpoints[4] = {
  742. selection_drawing.position,
  743. selection_drawing.position + Point2(selection_drawing.size.x, 0),
  744. selection_drawing.position + selection_drawing.size,
  745. selection_drawing.position + Point2(0, selection_drawing.size.y)
  746. };
  747. // Draw fill.
  748. RS::get_singleton()->canvas_item_add_rect(sel_drag_ci, selection_drawing, selection_area_fill);
  749. // Draw outline.
  750. for (int i = 0; i < 4; i++) {
  751. RS::get_singleton()->canvas_item_add_line(sel_drag_ci, endpoints[i], endpoints[(i + 1) % 4], selection_area_outline, thickness);
  752. }
  753. }
  754. void RuntimeNodeSelect::_open_selection_list(const Vector<SelectResult> &p_items, const Point2 &p_pos) {
  755. Window *root = SceneTree::get_singleton()->get_root();
  756. selection_list = memnew(PopupMenu);
  757. selection_list->set_theme(ThemeDB::get_singleton()->get_default_theme());
  758. selection_list->set_auto_translate_mode(Node::AUTO_TRANSLATE_MODE_DISABLED);
  759. selection_list->set_force_native(true);
  760. selection_list->connect("index_pressed", callable_mp(this, &RuntimeNodeSelect::_items_popup_index_pressed).bind(selection_list));
  761. selection_list->connect("popup_hide", callable_mp(this, &RuntimeNodeSelect::_close_selection_list));
  762. root->add_child(selection_list);
  763. for (const SelectResult &I : p_items) {
  764. int locked = 0;
  765. if (I.item->get_meta("_edit_lock_", false)) {
  766. locked = 1;
  767. } else {
  768. Node *scene = SceneTree::get_singleton()->get_root();
  769. Node *node = I.item;
  770. while (node && node != scene->get_parent()) {
  771. if (node->has_meta("_edit_group_")) {
  772. locked = 2;
  773. }
  774. node = node->get_parent();
  775. }
  776. }
  777. String suffix;
  778. if (locked == 1) {
  779. suffix = " (" + RTR("Locked") + ")";
  780. } else if (locked == 2) {
  781. suffix = " (" + RTR("Grouped") + ")";
  782. }
  783. selection_list->add_item((String)I.item->get_name() + suffix);
  784. selection_list->set_item_metadata(-1, I.item);
  785. }
  786. selection_list->set_position(selection_list->is_embedded() ? p_pos : (Input::get_singleton()->get_mouse_position() + root->get_position()));
  787. selection_list->reset_size();
  788. selection_list->popup();
  789. selection_list->set_content_scale_factor(1);
  790. selection_list->set_min_size(selection_list->get_contents_minimum_size());
  791. selection_list->reset_size();
  792. // FIXME: Ugly hack that stops the popup from hiding when the button is released.
  793. selection_list->call_deferred(SNAME("set_position"), selection_list->get_position() + Point2(1, 0));
  794. }
  795. void RuntimeNodeSelect::_close_selection_list() {
  796. selection_list->queue_free();
  797. selection_list = nullptr;
  798. }
  799. void RuntimeNodeSelect::_set_selection_visible(bool p_visible) {
  800. selection_visible = p_visible;
  801. if (has_selection) {
  802. _update_selection();
  803. }
  804. }
  805. void RuntimeNodeSelect::_set_avoid_locked(bool p_enabled) {
  806. avoid_locked_nodes = p_enabled;
  807. }
  808. void RuntimeNodeSelect::_set_prefer_group(bool p_enabled) {
  809. prefer_group_selection = p_enabled;
  810. }
  811. // Copied and trimmed from the CanvasItemEditor implementation.
  812. void RuntimeNodeSelect::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_node, Vector<SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  813. if (!p_node || Object::cast_to<Viewport>(p_node)) {
  814. return;
  815. }
  816. CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
  817. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  818. if (ci) {
  819. if (!ci->is_set_as_top_level()) {
  820. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, p_parent_xform * ci->get_transform(), p_canvas_xform);
  821. } else {
  822. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, ci->get_transform(), p_canvas_xform);
  823. }
  824. } else {
  825. CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
  826. _find_canvas_items_at_pos(p_pos, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
  827. }
  828. }
  829. if (!ci || !ci->is_visible_in_tree()) {
  830. return;
  831. }
  832. Transform2D xform = p_canvas_xform;
  833. if (!ci->is_set_as_top_level()) {
  834. xform *= p_parent_xform;
  835. }
  836. Window *root = SceneTree::get_singleton()->get_root();
  837. Point2 pos;
  838. // Cameras don't affect `CanvasLayer`s.
  839. if (!ci->get_canvas_layer_node() || ci->get_canvas_layer_node()->is_following_viewport()) {
  840. pos = root->get_canvas_transform().affine_inverse().xform(p_pos);
  841. } else {
  842. pos = p_pos;
  843. }
  844. xform = (xform * ci->get_transform()).affine_inverse();
  845. const real_t local_grab_distance = xform.basis_xform(Vector2(sel_2d_grab_dist, 0)).length() / view_2d_zoom;
  846. if (ci->_edit_is_selected_on_click(xform.xform(pos), local_grab_distance)) {
  847. SelectResult res;
  848. res.item = ci;
  849. res.order = ci->get_effective_z_index() + ci->get_canvas_layer();
  850. r_items.push_back(res);
  851. #ifndef PHYSICS_2D_DISABLED
  852. // If it's a shape, get the collision object it's from.
  853. // FIXME: If the collision object has multiple shapes, only the topmost will be above it in the list.
  854. if (Object::cast_to<CollisionShape2D>(ci) || Object::cast_to<CollisionPolygon2D>(ci)) {
  855. CollisionObject2D *collision_object = Object::cast_to<CollisionObject2D>(ci->get_parent());
  856. if (collision_object) {
  857. SelectResult res_col;
  858. res_col.item = ci->get_parent();
  859. res_col.order = collision_object->get_z_index() + ci->get_canvas_layer();
  860. r_items.push_back(res_col);
  861. }
  862. }
  863. #endif // PHYSICS_2D_DISABLED
  864. }
  865. }
  866. // Copied and trimmed from the CanvasItemEditor implementation.
  867. void RuntimeNodeSelect::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_node, Vector<SelectResult> &r_items, const Transform2D &p_parent_xform, const Transform2D &p_canvas_xform) {
  868. if (!p_node || Object::cast_to<Viewport>(p_node)) {
  869. return;
  870. }
  871. CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
  872. for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
  873. if (ci) {
  874. if (!ci->is_set_as_top_level()) {
  875. _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, p_parent_xform * ci->get_transform(), p_canvas_xform);
  876. } else {
  877. _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, ci->get_transform(), p_canvas_xform);
  878. }
  879. } else {
  880. CanvasLayer *cl = Object::cast_to<CanvasLayer>(p_node);
  881. _find_canvas_items_at_rect(p_rect, p_node->get_child(i), r_items, Transform2D(), cl ? cl->get_transform() : p_canvas_xform);
  882. }
  883. }
  884. if (!ci || !ci->is_visible_in_tree()) {
  885. return;
  886. }
  887. Transform2D xform = p_canvas_xform;
  888. if (!ci->is_set_as_top_level()) {
  889. xform *= p_parent_xform;
  890. }
  891. Window *root = SceneTree::get_singleton()->get_root();
  892. Rect2 rect;
  893. // Cameras don't affect `CanvasLayer`s.
  894. if (!ci->get_canvas_layer_node() || ci->get_canvas_layer_node()->is_following_viewport()) {
  895. rect = root->get_canvas_transform().affine_inverse().xform(p_rect);
  896. } else {
  897. rect = p_rect;
  898. }
  899. rect = (xform * ci->get_transform()).affine_inverse().xform(rect);
  900. bool selected = false;
  901. if (ci->_edit_use_rect()) {
  902. Rect2 ci_rect = ci->_edit_get_rect();
  903. if (rect.has_point(ci_rect.position) &&
  904. rect.has_point(ci_rect.position + Vector2(ci_rect.size.x, 0)) &&
  905. rect.has_point(ci_rect.position + Vector2(ci_rect.size.x, ci_rect.size.y)) &&
  906. rect.has_point(ci_rect.position + Vector2(0, ci_rect.size.y))) {
  907. selected = true;
  908. }
  909. } else if (rect.has_point(Point2())) {
  910. selected = true;
  911. }
  912. if (selected) {
  913. SelectResult res;
  914. res.item = ci;
  915. res.order = ci->get_effective_z_index() + ci->get_canvas_layer();
  916. r_items.push_back(res);
  917. }
  918. }
  919. void RuntimeNodeSelect::_pan_callback(Vector2 p_scroll_vec, Ref<InputEvent> p_event) {
  920. Vector2 scroll = SceneTree::get_singleton()->get_root()->get_screen_transform().affine_inverse().xform(p_scroll_vec);
  921. view_2d_offset.x -= scroll.x / view_2d_zoom;
  922. view_2d_offset.y -= scroll.y / view_2d_zoom;
  923. _update_view_2d();
  924. }
  925. // A very shallow copy of the same function inside CanvasItemEditor.
  926. void RuntimeNodeSelect::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Ref<InputEvent> p_event) {
  927. real_t prev_zoom = view_2d_zoom;
  928. view_2d_zoom = CLAMP(view_2d_zoom * p_zoom_factor, VIEW_2D_MIN_ZOOM, VIEW_2D_MAX_ZOOM);
  929. Vector2 pos = SceneTree::get_singleton()->get_root()->get_screen_transform().affine_inverse().xform(p_origin);
  930. view_2d_offset += pos / prev_zoom - pos / view_2d_zoom;
  931. // We want to align in-scene pixels to screen pixels, this prevents blurry rendering
  932. // of small details (texts, lines).
  933. // This correction adds a jitter movement when zooming, so we correct only when the
  934. // zoom factor is an integer. (in the other cases, all pixels won't be aligned anyway)
  935. const real_t closest_zoom_factor = Math::round(view_2d_zoom);
  936. if (Math::is_zero_approx(view_2d_zoom - closest_zoom_factor)) {
  937. // Make sure scene pixel at view_offset is aligned on a screen pixel.
  938. Vector2 view_offset_int = view_2d_offset.floor();
  939. Vector2 view_offset_frac = view_2d_offset - view_offset_int;
  940. view_2d_offset = view_offset_int + (view_offset_frac * closest_zoom_factor).round() / closest_zoom_factor;
  941. }
  942. _update_view_2d();
  943. }
  944. void RuntimeNodeSelect::_reset_camera_2d() {
  945. camera_first_override = true;
  946. Window *root = SceneTree::get_singleton()->get_root();
  947. Camera2D *game_camera = root->is_camera_2d_override_enabled() ? root->get_overridden_camera_2d() : root->get_camera_2d();
  948. if (game_camera) {
  949. // Ideally we should be using Camera2D::get_camera_transform() but it's not so this hack will have to do for now.
  950. view_2d_offset = game_camera->get_camera_screen_center() - (0.5 * root->get_visible_rect().size);
  951. } else {
  952. view_2d_offset = Vector2();
  953. }
  954. view_2d_zoom = 1;
  955. if (root->is_camera_2d_override_enabled()) {
  956. _update_view_2d();
  957. }
  958. }
  959. void RuntimeNodeSelect::_update_view_2d() {
  960. Window *root = SceneTree::get_singleton()->get_root();
  961. ERR_FAIL_COND(!root->is_camera_2d_override_enabled());
  962. Camera2D *override_camera = root->get_override_camera_2d();
  963. override_camera->set_anchor_mode(Camera2D::ANCHOR_MODE_FIXED_TOP_LEFT);
  964. override_camera->set_zoom(Vector2(view_2d_zoom, view_2d_zoom));
  965. override_camera->set_offset(view_2d_offset);
  966. _queue_selection_update();
  967. }
  968. #ifndef _3D_DISABLED
  969. void RuntimeNodeSelect::_find_3d_items_at_pos(const Point2 &p_pos, Vector<SelectResult> &r_items) {
  970. Window *root = SceneTree::get_singleton()->get_root();
  971. Vector3 ray, pos, to;
  972. Camera3D *camera = root->get_camera_3d();
  973. if (!camera) {
  974. return;
  975. }
  976. ray = camera->project_ray_normal(p_pos);
  977. pos = camera->project_ray_origin(p_pos);
  978. to = pos + ray * camera->get_far();
  979. #ifndef PHYSICS_3D_DISABLED
  980. // Start with physical objects.
  981. PhysicsDirectSpaceState3D *ss = root->get_world_3d()->get_direct_space_state();
  982. PhysicsDirectSpaceState3D::RayResult result;
  983. HashSet<RID> excluded;
  984. PhysicsDirectSpaceState3D::RayParameters ray_params;
  985. ray_params.from = pos;
  986. ray_params.to = to;
  987. ray_params.collide_with_areas = true;
  988. while (true) {
  989. ray_params.exclude = excluded;
  990. if (ss->intersect_ray(ray_params, result)) {
  991. SelectResult res;
  992. res.item = Object::cast_to<Node>(result.collider);
  993. res.order = -pos.distance_to(result.position);
  994. // Fetch collision shapes.
  995. CollisionObject3D *collision = Object::cast_to<CollisionObject3D>(result.collider);
  996. if (collision) {
  997. List<uint32_t> owners;
  998. collision->get_shape_owners(&owners);
  999. for (uint32_t &I : owners) {
  1000. SelectResult res_shape;
  1001. res_shape.item = Object::cast_to<Node>(collision->shape_owner_get_owner(I));
  1002. res_shape.order = res.order;
  1003. r_items.push_back(res_shape);
  1004. }
  1005. }
  1006. r_items.push_back(res);
  1007. excluded.insert(result.rid);
  1008. } else {
  1009. break;
  1010. }
  1011. }
  1012. #endif // PHYSICS_3D_DISABLED
  1013. // Then go for the meshes.
  1014. Vector<ObjectID> items = RS::get_singleton()->instances_cull_ray(pos, to, root->get_world_3d()->get_scenario());
  1015. for (int i = 0; i < items.size(); i++) {
  1016. Object *obj = ObjectDB::get_instance(items[i]);
  1017. GeometryInstance3D *geo_instance = Object::cast_to<GeometryInstance3D>(obj);
  1018. if (geo_instance) {
  1019. Ref<TriangleMesh> mesh_collision = geo_instance->generate_triangle_mesh();
  1020. if (mesh_collision.is_valid()) {
  1021. Transform3D gt = geo_instance->get_global_transform();
  1022. Transform3D ai = gt.affine_inverse();
  1023. Vector3 point, normal;
  1024. if (mesh_collision->intersect_ray(ai.xform(pos), ai.basis.xform(ray).normalized(), point, normal)) {
  1025. SelectResult res;
  1026. res.item = Object::cast_to<Node>(obj);
  1027. res.order = -pos.distance_to(gt.xform(point));
  1028. r_items.push_back(res);
  1029. continue;
  1030. }
  1031. }
  1032. }
  1033. items.remove_at(i);
  1034. i--;
  1035. }
  1036. }
  1037. void RuntimeNodeSelect::_find_3d_items_at_rect(const Rect2 &p_rect, Vector<SelectResult> &r_items) {
  1038. Window *root = SceneTree::get_singleton()->get_root();
  1039. Camera3D *camera = root->get_camera_3d();
  1040. if (!camera) {
  1041. return;
  1042. }
  1043. Vector3 cam_pos = camera->get_global_position();
  1044. Vector3 dist_pos = camera->project_ray_origin(p_rect.position + p_rect.size / 2);
  1045. real_t znear = camera->get_near();
  1046. real_t zfar = camera->get_far();
  1047. real_t zofs = MAX(0.0, 5.0 - znear);
  1048. const Point2 pos_end = p_rect.position + p_rect.size;
  1049. Vector3 box[4] = {
  1050. Vector3(
  1051. MIN(p_rect.position.x, pos_end.x),
  1052. MIN(p_rect.position.y, pos_end.y),
  1053. zofs),
  1054. Vector3(
  1055. MAX(p_rect.position.x, pos_end.x),
  1056. MIN(p_rect.position.y, pos_end.y),
  1057. zofs),
  1058. Vector3(
  1059. MAX(p_rect.position.x, pos_end.x),
  1060. MAX(p_rect.position.y, pos_end.y),
  1061. zofs),
  1062. Vector3(
  1063. MIN(p_rect.position.x, pos_end.x),
  1064. MAX(p_rect.position.y, pos_end.y),
  1065. zofs)
  1066. };
  1067. Vector<Plane> frustum;
  1068. for (int i = 0; i < 4; i++) {
  1069. Vector3 a = _get_screen_to_space(box[i]);
  1070. Vector3 b = _get_screen_to_space(box[(i + 1) % 4]);
  1071. frustum.push_back(Plane(a, b, cam_pos));
  1072. }
  1073. // Get the camera normal.
  1074. Plane near_plane = Plane(camera->get_global_transform().basis.get_column(2), cam_pos);
  1075. near_plane.d -= znear;
  1076. frustum.push_back(near_plane);
  1077. Plane far_plane = -near_plane;
  1078. far_plane.d += zfar;
  1079. frustum.push_back(far_plane);
  1080. // Keep track of the currently listed nodes, so repeats can be ignored.
  1081. HashSet<Node *> node_list;
  1082. #ifndef PHYSICS_3D_DISABLED
  1083. Vector<Vector3> points = Geometry3D::compute_convex_mesh_points(&frustum[0], frustum.size());
  1084. Ref<ConvexPolygonShape3D> shape;
  1085. shape.instantiate();
  1086. shape->set_points(points);
  1087. // Start with physical objects.
  1088. PhysicsDirectSpaceState3D *ss = root->get_world_3d()->get_direct_space_state();
  1089. PhysicsDirectSpaceState3D::ShapeResult results[32];
  1090. PhysicsDirectSpaceState3D::ShapeParameters shape_params;
  1091. shape_params.shape_rid = shape->get_rid();
  1092. shape_params.collide_with_areas = true;
  1093. const int num_hits = ss->intersect_shape(shape_params, results, 32);
  1094. for (int i = 0; i < num_hits; i++) {
  1095. const PhysicsDirectSpaceState3D::ShapeResult &result = results[i];
  1096. SelectResult res;
  1097. res.item = Object::cast_to<Node>(result.collider);
  1098. res.order = -dist_pos.distance_to(Object::cast_to<Node3D>(res.item)->get_global_transform().origin);
  1099. // Fetch collision shapes.
  1100. CollisionObject3D *collision = Object::cast_to<CollisionObject3D>(result.collider);
  1101. if (collision) {
  1102. List<uint32_t> owners;
  1103. collision->get_shape_owners(&owners);
  1104. for (uint32_t &I : owners) {
  1105. SelectResult res_shape;
  1106. res_shape.item = Object::cast_to<Node>(collision->shape_owner_get_owner(I));
  1107. if (!node_list.has(res_shape.item)) {
  1108. node_list.insert(res_shape.item);
  1109. res_shape.order = res.order;
  1110. r_items.push_back(res_shape);
  1111. }
  1112. }
  1113. }
  1114. if (!node_list.has(res.item)) {
  1115. node_list.insert(res.item);
  1116. r_items.push_back(res);
  1117. }
  1118. }
  1119. #endif // PHYSICS_3D_DISABLED
  1120. // Then go for the meshes.
  1121. Vector<ObjectID> items = RS::get_singleton()->instances_cull_convex(frustum, root->get_world_3d()->get_scenario());
  1122. for (int i = 0; i < items.size(); i++) {
  1123. Object *obj = ObjectDB::get_instance(items[i]);
  1124. GeometryInstance3D *geo_instance = Object::cast_to<GeometryInstance3D>(obj);
  1125. if (geo_instance) {
  1126. Ref<TriangleMesh> mesh_collision = geo_instance->generate_triangle_mesh();
  1127. if (mesh_collision.is_valid()) {
  1128. Transform3D gt = geo_instance->get_global_transform();
  1129. Vector3 mesh_scale = gt.get_basis().get_scale();
  1130. gt.orthonormalize();
  1131. Transform3D it = gt.affine_inverse();
  1132. Vector<Plane> transformed_frustum;
  1133. int plane_count = frustum.size();
  1134. transformed_frustum.resize(plane_count);
  1135. for (int j = 0; j < plane_count; j++) {
  1136. transformed_frustum.write[j] = it.xform(frustum[j]);
  1137. }
  1138. Vector<Vector3> convex_points = Geometry3D::compute_convex_mesh_points(transformed_frustum.ptr(), plane_count);
  1139. if (mesh_collision->inside_convex_shape(transformed_frustum.ptr(), transformed_frustum.size(), convex_points.ptr(), convex_points.size(), mesh_scale)) {
  1140. SelectResult res;
  1141. res.item = Object::cast_to<Node>(obj);
  1142. if (!node_list.has(res.item)) {
  1143. node_list.insert(res.item);
  1144. res.order = -dist_pos.distance_to(gt.origin);
  1145. r_items.push_back(res);
  1146. }
  1147. continue;
  1148. }
  1149. }
  1150. }
  1151. items.remove_at(i);
  1152. i--;
  1153. }
  1154. }
  1155. Vector3 RuntimeNodeSelect::_get_screen_to_space(const Vector3 &p_vector3) {
  1156. Window *root = SceneTree::get_singleton()->get_root();
  1157. Camera3D *camera = root->get_camera_3d();
  1158. Transform3D camera_transform = camera->get_camera_transform();
  1159. Size2 size = root->get_size();
  1160. real_t znear = camera->get_near();
  1161. Projection cm = Projection::create_perspective(camera->get_fov(), size.aspect(), znear + p_vector3.z, camera->get_far());
  1162. Vector2 screen_he = cm.get_viewport_half_extents();
  1163. return camera_transform.xform(Vector3(((p_vector3.x / size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / size.height)) * 2.0 - 1.0) * screen_he.y, -(znear + p_vector3.z)));
  1164. }
  1165. bool RuntimeNodeSelect::_handle_3d_input(const Ref<InputEvent> &p_event) {
  1166. Ref<InputEventMouseButton> b = p_event;
  1167. if (b.is_valid()) {
  1168. const real_t zoom_factor = 1.08 * b->get_factor();
  1169. switch (b->get_button_index()) {
  1170. case MouseButton::WHEEL_UP: {
  1171. if (!camera_freelook) {
  1172. _cursor_scale_distance(1.0 / zoom_factor);
  1173. } else {
  1174. _scale_freelook_speed(zoom_factor);
  1175. }
  1176. return true;
  1177. } break;
  1178. case MouseButton::WHEEL_DOWN: {
  1179. if (!camera_freelook) {
  1180. _cursor_scale_distance(zoom_factor);
  1181. } else {
  1182. _scale_freelook_speed(1.0 / zoom_factor);
  1183. }
  1184. return true;
  1185. } break;
  1186. case MouseButton::RIGHT: {
  1187. _set_camera_freelook_enabled(b->is_pressed());
  1188. return true;
  1189. } break;
  1190. default: {
  1191. }
  1192. }
  1193. }
  1194. Ref<InputEventMouseMotion> m = p_event;
  1195. if (m.is_valid()) {
  1196. if (camera_freelook) {
  1197. _cursor_look(m);
  1198. } else if (m->get_button_mask().has_flag(MouseButtonMask::MIDDLE)) {
  1199. if (m->is_shift_pressed()) {
  1200. _cursor_pan(m);
  1201. } else {
  1202. _cursor_orbit(m);
  1203. }
  1204. }
  1205. return true;
  1206. }
  1207. Ref<InputEventKey> k = p_event;
  1208. if (k.is_valid()) {
  1209. if (k->get_physical_keycode() == Key::ESCAPE) {
  1210. _set_camera_freelook_enabled(false);
  1211. return true;
  1212. } else if (k->is_ctrl_pressed()) {
  1213. switch (k->get_physical_keycode()) {
  1214. case Key::EQUAL: {
  1215. ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
  1216. cursor.fov_scale = CLAMP(cursor.fov_scale - 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
  1217. SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
  1218. return true;
  1219. } break;
  1220. case Key::MINUS: {
  1221. ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
  1222. cursor.fov_scale = CLAMP(cursor.fov_scale + 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
  1223. SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
  1224. return true;
  1225. } break;
  1226. case Key::KEY_0: {
  1227. ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
  1228. cursor.fov_scale = 1;
  1229. SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov, camera_znear, camera_zfar);
  1230. return true;
  1231. } break;
  1232. default: {
  1233. }
  1234. }
  1235. }
  1236. }
  1237. // TODO: Handle magnify and pan input gestures.
  1238. return false;
  1239. }
  1240. void RuntimeNodeSelect::_set_camera_freelook_enabled(bool p_enabled) {
  1241. camera_freelook = p_enabled;
  1242. if (p_enabled) {
  1243. // Make sure eye_pos is synced, because freelook referential is eye pos rather than orbit pos
  1244. Vector3 forward = _get_cursor_transform().basis.xform(Vector3(0, 0, -1));
  1245. cursor.eye_pos = cursor.pos - cursor.distance * forward;
  1246. previous_mouse_position = SceneTree::get_singleton()->get_root()->get_mouse_position();
  1247. // Hide mouse like in an FPS (warping doesn't work).
  1248. Input::get_singleton()->set_mouse_mode_override(Input::MouseMode::MOUSE_MODE_CAPTURED);
  1249. } else {
  1250. // Restore mouse.
  1251. Input::get_singleton()->set_mouse_mode_override(Input::MouseMode::MOUSE_MODE_VISIBLE);
  1252. // Restore the previous mouse position when leaving freelook mode.
  1253. // This is done because leaving `Input.MOUSE_MODE_CAPTURED` will center the cursor
  1254. // due to OS limitations.
  1255. Input::get_singleton()->warp_mouse(previous_mouse_position);
  1256. }
  1257. }
  1258. void RuntimeNodeSelect::_cursor_scale_distance(real_t p_scale) {
  1259. ERR_FAIL_COND(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled());
  1260. real_t min_distance = MAX(camera_znear * 4, VIEW_3D_MIN_ZOOM);
  1261. real_t max_distance = MIN(camera_zfar / 4, VIEW_3D_MAX_ZOOM);
  1262. cursor.distance = CLAMP(cursor.distance * p_scale, min_distance, max_distance);
  1263. SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_transform(_get_cursor_transform());
  1264. }
  1265. void RuntimeNodeSelect::_scale_freelook_speed(real_t p_scale) {
  1266. real_t min_speed = MAX(camera_znear * 4, VIEW_3D_MIN_ZOOM);
  1267. real_t max_speed = MIN(camera_zfar / 4, VIEW_3D_MAX_ZOOM);
  1268. if (unlikely(min_speed > max_speed)) {
  1269. freelook_base_speed = (min_speed + max_speed) / 2;
  1270. } else {
  1271. freelook_base_speed = CLAMP(freelook_base_speed * p_scale, min_speed, max_speed);
  1272. }
  1273. }
  1274. void RuntimeNodeSelect::_cursor_look(Ref<InputEventWithModifiers> p_event) {
  1275. Window *root = SceneTree::get_singleton()->get_root();
  1276. ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
  1277. const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(), root->get_size()));
  1278. const Transform3D prev_camera_transform = _get_cursor_transform();
  1279. if (invert_y_axis) {
  1280. cursor.x_rot -= relative.y * freelook_sensitivity;
  1281. } else {
  1282. cursor.x_rot += relative.y * freelook_sensitivity;
  1283. }
  1284. // Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
  1285. cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57);
  1286. cursor.y_rot += relative.x * freelook_sensitivity;
  1287. // Look is like the opposite of Orbit: the focus point rotates around the camera.
  1288. Transform3D camera_transform = _get_cursor_transform();
  1289. Vector3 pos = camera_transform.xform(Vector3(0, 0, 0));
  1290. Vector3 prev_pos = prev_camera_transform.xform(Vector3(0, 0, 0));
  1291. Vector3 diff = prev_pos - pos;
  1292. cursor.pos += diff;
  1293. root->get_override_camera_3d()->set_transform(_get_cursor_transform());
  1294. }
  1295. void RuntimeNodeSelect::_cursor_pan(Ref<InputEventWithModifiers> p_event) {
  1296. Window *root = SceneTree::get_singleton()->get_root();
  1297. ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
  1298. // Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen.
  1299. const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2)));
  1300. const real_t pan_speed = translation_sensitivity / 150.0;
  1301. Transform3D camera_transform;
  1302. camera_transform.translate_local(cursor.pos);
  1303. camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
  1304. camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
  1305. Vector3 translation(1 * -relative.x * pan_speed, relative.y * pan_speed, 0);
  1306. translation *= cursor.distance / 4;
  1307. camera_transform.translate_local(translation);
  1308. cursor.pos = camera_transform.origin;
  1309. root->get_override_camera_3d()->set_transform(_get_cursor_transform());
  1310. }
  1311. void RuntimeNodeSelect::_cursor_orbit(Ref<InputEventWithModifiers> p_event) {
  1312. Window *root = SceneTree::get_singleton()->get_root();
  1313. ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
  1314. // Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen.
  1315. const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2)));
  1316. if (invert_y_axis) {
  1317. cursor.x_rot -= relative.y * orbit_sensitivity;
  1318. } else {
  1319. cursor.x_rot += relative.y * orbit_sensitivity;
  1320. }
  1321. // Clamp the Y rotation to roughly -90..90 degrees so the user can't look upside-down and end up disoriented.
  1322. cursor.x_rot = CLAMP(cursor.x_rot, -1.57, 1.57);
  1323. if (invert_x_axis) {
  1324. cursor.y_rot -= relative.x * orbit_sensitivity;
  1325. } else {
  1326. cursor.y_rot += relative.x * orbit_sensitivity;
  1327. }
  1328. root->get_override_camera_3d()->set_transform(_get_cursor_transform());
  1329. }
  1330. Point2 RuntimeNodeSelect::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_event, Rect2 p_area) const {
  1331. ERR_FAIL_COND_V(p_event.is_null(), Point2());
  1332. if (warped_mouse_panning_3d) {
  1333. return Input::get_singleton()->warp_mouse_motion(p_event, p_area);
  1334. }
  1335. return p_event->get_relative();
  1336. }
  1337. Transform3D RuntimeNodeSelect::_get_cursor_transform() {
  1338. Transform3D camera_transform;
  1339. camera_transform.translate_local(cursor.pos);
  1340. camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
  1341. camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
  1342. camera_transform.translate_local(0, 0, cursor.distance);
  1343. return camera_transform;
  1344. }
  1345. void RuntimeNodeSelect::_reset_camera_3d() {
  1346. camera_first_override = true;
  1347. cursor = Cursor();
  1348. Window *root = SceneTree::get_singleton()->get_root();
  1349. Camera3D *game_camera = root->is_camera_3d_override_enabled() ? root->get_overridden_camera_3d() : root->get_camera_3d();
  1350. if (game_camera) {
  1351. Transform3D transform = game_camera->get_camera_transform();
  1352. transform.translate_local(0, 0, -cursor.distance);
  1353. cursor.pos = transform.origin;
  1354. cursor.x_rot = -game_camera->get_global_rotation().x;
  1355. cursor.y_rot = -game_camera->get_global_rotation().y;
  1356. cursor.fov_scale = CLAMP(game_camera->get_fov() / camera_fov, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
  1357. } else {
  1358. cursor.fov_scale = 1.0;
  1359. }
  1360. if (root->is_camera_3d_override_enabled()) {
  1361. Camera3D *override_camera = root->get_override_camera_3d();
  1362. override_camera->set_transform(_get_cursor_transform());
  1363. override_camera->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
  1364. }
  1365. }
  1366. #endif // _3D_DISABLED
  1367. #endif // DEBUG_ENABLED