Browse Source

Added extra rewriting in the code to improve mouse drag

* Made the whole block a separated scene to demonstrate it can work across multiple instances.
* Dropped the Area.input_event and did everything manually with raycasting.
* Made quad_mesh_size automatically pick the quad size, avoiding the extra setup.
* Changed from PlaneMesh to QuadMesh. Now everyting can start with 0 rotation.
* The function will keep handling input when the mouse is outside of the area to avoid orphan clicks, but stop when the click is released.
* Changed some variable and function names to make sense with the code changes.
* Added an extra function to deal with billboard mode. But is not perfect, specially with scaling and Y-billboard + camera tilting.
Wagner Ferreira 6 years ago
parent
commit
9adc81ce7f

+ 118 - 64
viewport/gui_in_3d/gui_3d.gd

@@ -1,102 +1,156 @@
 extends Spatial
-
 # Member variables
 # The size of the quad mesh itself.
-# NOTE: Do not apply the scale of the MeshInstance node, just the scale of the quad mesh!
-export (Vector2) var quad_mesh_size = Vector2(3, 2)
-# The scale of the quad node. It is assumed that the node is scaled evenly across the X, Y, and Z axes.
-export (float) var quad_node_scale = 1
-# The position of the last processed input touch/mouse event.
-var prev_pos = null
-# The last non-empty click_pos position. We need this to simulate drag events.
-var last_click_pos = null
-# The viewport we want to interact with.
-var viewport = null
-# A empty Vector3 used for comparison.
-var empty_vector = Vector3(0,0,0)
+var quad_mesh_size
+# Indentify if the mouse is inside the Area
+var mouse_inside = false
+# Identify if the mouse was pressed inside the Area
+var mouse_held = false
+# The last non-empty mouse position. Used when dragging outside of the box.
+var last_mouse_pos3D = null
+# The last processed input touch/mouse event. To calculate relative movement.
+var last_mouse_pos2D = null
+# Most used nodes
+onready var node_viewport = $Viewport
+onready var node_quad = $Quad
+onready var node_area = $Quad/Area
+onready var node_collision = $Quad/Area/CollisionShape
+
+func _ready():
+	node_area.connect("mouse_entered", self, "_mouse_entered_area")
+	print(node_quad.get_surface_material(0).params_billboard_mode)
 
+func _process(delta):
+	#NOTE: Remove this function if you don't plan on using billboard settings.
+	rotate_area_to_billboard()
 
+func _mouse_entered_area():
+	mouse_inside = true
+	
 func _input(event):
 	# Check if the event is a non-mouse/non-touch event
 	var is_mouse_event = false
-	var mouse_events = [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]
-	for mouse_event in mouse_events:
+	for mouse_event in [InputEventMouseButton, InputEventMouseMotion, InputEventScreenDrag, InputEventScreenTouch]:
 		if event is mouse_event:
 			is_mouse_event = true
 			break
-  
+	
 	# If the event is not a mouse/touch event, then pass the event to the viewport as we do not
 	# need to do any conversions for these events.
-	if is_mouse_event == false:
-		viewport.input(event)
-
+	if is_mouse_event and (mouse_inside or mouse_held):
+		handle_mouse(event)
+	elif not is_mouse_event:
+		node_viewport.input(event)
 
