Table of Contents

Class ManipulationSystem

Namespace
GridPlacement.GDScript
Assembly
MoonBark.GridPlacement.GDScript.dll

System for manipulating (move, rotate, flip, demolish, build preview integration) grid building objects.\n\nResponsibilities: - Creates and manages a temporary manipulation copy ("move copy") when entering MOVE workflows. - Delegates spatial translation to the external targeting/positioner system. (No per-frame movement logic here.) - Sets up and tears down placement validation rules for move and build actions. - Manages physics layer disabling/enabling during active manipulation. - Emits structured status transitions via ManipulationData.status (STARTED, FAILED, FINISHED, CANCELED).\n\nNon‑Responsibilities (by design): - Calculating or enforcing cursor/keyboard driven position updates (handled by GridTargetingSystem & its positioner node). - Determining selection/target acquisition (handled by targeting state & systems). - Rendering or UI feedback (delegated to name displayer / external UI nodes).\n\nDesign Notes: - The move copy is parented under the active positioner when available so that any positioner movement (mouse, keyboard, gamepad) naturally repositions the copy without duplicate logic or tight coupling. - If no positioner exists (edge/test fallback), the copy is parented under the manipulation parent as a legacy behavior. - Rotation / flip actions operate directly on the target Node2D passed in, typically the move copy's root while an action is active.

class ManipulationSystem extends GBSystem
ManipulationSystem

Properties

system

var system = ManipulationSystem.new()

issues

var issues = setup_report.indicators_report.issues

logger

var logger = container.get_logger()

issues

var issues = setup_report.indicators_report.issues

required_props

var required_props: Array[String] = ["_states", "_manipulation_settings", "_actions", "_indicator_context"]

issues

var issues = setup_report.indicators_report.issues

failed_reason

var failed_reason: String

source

var source: Manipulatable = GBSearchUtils.find_first(p_root, Manipulatable)

move_data

var move_data = _states.manipulation.data

started

Validate all possible reasons for failing

var started: bool = _start_move(move_data)

root

var root: Node = target.root

kept_script_types

var kept_script_types: Array[String] = ["Manipulatable"]

source_rotation

var source_rotation: float = p_data.source.root.rotation

source_scale

var source_scale: Vector2 = p_data.source.root.scale

move_rules

var move_rules: Array[PlacementRule] = []

ignore_base_rules

var ignore_base_rules = p_data.source.settings != null and p_data.source.settings.ignore_base_rules == true

report

var report = _indicator_context.get_manager().try_setup(move_rules, _states.targeting, ignore_base_rules)

indicators

var indicators: Array[RuleCheckIndicator] = _indicator_context.get_manager().get_indicators()

bad_move_results

var bad_move_results = ValidationResults.new(false, "[p_move] is not valid. Cannot move object.", {})

target_root

var target_root = p_move.target.root

move_rules

var move_rules: Array[PlacementRule] = []

ignore_base

var ignore_base: bool = false

validation_results

var validation_results: ValidationResults

setup_report

var setup_report: PlacementReport = _indicator_context.get_manager().try_setup(

issues

var issues = setup_report.indicators_report.issues

vr

var vr = ValidationResults.new(

old_transform

var old_transform: Transform2D = p_move.source.root.global_transform

manipulation_parent

var manipulation_parent: ManipulationParent = _states.manipulation.parent

final_position

var final_position: Vector2 = target_root.global_position

accumulated_rotation

var accumulated_rotation: float = manipulation_parent.rotation

accumulated_scale

var accumulated_scale: Vector2 = manipulation_parent.scale

root_node

var root_node: Node = p_move.source.root

body

var body = root_node as RigidBody2D

node2d

var node2d = root_node as Node2D

applied_position

var applied_position: Vector2 = (root_node as Node2D).global_position if root_node is Node2D else final_position

passing

var passing = true

data

var data: ManipulationData = _states.manipulation.data

target

var target: Manipulatable = p_manipulatable if p_manipulatable != null else _states.manipulation.active_manipulatable

demolish_data

var demolish_data = try_demolish(p_manipulatable)

root

var root: Node = target.root

display_name

var display_name: String = _get_demolish_display_name(target)

demolish_data

var demolish_data = try_demolish(p_manipulatable)

tree

var tree = get_tree()

tree

var tree = get_tree()

manipulation_parent

var manipulation_parent: ManipulationParent = _states.manipulation.parent

manipulation_parent

var manipulation_parent: ManipulationParent = _states.manipulation.parent

manipulation_parent

var manipulation_parent: ManipulationParent = _states.manipulation.parent

active_data

var active_data = _states.manipulation.data

move_data

var move_data = _states.manipulation.data

manipulatable

var manipulatable = GBSearchUtils.find_first(p_preview, Manipulatable)

area2d

var area2d = p_new if p_new is Area2D else null

has_targetable

var has_targetable: bool = area2d.get_collision_layer_value(12)

manipulatable

var manipulatable = GBSearchUtils.find_first(p_preview, Manipulatable)

failed

var failed = ManipulationData.new(_states.manipulation.get_manipulator(), _states.manipulation.data.source, p_manipulated, p_action)

physics_objects

var physics_objects = GBSearchUtils.get_collision_object_2ds(p_container)

node

var node: Node = p_manipulatable.root if p_manipulatable.root != null else p_manipulatable

bits

var bits: Array[int] = []

Methods

create_with_injection

static func create_with_injection(p_parent: Node, container: PlacementContainer) -> ManipulationSystem:

Parameters

p_parent
container

Returns

get_runtime_issues

func get_runtime_issues() -> Array[String]:

Returns

resolve_gb_dependencies

func resolve_gb_dependencies(p_container: PlacementContainer) -> void:

Parameters

p_container

Returns

try_move

func try_move(p_root: Node) -> ManipulationData:

Parameters

p_root

Returns

try_placement

func try_placement(p_move: ManipulationData) -> ValidationResults:

Parameters

p_move

Returns

is_ready

func is_ready() -> bool:

Returns

cancel

func cancel() -> void:

Returns

try_demolish

func try_demolish(p_manipulatable: Manipulatable) -> ManipulationData:

Parameters

p_manipulatable

Returns

demolish

func demolish(p_manipulatable: Manipulatable) -> bool:

Parameters

p_manipulatable

Returns

rotate

func rotate(p_target: Node, degrees: float) -> bool:

Parameters

p_target
degrees

Returns

flip_horizontal

func flip_horizontal(p_target: Node) -> bool:

Parameters

p_target

Returns

flip_vertical

func flip_vertical(p_target: Node) -> bool:

Parameters

p_target

Returns

get_targeted

func get_targeted() -> Node:

Returns

set_targeted

func set_targeted(p_obj_root: Node) -> void:

Parameters

p_obj_root

Returns

Events

move_indicators_ready

Emitted when move indicators have been fully set up after physics frame Passes the array of created indicators for debugging and validation

signal move_indicators_ready(indicators: Array[RuleCheckIndicator])