1 /*************************************************************************/
2 /*  viewport.cpp                                                         */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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 
31 #include "viewport.h"
32 
33 #include "core/core_string_names.h"
34 #include "core/os/input.h"
35 #include "core/os/os.h"
36 #include "core/project_settings.h"
37 #include "scene/2d/collision_object_2d.h"
38 #include "scene/3d/camera.h"
39 #include "scene/3d/collision_object.h"
40 #include "scene/3d/listener.h"
41 #include "scene/3d/spatial.h"
42 #include "scene/3d/world_environment.h"
43 #include "scene/gui/control.h"
44 #include "scene/gui/label.h"
45 #include "scene/gui/menu_button.h"
46 #include "scene/gui/panel.h"
47 #include "scene/gui/panel_container.h"
48 #include "scene/gui/popup_menu.h"
49 #include "scene/main/canvas_layer.h"
50 #include "scene/main/timer.h"
51 #include "scene/resources/mesh.h"
52 #include "scene/scene_string_names.h"
53 #include "servers/physics_2d_server.h"
54 
setup_local_to_scene()55 void ViewportTexture::setup_local_to_scene() {
56 
57 	if (vp) {
58 		vp->viewport_textures.erase(this);
59 	}
60 
61 	vp = NULL;
62 
63 	Node *local_scene = get_local_scene();
64 	if (!local_scene) {
65 		return;
66 	}
67 
68 	Node *vpn = local_scene->get_node(path);
69 	ERR_FAIL_COND_MSG(!vpn, "ViewportTexture: Path to node is invalid.");
70 
71 	vp = Object::cast_to<Viewport>(vpn);
72 
73 	ERR_FAIL_COND_MSG(!vp, "ViewportTexture: Path to node does not point to a viewport.");
74 
75 	vp->viewport_textures.insert(this);
76 
77 	VS::get_singleton()->texture_set_proxy(proxy, vp->texture_rid);
78 
79 	vp->texture_flags = flags;
80 	VS::get_singleton()->texture_set_flags(vp->texture_rid, flags);
81 }
82 
set_viewport_path_in_scene(const NodePath & p_path)83 void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) {
84 
85 	if (path == p_path)
86 		return;
87 
88 	path = p_path;
89 
90 	if (get_local_scene()) {
91 		setup_local_to_scene();
92 	}
93 }
94 
get_viewport_path_in_scene() const95 NodePath ViewportTexture::get_viewport_path_in_scene() const {
96 
97 	return path;
98 }
99 
get_width() const100 int ViewportTexture::get_width() const {
101 
102 	ERR_FAIL_COND_V_MSG(!vp, 0, "Viewport Texture must be set to use it.");
103 	return vp->size.width;
104 }
get_height() const105 int ViewportTexture::get_height() const {
106 
107 	ERR_FAIL_COND_V_MSG(!vp, 0, "Viewport Texture must be set to use it.");
108 	return vp->size.height;
109 }
get_size() const110 Size2 ViewportTexture::get_size() const {
111 
112 	ERR_FAIL_COND_V_MSG(!vp, Size2(), "Viewport Texture must be set to use it.");
113 	return vp->size;
114 }
get_rid() const115 RID ViewportTexture::get_rid() const {
116 
117 	//ERR_FAIL_COND_V_MSG(!vp, RID(), "Viewport Texture must be set to use it.");
118 	return proxy;
119 }
120 
has_alpha() const121 bool ViewportTexture::has_alpha() const {
122 
123 	return false;
124 }
get_data() const125 Ref<Image> ViewportTexture::get_data() const {
126 
127 	ERR_FAIL_COND_V_MSG(!vp, Ref<Image>(), "Viewport Texture must be set to use it.");
128 	return VS::get_singleton()->texture_get_data(vp->texture_rid);
129 }
set_flags(uint32_t p_flags)130 void ViewportTexture::set_flags(uint32_t p_flags) {
131 	flags = p_flags;
132 
133 	if (!vp)
134 		return;
135 
136 	vp->texture_flags = flags;
137 	VS::get_singleton()->texture_set_flags(vp->texture_rid, flags);
138 }
139 
get_flags() const140 uint32_t ViewportTexture::get_flags() const {
141 
142 	return flags;
143 }
144 
_bind_methods()145 void ViewportTexture::_bind_methods() {
146 
147 	ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene);
148 	ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene);
149 
150 	ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
151 }
152 
ViewportTexture()153 ViewportTexture::ViewportTexture() {
154 
155 	vp = NULL;
156 	flags = 0;
157 	set_local_to_scene(true);
158 	proxy = VS::get_singleton()->texture_create();
159 }
160 
~ViewportTexture()161 ViewportTexture::~ViewportTexture() {
162 
163 	if (vp) {
164 		vp->viewport_textures.erase(this);
165 	}
166 
167 	VS::get_singleton()->free(proxy);
168 }
169 
170 /////////////////////////////////////
171 
172 class TooltipPanel : public PanelContainer {
173 
174 	GDCLASS(TooltipPanel, PanelContainer);
175 
176 public:
TooltipPanel()177 	TooltipPanel(){};
178 };
179 
180 class TooltipLabel : public Label {
181 
182 	GDCLASS(TooltipLabel, Label);
183 
184 public:
TooltipLabel()185 	TooltipLabel(){};
186 };
187 
GUI()188 Viewport::GUI::GUI() {
189 
190 	dragging = false;
191 	mouse_focus = NULL;
192 	mouse_click_grabber = NULL;
193 	mouse_focus_mask = 0;
194 	key_focus = NULL;
195 	mouse_over = NULL;
196 
197 	tooltip = NULL;
198 	tooltip_popup = NULL;
199 	tooltip_label = NULL;
200 	subwindow_visibility_dirty = false;
201 	subwindow_order_dirty = false;
202 }
203 
204 /////////////////////////////////////
205 
_update_stretch_transform()206 void Viewport::_update_stretch_transform() {
207 
208 	if (size_override_stretch && size_override) {
209 
210 		stretch_transform = Transform2D();
211 		Size2 scale = size / (size_override_size + size_override_margin * 2);
212 		stretch_transform.scale(scale);
213 		stretch_transform.elements[2] = size_override_margin * scale;
214 
215 	} else {
216 
217 		stretch_transform = Transform2D();
218 	}
219 
220 	_update_global_transform();
221 }
222 
update_worlds()223 void Viewport::update_worlds() {
224 
225 	if (!is_inside_tree())
226 		return;
227 
228 	Rect2 abstracted_rect = Rect2(Vector2(), get_visible_rect().size);
229 	Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(abstracted_rect);
230 	find_world_2d()->_update_viewport(this, xformed_rect);
231 	find_world_2d()->_update();
232 
233 	find_world()->_update(get_tree()->get_frame());
234 }
235 
_collision_object_input_event(CollisionObject * p_object,Camera * p_camera,const Ref<InputEvent> & p_input_event,const Vector3 & p_pos,const Vector3 & p_normal,int p_shape)236 void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) {
237 
238 	Transform object_transform = p_object->get_global_transform();
239 	Transform camera_transform = p_camera->get_global_transform();
240 	ObjectID id = p_object->get_instance_id();
241 
242 	//avoid sending the fake event unnecessarily if nothing really changed in the context
243 	if (object_transform == physics_last_object_transform && camera_transform == physics_last_camera_transform && physics_last_id == id) {
244 		Ref<InputEventMouseMotion> mm = p_input_event;
245 		if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
246 			return; //discarded
247 		}
248 	}
249 	p_object->_input_event(camera, p_input_event, p_pos, p_normal, p_shape);
250 	physics_last_object_transform = object_transform;
251 	physics_last_camera_transform = camera_transform;
252 	physics_last_id = id;
253 }
254 
_own_world_changed()255 void Viewport::_own_world_changed() {
256 	ERR_FAIL_COND(world.is_null());
257 	ERR_FAIL_COND(own_world.is_null());
258 
259 	if (is_inside_tree()) {
260 		_propagate_exit_world(this);
261 	}
262 
263 	own_world = world->duplicate();
264 
265 	if (is_inside_tree()) {
266 		_propagate_enter_world(this);
267 	}
268 
269 	if (is_inside_tree()) {
270 		VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
271 	}
272 
273 	_update_listener();
274 }
275 
_notification(int p_what)276 void Viewport::_notification(int p_what) {
277 
278 	switch (p_what) {
279 
280 		case NOTIFICATION_ENTER_TREE: {
281 
282 			if (get_parent()) {
283 				parent = get_parent()->get_viewport();
284 				VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid());
285 			} else {
286 				parent = NULL;
287 			}
288 
289 			current_canvas = find_world_2d()->get_canvas();
290 			VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
291 			VisualServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
292 
293 			_update_listener();
294 			_update_listener_2d();
295 
296 			find_world_2d()->_register_viewport(this, Rect2());
297 
298 			add_to_group("_viewports");
299 			if (get_tree()->is_debugging_collisions_hint()) {
300 				//2D
301 				Physics2DServer::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count());
302 				contact_2d_debug = VisualServer::get_singleton()->canvas_item_create();
303 				VisualServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, find_world_2d()->get_canvas());
304 				//3D
305 				PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(), get_tree()->get_collision_debug_contact_count());
306 				contact_3d_debug_multimesh = VisualServer::get_singleton()->multimesh_create();
307 				VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_8BIT);
308 				VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0);
309 				VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid());
310 				contact_3d_debug_instance = VisualServer::get_singleton()->instance_create();
311 				VisualServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh);
312 				VisualServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world()->get_scenario());
313 				//VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
314 			}
315 
316 			VS::get_singleton()->viewport_set_active(viewport, true);
317 		} break;
318 		case NOTIFICATION_READY: {
319 #ifndef _3D_DISABLED
320 			if (listeners.size() && !listener) {
321 				Listener *first = NULL;
322 				for (Set<Listener *>::Element *E = listeners.front(); E; E = E->next()) {
323 
324 					if (first == NULL || first->is_greater_than(E->get())) {
325 						first = E->get();
326 					}
327 				}
328 
329 				if (first)
330 					first->make_current();
331 			}
332 
333 			if (cameras.size() && !camera) {
334 				//there are cameras but no current camera, pick first in tree and make it current
335 				Camera *first = NULL;
336 				for (Set<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
337 
338 					if (first == NULL || first->is_greater_than(E->get())) {
339 						first = E->get();
340 					}
341 				}
342 
343 				if (first)
344 					first->make_current();
345 			}
346 #endif
347 
348 			// Enable processing for tooltips, collision debugging, physics object picking, etc.
349 			set_process_internal(true);
350 			set_physics_process_internal(true);
351 
352 		} break;
353 		case NOTIFICATION_EXIT_TREE: {
354 
355 			_gui_cancel_tooltip();
356 			if (world_2d.is_valid())
357 				world_2d->_remove_viewport(this);
358 
359 			VisualServer::get_singleton()->viewport_set_scenario(viewport, RID());
360 			//			SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID());
361 			VisualServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
362 			if (contact_2d_debug.is_valid()) {
363 				VisualServer::get_singleton()->free(contact_2d_debug);
364 				contact_2d_debug = RID();
365 			}
366 
367 			if (contact_3d_debug_multimesh.is_valid()) {
368 				VisualServer::get_singleton()->free(contact_3d_debug_multimesh);
369 				VisualServer::get_singleton()->free(contact_3d_debug_instance);
370 				contact_3d_debug_instance = RID();
371 				contact_3d_debug_multimesh = RID();
372 			}
373 
374 			remove_from_group("_viewports");
375 
376 			VS::get_singleton()->viewport_set_active(viewport, false);
377 
378 		} break;
379 		case NOTIFICATION_INTERNAL_PROCESS: {
380 
381 			if (gui.tooltip_timer >= 0) {
382 				gui.tooltip_timer -= get_process_delta_time();
383 				if (gui.tooltip_timer < 0) {
384 					_gui_show_tooltip();
385 				}
386 			}
387 
388 		} break;
389 		case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
390 
391 			if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) {
392 
393 				VisualServer::get_singleton()->canvas_item_clear(contact_2d_debug);
394 				VisualServer::get_singleton()->canvas_item_set_draw_index(contact_2d_debug, 0xFFFFF); //very high index
395 
396 				Vector<Vector2> points = Physics2DServer::get_singleton()->space_get_contacts(find_world_2d()->get_space());
397 				int point_count = Physics2DServer::get_singleton()->space_get_contact_count(find_world_2d()->get_space());
398 				Color ccol = get_tree()->get_debug_collision_contact_color();
399 
400 				for (int i = 0; i < point_count; i++) {
401 
402 					VisualServer::get_singleton()->canvas_item_add_rect(contact_2d_debug, Rect2(points[i] - Vector2(2, 2), Vector2(5, 5)), ccol);
403 				}
404 			}
405 
406 			if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) {
407 
408 				Vector<Vector3> points = PhysicsServer::get_singleton()->space_get_contacts(find_world()->get_space());
409 				int point_count = PhysicsServer::get_singleton()->space_get_contact_count(find_world()->get_space());
410 
411 				VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
412 			}
413 
414 			if (physics_object_picking && (to_screen_rect == Rect2() || Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED)) {
415 
416 #ifndef _3D_DISABLED
417 				Vector2 last_pos(1e20, 1e20);
418 				CollisionObject *last_object = NULL;
419 				ObjectID last_id = 0;
420 #endif
421 				PhysicsDirectSpaceState::RayResult result;
422 				Physics2DDirectSpaceState *ss2d = Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space());
423 
424 				if (physics_has_last_mousepos) {
425 					// if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved.
426 					// while this extra event is sent, it is checked if both camera and last object and last ID did not move. If nothing changed, the event is discarded to avoid flooding with unnecessary motion events every frame
427 					bool has_mouse_event = false;
428 					for (List<Ref<InputEvent> >::Element *E = physics_picking_events.front(); E; E = E->next()) {
429 						Ref<InputEventMouse> m = E->get();
430 						if (m.is_valid()) {
431 							has_mouse_event = true;
432 							break;
433 						}
434 					}
435 
436 					if (!has_mouse_event) {
437 						Ref<InputEventMouseMotion> mm;
438 						mm.instance();
439 						mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
440 						mm->set_global_position(physics_last_mousepos);
441 						mm->set_position(physics_last_mousepos);
442 						mm->set_alt(physics_last_mouse_state.alt);
443 						mm->set_shift(physics_last_mouse_state.shift);
444 						mm->set_control(physics_last_mouse_state.control);
445 						mm->set_metakey(physics_last_mouse_state.meta);
446 						mm->set_button_mask(physics_last_mouse_state.mouse_mask);
447 						physics_picking_events.push_back(mm);
448 					}
449 				}
450 
451 				while (physics_picking_events.size()) {
452 
453 					Ref<InputEvent> ev = physics_picking_events.front()->get();
454 					physics_picking_events.pop_front();
455 
456 					Vector2 pos;
457 					bool is_mouse = false;
458 
459 					Ref<InputEventMouseMotion> mm = ev;
460 
461 					if (mm.is_valid()) {
462 
463 						pos = mm->get_position();
464 						is_mouse = true;
465 
466 						physics_has_last_mousepos = true;
467 						physics_last_mousepos = pos;
468 						physics_last_mouse_state.alt = mm->get_alt();
469 						physics_last_mouse_state.shift = mm->get_shift();
470 						physics_last_mouse_state.control = mm->get_control();
471 						physics_last_mouse_state.meta = mm->get_metakey();
472 						physics_last_mouse_state.mouse_mask = mm->get_button_mask();
473 					}
474 
475 					Ref<InputEventMouseButton> mb = ev;
476 
477 					if (mb.is_valid()) {
478 
479 						pos = mb->get_position();
480 						is_mouse = true;
481 
482 						physics_has_last_mousepos = true;
483 						physics_last_mousepos = pos;
484 						physics_last_mouse_state.alt = mb->get_alt();
485 						physics_last_mouse_state.shift = mb->get_shift();
486 						physics_last_mouse_state.control = mb->get_control();
487 						physics_last_mouse_state.meta = mb->get_metakey();
488 
489 						if (mb->is_pressed()) {
490 							physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1));
491 						} else {
492 							physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1));
493 
494 							// If touch mouse raised, assume we don't know last mouse pos until new events come
495 							if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) {
496 								physics_has_last_mousepos = false;
497 							}
498 						}
499 					}
500 
501 					Ref<InputEventKey> k = ev;
502 					if (k.is_valid()) {
503 						//only for mask
504 						physics_last_mouse_state.alt = k->get_alt();
505 						physics_last_mouse_state.shift = k->get_shift();
506 						physics_last_mouse_state.control = k->get_control();
507 						physics_last_mouse_state.meta = k->get_metakey();
508 						continue;
509 					}
510 
511 					Ref<InputEventScreenDrag> sd = ev;
512 
513 					if (sd.is_valid()) {
514 						pos = sd->get_position();
515 					}
516 
517 					Ref<InputEventScreenTouch> st = ev;
518 
519 					if (st.is_valid()) {
520 						pos = st->get_position();
521 					}
522 
523 					if (ss2d) {
524 						//send to 2D
525 
526 						uint64_t frame = get_tree()->get_frame();
527 
528 						Physics2DDirectSpaceState::ShapeResult res[64];
529 						for (Set<CanvasLayer *>::Element *E = canvas_layers.front(); E; E = E->next()) {
530 							Transform2D canvas_transform;
531 							ObjectID canvas_layer_id;
532 							if (E->get()) {
533 								// A descendant CanvasLayer
534 								canvas_transform = E->get()->get_transform();
535 								canvas_layer_id = E->get()->get_instance_id();
536 							} else {
537 								// This Viewport's builtin canvas
538 								canvas_transform = get_canvas_transform();
539 								canvas_layer_id = 0;
540 							}
541 
542 							Vector2 point = canvas_transform.affine_inverse().xform(pos);
543 
544 							int rc = ss2d->intersect_point_on_canvas(point, canvas_layer_id, res, 64, Set<RID>(), 0xFFFFFFFF, true, true, true);
545 							for (int i = 0; i < rc; i++) {
546 
547 								if (res[i].collider_id && res[i].collider) {
548 									CollisionObject2D *co = Object::cast_to<CollisionObject2D>(res[i].collider);
549 									if (co) {
550 										bool send_event = true;
551 										if (is_mouse) {
552 											Map<ObjectID, uint64_t>::Element *F = physics_2d_mouseover.find(res[i].collider_id);
553 
554 											if (!F) {
555 												physics_2d_mouseover.insert(res[i].collider_id, frame);
556 												co->_mouse_enter();
557 											} else {
558 												F->get() = frame;
559 												// It was already hovered, so don't send the event if it's faked
560 												if (mm.is_valid() && mm->get_device() == InputEvent::DEVICE_ID_INTERNAL) {
561 													send_event = false;
562 												}
563 											}
564 										}
565 
566 										if (send_event) {
567 											co->_input_event(this, ev, res[i].shape);
568 										}
569 									}
570 								}
571 							}
572 						}
573 
574 						if (is_mouse) {
575 							List<Map<ObjectID, uint64_t>::Element *> to_erase;
576 
577 							for (Map<ObjectID, uint64_t>::Element *E = physics_2d_mouseover.front(); E; E = E->next()) {
578 								if (E->get() != frame) {
579 									Object *o = ObjectDB::get_instance(E->key());
580 									if (o) {
581 
582 										CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
583 										if (co) {
584 											co->_mouse_exit();
585 										}
586 									}
587 									to_erase.push_back(E);
588 								}
589 							}
590 
591 							while (to_erase.size()) {
592 								physics_2d_mouseover.erase(to_erase.front()->get());
593 								to_erase.pop_front();
594 							}
595 						}
596 					}
597 
598 #ifndef _3D_DISABLED
599 					bool captured = false;
600 
601 					if (physics_object_capture != 0) {
602 
603 						CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_capture));
604 						if (co && camera) {
605 							_collision_object_input_event(co, camera, ev, Vector3(), Vector3(), 0);
606 							captured = true;
607 							if (mb.is_valid() && mb->get_button_index() == 1 && !mb->is_pressed()) {
608 								physics_object_capture = 0;
609 							}
610 
611 						} else {
612 							physics_object_capture = 0;
613 						}
614 					}
615 
616 					if (captured) {
617 						//none
618 					} else if (pos == last_pos) {
619 
620 						if (last_id) {
621 							if (ObjectDB::get_instance(last_id) && last_object) {
622 								//good, exists
623 								_collision_object_input_event(last_object, camera, ev, result.position, result.normal, result.shape);
624 								if (last_object->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
625 									physics_object_capture = last_id;
626 								}
627 							}
628 						}
629 					} else {
630 
631 						if (camera) {
632 
633 							Vector3 from = camera->project_ray_origin(pos);
634 							Vector3 dir = camera->project_ray_normal(pos);
635 
636 							PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space());
637 							if (space) {
638 
639 								bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true, true, true);
640 								ObjectID new_collider = 0;
641 								if (col) {
642 
643 									CollisionObject *co = Object::cast_to<CollisionObject>(result.collider);
644 									if (co) {
645 
646 										_collision_object_input_event(co, camera, ev, result.position, result.normal, result.shape);
647 										last_object = co;
648 										last_id = result.collider_id;
649 										new_collider = last_id;
650 										if (co->get_capture_input_on_drag() && mb.is_valid() && mb->get_button_index() == 1 && mb->is_pressed()) {
651 											physics_object_capture = last_id;
652 										}
653 									}
654 								}
655 
656 								if (is_mouse && new_collider != physics_object_over) {
657 
658 									if (physics_object_over) {
659 
660 										CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
661 										if (co) {
662 											co->_mouse_exit();
663 										}
664 									}
665 
666 									if (new_collider) {
667 
668 										CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(new_collider));
669 										if (co) {
670 											co->_mouse_enter();
671 										}
672 									}
673 
674 									physics_object_over = new_collider;
675 								}
676 							}
677 
678 							last_pos = pos;
679 						}
680 					}
681 #endif
682 				}
683 			}
684 
685 		} break;
686 		case SceneTree::NOTIFICATION_WM_MOUSE_EXIT:
687 		case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
688 
689 			_drop_physics_mouseover();
690 
691 			if (gui.mouse_focus) {
692 				//if mouse is being pressed, send a release event
693 				_drop_mouse_focus();
694 			}
695 		} break;
696 	}
697 }
698 
get_viewport_rid() const699 RID Viewport::get_viewport_rid() const {
700 
701 	return viewport;
702 }
703 
set_use_arvr(bool p_use_arvr)704 void Viewport::set_use_arvr(bool p_use_arvr) {
705 	arvr = p_use_arvr;
706 
707 	VS::get_singleton()->viewport_set_use_arvr(viewport, arvr);
708 }
709 
use_arvr()710 bool Viewport::use_arvr() {
711 	return arvr;
712 }
713 
update_canvas_items()714 void Viewport::update_canvas_items() {
715 	if (!is_inside_tree())
716 		return;
717 
718 	_update_canvas_items(this);
719 }
720 
set_size(const Size2 & p_size)721 void Viewport::set_size(const Size2 &p_size) {
722 
723 	if (size == p_size.floor())
724 		return;
725 	size = p_size.floor();
726 	VS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
727 
728 	_update_stretch_transform();
729 
730 	emit_signal("size_changed");
731 }
732 
get_visible_rect() const733 Rect2 Viewport::get_visible_rect() const {
734 
735 	Rect2 r;
736 
737 	if (size == Size2()) {
738 		r = Rect2(Point2(), OS::get_singleton()->get_window_size());
739 	} else {
740 		r = Rect2(Point2(), size);
741 	}
742 
743 	if (size_override) {
744 		r.size = size_override_size;
745 	}
746 
747 	return r;
748 }
749 
get_size() const750 Size2 Viewport::get_size() const {
751 
752 	return size;
753 }
754 
_update_listener()755 void Viewport::_update_listener() {
756 	/*
757 	if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))  {
758 		SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, find_world()->get_sound_space());
759 	} else {
760 		SpatialSoundServer::get_singleton()->listener_set_space(internal_listener, RID());
761 	}
762 */
763 }
764 
_update_listener_2d()765 void Viewport::_update_listener_2d() {
766 
767 	/*
768 	if (is_inside_tree() && audio_listener && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
769 		SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, find_world_2d()->get_sound_space());
770 	else
771 		SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, RID());
772 */
773 }
774 
set_as_audio_listener(bool p_enable)775 void Viewport::set_as_audio_listener(bool p_enable) {
776 
777 	if (p_enable == audio_listener)
778 		return;
779 
780 	audio_listener = p_enable;
781 	_update_listener();
782 }
783 
is_audio_listener() const784 bool Viewport::is_audio_listener() const {
785 
786 	return audio_listener;
787 }
788 
set_as_audio_listener_2d(bool p_enable)789 void Viewport::set_as_audio_listener_2d(bool p_enable) {
790 
791 	if (p_enable == audio_listener_2d)
792 		return;
793 
794 	audio_listener_2d = p_enable;
795 
796 	_update_listener_2d();
797 }
798 
is_audio_listener_2d() const799 bool Viewport::is_audio_listener_2d() const {
800 
801 	return audio_listener_2d;
802 }
803 
enable_canvas_transform_override(bool p_enable)804 void Viewport::enable_canvas_transform_override(bool p_enable) {
805 	if (override_canvas_transform == p_enable) {
806 		return;
807 	}
808 
809 	override_canvas_transform = p_enable;
810 	if (p_enable) {
811 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
812 	} else {
813 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
814 	}
815 }
816 
is_canvas_transform_override_enbled() const817 bool Viewport::is_canvas_transform_override_enbled() const {
818 	return override_canvas_transform;
819 }
820 
set_canvas_transform_override(const Transform2D & p_transform)821 void Viewport::set_canvas_transform_override(const Transform2D &p_transform) {
822 	if (canvas_transform_override == p_transform) {
823 		return;
824 	}
825 
826 	canvas_transform_override = p_transform;
827 	if (override_canvas_transform) {
828 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
829 	}
830 }
831 
get_canvas_transform_override() const832 Transform2D Viewport::get_canvas_transform_override() const {
833 	return canvas_transform_override;
834 }
835 
set_canvas_transform(const Transform2D & p_transform)836 void Viewport::set_canvas_transform(const Transform2D &p_transform) {
837 
838 	canvas_transform = p_transform;
839 
840 	if (!override_canvas_transform) {
841 		VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
842 	}
843 }
844 
get_canvas_transform() const845 Transform2D Viewport::get_canvas_transform() const {
846 
847 	return canvas_transform;
848 }
849 
_update_global_transform()850 void Viewport::_update_global_transform() {
851 
852 	Transform2D sxform = stretch_transform * global_canvas_transform;
853 
854 	VisualServer::get_singleton()->viewport_set_global_canvas_transform(viewport, sxform);
855 }
856 
set_global_canvas_transform(const Transform2D & p_transform)857 void Viewport::set_global_canvas_transform(const Transform2D &p_transform) {
858 
859 	global_canvas_transform = p_transform;
860 
861 	_update_global_transform();
862 }
863 
get_global_canvas_transform() const864 Transform2D Viewport::get_global_canvas_transform() const {
865 
866 	return global_canvas_transform;
867 }
868 
_listener_transform_changed_notify()869 void Viewport::_listener_transform_changed_notify() {
870 
871 #ifndef _3D_DISABLED
872 //if (listener)
873 //		SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, listener->get_listener_transform());
874 #endif
875 }
876 
_listener_set(Listener * p_listener)877 void Viewport::_listener_set(Listener *p_listener) {
878 
879 #ifndef _3D_DISABLED
880 
881 	if (listener == p_listener)
882 		return;
883 
884 	listener = p_listener;
885 
886 	_update_listener();
887 	_listener_transform_changed_notify();
888 #endif
889 }
890 
_listener_add(Listener * p_listener)891 bool Viewport::_listener_add(Listener *p_listener) {
892 
893 	listeners.insert(p_listener);
894 	return listeners.size() == 1;
895 }
896 
_listener_remove(Listener * p_listener)897 void Viewport::_listener_remove(Listener *p_listener) {
898 
899 	listeners.erase(p_listener);
900 	if (listener == p_listener) {
901 		listener = NULL;
902 	}
903 }
904 
905 #ifndef _3D_DISABLED
_listener_make_next_current(Listener * p_exclude)906 void Viewport::_listener_make_next_current(Listener *p_exclude) {
907 
908 	if (listeners.size() > 0) {
909 		for (Set<Listener *>::Element *E = listeners.front(); E; E = E->next()) {
910 
911 			if (p_exclude == E->get())
912 				continue;
913 			if (!E->get()->is_inside_tree())
914 				continue;
915 			if (listener != NULL)
916 				return;
917 
918 			E->get()->make_current();
919 		}
920 	} else {
921 		// Attempt to reset listener to the camera position
922 		if (camera != NULL) {
923 			_update_listener();
924 			_camera_transform_changed_notify();
925 		}
926 	}
927 }
928 #endif
929 
_camera_transform_changed_notify()930 void Viewport::_camera_transform_changed_notify() {
931 
932 #ifndef _3D_DISABLED
933 // If there is an active listener in the scene, it takes priority over the camera
934 //	if (camera && !listener)
935 //		SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform());
936 #endif
937 }
938 
_camera_set(Camera * p_camera)939 void Viewport::_camera_set(Camera *p_camera) {
940 
941 #ifndef _3D_DISABLED
942 
943 	if (camera == p_camera)
944 		return;
945 
946 	if (camera) {
947 		camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
948 	}
949 	camera = p_camera;
950 	if (!camera_override) {
951 		if (camera)
952 			VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
953 		else
954 			VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
955 	}
956 
957 	if (camera) {
958 		camera->notification(Camera::NOTIFICATION_BECAME_CURRENT);
959 	}
960 
961 	_update_listener();
962 	_camera_transform_changed_notify();
963 #endif
964 }
965 
_camera_add(Camera * p_camera)966 bool Viewport::_camera_add(Camera *p_camera) {
967 
968 	cameras.insert(p_camera);
969 	return cameras.size() == 1;
970 }
971 
_camera_remove(Camera * p_camera)972 void Viewport::_camera_remove(Camera *p_camera) {
973 
974 	cameras.erase(p_camera);
975 	if (camera == p_camera) {
976 		camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
977 		camera = NULL;
978 	}
979 }
980 
981 #ifndef _3D_DISABLED
_camera_make_next_current(Camera * p_exclude)982 void Viewport::_camera_make_next_current(Camera *p_exclude) {
983 
984 	for (Set<Camera *>::Element *E = cameras.front(); E; E = E->next()) {
985 
986 		if (p_exclude == E->get())
987 			continue;
988 		if (!E->get()->is_inside_tree())
989 			continue;
990 		if (camera != NULL)
991 			return;
992 
993 		E->get()->make_current();
994 	}
995 }
996 #endif
997 
_canvas_layer_add(CanvasLayer * p_canvas_layer)998 void Viewport::_canvas_layer_add(CanvasLayer *p_canvas_layer) {
999 
1000 	canvas_layers.insert(p_canvas_layer);
1001 }
1002 
_canvas_layer_remove(CanvasLayer * p_canvas_layer)1003 void Viewport::_canvas_layer_remove(CanvasLayer *p_canvas_layer) {
1004 
1005 	canvas_layers.erase(p_canvas_layer);
1006 }
1007 
set_transparent_background(bool p_enable)1008 void Viewport::set_transparent_background(bool p_enable) {
1009 
1010 	transparent_bg = p_enable;
1011 	VS::get_singleton()->viewport_set_transparent_background(viewport, p_enable);
1012 }
1013 
has_transparent_background() const1014 bool Viewport::has_transparent_background() const {
1015 
1016 	return transparent_bg;
1017 }
1018 
set_world_2d(const Ref<World2D> & p_world_2d)1019 void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) {
1020 	if (world_2d == p_world_2d)
1021 		return;
1022 
1023 	if (parent && parent->find_world_2d() == p_world_2d) {
1024 		WARN_PRINT("Unable to use parent world as world_2d");
1025 		return;
1026 	}
1027 
1028 	if (is_inside_tree()) {
1029 		find_world_2d()->_remove_viewport(this);
1030 		VisualServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas);
1031 	}
1032 
1033 	if (p_world_2d.is_valid())
1034 		world_2d = p_world_2d;
1035 	else {
1036 		WARN_PRINT("Invalid world");
1037 		world_2d = Ref<World2D>(memnew(World2D));
1038 	}
1039 
1040 	_update_listener_2d();
1041 
1042 	if (is_inside_tree()) {
1043 		current_canvas = find_world_2d()->get_canvas();
1044 		VisualServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas);
1045 		find_world_2d()->_register_viewport(this, Rect2());
1046 	}
1047 }
1048 
find_world_2d() const1049 Ref<World2D> Viewport::find_world_2d() const {
1050 
1051 	if (world_2d.is_valid())
1052 		return world_2d;
1053 	else if (parent)
1054 		return parent->find_world_2d();
1055 	else
1056 		return Ref<World2D>();
1057 }
1058 
_propagate_enter_world(Node * p_node)1059 void Viewport::_propagate_enter_world(Node *p_node) {
1060 
1061 	if (p_node != this) {
1062 
1063 		if (!p_node->is_inside_tree()) //may not have entered scene yet
1064 			return;
1065 
1066 		if (Object::cast_to<Spatial>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
1067 
1068 			p_node->notification(Spatial::NOTIFICATION_ENTER_WORLD);
1069 		} else {
1070 			Viewport *v = Object::cast_to<Viewport>(p_node);
1071 			if (v) {
1072 
1073 				if (v->world.is_valid() || v->own_world.is_valid())
1074 					return;
1075 			}
1076 		}
1077 	}
1078 
1079 	for (int i = 0; i < p_node->get_child_count(); i++) {
1080 
1081 		_propagate_enter_world(p_node->get_child(i));
1082 	}
1083 }
1084 
_propagate_viewport_notification(Node * p_node,int p_what)1085 void Viewport::_propagate_viewport_notification(Node *p_node, int p_what) {
1086 
1087 	p_node->notification(p_what);
1088 	for (int i = 0; i < p_node->get_child_count(); i++) {
1089 		Node *c = p_node->get_child(i);
1090 		if (Object::cast_to<Viewport>(c))
1091 			continue;
1092 		_propagate_viewport_notification(c, p_what);
1093 	}
1094 }
1095 
_propagate_exit_world(Node * p_node)1096 void Viewport::_propagate_exit_world(Node *p_node) {
1097 
1098 	if (p_node != this) {
1099 
1100 		if (!p_node->is_inside_tree()) //may have exited scene already
1101 			return;
1102 
1103 		if (Object::cast_to<Spatial>(p_node) || Object::cast_to<WorldEnvironment>(p_node)) {
1104 
1105 			p_node->notification(Spatial::NOTIFICATION_EXIT_WORLD);
1106 		} else {
1107 			Viewport *v = Object::cast_to<Viewport>(p_node);
1108 			if (v) {
1109 
1110 				if (v->world.is_valid() || v->own_world.is_valid())
1111 					return;
1112 			}
1113 		}
1114 	}
1115 
1116 	for (int i = 0; i < p_node->get_child_count(); i++) {
1117 
1118 		_propagate_exit_world(p_node->get_child(i));
1119 	}
1120 }
1121 
set_world(const Ref<World> & p_world)1122 void Viewport::set_world(const Ref<World> &p_world) {
1123 
1124 	if (world == p_world)
1125 		return;
1126 
1127 	if (is_inside_tree())
1128 		_propagate_exit_world(this);
1129 
1130 	if (own_world.is_valid() && world.is_valid()) {
1131 		world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
1132 	}
1133 
1134 	world = p_world;
1135 
1136 	if (own_world.is_valid()) {
1137 		if (world.is_valid()) {
1138 			own_world = world->duplicate();
1139 			world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
1140 		} else {
1141 			own_world = Ref<World>(memnew(World));
1142 		}
1143 	}
1144 
1145 	if (is_inside_tree())
1146 		_propagate_enter_world(this);
1147 
1148 	if (is_inside_tree()) {
1149 		VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
1150 	}
1151 
1152 	_update_listener();
1153 }
1154 
get_world() const1155 Ref<World> Viewport::get_world() const {
1156 
1157 	return world;
1158 }
1159 
get_world_2d() const1160 Ref<World2D> Viewport::get_world_2d() const {
1161 
1162 	return world_2d;
1163 }
1164 
find_world() const1165 Ref<World> Viewport::find_world() const {
1166 
1167 	if (own_world.is_valid())
1168 		return own_world;
1169 	else if (world.is_valid())
1170 		return world;
1171 	else if (parent)
1172 		return parent->find_world();
1173 	else
1174 		return Ref<World>();
1175 }
1176 
get_listener() const1177 Listener *Viewport::get_listener() const {
1178 
1179 	return listener;
1180 }
1181 
get_camera() const1182 Camera *Viewport::get_camera() const {
1183 	return camera;
1184 }
1185 
enable_camera_override(bool p_enable)1186 void Viewport::enable_camera_override(bool p_enable) {
1187 
1188 #ifndef _3D_DISABLED
1189 	if (p_enable == camera_override) {
1190 		return;
1191 	}
1192 
1193 	if (p_enable) {
1194 		camera_override.rid = VisualServer::get_singleton()->camera_create();
1195 	} else {
1196 		VisualServer::get_singleton()->free(camera_override.rid);
1197 		camera_override.rid = RID();
1198 	}
1199 
1200 	if (p_enable) {
1201 		VisualServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid);
1202 	} else if (camera) {
1203 		VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
1204 	} else {
1205 		VisualServer::get_singleton()->viewport_attach_camera(viewport, RID());
1206 	}
1207 #endif
1208 }
1209 
is_camera_override_enabled() const1210 bool Viewport::is_camera_override_enabled() const {
1211 	return camera_override;
1212 }
1213 
set_camera_override_transform(const Transform & p_transform)1214 void Viewport::set_camera_override_transform(const Transform &p_transform) {
1215 	if (camera_override) {
1216 		camera_override.transform = p_transform;
1217 		VisualServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform);
1218 	}
1219 }
1220 
get_camera_override_transform() const1221 Transform Viewport::get_camera_override_transform() const {
1222 	if (camera_override) {
1223 		return camera_override.transform;
1224 	}
1225 
1226 	return Transform();
1227 }
1228 
set_camera_override_perspective(float p_fovy_degrees,float p_z_near,float p_z_far)1229 void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) {
1230 	if (camera_override) {
1231 		if (camera_override.fov == p_fovy_degrees && camera_override.z_near == p_z_near &&
1232 				camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_PERSPECTIVE)
1233 			return;
1234 
1235 		camera_override.fov = p_fovy_degrees;
1236 		camera_override.z_near = p_z_near;
1237 		camera_override.z_far = p_z_far;
1238 		camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE;
1239 
1240 		VisualServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far);
1241 	}
1242 }
1243 
set_camera_override_orthogonal(float p_size,float p_z_near,float p_z_far)1244 void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far) {
1245 	if (camera_override) {
1246 		if (camera_override.size == p_size && camera_override.z_near == p_z_near &&
1247 				camera_override.z_far == p_z_far && camera_override.projection == CameraOverrideData::PROJECTION_ORTHOGONAL)
1248 			return;
1249 
1250 		camera_override.size = p_size;
1251 		camera_override.z_near = p_z_near;
1252 		camera_override.z_far = p_z_far;
1253 		camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL;
1254 
1255 		VisualServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far);
1256 	}
1257 }
1258 
get_final_transform() const1259 Transform2D Viewport::get_final_transform() const {
1260 
1261 	return stretch_transform * global_canvas_transform;
1262 }
1263 
_update_canvas_items(Node * p_node)1264 void Viewport::_update_canvas_items(Node *p_node) {
1265 	if (p_node != this) {
1266 
1267 		Viewport *vp = Object::cast_to<Viewport>(p_node);
1268 		if (vp)
1269 			return;
1270 
1271 		CanvasItem *ci = Object::cast_to<CanvasItem>(p_node);
1272 		if (ci) {
1273 			ci->update();
1274 		}
1275 	}
1276 
1277 	int cc = p_node->get_child_count();
1278 
1279 	for (int i = 0; i < cc; i++) {
1280 		_update_canvas_items(p_node->get_child(i));
1281 	}
1282 }
1283 
set_size_override(bool p_enable,const Size2 & p_size,const Vector2 & p_margin)1284 void Viewport::set_size_override(bool p_enable, const Size2 &p_size, const Vector2 &p_margin) {
1285 
1286 	if (size_override == p_enable && p_size == size_override_size)
1287 		return;
1288 
1289 	size_override = p_enable;
1290 	if (p_size.x >= 0 || p_size.y >= 0) {
1291 		size_override_size = p_size;
1292 	}
1293 	size_override_margin = p_margin;
1294 
1295 	_update_stretch_transform();
1296 	emit_signal("size_changed");
1297 }
1298 
get_size_override() const1299 Size2 Viewport::get_size_override() const {
1300 
1301 	return size_override_size;
1302 }
is_size_override_enabled() const1303 bool Viewport::is_size_override_enabled() const {
1304 
1305 	return size_override;
1306 }
set_size_override_stretch(bool p_enable)1307 void Viewport::set_size_override_stretch(bool p_enable) {
1308 
1309 	if (p_enable == size_override_stretch)
1310 		return;
1311 
1312 	size_override_stretch = p_enable;
1313 
1314 	_update_stretch_transform();
1315 }
1316 
is_size_override_stretch_enabled() const1317 bool Viewport::is_size_override_stretch_enabled() const {
1318 
1319 	return size_override_stretch;
1320 }
1321 
set_update_mode(UpdateMode p_mode)1322 void Viewport::set_update_mode(UpdateMode p_mode) {
1323 
1324 	update_mode = p_mode;
1325 	VS::get_singleton()->viewport_set_update_mode(viewport, VS::ViewportUpdateMode(p_mode));
1326 }
get_update_mode() const1327 Viewport::UpdateMode Viewport::get_update_mode() const {
1328 
1329 	return update_mode;
1330 }
1331 
get_texture() const1332 Ref<ViewportTexture> Viewport::get_texture() const {
1333 
1334 	return default_texture;
1335 }
1336 
set_vflip(bool p_enable)1337 void Viewport::set_vflip(bool p_enable) {
1338 
1339 	vflip = p_enable;
1340 	VisualServer::get_singleton()->viewport_set_vflip(viewport, p_enable);
1341 }
1342 
get_vflip() const1343 bool Viewport::get_vflip() const {
1344 
1345 	return vflip;
1346 }
1347 
set_clear_mode(ClearMode p_mode)1348 void Viewport::set_clear_mode(ClearMode p_mode) {
1349 
1350 	clear_mode = p_mode;
1351 	VS::get_singleton()->viewport_set_clear_mode(viewport, VS::ViewportClearMode(p_mode));
1352 }
1353 
get_clear_mode() const1354 Viewport::ClearMode Viewport::get_clear_mode() const {
1355 
1356 	return clear_mode;
1357 }
1358 
set_shadow_atlas_size(int p_size)1359 void Viewport::set_shadow_atlas_size(int p_size) {
1360 
1361 	if (shadow_atlas_size == p_size)
1362 		return;
1363 
1364 	shadow_atlas_size = p_size;
1365 	VS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size);
1366 }
1367 
get_shadow_atlas_size() const1368 int Viewport::get_shadow_atlas_size() const {
1369 
1370 	return shadow_atlas_size;
1371 }
1372 
set_shadow_atlas_quadrant_subdiv(int p_quadrant,ShadowAtlasQuadrantSubdiv p_subdiv)1373 void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadrantSubdiv p_subdiv) {
1374 
1375 	ERR_FAIL_INDEX(p_quadrant, 4);
1376 	ERR_FAIL_INDEX(p_subdiv, SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
1377 
1378 	if (shadow_atlas_quadrant_subdiv[p_quadrant] == p_subdiv)
1379 		return;
1380 
1381 	shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv;
1382 	static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX] = { 0, 1, 4, 16, 64, 256, 1024 };
1383 
1384 	VS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]);
1385 }
get_shadow_atlas_quadrant_subdiv(int p_quadrant) const1386 Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const {
1387 
1388 	ERR_FAIL_INDEX_V(p_quadrant, 4, SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
1389 	return shadow_atlas_quadrant_subdiv[p_quadrant];
1390 }
1391 
_get_input_pre_xform() const1392 Transform2D Viewport::_get_input_pre_xform() const {
1393 
1394 	Transform2D pre_xf;
1395 
1396 	if (to_screen_rect != Rect2()) {
1397 
1398 		pre_xf.elements[2] = -to_screen_rect.position;
1399 		pre_xf.scale(size / to_screen_rect.size);
1400 	}
1401 
1402 	return pre_xf;
1403 }
1404 
_get_window_offset() const1405 Vector2 Viewport::_get_window_offset() const {
1406 
1407 	if (get_parent() && get_parent()->has_method("get_global_position")) {
1408 		return get_parent()->call("get_global_position");
1409 	}
1410 	return Vector2();
1411 }
1412 
_make_input_local(const Ref<InputEvent> & ev)1413 Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
1414 
1415 	Vector2 vp_ofs = _get_window_offset();
1416 	Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform();
1417 
1418 	return ev->xformed_by(ai, -vp_ofs);
1419 }
1420 
_vp_input_text(const String & p_text)1421 void Viewport::_vp_input_text(const String &p_text) {
1422 
1423 	if (gui.key_focus) {
1424 		gui.key_focus->call("set_text", p_text);
1425 	}
1426 }
1427 
_vp_input(const Ref<InputEvent> & p_ev)1428 void Viewport::_vp_input(const Ref<InputEvent> &p_ev) {
1429 
1430 	if (disable_input)
1431 		return;
1432 
1433 #ifdef TOOLS_ENABLED
1434 	if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
1435 		return;
1436 	}
1437 #endif
1438 
1439 	if (to_screen_rect == Rect2())
1440 		return; //if render target, can't get input events
1441 
1442 	//this one handles system input, p_ev are in system coordinates
1443 	//they are converted to viewport coordinates
1444 
1445 	Ref<InputEvent> ev = _make_input_local(p_ev);
1446 	input(ev);
1447 }
1448 
_vp_unhandled_input(const Ref<InputEvent> & p_ev)1449 void Viewport::_vp_unhandled_input(const Ref<InputEvent> &p_ev) {
1450 
1451 	if (disable_input)
1452 		return;
1453 #ifdef TOOLS_ENABLED
1454 	if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
1455 		return;
1456 	}
1457 #endif
1458 
1459 	/*
1460 	if (parent_control && !parent_control->is_visible_in_tree())
1461 		return;
1462 	*/
1463 
1464 	if (to_screen_rect == Rect2())
1465 		return; //if render target, can't get input events
1466 
1467 	//this one handles system input, p_ev are in system coordinates
1468 	//they are converted to viewport coordinates
1469 
1470 	Ref<InputEvent> ev = _make_input_local(p_ev);
1471 	unhandled_input(ev);
1472 }
1473 
get_mouse_position() const1474 Vector2 Viewport::get_mouse_position() const {
1475 
1476 	return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_position() - _get_window_offset());
1477 }
1478 
warp_mouse(const Vector2 & p_pos)1479 void Viewport::warp_mouse(const Vector2 &p_pos) {
1480 
1481 	Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos);
1482 	Input::get_singleton()->warp_mouse_position(gpos);
1483 }
1484 
_gui_prepare_subwindows()1485 void Viewport::_gui_prepare_subwindows() {
1486 
1487 	if (gui.subwindow_visibility_dirty) {
1488 
1489 		gui.subwindows.clear();
1490 		for (List<Control *>::Element *E = gui.all_known_subwindows.front(); E; E = E->next()) {
1491 			if (E->get()->is_visible_in_tree()) {
1492 				gui.subwindows.push_back(E->get());
1493 			}
1494 		}
1495 
1496 		gui.subwindow_visibility_dirty = false;
1497 		gui.subwindow_order_dirty = true;
1498 	}
1499 
1500 	_gui_sort_subwindows();
1501 }
1502 
_gui_sort_subwindows()1503 void Viewport::_gui_sort_subwindows() {
1504 
1505 	if (!gui.subwindow_order_dirty)
1506 		return;
1507 
1508 	gui.modal_stack.sort_custom<Control::CComparator>();
1509 	gui.subwindows.sort_custom<Control::CComparator>();
1510 
1511 	gui.subwindow_order_dirty = false;
1512 }
1513 
_gui_sort_modal_stack()1514 void Viewport::_gui_sort_modal_stack() {
1515 
1516 	gui.modal_stack.sort_custom<Control::CComparator>();
1517 }
1518 
_gui_sort_roots()1519 void Viewport::_gui_sort_roots() {
1520 
1521 	if (!gui.roots_order_dirty)
1522 		return;
1523 
1524 	gui.roots.sort_custom<Control::CComparator>();
1525 
1526 	gui.roots_order_dirty = false;
1527 }
1528 
_gui_cancel_tooltip()1529 void Viewport::_gui_cancel_tooltip() {
1530 
1531 	gui.tooltip = NULL;
1532 	gui.tooltip_timer = -1;
1533 	if (gui.tooltip_popup) {
1534 		gui.tooltip_popup->queue_delete();
1535 		gui.tooltip_popup = NULL;
1536 		gui.tooltip_label = NULL;
1537 	}
1538 }
1539 
_gui_get_tooltip(Control * p_control,const Vector2 & p_pos,Control ** r_which)1540 String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which) {
1541 
1542 	Vector2 pos = p_pos;
1543 	String tooltip;
1544 
1545 	while (p_control) {
1546 
1547 		tooltip = p_control->get_tooltip(pos);
1548 
1549 		if (r_which) {
1550 			*r_which = p_control;
1551 		}
1552 
1553 		if (tooltip != String())
1554 			break;
1555 		pos = p_control->get_transform().xform(pos);
1556 
1557 		if (p_control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
1558 			break;
1559 		if (p_control->is_set_as_toplevel())
1560 			break;
1561 
1562 		p_control = p_control->get_parent_control();
1563 	}
1564 
1565 	return tooltip;
1566 }
1567 
_gui_show_tooltip()1568 void Viewport::_gui_show_tooltip() {
1569 
1570 	if (!gui.tooltip) {
1571 		return;
1572 	}
1573 
1574 	Control *which = NULL;
1575 	String tooltip = _gui_get_tooltip(gui.tooltip, gui.tooltip->get_global_transform().xform_inv(gui.tooltip_pos), &which);
1576 	tooltip = tooltip.strip_edges();
1577 	if (tooltip.length() == 0)
1578 		return; // bye
1579 
1580 	if (gui.tooltip_popup) {
1581 		memdelete(gui.tooltip_popup);
1582 		gui.tooltip_popup = NULL;
1583 		gui.tooltip_label = NULL;
1584 	}
1585 
1586 	if (!which) {
1587 		return;
1588 	}
1589 
1590 	Control *rp = which;
1591 
1592 	gui.tooltip_popup = which->make_custom_tooltip(tooltip);
1593 
1594 	if (!gui.tooltip_popup) {
1595 		gui.tooltip_popup = memnew(TooltipPanel);
1596 
1597 		gui.tooltip_label = memnew(TooltipLabel);
1598 		gui.tooltip_popup->add_child(gui.tooltip_label);
1599 
1600 		Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel", "TooltipPanel");
1601 
1602 		gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT));
1603 		gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP));
1604 		gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT));
1605 		gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM));
1606 		gui.tooltip_label->set_text(tooltip);
1607 	}
1608 
1609 	rp->add_child(gui.tooltip_popup);
1610 	gui.tooltip_popup->force_parent_owned();
1611 	gui.tooltip_popup->set_as_toplevel(true);
1612 	if (gui.tooltip) // Avoids crash when rapidly switching controls.
1613 		gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale());
1614 
1615 	Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset");
1616 	Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_minimum_size());
1617 	Rect2 vr = gui.tooltip_popup->get_viewport_rect();
1618 	if (r.size.x * gui.tooltip_popup->get_scale().x + r.position.x > vr.size.x)
1619 		r.position.x = vr.size.x - r.size.x * gui.tooltip_popup->get_scale().x;
1620 	else if (r.position.x < 0)
1621 		r.position.x = 0;
1622 
1623 	if (r.size.y * gui.tooltip_popup->get_scale().y + r.position.y > vr.size.y)
1624 		r.position.y = vr.size.y - r.size.y * gui.tooltip_popup->get_scale().y;
1625 	else if (r.position.y < 0)
1626 		r.position.y = 0;
1627 
1628 	gui.tooltip_popup->set_global_position(r.position);
1629 	gui.tooltip_popup->set_size(r.size);
1630 
1631 	gui.tooltip_popup->raise();
1632 	gui.tooltip_popup->show();
1633 }
1634 
_gui_call_input(Control * p_control,const Ref<InputEvent> & p_input)1635 void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) {
1636 
1637 	//_block();
1638 
1639 	Ref<InputEvent> ev = p_input;
1640 
1641 	//mouse wheel events can't be stopped
1642 	Ref<InputEventMouseButton> mb = p_input;
1643 
1644 	bool cant_stop_me_now = (mb.is_valid() &&
1645 							 (mb->get_button_index() == BUTTON_WHEEL_DOWN ||
1646 									 mb->get_button_index() == BUTTON_WHEEL_UP ||
1647 									 mb->get_button_index() == BUTTON_WHEEL_LEFT ||
1648 									 mb->get_button_index() == BUTTON_WHEEL_RIGHT));
1649 	Ref<InputEventPanGesture> pn = p_input;
1650 	cant_stop_me_now = pn.is_valid() || cant_stop_me_now;
1651 
1652 	bool ismouse = ev.is_valid() || Object::cast_to<InputEventMouseMotion>(*p_input) != NULL;
1653 
1654 	CanvasItem *ci = p_control;
1655 	while (ci) {
1656 
1657 		Control *control = Object::cast_to<Control>(ci);
1658 		if (control) {
1659 
1660 			if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
1661 				control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
1662 			}
1663 			if (gui.key_event_accepted)
1664 				break;
1665 			if (!control->is_inside_tree())
1666 				break;
1667 
1668 			if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
1669 				control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev);
1670 			}
1671 
1672 			if (!control->is_inside_tree() || control->is_set_as_toplevel())
1673 				break;
1674 			if (gui.key_event_accepted)
1675 				break;
1676 			if (!cant_stop_me_now && control->data.mouse_filter == Control::MOUSE_FILTER_STOP && ismouse)
1677 				break;
1678 		}
1679 
1680 		if (ci->is_set_as_toplevel())
1681 			break;
1682 
1683 		ev = ev->xformed_by(ci->get_transform()); //transform event upwards
1684 		ci = ci->get_parent_item();
1685 	}
1686 
1687 	//_unblock();
1688 }
1689 
_gui_call_notification(Control * p_control,int p_what)1690 void Viewport::_gui_call_notification(Control *p_control, int p_what) {
1691 
1692 	CanvasItem *ci = p_control;
1693 	while (ci) {
1694 
1695 		Control *control = Object::cast_to<Control>(ci);
1696 		if (control) {
1697 
1698 			if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
1699 				control->notification(p_what);
1700 			}
1701 
1702 			if (!control->is_inside_tree())
1703 				break;
1704 
1705 			if (!control->is_inside_tree() || control->is_set_as_toplevel())
1706 				break;
1707 			if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
1708 				break;
1709 		}
1710 
1711 		if (ci->is_set_as_toplevel())
1712 			break;
1713 
1714 		ci = ci->get_parent_item();
1715 	}
1716 
1717 	//_unblock();
1718 }
_gui_find_control(const Point2 & p_global)1719 Control *Viewport::_gui_find_control(const Point2 &p_global) {
1720 
1721 	_gui_prepare_subwindows();
1722 
1723 	for (List<Control *>::Element *E = gui.subwindows.back(); E; E = E->prev()) {
1724 
1725 		Control *sw = E->get();
1726 		if (!sw->is_visible_in_tree())
1727 			continue;
1728 
1729 		Transform2D xform;
1730 		CanvasItem *pci = sw->get_parent_item();
1731 		if (pci)
1732 			xform = pci->get_global_transform_with_canvas();
1733 		else
1734 			xform = sw->get_canvas_transform();
1735 
1736 		Control *ret = _gui_find_control_at_pos(sw, p_global, xform, gui.focus_inv_xform);
1737 		if (ret)
1738 			return ret;
1739 	}
1740 
1741 	_gui_sort_roots();
1742 
1743 	for (List<Control *>::Element *E = gui.roots.back(); E; E = E->prev()) {
1744 
1745 		Control *sw = E->get();
1746 		if (!sw->is_visible_in_tree())
1747 			continue;
1748 
1749 		Transform2D xform;
1750 		CanvasItem *pci = sw->get_parent_item();
1751 		if (pci)
1752 			xform = pci->get_global_transform_with_canvas();
1753 		else
1754 			xform = sw->get_canvas_transform();
1755 
1756 		Control *ret = _gui_find_control_at_pos(sw, p_global, xform, gui.focus_inv_xform);
1757 		if (ret)
1758 			return ret;
1759 	}
1760 
1761 	return NULL;
1762 }
1763 
_gui_find_control_at_pos(CanvasItem * p_node,const Point2 & p_global,const Transform2D & p_xform,Transform2D & r_inv_xform)1764 Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform) {
1765 
1766 	if (Object::cast_to<Viewport>(p_node))
1767 		return NULL;
1768 
1769 	//subwindows first!!
1770 
1771 	if (!p_node->is_visible()) {
1772 		//return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform);
1773 		return NULL; //canvas item hidden, discard
1774 	}
1775 
1776 	Transform2D matrix = p_xform * p_node->get_transform();
1777 	// matrix.basis_determinant() == 0.0f implies that node does not exist on scene
1778 	if (matrix.basis_determinant() == 0.0f)
1779 		return NULL;
1780 
1781 	Control *c = Object::cast_to<Control>(p_node);
1782 
1783 	if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) {
1784 
1785 		for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
1786 
1787 			if (p_node == gui.tooltip_popup)
1788 				continue;
1789 
1790 			CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
1791 			if (!ci || ci->is_set_as_toplevel())
1792 				continue;
1793 
1794 			Control *ret = _gui_find_control_at_pos(ci, p_global, matrix, r_inv_xform);
1795 			if (ret)
1796 				return ret;
1797 		}
1798 	}
1799 
1800 	if (!c)
1801 		return NULL;
1802 
1803 	matrix.affine_invert();
1804 
1805 	//conditions for considering this as a valid control for return
1806 	if (c->data.mouse_filter != Control::MOUSE_FILTER_IGNORE && c->has_point(matrix.xform(p_global)) && (!gui.drag_preview || (c != gui.drag_preview && !gui.drag_preview->is_a_parent_of(c)))) {
1807 		r_inv_xform = matrix;
1808 		return c;
1809 	} else
1810 		return NULL;
1811 }
1812 
_gui_drop(Control * p_at_control,Point2 p_at_pos,bool p_just_check)1813 bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check) {
1814 
1815 	{ //attempt grab, try parent controls too
1816 		CanvasItem *ci = p_at_control;
1817 		while (ci) {
1818 
1819 			Control *control = Object::cast_to<Control>(ci);
1820 			if (control) {
1821 
1822 				if (control->can_drop_data(p_at_pos, gui.drag_data)) {
1823 					if (!p_just_check) {
1824 						control->drop_data(p_at_pos, gui.drag_data);
1825 					}
1826 
1827 					return true;
1828 				}
1829 
1830 				if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
1831 					break;
1832 			}
1833 
1834 			p_at_pos = ci->get_transform().xform(p_at_pos);
1835 
1836 			if (ci->is_set_as_toplevel())
1837 				break;
1838 
1839 			ci = ci->get_parent_item();
1840 		}
1841 	}
1842 
1843 	return false;
1844 }
1845 
_gui_input_event(Ref<InputEvent> p_event)1846 void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
1847 
1848 	ERR_FAIL_COND(p_event.is_null())
1849 
1850 	//?
1851 	/*
1852 	if (!is_visible()) {
1853 		return; //simple and plain
1854 	}
1855 	*/
1856 
1857 	Ref<InputEventMouseButton> mb = p_event;
1858 
1859 	if (mb.is_valid()) {
1860 
1861 		gui.key_event_accepted = false;
1862 
1863 		Point2 mpos = mb->get_position();
1864 		if (mb->is_pressed()) {
1865 
1866 			Size2 pos = mpos;
1867 			if (gui.mouse_focus_mask) {
1868 
1869 				//do not steal mouse focus and stuff while a focus mask exists
1870 				gui.mouse_focus_mask |= 1 << (mb->get_button_index() - 1); //add the button to the mask
1871 			} else {
1872 
1873 				bool is_handled = false;
1874 
1875 				_gui_sort_modal_stack();
1876 				while (!gui.modal_stack.empty()) {
1877 
1878 					Control *top = gui.modal_stack.back()->get();
1879 					Vector2 pos2 = top->get_global_transform_with_canvas().affine_inverse().xform(mpos);
1880 					if (!top->has_point(pos2)) {
1881 
1882 						if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) {
1883 							//cancel event, sorry, modal exclusive EATS UP ALL
1884 							//alternative, you can't pop out a window the same frame it was made modal (fixes many issues)
1885 							set_input_as_handled();
1886 
1887 							return; // no one gets the event if exclusive NO ONE
1888 						}
1889 
1890 						if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN || mb->get_button_index() == BUTTON_WHEEL_LEFT || mb->get_button_index() == BUTTON_WHEEL_RIGHT) {
1891 							//cancel scroll wheel events, only clicks should trigger focus changes.
1892 							set_input_as_handled();
1893 							return;
1894 						}
1895 
1896 						top->notification(Control::NOTIFICATION_MODAL_CLOSE);
1897 						top->_modal_stack_remove();
1898 						top->hide();
1899 
1900 						if (!top->pass_on_modal_close_click()) {
1901 							is_handled = true;
1902 						}
1903 					} else {
1904 						break;
1905 					}
1906 				}
1907 
1908 				if (is_handled) {
1909 					set_input_as_handled();
1910 					return;
1911 				}
1912 
1913 				//Matrix32 parent_xform;
1914 
1915 				/*
1916 				if (data.parent_canvas_item)
1917 					parent_xform=data.parent_canvas_item->get_global_transform();
1918 				*/
1919 
1920 				gui.mouse_focus = _gui_find_control(pos);
1921 				gui.last_mouse_focus = gui.mouse_focus;
1922 
1923 				if (!gui.mouse_focus) {
1924 					gui.mouse_focus_mask = 0;
1925 					return;
1926 				}
1927 
1928 				gui.mouse_focus_mask = 1 << (mb->get_button_index() - 1);
1929 
1930 				if (mb->get_button_index() == BUTTON_LEFT) {
1931 					gui.drag_accum = Vector2();
1932 					gui.drag_attempted = false;
1933 				}
1934 			}
1935 
1936 			mb = mb->xformed_by(Transform2D()); // make a copy of the event
1937 
1938 			mb->set_global_position(pos);
1939 
1940 			pos = gui.focus_inv_xform.xform(pos);
1941 
1942 			mb->set_position(pos);
1943 
1944 #ifdef DEBUG_ENABLED
1945 			if (ScriptDebugger::get_singleton() && gui.mouse_focus) {
1946 
1947 				Array arr;
1948 				arr.push_back(gui.mouse_focus->get_path());
1949 				arr.push_back(gui.mouse_focus->get_class());
1950 				ScriptDebugger::get_singleton()->send_message("click_ctrl", arr);
1951 			}
1952 #endif
1953 
1954 			if (mb->get_button_index() == BUTTON_LEFT) { //assign focus
1955 				CanvasItem *ci = gui.mouse_focus;
1956 				while (ci) {
1957 
1958 					Control *control = Object::cast_to<Control>(ci);
1959 					if (control) {
1960 						if (control->get_focus_mode() != Control::FOCUS_NONE) {
1961 							if (control != gui.key_focus) {
1962 								control->grab_focus();
1963 							}
1964 							break;
1965 						}
1966 
1967 						if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
1968 							break;
1969 					}
1970 
1971 					if (ci->is_set_as_toplevel())
1972 						break;
1973 
1974 					ci = ci->get_parent_item();
1975 				}
1976 			}
1977 
1978 			if (gui.mouse_focus && gui.mouse_focus->can_process()) {
1979 				_gui_call_input(gui.mouse_focus, mb);
1980 			}
1981 
1982 			set_input_as_handled();
1983 
1984 			if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
1985 
1986 				//alternate drop use (when using force_drag(), as proposed by #5342
1987 				if (gui.mouse_focus) {
1988 					_gui_drop(gui.mouse_focus, pos, false);
1989 				}
1990 
1991 				gui.drag_data = Variant();
1992 				gui.dragging = false;
1993 
1994 				if (gui.drag_preview) {
1995 					memdelete(gui.drag_preview);
1996 					gui.drag_preview = NULL;
1997 				}
1998 				_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
1999 				//change mouse accordingly
2000 			}
2001 
2002 			_gui_cancel_tooltip();
2003 			//gui.tooltip_popup->hide();
2004 
2005 		} else {
2006 
2007 			if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
2008 
2009 				if (gui.mouse_over) {
2010 					Size2 pos = mpos;
2011 					pos = gui.focus_inv_xform.xform(pos);
2012 
2013 					_gui_drop(gui.mouse_over, pos, false);
2014 				}
2015 
2016 				if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) {
2017 					memdelete(gui.drag_preview);
2018 					gui.drag_preview = NULL;
2019 				}
2020 
2021 				gui.drag_data = Variant();
2022 				gui.dragging = false;
2023 				_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
2024 				//change mouse accordingly
2025 			}
2026 
2027 			gui.mouse_focus_mask &= ~(1 << (mb->get_button_index() - 1)); //remove from mask
2028 
2029 			if (!gui.mouse_focus) {
2030 				//release event is only sent if a mouse focus (previously pressed button) exists
2031 				return;
2032 			}
2033 
2034 			Size2 pos = mpos;
2035 
2036 			mb = mb->xformed_by(Transform2D()); //make a copy
2037 			mb->set_global_position(pos);
2038 			pos = gui.focus_inv_xform.xform(pos);
2039 			mb->set_position(pos);
2040 
2041 			Control *mouse_focus = gui.mouse_focus;
2042 
2043 			//disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise
2044 			if (gui.mouse_focus_mask == 0) {
2045 				gui.mouse_focus = NULL;
2046 			}
2047 
2048 			if (mouse_focus && mouse_focus->can_process()) {
2049 				_gui_call_input(mouse_focus, mb);
2050 			}
2051 
2052 			/*if (gui.drag_data.get_type()!=Variant::NIL && mb->get_button_index()==BUTTON_LEFT) {
2053 				_propagate_viewport_notification(this,NOTIFICATION_DRAG_END);
2054 				gui.drag_data=Variant(); //always clear
2055 			}*/
2056 
2057 			set_input_as_handled();
2058 		}
2059 	}
2060 
2061 	Ref<InputEventMouseMotion> mm = p_event;
2062 
2063 	if (mm.is_valid()) {
2064 
2065 		gui.key_event_accepted = false;
2066 		Point2 mpos = mm->get_position();
2067 
2068 		gui.last_mouse_pos = mpos;
2069 
2070 		Control *over = NULL;
2071 
2072 		// D&D
2073 		if (!gui.drag_attempted && gui.mouse_focus && mm->get_button_mask() & BUTTON_MASK_LEFT) {
2074 
2075 			gui.drag_accum += mm->get_relative();
2076 			float len = gui.drag_accum.length();
2077 			if (len > 10) {
2078 
2079 				{ //attempt grab, try parent controls too
2080 					CanvasItem *ci = gui.mouse_focus;
2081 					while (ci) {
2082 
2083 						Control *control = Object::cast_to<Control>(ci);
2084 						if (control) {
2085 
2086 							gui.dragging = true;
2087 							gui.drag_data = control->get_drag_data(control->get_global_transform_with_canvas().affine_inverse().xform(mpos) - gui.drag_accum);
2088 							if (gui.drag_data.get_type() != Variant::NIL) {
2089 
2090 								gui.mouse_focus = NULL;
2091 								gui.mouse_focus_mask = 0;
2092 								break;
2093 							} else {
2094 								if (gui.drag_preview != NULL) {
2095 									ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored.");
2096 									memdelete(gui.drag_preview);
2097 									gui.drag_preview = NULL;
2098 								}
2099 								gui.dragging = false;
2100 							}
2101 
2102 							if (control->data.mouse_filter == Control::MOUSE_FILTER_STOP)
2103 								break;
2104 						}
2105 
2106 						if (ci->is_set_as_toplevel())
2107 							break;
2108 
2109 						ci = ci->get_parent_item();
2110 					}
2111 				}
2112 
2113 				gui.drag_attempted = true;
2114 				if (gui.drag_data.get_type() != Variant::NIL) {
2115 
2116 					_propagate_viewport_notification(this, NOTIFICATION_DRAG_BEGIN);
2117 				}
2118 			}
2119 		}
2120 
2121 		if (gui.mouse_focus) {
2122 			over = gui.mouse_focus;
2123 			//recompute focus_inv_xform again here
2124 
2125 		} else {
2126 
2127 			over = _gui_find_control(mpos);
2128 		}
2129 
2130 		if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) {
2131 
2132 			Control *top = gui.modal_stack.back()->get();
2133 
2134 			if (over != top && !top->is_a_parent_of(over)) {
2135 
2136 				PopupMenu *popup_menu = Object::cast_to<PopupMenu>(top);
2137 				MenuButton *popup_menu_parent = NULL;
2138 				MenuButton *menu_button = Object::cast_to<MenuButton>(over);
2139 
2140 				if (popup_menu) {
2141 					popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent());
2142 					if (!popup_menu_parent) {
2143 						// Go through the parents to see if there's a MenuButton at the end.
2144 						while (Object::cast_to<PopupMenu>(popup_menu->get_parent())) {
2145 							popup_menu = Object::cast_to<PopupMenu>(popup_menu->get_parent());
2146 						}
2147 						popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent());
2148 					}
2149 				}
2150 
2151 				// If the mouse is over a menu button, this menu will open automatically
2152 				// if there is already a pop-up menu open at the same hierarchical level.
2153 				if (popup_menu_parent && menu_button && popup_menu_parent->is_switch_on_hover() &&
2154 						!menu_button->is_disabled() && menu_button->is_switch_on_hover() &&
2155 						(popup_menu_parent->get_parent()->is_a_parent_of(menu_button) ||
2156 								menu_button->get_parent()->is_a_parent_of(popup_menu))) {
2157 
2158 					popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE);
2159 					popup_menu->_modal_stack_remove();
2160 					popup_menu->hide();
2161 
2162 					menu_button->pressed();
2163 				} else {
2164 					over = NULL; //nothing can be found outside the modal stack
2165 				}
2166 			}
2167 		}
2168 
2169 		if (over != gui.mouse_over) {
2170 
2171 			if (gui.mouse_over) {
2172 				_gui_call_notification(gui.mouse_over, Control::NOTIFICATION_MOUSE_EXIT);
2173 			}
2174 
2175 			_gui_cancel_tooltip();
2176 
2177 			if (over) {
2178 				_gui_call_notification(over, Control::NOTIFICATION_MOUSE_ENTER);
2179 			}
2180 		}
2181 
2182 		gui.mouse_over = over;
2183 
2184 		if (gui.drag_preview) {
2185 			gui.drag_preview->set_position(mpos);
2186 		}
2187 
2188 		if (!over) {
2189 			OS::get_singleton()->set_cursor_shape((OS::CursorShape)Input::get_singleton()->get_default_cursor_shape());
2190 			return;
2191 		}
2192 
2193 		Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
2194 		Size2 pos = localizer.xform(mpos);
2195 		Vector2 speed = localizer.basis_xform(mm->get_speed());
2196 		Vector2 rel = localizer.basis_xform(mm->get_relative());
2197 
2198 		mm = mm->xformed_by(Transform2D()); //make a copy
2199 
2200 		mm->set_global_position(mpos);
2201 		mm->set_speed(speed);
2202 		mm->set_relative(rel);
2203 
2204 		if (mm->get_button_mask() == 0) {
2205 			//nothing pressed
2206 
2207 			bool can_tooltip = true;
2208 
2209 			if (!gui.modal_stack.empty()) {
2210 				if (gui.modal_stack.back()->get() != over && !gui.modal_stack.back()->get()->is_a_parent_of(over))
2211 					can_tooltip = false;
2212 			}
2213 
2214 			bool is_tooltip_shown = false;
2215 
2216 			if (gui.tooltip_popup) {
2217 				if (can_tooltip && gui.tooltip) {
2218 					String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
2219 
2220 					if (tooltip.length() == 0)
2221 						_gui_cancel_tooltip();
2222 					else if (gui.tooltip_label) {
2223 						if (tooltip == gui.tooltip_label->get_text()) {
2224 							is_tooltip_shown = true;
2225 						}
2226 					} else if (tooltip == String(gui.tooltip_popup->call("get_tooltip_text"))) {
2227 						is_tooltip_shown = true;
2228 					}
2229 				} else
2230 					_gui_cancel_tooltip();
2231 			}
2232 
2233 			if (can_tooltip && !is_tooltip_shown) {
2234 
2235 				gui.tooltip = over;
2236 				gui.tooltip_pos = mpos; //(parent_xform * get_transform()).affine_inverse().xform(pos);
2237 				gui.tooltip_timer = gui.tooltip_delay;
2238 			}
2239 		}
2240 
2241 		//pos = gui.focus_inv_xform.xform(pos);
2242 
2243 		mm->set_position(pos);
2244 
2245 		Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
2246 		{
2247 			Control *c = over;
2248 			Vector2 cpos = pos;
2249 			while (c) {
2250 				cursor_shape = c->get_cursor_shape(cpos);
2251 				cpos = c->get_transform().xform(cpos);
2252 				if (cursor_shape != Control::CURSOR_ARROW)
2253 					break;
2254 				if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
2255 					break;
2256 				if (c->is_set_as_toplevel())
2257 					break;
2258 				c = c->get_parent_control();
2259 			}
2260 		}
2261 
2262 		OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape);
2263 
2264 		if (over && over->can_process()) {
2265 			_gui_call_input(over, mm);
2266 		}
2267 
2268 		set_input_as_handled();
2269 
2270 		if (gui.drag_data.get_type() != Variant::NIL && mm->get_button_mask() & BUTTON_MASK_LEFT) {
2271 
2272 			bool can_drop = _gui_drop(over, pos, true);
2273 
2274 			if (!can_drop) {
2275 				OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN);
2276 			} else {
2277 				OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP);
2278 			}
2279 			//change mouse accordingly i guess
2280 		}
2281 	}
2282 
2283 	Ref<InputEventScreenTouch> touch_event = p_event;
2284 	if (touch_event.is_valid()) {
2285 
2286 		Size2 pos = touch_event->get_position();
2287 		if (touch_event->is_pressed()) {
2288 
2289 			Control *over = _gui_find_control(pos);
2290 			if (over) {
2291 
2292 				if (!gui.modal_stack.empty()) {
2293 
2294 					Control *top = gui.modal_stack.back()->get();
2295 					if (over != top && !top->is_a_parent_of(over)) {
2296 
2297 						return;
2298 					}
2299 				}
2300 				if (over->can_process()) {
2301 
2302 					touch_event = touch_event->xformed_by(Transform2D()); //make a copy
2303 					if (over == gui.mouse_focus) {
2304 						pos = gui.focus_inv_xform.xform(pos);
2305 					} else {
2306 						pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
2307 					}
2308 					touch_event->set_position(pos);
2309 					_gui_call_input(over, touch_event);
2310 				}
2311 				set_input_as_handled();
2312 				return;
2313 			}
2314 		} else if (touch_event->get_index() == 0 && gui.last_mouse_focus) {
2315 
2316 			if (gui.last_mouse_focus->can_process()) {
2317 
2318 				touch_event = touch_event->xformed_by(Transform2D()); //make a copy
2319 				touch_event->set_position(gui.focus_inv_xform.xform(pos));
2320 
2321 				_gui_call_input(gui.last_mouse_focus, touch_event);
2322 			}
2323 			set_input_as_handled();
2324 			return;
2325 		}
2326 	}
2327 
2328 	Ref<InputEventGesture> gesture_event = p_event;
2329 	if (gesture_event.is_valid()) {
2330 
2331 		gui.key_event_accepted = false;
2332 
2333 		_gui_cancel_tooltip();
2334 
2335 		Size2 pos = gesture_event->get_position();
2336 
2337 		Control *over = _gui_find_control(pos);
2338 		if (over) {
2339 
2340 			if (over->can_process()) {
2341 
2342 				gesture_event = gesture_event->xformed_by(Transform2D()); //make a copy
2343 				if (over == gui.mouse_focus) {
2344 					pos = gui.focus_inv_xform.xform(pos);
2345 				} else {
2346 					pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
2347 				}
2348 				gesture_event->set_position(pos);
2349 				_gui_call_input(over, gesture_event);
2350 			}
2351 			set_input_as_handled();
2352 			return;
2353 		}
2354 	}
2355 
2356 	Ref<InputEventScreenDrag> drag_event = p_event;
2357 	if (drag_event.is_valid()) {
2358 
2359 		Control *over = gui.mouse_focus;
2360 		if (!over) {
2361 			over = _gui_find_control(drag_event->get_position());
2362 		}
2363 		if (over) {
2364 
2365 			if (!gui.modal_stack.empty()) {
2366 
2367 				Control *top = gui.modal_stack.back()->get();
2368 				if (over != top && !top->is_a_parent_of(over)) {
2369 
2370 					return;
2371 				}
2372 			}
2373 			if (over->can_process()) {
2374 
2375 				Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
2376 				Size2 pos = localizer.xform(drag_event->get_position());
2377 				Vector2 speed = localizer.basis_xform(drag_event->get_speed());
2378 				Vector2 rel = localizer.basis_xform(drag_event->get_relative());
2379 
2380 				drag_event = drag_event->xformed_by(Transform2D()); //make a copy
2381 
2382 				drag_event->set_speed(speed);
2383 				drag_event->set_relative(rel);
2384 				drag_event->set_position(pos);
2385 
2386 				_gui_call_input(over, drag_event);
2387 			}
2388 
2389 			set_input_as_handled();
2390 			return;
2391 		}
2392 	}
2393 
2394 	if (mm.is_null() && mb.is_null() && p_event->is_action_type()) {
2395 
2396 		if (gui.key_focus && !gui.key_focus->is_visible_in_tree()) {
2397 			gui.key_focus->release_focus();
2398 		}
2399 
2400 		if (gui.key_focus) {
2401 
2402 			gui.key_event_accepted = false;
2403 			if (gui.key_focus->can_process()) {
2404 				gui.key_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, p_event);
2405 				if (gui.key_focus) //maybe lost it
2406 					gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event);
2407 			}
2408 
2409 			if (gui.key_event_accepted) {
2410 
2411 				set_input_as_handled();
2412 				return;
2413 			}
2414 		}
2415 
2416 		if (p_event->is_pressed() && p_event->is_action("ui_cancel") && !gui.modal_stack.empty()) {
2417 
2418 			_gui_sort_modal_stack();
2419 			Control *top = gui.modal_stack.back()->get();
2420 			if (!top->data.modal_exclusive) {
2421 
2422 				top->notification(Control::NOTIFICATION_MODAL_CLOSE);
2423 				top->_modal_stack_remove();
2424 				top->hide();
2425 				// Close modal, set input as handled
2426 				set_input_as_handled();
2427 				return;
2428 			}
2429 		}
2430 
2431 		Control *from = gui.key_focus ? gui.key_focus : NULL; //hmm
2432 
2433 		//keyboard focus
2434 		//if (from && p_event->is_pressed() && !p_event->get_alt() && !p_event->get_metakey() && !p_event->key->get_command()) {
2435 
2436 		Ref<InputEventKey> k = p_event;
2437 		//need to check for mods, otherwise any combination of alt/ctrl/shift+<up/down/left/righ/etc> is handled here when it shouldn't be.
2438 		bool mods = k.is_valid() && (k->get_control() || k->get_alt() || k->get_shift() || k->get_metakey());
2439 
2440 		if (from && p_event->is_pressed()) {
2441 			Control *next = NULL;
2442 
2443 			Input *input = Input::get_singleton();
2444 
2445 			if (p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) {
2446 
2447 				next = from->find_next_valid_focus();
2448 			}
2449 
2450 			if (p_event->is_action_pressed("ui_focus_prev") && input->is_action_just_pressed("ui_focus_prev")) {
2451 
2452 				next = from->find_prev_valid_focus();
2453 			}
2454 
2455 			if (!mods && p_event->is_action_pressed("ui_up") && input->is_action_just_pressed("ui_up")) {
2456 
2457 				next = from->_get_focus_neighbour(MARGIN_TOP);
2458 			}
2459 
2460 			if (!mods && p_event->is_action_pressed("ui_left") && input->is_action_just_pressed("ui_left")) {
2461 
2462 				next = from->_get_focus_neighbour(MARGIN_LEFT);
2463 			}
2464 
2465 			if (!mods && p_event->is_action_pressed("ui_right") && input->is_action_just_pressed("ui_right")) {
2466 
2467 				next = from->_get_focus_neighbour(MARGIN_RIGHT);
2468 			}
2469 
2470 			if (!mods && p_event->is_action_pressed("ui_down") && input->is_action_just_pressed("ui_down")) {
2471 
2472 				next = from->_get_focus_neighbour(MARGIN_BOTTOM);
2473 			}
2474 
2475 			if (next) {
2476 				next->grab_focus();
2477 				set_input_as_handled();
2478 			}
2479 		}
2480 	}
2481 }
2482 
_gui_add_root_control(Control * p_control)2483 List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) {
2484 
2485 	gui.roots_order_dirty = true;
2486 	return gui.roots.push_back(p_control);
2487 }
2488 
_gui_add_subwindow_control(Control * p_control)2489 List<Control *>::Element *Viewport::_gui_add_subwindow_control(Control *p_control) {
2490 
2491 	p_control->connect("visibility_changed", this, "_subwindow_visibility_changed");
2492 
2493 	if (p_control->is_visible_in_tree()) {
2494 		gui.subwindow_order_dirty = true;
2495 		gui.subwindows.push_back(p_control);
2496 	}
2497 
2498 	return gui.all_known_subwindows.push_back(p_control);
2499 }
2500 
_gui_set_subwindow_order_dirty()2501 void Viewport::_gui_set_subwindow_order_dirty() {
2502 	gui.subwindow_order_dirty = true;
2503 }
2504 
_gui_set_root_order_dirty()2505 void Viewport::_gui_set_root_order_dirty() {
2506 	gui.roots_order_dirty = true;
2507 }
2508 
_gui_remove_modal_control(List<Control * >::Element * MI)2509 void Viewport::_gui_remove_modal_control(List<Control *>::Element *MI) {
2510 
2511 	gui.modal_stack.erase(MI);
2512 }
2513 
_gui_remove_from_modal_stack(List<Control * >::Element * MI,ObjectID p_prev_focus_owner)2514 void Viewport::_gui_remove_from_modal_stack(List<Control *>::Element *MI, ObjectID p_prev_focus_owner) {
2515 
2516 	//transfer the focus stack to the next
2517 
2518 	List<Control *>::Element *next = MI->next();
2519 
2520 	gui.modal_stack.erase(MI);
2521 
2522 	if (p_prev_focus_owner) {
2523 
2524 		// for previous window in stack, pass the focus so it feels more
2525 		// natural
2526 
2527 		if (!next) { //top of stack
2528 
2529 			Object *pfo = ObjectDB::get_instance(p_prev_focus_owner);
2530 			Control *pfoc = Object::cast_to<Control>(pfo);
2531 			if (!pfoc)
2532 				return;
2533 
2534 			if (!pfoc->is_inside_tree() || !pfoc->is_visible_in_tree())
2535 				return;
2536 			pfoc->grab_focus();
2537 		} else {
2538 
2539 			next->get()->_modal_set_prev_focus_owner(p_prev_focus_owner);
2540 		}
2541 	}
2542 }
2543 
_gui_force_drag(Control * p_base,const Variant & p_data,Control * p_control)2544 void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control) {
2545 
2546 	ERR_FAIL_COND_MSG(p_data.get_type() == Variant::NIL, "Drag data must be a value.");
2547 
2548 	gui.dragging = true;
2549 	gui.drag_data = p_data;
2550 	gui.mouse_focus = NULL;
2551 
2552 	if (p_control) {
2553 		_gui_set_drag_preview(p_base, p_control);
2554 	}
2555 }
2556 
_gui_set_drag_preview(Control * p_base,Control * p_control)2557 void Viewport::_gui_set_drag_preview(Control *p_base, Control *p_control) {
2558 
2559 	ERR_FAIL_NULL(p_control);
2560 	ERR_FAIL_COND(!Object::cast_to<Control>((Object *)p_control));
2561 	ERR_FAIL_COND(p_control->is_inside_tree());
2562 	ERR_FAIL_COND(p_control->get_parent() != NULL);
2563 
2564 	if (gui.drag_preview) {
2565 		memdelete(gui.drag_preview);
2566 	}
2567 	p_control->set_as_toplevel(true);
2568 	p_control->set_position(gui.last_mouse_pos);
2569 	p_base->get_root_parent_control()->add_child(p_control); //add as child of viewport
2570 	p_control->raise();
2571 
2572 	gui.drag_preview = p_control;
2573 }
2574 
_gui_remove_root_control(List<Control * >::Element * RI)2575 void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) {
2576 
2577 	gui.roots.erase(RI);
2578 }
2579 
_gui_remove_subwindow_control(List<Control * >::Element * SI)2580 void Viewport::_gui_remove_subwindow_control(List<Control *>::Element *SI) {
2581 
2582 	ERR_FAIL_COND(!SI);
2583 
2584 	Control *control = SI->get();
2585 
2586 	control->disconnect("visibility_changed", this, "_subwindow_visibility_changed");
2587 
2588 	List<Control *>::Element *E = gui.subwindows.find(control);
2589 	if (E)
2590 		gui.subwindows.erase(E);
2591 
2592 	gui.all_known_subwindows.erase(SI);
2593 }
2594 
_gui_unfocus_control(Control * p_control)2595 void Viewport::_gui_unfocus_control(Control *p_control) {
2596 
2597 	if (gui.key_focus == p_control) {
2598 		gui.key_focus->release_focus();
2599 	}
2600 }
2601 
_gui_hid_control(Control * p_control)2602 void Viewport::_gui_hid_control(Control *p_control) {
2603 
2604 	if (gui.mouse_focus == p_control) {
2605 		_drop_mouse_focus();
2606 	}
2607 
2608 	/* ???
2609 	if (data.window==p_control) {
2610 		window->drag_data=Variant();
2611 		if (window->drag_preview) {
2612 			memdelete( window->drag_preview);
2613 			window->drag_preview=NULL;
2614 		}
2615 	}
2616 	*/
2617 
2618 	if (gui.key_focus == p_control)
2619 		_gui_remove_focus();
2620 	if (gui.mouse_over == p_control)
2621 		gui.mouse_over = NULL;
2622 	if (gui.tooltip == p_control)
2623 		_gui_cancel_tooltip();
2624 }
2625 
_gui_remove_control(Control * p_control)2626 void Viewport::_gui_remove_control(Control *p_control) {
2627 
2628 	if (gui.mouse_focus == p_control) {
2629 		gui.mouse_focus = NULL;
2630 		gui.mouse_focus_mask = 0;
2631 	}
2632 	if (gui.last_mouse_focus == p_control) {
2633 		gui.last_mouse_focus = NULL;
2634 	}
2635 	if (gui.key_focus == p_control)
2636 		gui.key_focus = NULL;
2637 	if (gui.mouse_over == p_control)
2638 		gui.mouse_over = NULL;
2639 	if (gui.tooltip == p_control)
2640 		gui.tooltip = NULL;
2641 	if (gui.tooltip_popup == p_control) {
2642 		_gui_cancel_tooltip();
2643 	}
2644 }
2645 
_gui_remove_focus()2646 void Viewport::_gui_remove_focus() {
2647 
2648 	if (gui.key_focus) {
2649 		Node *f = gui.key_focus;
2650 		gui.key_focus = NULL;
2651 		f->notification(Control::NOTIFICATION_FOCUS_EXIT, true);
2652 	}
2653 }
2654 
_gui_is_modal_on_top(const Control * p_control)2655 bool Viewport::_gui_is_modal_on_top(const Control *p_control) {
2656 
2657 	return (gui.modal_stack.size() && gui.modal_stack.back()->get() == p_control);
2658 }
2659 
_gui_control_has_focus(const Control * p_control)2660 bool Viewport::_gui_control_has_focus(const Control *p_control) {
2661 
2662 	return gui.key_focus == p_control;
2663 }
2664 
_gui_control_grab_focus(Control * p_control)2665 void Viewport::_gui_control_grab_focus(Control *p_control) {
2666 
2667 	//no need for change
2668 	if (gui.key_focus && gui.key_focus == p_control)
2669 		return;
2670 	get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, "_viewports", "_gui_remove_focus");
2671 	gui.key_focus = p_control;
2672 	emit_signal("gui_focus_changed", p_control);
2673 	p_control->notification(Control::NOTIFICATION_FOCUS_ENTER);
2674 	p_control->update();
2675 }
2676 
_gui_accept_event()2677 void Viewport::_gui_accept_event() {
2678 
2679 	gui.key_event_accepted = true;
2680 	if (is_inside_tree())
2681 		set_input_as_handled();
2682 }
2683 
_drop_mouse_focus()2684 void Viewport::_drop_mouse_focus() {
2685 
2686 	Control *c = gui.mouse_focus;
2687 	int mask = gui.mouse_focus_mask;
2688 	gui.mouse_focus = NULL;
2689 	gui.mouse_focus_mask = 0;
2690 
2691 	for (int i = 0; i < 3; i++) {
2692 
2693 		if (mask & (1 << i)) {
2694 			Ref<InputEventMouseButton> mb;
2695 			mb.instance();
2696 			mb->set_position(c->get_local_mouse_position());
2697 			mb->set_global_position(c->get_local_mouse_position());
2698 			mb->set_button_index(i + 1);
2699 			mb->set_pressed(false);
2700 			c->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
2701 		}
2702 	}
2703 }
2704 
_drop_physics_mouseover()2705 void Viewport::_drop_physics_mouseover() {
2706 
2707 	physics_has_last_mousepos = false;
2708 
2709 	while (physics_2d_mouseover.size()) {
2710 		Object *o = ObjectDB::get_instance(physics_2d_mouseover.front()->key());
2711 		if (o) {
2712 			CollisionObject2D *co = Object::cast_to<CollisionObject2D>(o);
2713 			co->_mouse_exit();
2714 		}
2715 		physics_2d_mouseover.erase(physics_2d_mouseover.front());
2716 	}
2717 
2718 #ifndef _3D_DISABLED
2719 	if (physics_object_over) {
2720 		CollisionObject *co = Object::cast_to<CollisionObject>(ObjectDB::get_instance(physics_object_over));
2721 		if (co) {
2722 			co->_mouse_exit();
2723 		}
2724 	}
2725 
2726 	physics_object_over = physics_object_capture = 0;
2727 #endif
2728 }
2729 
_gui_show_modal(Control * p_control)2730 List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
2731 
2732 	List<Control *>::Element *node = gui.modal_stack.push_back(p_control);
2733 	if (gui.key_focus)
2734 		p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id());
2735 	else
2736 		p_control->_modal_set_prev_focus_owner(0);
2737 
2738 	if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) {
2739 
2740 		_drop_mouse_focus();
2741 	}
2742 
2743 	return node;
2744 }
2745 
_gui_get_focus_owner()2746 Control *Viewport::_gui_get_focus_owner() {
2747 
2748 	return gui.key_focus;
2749 }
2750 
_gui_grab_click_focus(Control * p_control)2751 void Viewport::_gui_grab_click_focus(Control *p_control) {
2752 
2753 	gui.mouse_click_grabber = p_control;
2754 	call_deferred("_post_gui_grab_click_focus");
2755 }
2756 
_post_gui_grab_click_focus()2757 void Viewport::_post_gui_grab_click_focus() {
2758 
2759 	Control *focus_grabber = gui.mouse_click_grabber;
2760 	if (!focus_grabber) {
2761 		// Redundant grab requests were made
2762 		return;
2763 	}
2764 	gui.mouse_click_grabber = NULL;
2765 
2766 	if (gui.mouse_focus) {
2767 
2768 		if (gui.mouse_focus == focus_grabber)
2769 			return;
2770 
2771 		int mask = gui.mouse_focus_mask;
2772 		Point2 click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
2773 
2774 		for (int i = 0; i < 3; i++) {
2775 
2776 			if (mask & (1 << i)) {
2777 
2778 				Ref<InputEventMouseButton> mb;
2779 				mb.instance();
2780 
2781 				//send unclic
2782 
2783 				mb->set_position(click);
2784 				mb->set_button_index(i + 1);
2785 				mb->set_pressed(false);
2786 				gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
2787 			}
2788 		}
2789 
2790 		gui.mouse_focus = focus_grabber;
2791 		gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse();
2792 		click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
2793 
2794 		for (int i = 0; i < 3; i++) {
2795 
2796 			if (mask & (1 << i)) {
2797 
2798 				Ref<InputEventMouseButton> mb;
2799 				mb.instance();
2800 
2801 				//send clic
2802 
2803 				mb->set_position(click);
2804 				mb->set_button_index(i + 1);
2805 				mb->set_pressed(true);
2806 				gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb);
2807 			}
2808 		}
2809 	}
2810 }
2811 
2812 ///////////////////////////////
2813 
input(const Ref<InputEvent> & p_event)2814 void Viewport::input(const Ref<InputEvent> &p_event) {
2815 
2816 	ERR_FAIL_COND(!is_inside_tree());
2817 
2818 	local_input_handled = false;
2819 
2820 	if (!is_input_handled()) {
2821 		get_tree()->_call_input_pause(input_group, "_input", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
2822 	}
2823 
2824 	if (!is_input_handled()) {
2825 		_gui_input_event(p_event);
2826 	}
2827 	//get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
2828 }
2829 
unhandled_input(const Ref<InputEvent> & p_event)2830 void Viewport::unhandled_input(const Ref<InputEvent> &p_event) {
2831 
2832 	ERR_FAIL_COND(!is_inside_tree());
2833 
2834 	get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", p_event);
2835 	//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
2836 	if (!get_tree()->input_handled && Object::cast_to<InputEventKey>(*p_event) != NULL) {
2837 		get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", p_event);
2838 		//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
2839 	}
2840 
2841 	if (physics_object_picking && !get_tree()->input_handled) {
2842 
2843 		if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED &&
2844 				(Object::cast_to<InputEventMouseButton>(*p_event) ||
2845 						Object::cast_to<InputEventMouseMotion>(*p_event) ||
2846 						Object::cast_to<InputEventScreenDrag>(*p_event) ||
2847 						Object::cast_to<InputEventScreenTouch>(*p_event) ||
2848 						Object::cast_to<InputEventKey>(*p_event) //to remember state
2849 
2850 						)) {
2851 			physics_picking_events.push_back(p_event);
2852 		}
2853 	}
2854 }
2855 
set_use_own_world(bool p_world)2856 void Viewport::set_use_own_world(bool p_world) {
2857 
2858 	if (p_world == own_world.is_valid())
2859 		return;
2860 
2861 	if (is_inside_tree())
2862 		_propagate_exit_world(this);
2863 
2864 	if (!p_world) {
2865 		own_world = Ref<World>();
2866 		if (world.is_valid()) {
2867 			world->disconnect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
2868 		}
2869 	} else {
2870 		if (world.is_valid()) {
2871 			own_world = world->duplicate();
2872 			world->connect(CoreStringNames::get_singleton()->changed, this, "_own_world_changed");
2873 		} else {
2874 			own_world = Ref<World>(memnew(World));
2875 		}
2876 	}
2877 
2878 	if (is_inside_tree())
2879 		_propagate_enter_world(this);
2880 
2881 	if (is_inside_tree()) {
2882 		VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario());
2883 	}
2884 
2885 	_update_listener();
2886 }
2887 
is_using_own_world() const2888 bool Viewport::is_using_own_world() const {
2889 
2890 	return own_world.is_valid();
2891 }
2892 
set_attach_to_screen_rect(const Rect2 & p_rect)2893 void Viewport::set_attach_to_screen_rect(const Rect2 &p_rect) {
2894 
2895 	VS::get_singleton()->viewport_attach_to_screen(viewport, p_rect);
2896 	to_screen_rect = p_rect;
2897 }
2898 
get_attach_to_screen_rect() const2899 Rect2 Viewport::get_attach_to_screen_rect() const {
2900 
2901 	return to_screen_rect;
2902 }
2903 
set_use_render_direct_to_screen(bool p_render_direct_to_screen)2904 void Viewport::set_use_render_direct_to_screen(bool p_render_direct_to_screen) {
2905 
2906 	if (p_render_direct_to_screen == render_direct_to_screen)
2907 		return;
2908 
2909 	render_direct_to_screen = p_render_direct_to_screen;
2910 	VS::get_singleton()->viewport_set_render_direct_to_screen(viewport, p_render_direct_to_screen);
2911 }
2912 
is_using_render_direct_to_screen() const2913 bool Viewport::is_using_render_direct_to_screen() const {
2914 	return render_direct_to_screen;
2915 }
2916 
set_physics_object_picking(bool p_enable)2917 void Viewport::set_physics_object_picking(bool p_enable) {
2918 
2919 	physics_object_picking = p_enable;
2920 	if (!physics_object_picking) {
2921 		physics_picking_events.clear();
2922 	}
2923 }
2924 
get_physics_object_picking()2925 bool Viewport::get_physics_object_picking() {
2926 
2927 	return physics_object_picking;
2928 }
2929 
get_camera_coords(const Vector2 & p_viewport_coords) const2930 Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const {
2931 
2932 	Transform2D xf = get_final_transform();
2933 	return xf.xform(p_viewport_coords);
2934 }
2935 
get_camera_rect_size() const2936 Vector2 Viewport::get_camera_rect_size() const {
2937 
2938 	return size;
2939 }
2940 
gui_has_modal_stack() const2941 bool Viewport::gui_has_modal_stack() const {
2942 
2943 	return gui.modal_stack.size();
2944 }
2945 
set_disable_input(bool p_disable)2946 void Viewport::set_disable_input(bool p_disable) {
2947 	disable_input = p_disable;
2948 }
2949 
is_input_disabled() const2950 bool Viewport::is_input_disabled() const {
2951 
2952 	return disable_input;
2953 }
2954 
set_disable_3d(bool p_disable)2955 void Viewport::set_disable_3d(bool p_disable) {
2956 	disable_3d = p_disable;
2957 	VS::get_singleton()->viewport_set_disable_3d(viewport, p_disable);
2958 }
2959 
is_3d_disabled() const2960 bool Viewport::is_3d_disabled() const {
2961 
2962 	return disable_3d;
2963 }
2964 
set_keep_3d_linear(bool p_keep_3d_linear)2965 void Viewport::set_keep_3d_linear(bool p_keep_3d_linear) {
2966 	keep_3d_linear = p_keep_3d_linear;
2967 	VS::get_singleton()->viewport_set_keep_3d_linear(viewport, keep_3d_linear);
2968 }
2969 
get_keep_3d_linear() const2970 bool Viewport::get_keep_3d_linear() const {
2971 
2972 	return keep_3d_linear;
2973 }
2974 
gui_get_drag_data() const2975 Variant Viewport::gui_get_drag_data() const {
2976 	return gui.drag_data;
2977 }
2978 
get_modal_stack_top() const2979 Control *Viewport::get_modal_stack_top() const {
2980 	return gui.modal_stack.size() ? gui.modal_stack.back()->get() : NULL;
2981 }
2982 
get_configuration_warning() const2983 String Viewport::get_configuration_warning() const {
2984 	/*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) {
2985 
2986 		return TTR("This viewport is not set as render target. If you intend for it to display its contents directly to the screen, make it a child of a Control so it can obtain a size. Otherwise, make it a RenderTarget and assign its internal texture to some node for display.");
2987 	}*/
2988 
2989 	if (size.x == 0 || size.y == 0) {
2990 		return TTR("Viewport size must be greater than 0 to render anything.");
2991 	}
2992 	return String();
2993 }
2994 
gui_reset_canvas_sort_index()2995 void Viewport::gui_reset_canvas_sort_index() {
2996 	gui.canvas_sort_index = 0;
2997 }
gui_get_canvas_sort_index()2998 int Viewport::gui_get_canvas_sort_index() {
2999 
3000 	return gui.canvas_sort_index++;
3001 }
3002 
set_msaa(MSAA p_msaa)3003 void Viewport::set_msaa(MSAA p_msaa) {
3004 
3005 	ERR_FAIL_INDEX(p_msaa, 7);
3006 	if (msaa == p_msaa)
3007 		return;
3008 	msaa = p_msaa;
3009 	VS::get_singleton()->viewport_set_msaa(viewport, VS::ViewportMSAA(p_msaa));
3010 }
3011 
get_msaa() const3012 Viewport::MSAA Viewport::get_msaa() const {
3013 
3014 	return msaa;
3015 }
3016 
set_hdr(bool p_hdr)3017 void Viewport::set_hdr(bool p_hdr) {
3018 
3019 	if (hdr == p_hdr)
3020 		return;
3021 
3022 	hdr = p_hdr;
3023 	VS::get_singleton()->viewport_set_hdr(viewport, p_hdr);
3024 }
3025 
get_hdr() const3026 bool Viewport::get_hdr() const {
3027 
3028 	return hdr;
3029 }
3030 
set_usage(Usage p_usage)3031 void Viewport::set_usage(Usage p_usage) {
3032 
3033 	usage = p_usage;
3034 	VS::get_singleton()->viewport_set_usage(viewport, VS::ViewportUsage(p_usage));
3035 }
3036 
get_usage() const3037 Viewport::Usage Viewport::get_usage() const {
3038 	return usage;
3039 }
3040 
set_debug_draw(DebugDraw p_debug_draw)3041 void Viewport::set_debug_draw(DebugDraw p_debug_draw) {
3042 
3043 	debug_draw = p_debug_draw;
3044 	VS::get_singleton()->viewport_set_debug_draw(viewport, VS::ViewportDebugDraw(p_debug_draw));
3045 }
3046 
get_debug_draw() const3047 Viewport::DebugDraw Viewport::get_debug_draw() const {
3048 
3049 	return debug_draw;
3050 }
3051 
get_render_info(RenderInfo p_info)3052 int Viewport::get_render_info(RenderInfo p_info) {
3053 
3054 	return VS::get_singleton()->viewport_get_render_info(viewport, VS::ViewportRenderInfo(p_info));
3055 }
3056 
set_snap_controls_to_pixels(bool p_enable)3057 void Viewport::set_snap_controls_to_pixels(bool p_enable) {
3058 
3059 	snap_controls_to_pixels = p_enable;
3060 }
3061 
is_snap_controls_to_pixels_enabled() const3062 bool Viewport::is_snap_controls_to_pixels_enabled() const {
3063 
3064 	return snap_controls_to_pixels;
3065 }
3066 
gui_is_dragging() const3067 bool Viewport::gui_is_dragging() const {
3068 	return gui.dragging;
3069 }
3070 
set_input_as_handled()3071 void Viewport::set_input_as_handled() {
3072 	_drop_physics_mouseover();
3073 	if (handle_input_locally) {
3074 		local_input_handled = true;
3075 	} else {
3076 		ERR_FAIL_COND(!is_inside_tree());
3077 		get_tree()->set_input_as_handled();
3078 	}
3079 }
3080 
is_input_handled() const3081 bool Viewport::is_input_handled() const {
3082 	if (handle_input_locally) {
3083 		return local_input_handled;
3084 	} else {
3085 		ERR_FAIL_COND_V(!is_inside_tree(), false);
3086 		return get_tree()->is_input_handled();
3087 	}
3088 }
3089 
set_handle_input_locally(bool p_enable)3090 void Viewport::set_handle_input_locally(bool p_enable) {
3091 	handle_input_locally = p_enable;
3092 }
3093 
is_handling_input_locally() const3094 bool Viewport::is_handling_input_locally() const {
3095 	return handle_input_locally;
3096 }
3097 
_validate_property(PropertyInfo & property) const3098 void Viewport::_validate_property(PropertyInfo &property) const {
3099 
3100 	if (VisualServer::get_singleton()->is_low_end() && property.name == "hdr") {
3101 		property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
3102 	}
3103 }
3104 
_bind_methods()3105 void Viewport::_bind_methods() {
3106 
3107 	ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
3108 	ClassDB::bind_method(D_METHOD("use_arvr"), &Viewport::use_arvr);
3109 
3110 	ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size);
3111 	ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size);
3112 	ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
3113 	ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
3114 	ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d);
3115 	ClassDB::bind_method(D_METHOD("set_world", "world"), &Viewport::set_world);
3116 	ClassDB::bind_method(D_METHOD("get_world"), &Viewport::get_world);
3117 	ClassDB::bind_method(D_METHOD("find_world"), &Viewport::find_world);
3118 
3119 	ClassDB::bind_method(D_METHOD("set_canvas_transform", "xform"), &Viewport::set_canvas_transform);
3120 	ClassDB::bind_method(D_METHOD("get_canvas_transform"), &Viewport::get_canvas_transform);
3121 
3122 	ClassDB::bind_method(D_METHOD("set_global_canvas_transform", "xform"), &Viewport::set_global_canvas_transform);
3123 	ClassDB::bind_method(D_METHOD("get_global_canvas_transform"), &Viewport::get_global_canvas_transform);
3124 	ClassDB::bind_method(D_METHOD("get_final_transform"), &Viewport::get_final_transform);
3125 
3126 	ClassDB::bind_method(D_METHOD("get_visible_rect"), &Viewport::get_visible_rect);
3127 	ClassDB::bind_method(D_METHOD("set_transparent_background", "enable"), &Viewport::set_transparent_background);
3128 	ClassDB::bind_method(D_METHOD("has_transparent_background"), &Viewport::has_transparent_background);
3129 
3130 	ClassDB::bind_method(D_METHOD("_vp_input"), &Viewport::_vp_input);
3131 	ClassDB::bind_method(D_METHOD("_vp_input_text", "text"), &Viewport::_vp_input_text);
3132 	ClassDB::bind_method(D_METHOD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
3133 
3134 	ClassDB::bind_method(D_METHOD("set_size_override", "enable", "size", "margin"), &Viewport::set_size_override, DEFVAL(Size2(-1, -1)), DEFVAL(Size2(0, 0)));
3135 	ClassDB::bind_method(D_METHOD("get_size_override"), &Viewport::get_size_override);
3136 	ClassDB::bind_method(D_METHOD("is_size_override_enabled"), &Viewport::is_size_override_enabled);
3137 	ClassDB::bind_method(D_METHOD("set_size_override_stretch", "enabled"), &Viewport::set_size_override_stretch);
3138 	ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled);
3139 
3140 	ClassDB::bind_method(D_METHOD("set_vflip", "enable"), &Viewport::set_vflip);
3141 	ClassDB::bind_method(D_METHOD("get_vflip"), &Viewport::get_vflip);
3142 
3143 	ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &Viewport::set_clear_mode);
3144 	ClassDB::bind_method(D_METHOD("get_clear_mode"), &Viewport::get_clear_mode);
3145 
3146 	ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &Viewport::set_update_mode);
3147 	ClassDB::bind_method(D_METHOD("get_update_mode"), &Viewport::get_update_mode);
3148 
3149 	ClassDB::bind_method(D_METHOD("set_msaa", "msaa"), &Viewport::set_msaa);
3150 	ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa);
3151 
3152 	ClassDB::bind_method(D_METHOD("set_hdr", "enable"), &Viewport::set_hdr);
3153 	ClassDB::bind_method(D_METHOD("get_hdr"), &Viewport::get_hdr);
3154 
3155 	ClassDB::bind_method(D_METHOD("set_usage", "usage"), &Viewport::set_usage);
3156 	ClassDB::bind_method(D_METHOD("get_usage"), &Viewport::get_usage);
3157 
3158 	ClassDB::bind_method(D_METHOD("set_debug_draw", "debug_draw"), &Viewport::set_debug_draw);
3159 	ClassDB::bind_method(D_METHOD("get_debug_draw"), &Viewport::get_debug_draw);
3160 
3161 	ClassDB::bind_method(D_METHOD("get_render_info", "info"), &Viewport::get_render_info);
3162 
3163 	ClassDB::bind_method(D_METHOD("get_texture"), &Viewport::get_texture);
3164 
3165 	ClassDB::bind_method(D_METHOD("set_physics_object_picking", "enable"), &Viewport::set_physics_object_picking);
3166 	ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
3167 
3168 	ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
3169 	ClassDB::bind_method(D_METHOD("input", "local_event"), &Viewport::input);
3170 	ClassDB::bind_method(D_METHOD("unhandled_input", "local_event"), &Viewport::unhandled_input);
3171 
3172 	ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
3173 
3174 	ClassDB::bind_method(D_METHOD("set_use_own_world", "enable"), &Viewport::set_use_own_world);
3175 	ClassDB::bind_method(D_METHOD("is_using_own_world"), &Viewport::is_using_own_world);
3176 
3177 	ClassDB::bind_method(D_METHOD("get_camera"), &Viewport::get_camera);
3178 
3179 	ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener);
3180 	ClassDB::bind_method(D_METHOD("is_audio_listener"), &Viewport::is_audio_listener);
3181 
3182 	ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
3183 	ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
3184 	ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect);
3185 	ClassDB::bind_method(D_METHOD("set_use_render_direct_to_screen", "enable"), &Viewport::set_use_render_direct_to_screen);
3186 	ClassDB::bind_method(D_METHOD("is_using_render_direct_to_screen"), &Viewport::is_using_render_direct_to_screen);
3187 
3188 	ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
3189 	ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
3190 
3191 	ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
3192 	ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data);
3193 	ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging);
3194 
3195 	ClassDB::bind_method(D_METHOD("get_modal_stack_top"), &Viewport::get_modal_stack_top);
3196 
3197 	ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input);
3198 	ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled);
3199 
3200 	ClassDB::bind_method(D_METHOD("set_disable_3d", "disable"), &Viewport::set_disable_3d);
3201 	ClassDB::bind_method(D_METHOD("is_3d_disabled"), &Viewport::is_3d_disabled);
3202 
3203 	ClassDB::bind_method(D_METHOD("set_keep_3d_linear", "keep_3d_linear"), &Viewport::set_keep_3d_linear);
3204 	ClassDB::bind_method(D_METHOD("get_keep_3d_linear"), &Viewport::get_keep_3d_linear);
3205 
3206 	ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
3207 	ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
3208 	ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
3209 
3210 	ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size);
3211 	ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
3212 
3213 	ClassDB::bind_method(D_METHOD("set_snap_controls_to_pixels", "enabled"), &Viewport::set_snap_controls_to_pixels);
3214 	ClassDB::bind_method(D_METHOD("is_snap_controls_to_pixels_enabled"), &Viewport::is_snap_controls_to_pixels_enabled);
3215 
3216 	ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv);
3217 	ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv);
3218 
3219 	ClassDB::bind_method(D_METHOD("set_input_as_handled"), &Viewport::set_input_as_handled);
3220 	ClassDB::bind_method(D_METHOD("is_input_handled"), &Viewport::is_input_handled);
3221 
3222 	ClassDB::bind_method(D_METHOD("set_handle_input_locally", "enable"), &Viewport::set_handle_input_locally);
3223 	ClassDB::bind_method(D_METHOD("is_handling_input_locally"), &Viewport::is_handling_input_locally);
3224 
3225 	ClassDB::bind_method(D_METHOD("_subwindow_visibility_changed"), &Viewport::_subwindow_visibility_changed);
3226 
3227 	ClassDB::bind_method(D_METHOD("_own_world_changed"), &Viewport::_own_world_changed);
3228 
3229 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr");
3230 
3231 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
3232 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_override_stretch"), "set_size_override_stretch", "is_size_override_stretch_enabled");
3233 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world"), "set_use_own_world", "is_using_own_world");
3234 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World"), "set_world", "get_world");
3235 	ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
3236 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background");
3237 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
3238 	ADD_GROUP("Rendering", "");
3239 	ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
3240 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr");
3241 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
3242 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_3d_linear"), "set_keep_3d_linear", "get_keep_3d_linear");
3243 	ADD_PROPERTY(PropertyInfo(Variant::INT, "usage", PROPERTY_HINT_ENUM, "2D,2D No-Sampling,3D,3D No-Effects"), "set_usage", "get_usage");
3244 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_direct_to_screen"), "set_use_render_direct_to_screen", "is_using_render_direct_to_screen");
3245 	ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
3246 	ADD_GROUP("Render Target", "render_target_");
3247 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_target_v_flip"), "set_vflip", "get_vflip");
3248 	ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
3249 	ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode");
3250 	ADD_GROUP("Audio Listener", "audio_listener_");
3251 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_2d"), "set_as_audio_listener_2d", "is_audio_listener_2d");
3252 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener", "is_audio_listener");
3253 	ADD_GROUP("Physics", "physics_");
3254 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "physics_object_picking"), "set_physics_object_picking", "get_physics_object_picking");
3255 	ADD_GROUP("GUI", "gui_");
3256 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
3257 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
3258 	ADD_GROUP("Shadow Atlas", "shadow_atlas_");
3259 	ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
3260 	ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
3261 	ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1);
3262 	ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2);
3263 	ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 3);
3264 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_canvas_transform", "get_canvas_transform");
3265 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_global_canvas_transform", "get_global_canvas_transform");
3266 
3267 	ADD_SIGNAL(MethodInfo("size_changed"));
3268 	ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
3269 
3270 	BIND_ENUM_CONSTANT(UPDATE_DISABLED);
3271 	BIND_ENUM_CONSTANT(UPDATE_ONCE);
3272 	BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE);
3273 	BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
3274 
3275 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
3276 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1);
3277 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4);
3278 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_16);
3279 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_64);
3280 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_256);
3281 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1024);
3282 	BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_MAX);
3283 
3284 	BIND_ENUM_CONSTANT(RENDER_INFO_OBJECTS_IN_FRAME);
3285 	BIND_ENUM_CONSTANT(RENDER_INFO_VERTICES_IN_FRAME);
3286 	BIND_ENUM_CONSTANT(RENDER_INFO_MATERIAL_CHANGES_IN_FRAME);
3287 	BIND_ENUM_CONSTANT(RENDER_INFO_SHADER_CHANGES_IN_FRAME);
3288 	BIND_ENUM_CONSTANT(RENDER_INFO_SURFACE_CHANGES_IN_FRAME);
3289 	BIND_ENUM_CONSTANT(RENDER_INFO_DRAW_CALLS_IN_FRAME);
3290 	BIND_ENUM_CONSTANT(RENDER_INFO_2D_ITEMS_IN_FRAME);
3291 	BIND_ENUM_CONSTANT(RENDER_INFO_2D_DRAW_CALLS_IN_FRAME);
3292 	BIND_ENUM_CONSTANT(RENDER_INFO_MAX);
3293 
3294 	BIND_ENUM_CONSTANT(DEBUG_DRAW_DISABLED);
3295 	BIND_ENUM_CONSTANT(DEBUG_DRAW_UNSHADED);
3296 	BIND_ENUM_CONSTANT(DEBUG_DRAW_OVERDRAW);
3297 	BIND_ENUM_CONSTANT(DEBUG_DRAW_WIREFRAME);
3298 
3299 	BIND_ENUM_CONSTANT(MSAA_DISABLED);
3300 	BIND_ENUM_CONSTANT(MSAA_2X);
3301 	BIND_ENUM_CONSTANT(MSAA_4X);
3302 	BIND_ENUM_CONSTANT(MSAA_8X);
3303 	BIND_ENUM_CONSTANT(MSAA_16X);
3304 
3305 	BIND_ENUM_CONSTANT(USAGE_2D);
3306 	BIND_ENUM_CONSTANT(USAGE_2D_NO_SAMPLING);
3307 	BIND_ENUM_CONSTANT(USAGE_3D);
3308 	BIND_ENUM_CONSTANT(USAGE_3D_NO_EFFECTS);
3309 
3310 	BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS);
3311 	BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER);
3312 	BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME);
3313 }
3314 
_subwindow_visibility_changed()3315 void Viewport::_subwindow_visibility_changed() {
3316 
3317 	// unfortunately, we don't know the sender, i.e. which subwindow changed;
3318 	// so we have to check them all.
3319 	gui.subwindow_visibility_dirty = true;
3320 }
3321 
Viewport()3322 Viewport::Viewport() {
3323 
3324 	world_2d = Ref<World2D>(memnew(World2D));
3325 
3326 	viewport = VisualServer::get_singleton()->viewport_create();
3327 	texture_rid = VisualServer::get_singleton()->viewport_get_texture(viewport);
3328 	texture_flags = 0;
3329 
3330 	render_direct_to_screen = false;
3331 
3332 	default_texture.instance();
3333 	default_texture->vp = const_cast<Viewport *>(this);
3334 	viewport_textures.insert(default_texture.ptr());
3335 	VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid);
3336 
3337 	//internal_listener = SpatialSoundServer::get_singleton()->listener_create();
3338 	audio_listener = false;
3339 	//internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create();
3340 	audio_listener_2d = false;
3341 	transparent_bg = false;
3342 	parent = NULL;
3343 	listener = NULL;
3344 	camera = NULL;
3345 	override_canvas_transform = false;
3346 	canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport)
3347 	arvr = false;
3348 	size_override = false;
3349 	size_override_stretch = false;
3350 	size_override_size = Size2(1, 1);
3351 	gen_mipmaps = false;
3352 
3353 	vflip = false;
3354 
3355 	//clear=true;
3356 	update_mode = UPDATE_WHEN_VISIBLE;
3357 
3358 	physics_object_picking = false;
3359 	physics_object_capture = 0;
3360 	physics_object_over = 0;
3361 	physics_has_last_mousepos = false;
3362 	physics_last_mousepos = Vector2(Math_INF, Math_INF);
3363 
3364 	shadow_atlas_size = 0;
3365 	for (int i = 0; i < 4; i++) {
3366 		shadow_atlas_quadrant_subdiv[i] = SHADOW_ATLAS_QUADRANT_SUBDIV_MAX;
3367 	}
3368 	set_shadow_atlas_quadrant_subdiv(0, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
3369 	set_shadow_atlas_quadrant_subdiv(1, SHADOW_ATLAS_QUADRANT_SUBDIV_4);
3370 	set_shadow_atlas_quadrant_subdiv(2, SHADOW_ATLAS_QUADRANT_SUBDIV_16);
3371 	set_shadow_atlas_quadrant_subdiv(3, SHADOW_ATLAS_QUADRANT_SUBDIV_64);
3372 
3373 	String id = itos(get_instance_id());
3374 	input_group = "_vp_input" + id;
3375 	gui_input_group = "_vp_gui_input" + id;
3376 	unhandled_input_group = "_vp_unhandled_input" + id;
3377 	unhandled_key_input_group = "_vp_unhandled_key_input" + id;
3378 
3379 	disable_input = false;
3380 	disable_3d = false;
3381 	keep_3d_linear = false;
3382 
3383 	//window tooltip
3384 	gui.tooltip_timer = -1;
3385 
3386 	//gui.tooltip_timer->force_parent_owned();
3387 	gui.tooltip_delay = GLOBAL_DEF("gui/timers/tooltip_delay_sec", 0.5);
3388 	ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::REAL, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers
3389 
3390 	gui.tooltip = NULL;
3391 	gui.tooltip_label = NULL;
3392 	gui.drag_preview = NULL;
3393 	gui.drag_attempted = false;
3394 	gui.canvas_sort_index = 0;
3395 	gui.roots_order_dirty = false;
3396 	gui.mouse_focus = NULL;
3397 	gui.last_mouse_focus = NULL;
3398 
3399 	msaa = MSAA_DISABLED;
3400 	hdr = true;
3401 
3402 	usage = USAGE_3D;
3403 	debug_draw = DEBUG_DRAW_DISABLED;
3404 	clear_mode = CLEAR_MODE_ALWAYS;
3405 
3406 	snap_controls_to_pixels = true;
3407 	physics_last_mouse_state.alt = false;
3408 	physics_last_mouse_state.control = false;
3409 	physics_last_mouse_state.shift = false;
3410 	physics_last_mouse_state.meta = false;
3411 	physics_last_mouse_state.mouse_mask = 0;
3412 	local_input_handled = false;
3413 	handle_input_locally = true;
3414 	physics_last_id = 0; //ensures first time there will be a check
3415 }
3416 
~Viewport()3417 Viewport::~Viewport() {
3418 
3419 	//erase itself from viewport textures
3420 	for (Set<ViewportTexture *>::Element *E = viewport_textures.front(); E; E = E->next()) {
3421 		E->get()->vp = NULL;
3422 	}
3423 	VisualServer::get_singleton()->free(viewport);
3424 	//SpatialSoundServer::get_singleton()->free(internal_listener);
3425 	//SpatialSound2DServer::get_singleton()->free(internal_listener_2d);
3426 }
3427