-# Mouse events for Area
-func _on_area_input_event(camera, event, click_pos, click_normal, shape_idx):
-	# If click_pos is not empty, then we want to store it so we can use it to simulate drag events.
-	if click_pos != empty_vector:
-		last_click_pos = click_pos
-	
-	var pos
-	if click_pos == empty_vector:
-		# Convert the last known click pos, last_click_pos, from world coordinate space to a coordinate space
-		# relative to the Area node.
-		# NOTE: affine_inverse accounts for the Area node's scale, rotation, and translation in the scene!
-		pos = get_node("Area").global_transform.affine_inverse()*last_click_pos
-		
-		# If the event is has some form of dragging, then we need to simulate that drag in code.
-		# NOTE: this is not a perfect solution, but it works okay.
-		if event is InputEventMouseMotion or event is InputEventScreenDrag:
-			pos.x += event.relative.x / viewport.size.x
-			pos.y -= event.relative.y / viewport.size.y
-		
-		# Update last_click_pos with the newest version of pos, with adjustments for quad size.
-		last_click_pos = pos * quad_node_scale
-		
-	else:
+# Handle mouse events inside Area. (Area.input_event had many issues with dragging)
+func handle_mouse(event):
+	#Get mesh size to detect edges and make conversions. This code only support PlaneMesh and QuadMesh.
+	quad_mesh_size = node_quad.mesh.size
+	
+	#Detect mouse being held to mantain event while outside of bounds. Avoid orphan clicks
+	if event is InputEventMouseButton or event is InputEventScreenTouch:
+		mouse_held = event.pressed
+	
+	#Find mouse position in Area
+	var mouse_pos3D = find_mouse(event.global_position)
+	
+	# Check if the mouse is outside of bounds, use last position to avoid errors
+	#NOTE: mouse_exited signal was unrealiable in this situation
+	mouse_inside = mouse_pos3D != null
+	if mouse_inside:
 		# Convert click_pos from world coordinate space to a coordinate space relative to the Area node.
 		# NOTE: affine_inverse accounts for the Area node's scale, rotation, and translation in the scene!
-		pos = get_node("Area").global_transform.affine_inverse()*click_pos
+		mouse_pos3D = node_area.global_transform.affine_inverse() * mouse_pos3D
+		last_mouse_pos3D = mouse_pos3D
+	else:
+		mouse_pos3D = last_mouse_pos3D
+	
+	#TODO: adapt to bilboard mode or avoid completelly
 	
 	# convert the relative event position from 3D to 2D
-	pos = Vector2(pos.x, -pos.y)
+	var mouse_pos2D = Vector2(mouse_pos3D.x, -mouse_pos3D.y)
 	
 	# Right now the event position's range is the following: (-quad_size/2) -> (quad_size/2)
 	# We need to convert it into the following range: 0 -> quad_size
-	pos.x += quad_mesh_size.x/2
-	pos.y += quad_mesh_size.y/2
+	mouse_pos2D.x += quad_mesh_size.x / 2
+	mouse_pos2D.y += quad_mesh_size.y / 2
 	# Then we need to convert it into the following range: 0 -> 1
-	pos.x = pos.x/quad_mesh_size.x
-	pos.y = pos.y/quad_mesh_size.y
+	mouse_pos2D.x = mouse_pos2D.x / quad_mesh_size.x
+	mouse_pos2D.y = mouse_pos2D.y / quad_mesh_size.y
+	
 	# Finally, we convert the position to the following range: 0 -> viewport.size
-	pos.x = pos.x * viewport.size.x
-	pos.y = pos.y * viewport.size.y
+	mouse_pos2D.x = mouse_pos2D.x * node_viewport.size.x
+	mouse_pos2D.y = mouse_pos2D.y * node_viewport.size.y
 	# We need to do these conversions so the event's position is in the viewport's coordinate system.
 	
 	# Set the event's position and global position.
-	event.position = pos
-	event.global_position = pos
+	event.position = mouse_pos2D
+	event.global_position = mouse_pos2D
 	
 	# If the event is a mouse motion event...
 	if event is InputEventMouseMotion:
 		# If there is not a stored previous position, then we'll assume there is no relative motion.
-		if prev_pos == null:
+		if last_mouse_pos2D == null:
 			event.relative = Vector2(0, 0)
 		# If there is a stored previous position, then we'll calculate the relative position by subtracting
 		# the previous position from the new position. This will give us the distance the event traveled from prev_pos
 		else:
-			event.relative = pos - prev_pos
-	
-	# Update prev_pos with the position we just calculated.
-	prev_pos = pos
+			event.relative = mouse_pos2D - last_mouse_pos2D
+	# Update last_mouse_pos2D with the position we just calculated.
+	last_mouse_pos2D = mouse_pos2D
 	
 	# Finally, send the processed input event to the viewport.
-	viewport.input(event)
+	node_viewport.input(event)
 
