parent
987cb61c1f
commit
8b7788fe49
@ -0,0 +1,98 @@ |
||||
extends Spatial |
||||
|
||||
const MOVE_MARGIN = 20 |
||||
const MOVE_SPEED = 30 |
||||
|
||||
const ray_length = 1000 |
||||
onready var cam = $Camera |
||||
|
||||
var team = 0 |
||||
var selected_units = [] |
||||
onready var selection_box = $SelectionBox |
||||
var start_sel_pos = Vector2() |
||||
|
||||
func _process(delta): |
||||
var m_pos = get_viewport().get_mouse_position() |
||||
# calc_move(m_pos, delta) |
||||
if Input.is_action_just_pressed("main_command"): |
||||
move_selected_units(m_pos) |
||||
if Input.is_action_just_pressed("alt_command"): |
||||
selection_box.start_sel_pos = m_pos |
||||
start_sel_pos = m_pos |
||||
if Input.is_action_pressed("alt_command"): |
||||
selection_box.m_pos = m_pos |
||||
selection_box.is_visible = true |
||||
else: |
||||
selection_box.is_visible = false |
||||
if Input.is_action_just_released("alt_command"): |
||||
select_units(m_pos) |
||||
|
||||
func calc_move(m_pos, delta): |
||||
var v_size = get_viewport().size |
||||
var move_vec = Vector3() |
||||
if m_pos.x < MOVE_MARGIN: |
||||
move_vec.x -= 1 |
||||
if m_pos.y < MOVE_MARGIN: |
||||
move_vec.z -= 1 |
||||
if m_pos.x > v_size.x - MOVE_MARGIN: |
||||
move_vec.x += 1 |
||||
if m_pos.y > v_size.y - MOVE_MARGIN: |
||||
move_vec.z += 1 |
||||
move_vec = move_vec.rotated(Vector3(0, 1, 0), rotation_degrees.y) |
||||
global_translate(move_vec * delta * MOVE_SPEED) |
||||
|
||||
func move_selected_units(m_pos): |
||||
var result = raycast_from_mouse(m_pos, 1) |
||||
if result: |
||||
var unit_index = 0 |
||||
for unit in selected_units: |
||||
var new_position = result.position |
||||
new_position.x = new_position.x + unit_index |
||||
unit.move_to(new_position) |
||||
unit_index += 1 |
||||
|
||||
func select_units(m_pos): |
||||
var new_selected_units = [] |
||||
if m_pos.distance_squared_to(start_sel_pos) < 16: |
||||
var u = get_unit_under_mouse(m_pos) |
||||
if u != null: |
||||
new_selected_units.append(u) |
||||
else: |
||||
new_selected_units = get_units_in_box(start_sel_pos, m_pos) |
||||
|
||||
for unit in selected_units: |
||||
unit.deselect() |
||||
for unit in new_selected_units: |
||||
unit.select() |
||||
selected_units = new_selected_units |
||||
|
||||
func get_unit_under_mouse(m_pos): |
||||
var result = raycast_from_mouse(m_pos, 3) |
||||
if result and result.collider.is_in_group("units"): |
||||
return result.collider |
||||
|
||||
func get_units_in_box(top_left, bot_right): |
||||
if top_left.x > bot_right.x: |
||||
var tmp = top_left.x |
||||
top_left.x = bot_right.x |
||||
bot_right.x = tmp |
||||
if top_left.y > bot_right.y: |
||||
var tmp = top_left.y |
||||
top_left.y = bot_right.y |
||||
bot_right.y = tmp |
||||
var box = Rect2(top_left, bot_right - top_left) |
||||
var box_selected_units = [] |
||||
for unit in get_tree().get_nodes_in_group("units"): |
||||
if box.has_point(cam.unproject_position(unit.global_transform.origin)): |
||||
box_selected_units.append(unit) |
||||
return box_selected_units |
||||
|
||||
func raycast_from_mouse(m_pos, collision_mask): |
||||
var ray_start = cam.project_ray_origin(m_pos) |
||||
var ray_end = ray_start + cam.project_ray_normal(m_pos) * ray_length |
||||
var space_state = get_world().direct_space_state |
||||
return space_state.intersect_ray(ray_start, ray_end, [], collision_mask) |
||||
|
||||
|
||||
func _on_Camera_camera_moved(new_location): |
||||
pass # Replace with function body. |
||||
@ -0,0 +1,33 @@ |
||||
[gd_scene load_steps=5 format=2] |
||||
|
||||
[ext_resource path="res://utils/camera/SelectionBox.gd" type="Script" id=1] |
||||
[ext_resource path="res://utils/camera/CamBase.gd" type="Script" id=2] |
||||
[ext_resource path="res://utils/camera/CameraController.gd" type="Script" id=3] |
||||
[ext_resource path="res://utils/camera/CameraInput.gd" type="Script" id=4] |
||||
|
||||
[node name="CamBase" type="Spatial"] |
||||
transform = Transform( 1, 0, 0, 0, 0.34202, 0.939693, 0, -0.939693, 0.34202, 0, 0, 0 ) |
||||
script = ExtResource( 2 ) |
||||
|
||||
[node name="Camera" type="Camera" parent="."] |
||||
size = 20.0 |
||||
near = 0.01 |
||||
far = 8192.0 |
||||
script = ExtResource( 3 ) |
||||
movement_speed = 70.017 |
||||
min_zoom = 51.0 |
||||
zoom_sensibility = 2.818 |
||||
rotation_sensibility = 1.0 |
||||
|
||||
[node name="Node" type="Node" parent="Camera"] |
||||
script = ExtResource( 4 ) |
||||
|
||||
[node name="SelectionBox" type="Control" parent="."] |
||||
margin_right = 40.0 |
||||
margin_bottom = 40.0 |
||||
script = ExtResource( 1 ) |
||||
|
||||
[connection signal="on_change_action" from="Camera/Node" to="Camera" method="change_action"] |
||||
[connection signal="on_change_velocity" from="Camera/Node" to="Camera" method="change_velocity"] |
||||
[connection signal="on_rotate_view" from="Camera/Node" to="Camera" method="rotate_view"] |
||||
[connection signal="on_zoom" from="Camera/Node" to="Camera" method="zoom"] |
||||
@ -0,0 +1,140 @@ |
||||
extends Camera |
||||
class_name CameraController |
||||
|
||||
signal camera_moved(new_location) |
||||
|
||||
enum CAMERA_ACTIONS{ |
||||
MOVING, |
||||
ROTATING_VIEW, |
||||
} |
||||
|
||||
export(float,1,100) var movement_speed = 30 |
||||
export(float,0.01,0.99) var movement_damping = 0.74 |
||||
export(float,0.01, 3.1415) var max_rotation = 1.2 |
||||
export(float,0.01, 3.1415) var min_rotation = 0.5 |
||||
|
||||
#Value in percentage of screen portion |
||||
#A value of 0.3 means that when you place the cursor 30% or less away from an edge it will start pushing the camera |
||||
export(float, 0.0,1.0) var edge_size = 0.0 |
||||
|
||||
#EDIT HERE--->**,***<--- ZOOM MIN AND MAX LIMITS |
||||
export(float, 10,100) var min_zoom = 25 |
||||
export(float, 10,100) var max_zoom = 100 |
||||
|
||||
export(float, 1,3) var zoom_sensibility = 2.5 |
||||
|
||||
export(float, 1,3) var rotation_sensibility = 2.3 |
||||
export(float, 1.0, 10.0) var height = 5.0 |
||||
var pitch : float |
||||
var yaw : float |
||||
var current_action = CAMERA_ACTIONS.MOVING |
||||
var velocity : Vector2 |
||||
|
||||
func _ready(): |
||||
# Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED) |
||||
|
||||
pitch = rotation.x |
||||
yaw = rotation.y |
||||
|
||||
# var new_rotation = (max_zoom - fov) * (max_rotation - min_rotation) / max_zoom + min_rotation |
||||
transform.basis = Basis(Vector3(1, 0, 0), (min_rotation + max_rotation) / 2.0) |
||||
fov = (min_zoom + max_zoom) / 2.0 |
||||
|
||||
func change_action(action): |
||||
current_action = action |
||||
match(current_action): |
||||
# CAMERA_ACTIONS.MOVING: |
||||
# Input.set_mouse_mode(Input.MOUSE_MODE_CONFINED) |
||||
CAMERA_ACTIONS.ROTATING_VIEW: |
||||
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED) |
||||
|
||||
func _process(delta): |
||||
|
||||
match(current_action): |
||||
CAMERA_ACTIONS.MOVING: |
||||
#CAMERA MOVEMENT |
||||
velocity.x = clamp(velocity.x * movement_damping,-1.0,1.0) |
||||
velocity.y = clamp(velocity.y * movement_damping,-1.0,1.0) |
||||
|
||||
if velocity != Vector2.ZERO: |
||||
move(velocity) |
||||
|
||||
|
||||
func change_velocity(_velocity : Vector2): |
||||
velocity = _velocity |
||||
|
||||
func move(_velocity : Vector2): |
||||
#Move along cameras X axis |
||||
global_transform.origin += global_transform.basis.x * velocity.x * movement_speed * get_process_delta_time() |
||||
#Calculate a forward camera direction that is perpendicular to the XZ plane |
||||
var forward = global_transform.basis.x.cross(Vector3.UP) |
||||
#Move the camera along that forward direction |
||||
global_transform.origin += forward * velocity.y * movement_speed * get_process_delta_time() |
||||
|
||||
var y_offset = 0 |
||||
var space_state = get_world().direct_space_state |
||||
var result = space_state.intersect_ray(Vector3(global_transform.origin.x, 100, global_transform.origin.z), Vector3(global_transform.origin.x, 0, global_transform.origin.z)) |
||||
if result: |
||||
y_offset = result.position.y |
||||
else: |
||||
y_offset = 0 |
||||
global_transform.origin.y = max(10 + y_offset * 1.3, 30) |
||||
|
||||
emit_signal("camera_moved", global_transform.origin) |
||||
|
||||
|
||||
func zoom(direction : float): |
||||
#Zooming using fov |
||||
var new_fov = fov + (sign(direction) * pow(abs(direction),zoom_sensibility)/100 * get_process_delta_time()) |
||||
fov = clamp(new_fov,min_zoom,max_zoom) |
||||
|
||||
# Linear equation |
||||
var slope = (min_rotation - max_rotation) / (max_zoom - min_zoom) |
||||
var b = max_rotation - slope * min_zoom |
||||
var new_rotation = slope * fov + b |
||||
transform.basis = Basis(Vector3(1, 0, 0), new_rotation) |
||||
|
||||
|
||||
func rotate_view(axis : Vector2): |
||||
|
||||
var pitch_rotation_amount = -axis.y/100 * get_process_delta_time() * rotation_sensibility |
||||
var yaw_rotation_amount = -axis.x/100 * get_process_delta_time() * rotation_sensibility |
||||
|
||||
pitch += pitch_rotation_amount |
||||
pitch = clamp(pitch,-PI/2,0) |
||||
|
||||
yaw += yaw_rotation_amount |
||||
|
||||
rotation.x = pitch |
||||
rotation.y = yaw |
||||
|
||||
func _on_Map_map_clicked(position): |
||||
global_transform.origin.x = position.x |
||||
global_transform.origin.z = position.y |
||||
|
||||
|
||||
var y_offset = 0 |
||||
var space_state = get_world().direct_space_state |
||||
var result = space_state.intersect_ray(Vector3(global_transform.origin.x, 100, global_transform.origin.z), Vector3(global_transform.origin.x, 0, global_transform.origin.z)) |
||||
if result: |
||||
y_offset = result.position.y |
||||
else: |
||||
y_offset = 0 |
||||
global_transform.origin.y = max(height + y_offset * 1.3, 30) |
||||
pass # Replace with function body. |
||||
|
||||
|
||||
func _on_World_character_created(position): |
||||
global_transform.origin.x = position.x |
||||
global_transform.origin.z = position.y |
||||
|
||||
|
||||
var y_offset = 0 |
||||
var space_state = get_world().direct_space_state |
||||
var result = space_state.intersect_ray(Vector3(global_transform.origin.x, 100, global_transform.origin.z), Vector3(global_transform.origin.x, 0, global_transform.origin.z)) |
||||
if result: |
||||
y_offset = result.position.y |
||||
else: |
||||
y_offset = 0 |
||||
global_transform.origin.y = max(height + y_offset * 1.3, 30) |
||||
pass # Replace with function body. |
||||
@ -0,0 +1,158 @@ |
||||
extends Node |
||||
|
||||
export(float,0.001,1.0) var screen_edge_size : float = 0.3 |
||||
export(float) var mouse_wheel_damping = 0.9 |
||||
|
||||
#USED TO CALCULATE RAW MOVEMENT WHILE PUSHING AN EDGE |
||||
var horizontal : float = 0.0 |
||||
var vertical : float = 0.0 |
||||
|
||||
#USED TO STORE MOUSE WHEEL INERTIA TO ENABLE SMOOTH STOPPING |
||||
var mouse_wheel : float = 0.0 |
||||
|
||||
signal on_change_velocity(velocity) |
||||
signal on_rotate_view(relative) |
||||
signal on_change_action(new_state) |
||||
signal on_zoom(value) |
||||
|
||||
var current_action |
||||
|
||||
#TOUCH VARIABLE FOR MOBILE |
||||
var touch_count : int = 0 |
||||
var swipe_start : Vector2 |
||||
|
||||
func _ready(): |
||||
connect("on_change_action",self,"change_action") |
||||
emit_signal("on_change_action",CameraController.CAMERA_ACTIONS.MOVING) |
||||
|
||||
func change_action(action): |
||||
current_action = action |
||||
|
||||
func toggle_action(): |
||||
current_action = 1 - current_action |
||||
|
||||
func start_swipe(position : Vector2): |
||||
swipe_start = position |
||||
|
||||
func move_swipe(position : Vector2): |
||||
if blocked_movement: |
||||
return |
||||
|
||||
var delta = (position - swipe_start)*-1 |
||||
var direction_x = sign(delta.x) |
||||
var direction_y = sign(delta.y) |
||||
|
||||
var view_size = get_viewport().get_visible_rect().size - Vector2.ONE |
||||
|
||||
horizontal = range_lerp(abs(delta.x),0,view_size.x,0.0,1.0) |
||||
vertical = range_lerp(abs(delta.y),0,view_size.y,0.0,1.0) |
||||
|
||||
#Applies direction |
||||
horizontal *= direction_x |
||||
vertical *= direction_y |
||||
|
||||
var touches = [ Vector2.ZERO, Vector2.ZERO ] |
||||
var start_pinch_distance : float |
||||
var last_pinch_distance : float |
||||
var pinching : float |
||||
|
||||
var blocked_movement : bool = false |
||||
|
||||
func _input(event): |
||||
|
||||
if OS.get_name() == "Android" or OS.get_name() == "iOS": |
||||
#MOBILE############## |
||||
if event is InputEventScreenTouch: |
||||
#SET TOUCH STARTING POSTIION |
||||
touches[event.index] = event.position |
||||
if event.pressed: |
||||
touch_count += 1 |
||||
start_swipe(event.position) |
||||
else: |
||||
touch_count -= 1 |
||||
#RENABLE SWIPE MOVEMENT BECAUSE EVERY TOUCH WAS LIFTED |
||||
if blocked_movement and touch_count <= 0: |
||||
blocked_movement = false |
||||
|
||||
#RESET PINCHING VALUE WHEN A NEW TOUCH IS DETECTED OR HAS BEEN LIFTED |
||||
pinching = 0.0 |
||||
if touch_count == 2: |
||||
#STARTED ZOOMING, BLOCK MOVEMENT UNTIL EVERY TOUCH IS LIFTED |
||||
blocked_movement = true |
||||
start_pinch_distance = (touches[1] - touches[0]).length() |
||||
|
||||
if event is InputEventScreenDrag: |
||||
if touch_count == 2: |
||||
#UPDATE TOUCHES POSITIONS |
||||
touches[event.index] = event.position |
||||
#CALCULATE DISTANCE BETWEEN TOUCHES |
||||
var pinch_distance = (touches[1] - touches[0]).length() |
||||
var pinch_direction = 1 if pinch_distance > last_pinch_distance else -1 |
||||
#CALCULATE PINCH DELTA |
||||
pinching = abs(start_pinch_distance - pinch_distance) * pinch_direction |
||||
#USE MOUSE WHEEL BUFFER TO ENABLE SMOOTHING |
||||
mouse_wheel += pinching * get_process_delta_time() |
||||
last_pinch_distance = pinch_distance |
||||
else: |
||||
if current_action == CameraController.CAMERA_ACTIONS.MOVING: |
||||
move_swipe(event.position) |
||||
elif current_action == CameraController.CAMERA_ACTIONS.ROTATING_VIEW: |
||||
emit_signal("on_rotate_view",event.relative) |
||||
|
||||
###############MOBILE |
||||
else: |
||||
#PC################## |
||||
#Camera edge pushing |
||||
if event is InputEventMouseMotion: |
||||
#ROTATE VIEW |
||||
if current_action == CameraController.CAMERA_ACTIONS.ROTATING_VIEW: |
||||
emit_signal("on_rotate_view",event.relative) |
||||
#Gets screen size |
||||
var view_size = get_viewport().get_visible_rect().size - Vector2.ONE |
||||
#Get mouse position in percentage values relative to the screen |
||||
var delta = (event.position) / view_size |
||||
#Convert it to a range between [-1,1] |
||||
delta = (delta * 2) - Vector2.ONE |
||||
|
||||
if current_action == CameraController.CAMERA_ACTIONS.MOVING: |
||||
#Store it an buffer to use it on _process |
||||
#Calculates delta based on percentage between the edge size and the actual edge |
||||
horizontal = max(abs(delta.x) - (1.0 - screen_edge_size),0) |
||||
vertical = max(abs(delta.y) - (1.0 - screen_edge_size),0) |
||||
#Converts it to an [0.0,1.0] range |
||||
horizontal = range_lerp(horizontal,0.0,screen_edge_size,0.0,1.0) |
||||
vertical = range_lerp(vertical,0.0,screen_edge_size,0.0,1.0) |
||||
#Applies direction |
||||
horizontal *= sign(delta.x) |
||||
vertical *= sign(delta.y) |
||||
elif current_action == CameraController.CAMERA_ACTIONS.ROTATING_VIEW: |
||||
horizontal = delta.x |
||||
vertical = delta.y |
||||
pass |
||||
|
||||
|
||||
if event is InputEventMouseButton: |
||||
#WHEEL SCROLL |
||||
if event.button_index == BUTTON_WHEEL_UP or event.button_index == BUTTON_WHEEL_DOWN: |
||||
if event.pressed and not event.is_echo(): |
||||
var direction = (-1 if event.button_index == BUTTON_WHEEL_UP else 0) + (1 if event.button_index == BUTTON_WHEEL_DOWN else 0) |
||||
mouse_wheel += direction * get_process_delta_time() * 1000 |
||||
###################PC |
||||
|
||||
func _process(delta): |
||||
|
||||
#PC###### |
||||
match(current_action): |
||||
CameraController.CAMERA_ACTIONS.MOVING: |
||||
#RESIDUAL MOVEMENT |
||||
if horizontal != 0 or vertical != 0: |
||||
emit_signal("on_change_velocity",Vector2(horizontal, vertical)) |
||||
|
||||
#MOUSE WHEEL |
||||
if mouse_wheel != 0: |
||||
mouse_wheel = mouse_wheel * mouse_wheel_damping |
||||
emit_signal("on_zoom",mouse_wheel) |
||||
#######PC |
||||
|
||||
|
||||
|
||||
@ -0,0 +1,17 @@ |
||||
extends Control |
||||
|
||||
var is_visible = false |
||||
var m_pos = Vector2() |
||||
var start_sel_pos = Vector2() |
||||
const sel_box_col = Color(0, 1, 0) |
||||
const sel_box_line_width = 3 |
||||
|
||||
func _draw(): |
||||
if is_visible and start_sel_pos != m_pos: |
||||
draw_line(start_sel_pos, Vector2(m_pos.x, start_sel_pos.y), sel_box_col, sel_box_line_width) |
||||
draw_line(start_sel_pos, Vector2(start_sel_pos.x, m_pos.y), sel_box_col, sel_box_line_width) |
||||
draw_line(m_pos, Vector2(m_pos.x, start_sel_pos.y), sel_box_col, sel_box_line_width) |
||||
draw_line(m_pos, Vector2(start_sel_pos.x, m_pos.y), sel_box_col, sel_box_line_width) |
||||
|
||||
func _process(delta): |
||||
update() |
||||
Loading…
Reference in new issue