<commit_before>extends Control

export(NodePath) var target
export var min_scale = 0.1
export var max_scale = 3.0
export var one_finger_rot_x = true
export var one_finger_rot_y = true
export var two_fingers_rot_z = true
export var two_fingers_zoom = true

var base_state
var curr_state

var target_node

# We keep here a copy of the state before the number of fingers changed to avoid accumulation errors.
var base_xform

func _ready():
	base_state = {}
	curr_state = {}
	target_node = get_node(target)


func _gui_input(event):
	# We must start touching inside, but we can drag or unpress outside.
#	if not (event is InputEventScreenDrag or
#		(event is InputEventScreenTouch and (not event.pressed or get_global_rect().has_point(event.position)))):
#		return

	var finger_count = base_state.size()

	if finger_count == 0:
		# No fingers => Accept press.
		if event is InputEventScreenTouch:
			if event.pressed:
				# A finger started touching.

				base_state = {
					event.index: event.position,
				}

	elif finger_count == 1:
		# One finger => For rotating around X and Y.
		# Accept one more press, unpress or drag.
		if event is InputEventScreenTouch:
			if event.pressed:
				# One more finger started touching.

				# Reset the base state to the only current and the new fingers.
				base_state = {
					curr_state.keys()[0]: curr_state.values()[0],
					event.index: event.position,
				}
			else:
				if base_state.has(event.index):
					# Only touching finger released.

					base_state.clear()

		elif event is InputEventScreenDrag:
			if curr_state.has(event.index):
				# Touching finger dragged.
				var unit_drag = _px2unit(base_state[base_state.keys()[0]] - event.position)
				if one_finger_rot_x:
					target_node.global_rotate(Vector3.UP, deg2rad(180.0 * unit_drag.x))
				if one_finger_rot_y:
					target_node.global_rotate(Vector3.RIGHT, deg2rad(180.0 * unit_drag.y))
				# Since rotating around two axes, we have to reset the base constantly.
				curr_state[event.index] = event.position
				base_state[event.index] = event.position
				base_xform = target_node.get_transform()

	elif finger_count == 2:
		# Two fingers => To pinch-zoom and rotate around Z.
		# Accept unpress or drag.
		if event is InputEventScreenTouch:
			if not event.pressed and base_state.has(event.index):
				# Some known touching finger released.

				# Remove released finger from the base state.
				base_state.erase(event.index)
				# Reset the base state to the now only toyching finger.
				base_state = {
					curr_state.keys()[0]: curr_state.values()[0],
				}

		elif event is InputEventScreenDrag:
			if curr_state.has(event.index):
				# Some known touching finger dragged.
				curr_state[event.index] = event.position

				# Compute base and current inter-finger vectors.
				var base_segment = base_state[base_state.keys()[0]] - base_state[base_state.keys()[1]]
				var new_segment = curr_state[curr_state.keys()[0]] - curr_state[curr_state.keys()[1]]

				# Get the base scale from the base matrix.<commit_msg>Fix jumps in scale and rotation when pinching<commit_after>extends Control

export(NodePath) var target
export var min_scale = 0.1
export var max_scale = 3.0
export var one_finger_rot_x = true
export var one_finger_rot_y = true
export var two_fingers_rot_z = true
export var two_fingers_zoom = true

var base_state
var curr_state

var target_node

# We keep here a copy of the state before the number of fingers changed to avoid accumulation errors.
var base_xform

func _ready():
	base_state = {}
	curr_state = {}
	target_node = get_node(target)


func _gui_input(event):
	# We must start touching inside, but we can drag or unpress outside.
#	if not (event is InputEventScreenDrag or
#		(event is InputEventScreenTouch and (not event.pressed or get_global_rect().has_point(event.position)))):
#		return

	var finger_count = base_state.size()

	if finger_count == 0:
		# No fingers => Accept press.
		if event is InputEventScreenTouch:
			if event.pressed:
				# A finger started touching.

				base_state = {
					event.index: event.position,
				}

	elif finger_count == 1:
		# One finger => For rotating around X and Y.
		# Accept one more press, unpress or drag.
		if event is InputEventScreenTouch:
			if event.pressed:
				# One more finger started touching.

				# Reset the base state to the only current and the new fingers.
				base_state = {
					curr_state.keys()[0]: curr_state.values()[0],
					event.index: event.position,
				}
			else:
				if base_state.has(event.index):
					# Only touching finger released.

					base_state.clear()

		elif event is InputEventScreenDrag:
			if curr_state.has(event.index):
				# Touching finger dragged.
				var unit_drag = _px2unit(base_state[base_state.keys()[0]] - event.position)
				if one_finger_rot_x:
					target_node.global_rotate(Vector3.UP, deg2rad(180.0 * unit_drag.x))
				if one_finger_rot_y:
					target_node.global_rotate(Vector3.RIGHT, deg2rad(180.0 * unit_drag.y))
				# Since rotating around two axes, we have to reset the base constantly.
				curr_state[event.index] = event.position
				base_state[event.index] = event.position
				base_xform = target_node.get_transform()

	elif finger_count == 2:
		# Two fingers => To pinch-zoom and rotate around Z.
		# Accept unpress or drag.
		if event is InputEventScreenTouch:
			if not event.pressed and base_state.has(event.index):
				# Some known touching finger released.

				# Clear the base state
				base_state.clear()

		elif event is InputEventScreenDrag:
			if curr_state.has(event.index):
				# Some known touching finger dragged.
				curr_state[event.index] = event.position

				# Compute base and current inter-finger vectors.
				var base_segment = base_state[base_state.keys()[0]] - base_state[base_state.keys()[1]]
				var new_segment = curr_state[curr_state.keys()[0]] - curr_state[curr_state.keys()[1]]

				# Get the base scale from the base matrix.
{'fraction_non_alphanumeric': 0.08846414073071719, 'fraction_numerical': 0.009472259810554804, 'mean_word_length': 3.707802547770701, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7644683', 'n_tokens_mistral': 2170, 'n_tokens_neox': 1847, 'n_words': 576}