+func find_mouse(global_position):
+	var camera = get_viewport().get_camera()
+	
+	#from camera center to the mouse position in the Area
+	var from = camera.project_ray_origin(global_position)
+	var dist = find_further_distance_to(camera.transform.origin)
+	var to = from + camera.project_ray_normal(global_position) * dist
+	
+	
+	#Manually raycasts the are to find the mouse position
+	var result = get_world().direct_space_state.intersect_ray(from, to, [], node_area.collision_layer) #,false,true) #for 3.1 changes
+	
+	if result.size() > 0:
+		return result.position
+	else:
+		return null
 
-func _ready():
-	# Get the Viewport node and assign it to viewport for later use.
-	viewport = get_node("Viewport")
-	# Connect the input_event signal to the _on_area_input_event function.
-	get_node("Area").connect("input_event", self, "_on_area_input_event")
-  
+func find_further_distance_to(origin):
+	#Find edges of collision and change to global positions
+	var edges = []
+	edges.append(node_area.to_global(Vector3(quad_mesh_size.x / 2, quad_mesh_size.y / 2, 0)))
+	edges.append(node_area.to_global(Vector3(quad_mesh_size.x / 2, -quad_mesh_size.y / 2, 0)))
+	edges.append(node_area.to_global(Vector3(-quad_mesh_size.x / 2, quad_mesh_size.y / 2, 0)))
+	edges.append(node_area.to_global(Vector3(-quad_mesh_size.x / 2, -quad_mesh_size.y / 2, 0)))
+	
+	#Get the furthest distance between the camera and collision to avoid raycasting too far or too short
+	var far_dist = 0
+	var temp_dist
+	for edge in edges:
+		temp_dist = origin.distance_to(edge)
+		if temp_dist > far_dist:
+			far_dist = temp_dist
+	
+	return far_dist
+
+func rotate_area_to_billboard():
+	var billboard_mode = node_quad.get_surface_material(0).params_billboard_mode
+	
+	#try to match the area with the material's billboard setting, if enabled
+	if billboard_mode > 0:
+		#Look in the same direction as the camera
+		var look = get_viewport().get_camera().to_global(Vector3(0,0,-100)) - get_viewport().get_camera().global_transform.origin
+		look = node_area.translation + look
+		
+		# Y-Billboard: Lock Y rotation, but gives bad results if the camera is tilted.
+		if billboard_mode == 2: 
+			look = Vector3(look.x,0,look.z)
+		
+		node_area.look_at(look, Vector3(0,1,0))
+		
+		#Ratate in the Z axis to compensate camera tilt
+		node_area.rotate_object_local(Vector3(0,0,1), get_viewport().get_camera().rotation.z)

+ 309 - 0
viewport/gui_in_3d/gui_in_3d.tscn

@@ -0,0 +1,309 @@
+[gd_scene load_steps=10 format=2]
+
+[ext_resource path="res://view_gui.tscn" type="PackedScene" id=1]
+
+[sub_resource type="Animation" id=1]
+
+length = 6.0
+loop = true
+step = 0.1
+tracks/0/type = "value"
+tracks/0/path = NodePath("Camera:transform")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/keys = {
+"times": PoolRealArray( 0, 2, 4, 6 ),
+"transitions": PoolRealArray( 1, 1, 1, 1 ),
+"update": 0,
+"values": [ Transform( 0.994592, 0, 0.103856, 0, 1, 0, -0.103856, 0, 0.994592, 0.465682, 0, 1.78523 ), Transform( 0.962984, 0, -0.269557, 0, 1, 0, 0.269557, 0, 0.962984, -0.462237, 0, 2.41934 ), Transform( 0.806599, 0, -0.591098, 0, 1, 0, 0.591098, 0, 0.806599, -1.59502, 0, 2.05358 ), Transform( 0.994592, 0, 0.103856, 0, 1, 0, -0.103856, 0, 0.994592, 0.465682, 0, 1.78523 ) ]
+}
+
+[sub_resource type="PlaneMesh" id=2]
+
+custom_aabb = AABB( 0, 0, 0, 0, 0, 0 )
+size = Vector2( 2, 2 )
+subdivide_width = 0
+subdivide_depth = 0
+
+[sub_resource type="GDScript" id=3]
+
+script/source = "tool
+extends Object
+func e():
+	return 0
+"
+
+[sub_resource type="GDScript" id=4]
+
+script/source = "tool
+extends Object
+func e():
+	return 90
+"
+
+[sub_resource type="GDScript" id=5]
+
+script/source = "tool
+extends Object
+func e():
+	return 0
+"
+
+[sub_resource type="CubeMesh" id=6]
+
+custom_aabb = AABB( 0, 0, 0, 0, 0, 0 )
+size = Vector3( 2, 2, 2 )
+subdivide_width = 0
+subdivide_height = 0
+subdivide_depth = 0
+
+[sub_resource type="SpatialMaterial" id=7]
+
+render_priority = 0
+flags_transparent = false
+flags_unshaded = false
+flags_vertex_lighting = false
+flags_no_depth_test = false
+flags_use_point_size = false
+flags_world_triplanar = false
+flags_fixed_size = false
+flags_albedo_tex_force_srgb = false
+vertex_color_use_as_albedo = false
+vertex_color_is_srgb = false
+params_diffuse_mode = 0
+params_specular_mode = 0
+params_blend_mode = 0
+params_cull_mode = 0
+params_depth_draw_mode = 0
+params_line_width = 1.0
+params_point_size = 1.0
+params_billboard_mode = 0
+params_grow = false
+params_use_alpha_scissor = false
+albedo_color = Color( 0.722656, 0.791992, 1, 1 )
+metallic = 0.0
+metallic_specular = 0.5
+metallic_texture_channel = 0
+roughness = 0.0
+roughness_texture_channel = 0
+emission_enabled = false
+normal_enabled = false
+rim_enabled = false
+clearcoat_enabled = false
+anisotropy_enabled = false
+ao_enabled = false
+depth_enabled = false
+subsurf_scatter_enabled = false
+transmission_enabled = false
+refraction_enabled = false
+detail_enabled = false
+uv1_scale = Vector3( 1, 1, 1 )
+uv1_offset = Vector3( 0, 0, 0 )
+uv1_triplanar = false
+uv1_triplanar_sharpness = 1.0
+uv2_scale = Vector3( 1, 1, 1 )
+uv2_offset = Vector3( 0, 0, 0 )
+uv2_triplanar = false
+uv2_triplanar_sharpness = 1.0
+proximity_fade_enable = false
+distance_fade_enable = false
+_sections_unfolded = [ "Albedo" ]
+
+[sub_resource type="GDScript" id=8]
+
+script/source = "tool
+extends Object
+func e():
+	return 0
+"
+
+[node name="gui_in_3d" type="Spatial" index="0"]
+
+[node name="view_gui" parent="." index="0" instance=ExtResource( 1 )]
+
+_sections_unfolded = [ "Transform", "Visibility" ]
+
+[node name="Camera" type="Camera" parent="." index="1"]
+
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 0.999999, 0, 0, 3 )
+keep_aspect = 1
+cull_mask = 1048575
+environment = null
+h_offset = 0.0
+v_offset = 0.0
+doppler_tracking = 0
+projection = 0
+current = false
+fov = 74.0
+size = 1.0
+near = 0.1
+far = 100.0
+_sections_unfolded = [ "Transform" ]
+
+[node name="OmniLight" type="OmniLight" parent="." index="2"]
+
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 1.38866, 1.2413, 2.72141 )
+layers = 1
+light_color = Color( 1, 1, 1, 1 )
+light_energy = 1.0
+light_indirect_energy = 1.0
+light_negative = false
+light_specular = 0.5
+light_bake_mode = 1
+light_cull_mask = -1
+shadow_enabled = true
+shadow_color = Color( 0, 0, 0, 1 )
+shadow_bias = 0.15
+shadow_contact = 0.0
+shadow_reverse_cull_face = false
+editor_only = false
+omni_range = 10.0
+omni_attenuation = 1.0
+omni_shadow_mode = 1
+omni_shadow_detail = 1
+_sections_unfolded = [ "Light", "Omni", "Shadow" ]
+
+[node name="Camera_Move" type="AnimationPlayer" parent="." index="3"]
+
+root_node = NodePath("..")
+autoplay = "Move_camera"
+playback_process_mode = 1
+playback_default_blend_time = 0.0
+playback_speed = 0.25
+anims/Move_camera = SubResource( 1 )
+blend_times = [  ]
+_sections_unfolded = [ "Playback Options" ]
+
+[node name="3D_background" type="Spatial" parent="." index="4"]
+
+editor/display_folded = true
+
+[node name="Wall" type="MeshInstance" parent="3D_background" index="0"]
+
+transform = Transform( 4, 0, 0, 0, -1.74846e-007, -4, 0, 4, -1.74846e-007, -2.60819, 0.589247, -2.08943 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 2 )
+skeleton = NodePath("..")
+material/0 = null
+script = SubResource( 3 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Wall2" type="MeshInstance" parent="3D_background" index="1"]
+
+transform = Transform( 4, 0, 0, 0, -1.74846e-007, -4, 0, 4, -1.74846e-007, 5.08055, 0.589247, -2.08943 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 2 )
+skeleton = NodePath("..")
+material/0 = null
+script = SubResource( 3 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Wall3" type="MeshInstance" parent="3D_background" index="2"]
+
+transform = Transform( -1.74846e-007, -4, 0, -1.74846e-007, 7.64274e-015, -4, 4, -1.74846e-007, -1.74846e-007, 9.04446, 0.589247, 1.62058 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 2 )
+skeleton = NodePath("..")
+material/0 = null
+script = SubResource( 4 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Floor" type="MeshInstance" parent="3D_background" index="3"]
+
+transform = Transform( 4, 0, 0, 0, 4, 0, 0, 0, 4, -2.60819, -2.68765, 1.46502 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 2 )
+skeleton = NodePath("..")
+material/0 = null
+script = SubResource( 5 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Floor2" type="MeshInstance" parent="3D_background" index="4"]
+
+transform = Transform( 4, 0, 0, 0, 4, 0, 0, 0, 4, 5.08055, -2.68765, 1.46502 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 2 )
+skeleton = NodePath("..")
+material/0 = null
+script = SubResource( 5 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Cube" type="MeshInstance" parent="3D_background" index="5"]
+
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 4.25901, -0.598608, 0.374871 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 6 )
+skeleton = NodePath("..")
+material/0 = SubResource( 7 )
+script = SubResource( 8 )
+_sections_unfolded = [ "Transform", "material" ]
+
+[node name="Cube2" type="MeshInstance" parent="3D_background" index="6"]
+
+transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 2.88761, 2.01326, 0.374871 )
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 6 )
+skeleton = NodePath("..")
+material/0 = SubResource( 7 )
+script = SubResource( 8 )
+_sections_unfolded = [ "Transform" ]
+
+

+ 5 - 1
viewport/gui_in_3d/project.godot

@@ -11,13 +11,17 @@ config_version=3
 [application]
 
 config/name="GUI in 3D"
-run/main_scene="res://Gui_in_3D.tscn"
+run/main_scene="res://gui_in_3d.tscn"
 config/icon="res://icon.png"
 
 [gdnative]
 
 singletons=[  ]
 
+[layer_names]
+
+3d_physics/layer_2="Control"
+
 [rendering]
 
 environment/default_environment="res://default_env.tres"

+ 389 - 0
viewport/gui_in_3d/view_gui.tscn

@@ -0,0 +1,389 @@
+[gd_scene load_steps=8 format=2]
+
+[ext_resource path="res://gui_3d.gd" type="Script" id=1]
+[ext_resource path="res://icon.png" type="Texture" id=2]
+
+[sub_resource type="QuadMesh" id=1]
+
+custom_aabb = AABB( 0, 0, 0, 0, 0, 0 )
+size = Vector2( 3, 2 )
+
+[sub_resource type="ViewportTexture" id=2]
+
+resource_local_to_scene = true
+flags = 0
+viewport_path = NodePath("Viewport")
+
+[sub_resource type="SpatialMaterial" id=3]
+
+resource_local_to_scene = true
+render_priority = 0
+flags_transparent = true
+flags_unshaded = true
+flags_vertex_lighting = false
+flags_no_depth_test = false
+flags_use_point_size = false
+flags_world_triplanar = false
+flags_fixed_size = false
+flags_albedo_tex_force_srgb = true
+vertex_color_use_as_albedo = false
+vertex_color_is_srgb = false
+params_diffuse_mode = 0
+params_specular_mode = 0
+params_blend_mode = 0
+params_cull_mode = 0
+params_depth_draw_mode = 0
+params_line_width = 1.0
+params_point_size = 1.0
+params_billboard_mode = 0
+params_grow = false
+params_use_alpha_scissor = false
+albedo_color = Color( 1, 1, 1, 1 )
+albedo_texture = SubResource( 2 )
+metallic = 0.0
+metallic_specular = 0.5
+metallic_texture_channel = 0
+roughness = 0.0
+roughness_texture_channel = 0
+emission_enabled = false
+normal_enabled = false
+rim_enabled = false
+clearcoat_enabled = false
+anisotropy_enabled = false
+ao_enabled = false
+depth_enabled = false
+subsurf_scatter_enabled = false
+transmission_enabled = false
+refraction_enabled = false
+detail_enabled = false
+uv1_scale = Vector3( 1, 1, 1 )
+uv1_offset = Vector3( 0, 0, 0 )
+uv1_triplanar = false
+uv1_triplanar_sharpness = 1.0
+uv2_scale = Vector3( 1, 1, 1 )
+uv2_offset = Vector3( 0, 0, 0 )
+uv2_triplanar = false
+uv2_triplanar_sharpness = 1.0
+proximity_fade_enable = false
+distance_fade_enable = false
+_sections_unfolded = [ "Flags", "Parameters", "Vertex Color" ]
+
+[sub_resource type="GDScript" id=4]
+
+script/source = "tool
+extends Object
+func e():
+	return 0.01
+"
+
+[sub_resource type="BoxShape" id=5]
+
+extents = Vector3( 1.5, 1, 0.01 )
+script = SubResource( 4 )
+
+[node name="GUI_3D" type="Spatial" index="0"]
+
+script = ExtResource( 1 )
+_sections_unfolded = [ "Transform" ]
+
+[node name="Viewport" type="Viewport" parent="." index="0"]
+
+arvr = false
+size = Vector2( 280, 180 )
+own_world = false
+world = null
+transparent_bg = false
+msaa = 0
+hdr = false
+disable_3d = false
+usage = 0
+debug_draw = 0
+render_target_v_flip = true
+render_target_clear_mode = 0
+render_target_update_mode = 3
+audio_listener_enable_2d = false
+audio_listener_enable_3d = false
+physics_object_picking = false
+gui_disable_input = false
+gui_snap_controls_to_pixels = true
+shadow_atlas_size = 0
+shadow_atlas_quad_0 = 2
+shadow_atlas_quad_1 = 2
+shadow_atlas_quad_2 = 3
+shadow_atlas_quad_3 = 4
+
+[node name="GUI" type="Control" parent="Viewport" index="0"]
+
+editor/display_folded = true
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_right = 280.0
+margin_bottom = 180.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+mouse_filter = 1
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+
+[node name="Panel" type="Panel" parent="Viewport/GUI" index="0"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 1.0
+anchor_bottom = 1.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+_sections_unfolded = [ "Rect" ]
+
+[node name="Label" type="Label" parent="Viewport/GUI/Panel" index="0"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 44.0
+margin_top = 27.0
+margin_right = 121.0
+margin_bottom = 41.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+mouse_filter = 2
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 4
+text = "Hello world!"
+percent_visible = 1.0
+lines_skipped = 0
+max_lines_visible = -1
+
+[node name="Button" type="Button" parent="Viewport/GUI/Panel" index="1"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 14.0
+margin_top = 46.0
+margin_right = 154.0
+margin_bottom = 74.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+focus_mode = 2
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+toggle_mode = false
+enabled_focus_mode = 2
+shortcut = null
+group = null
+text = "A button!"
+flat = false
+align = 1
+_sections_unfolded = [ "Rect" ]
+
+[node name="TextEdit" type="LineEdit" parent="Viewport/GUI/Panel" index="2"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 14.0
+margin_top = 87.0
+margin_right = 154.0
+margin_bottom = 111.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+focus_mode = 2
+mouse_filter = 0
+mouse_default_cursor_shape = 1
+size_flags_horizontal = 1
+size_flags_vertical = 1
+focus_mode = 2
+context_menu_enabled = true
+placeholder_alpha = 0.6
+caret_blink = false
+caret_blink_speed = 0.65
+caret_position = 0
+_sections_unfolded = [ "Rect" ]
+
+[node name="HSlider" type="HSlider" parent="Viewport/GUI/Panel" index="3"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 14.0
+margin_top = 118.0
+margin_right = 154.0
+margin_bottom = 143.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+focus_mode = 2
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 0
+min_value = 0.0
+max_value = 100.0
+step = 1.0
+page = 0.0
+value = 0.0
+exp_edit = false
+rounded = false
+editable = true
+tick_count = 0
+ticks_on_borders = false
+focus_mode = 2
+_sections_unfolded = [ "Rect" ]
+
+[node name="ColorRect" type="ColorRect" parent="Viewport/GUI/Panel" index="4"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 180.0
+margin_top = 26.0
+margin_right = 244.0
+margin_bottom = 90.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+color = Color( 1, 0, 0, 1 )
+_sections_unfolded = [ "Rect" ]
+
+[node name="TextureRect" type="TextureRect" parent="Viewport/GUI/Panel" index="5"]
+
+anchor_left = 0.5
+anchor_top = 0.5
+anchor_right = 0.5
+anchor_bottom = 0.5
+margin_left = 52.0
+margin_top = -52.0
+margin_right = 92.0
+margin_bottom = -12.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+mouse_filter = 1
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+texture = ExtResource( 2 )
+expand = true
+stretch_mode = 0
+
+[node name="VSlider" type="VSlider" parent="Viewport/GUI/Panel" index="6"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 260.0
+margin_top = 26.0
+margin_right = 276.0
+margin_bottom = 166.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+focus_mode = 2
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 0
+size_flags_vertical = 1
+min_value = 0.0
+max_value = 100.0
+step = 1.0
+page = 0.0
+value = 0.0
+exp_edit = false
+rounded = false
+editable = true
+tick_count = 0
+ticks_on_borders = false
+focus_mode = 2
+_sections_unfolded = [ "Rect" ]
+
+[node name="OptionButton" type="OptionButton" parent="Viewport/GUI/Panel" index="7"]
+
+anchor_left = 0.0
+anchor_top = 0.0
+anchor_right = 0.0
+anchor_bottom = 0.0
+margin_left = 170.0
+margin_top = 111.0
+margin_right = 252.0
+margin_bottom = 165.0
+rect_pivot_offset = Vector2( 0, 0 )
+rect_clip_content = false
+focus_mode = 2
+mouse_filter = 0
+mouse_default_cursor_shape = 0
+size_flags_horizontal = 1
+size_flags_vertical = 1
+toggle_mode = false
+action_mode = 0
+enabled_focus_mode = 2
+shortcut = null
+group = null
+text = "Item 0"
+flat = false
+align = 0
+items = [ "Item 0", null, false, -1, null, "Item 1", null, false, -1, null, "Item 2", null, false, -1, null ]
+selected = 0
+_sections_unfolded = [ "Rect" ]
+
+[node name="Quad" type="MeshInstance" parent="." index="1"]
+
+layers = 1
+material_override = null
+cast_shadow = 1
+extra_cull_margin = 0.0
+use_in_baked_light = false
+lod_min_distance = 0.0
+lod_min_hysteresis = 0.0
+lod_max_distance = 0.0
+lod_max_hysteresis = 0.0
+mesh = SubResource( 1 )
+skeleton = NodePath("..")
+material/0 = SubResource( 3 )
+_sections_unfolded = [ "Geometry", "Transform", "material" ]
+
+[node name="Area" type="Area" parent="Quad" index="0"]
+
+input_ray_pickable = true
+input_capture_on_drag = true
+space_override = 0
+gravity_point = false
+gravity_distance_scale = 0.0
+gravity_vec = Vector3( 0, -1, 0 )
+gravity = 9.8
+linear_damp = 0.1
+angular_damp = 1.0
+priority = 0.0
+monitoring = true
+monitorable = true
+collision_layer = 2
+collision_mask = 1
+audio_bus_override = false
+audio_bus_name = "Master"
+reverb_bus_enable = false
+reverb_bus_name = "Master"
+reverb_bus_amount = 0.0
+reverb_bus_uniformity = 0.0
+
+[node name="CollisionShape" type="CollisionShape" parent="Quad/Area" index="0"]
+
+shape = SubResource( 5 )
+disabled = false
+
+