1/**************************************************************************/
2/* remote_transform_2d.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
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 "remote_transform_2d.h"
32
33void RemoteTransform2D::_update_cache() {
34 cache = ObjectID();
35 if (has_node(remote_node)) {
36 Node *node = get_node(remote_node);
37 if (!node || this == node || node->is_ancestor_of(this) || this->is_ancestor_of(node)) {
38 return;
39 }
40
41 cache = node->get_instance_id();
42 }
43}
44
45void RemoteTransform2D::_update_remote() {
46 if (!is_inside_tree()) {
47 return;
48 }
49
50 if (cache.is_null()) {
51 return;
52 }
53
54 Node2D *n = Object::cast_to<Node2D>(ObjectDB::get_instance(cache));
55 if (!n) {
56 return;
57 }
58
59 if (!n->is_inside_tree()) {
60 return;
61 }
62
63 if (!(update_remote_position || update_remote_rotation || update_remote_scale)) {
64 return; // The transform data of the RemoteTransform2D is not used at all.
65 }
66
67 //todo make faster
68 if (use_global_coordinates) {
69 if (update_remote_position && update_remote_rotation && update_remote_scale) {
70 n->set_global_transform(get_global_transform());
71 return;
72 }
73
74 Transform2D n_trans = n->get_global_transform();
75 Transform2D our_trans = get_global_transform();
76
77 // There are more steps in the operation of set_rotation, so avoid calling it.
78 Transform2D trans = update_remote_rotation ? our_trans : n_trans;
79
80 if (update_remote_rotation ^ update_remote_position) {
81 trans.set_origin(update_remote_position ? our_trans.get_origin() : n_trans.get_origin());
82 }
83 if (update_remote_rotation ^ update_remote_scale) {
84 trans.set_scale(update_remote_scale ? our_trans.get_scale() : n_trans.get_scale());
85 }
86
87 n->set_global_transform(trans);
88 } else {
89 if (update_remote_position && update_remote_rotation && update_remote_scale) {
90 n->set_transform(get_transform());
91 return;
92 }
93
94 Transform2D n_trans = n->get_transform();
95 Transform2D our_trans = get_transform();
96
97 // There are more steps in the operation of set_rotation, so avoid calling it.
98 Transform2D trans = update_remote_rotation ? our_trans : n_trans;
99
100 if (update_remote_rotation ^ update_remote_position) {
101 trans.set_origin(update_remote_position ? our_trans.get_origin() : n_trans.get_origin());
102 }
103 if (update_remote_rotation ^ update_remote_scale) {
104 trans.set_scale(update_remote_scale ? our_trans.get_scale() : n_trans.get_scale());
105 }
106
107 n->set_transform(trans);
108 }
109}
110
111void RemoteTransform2D::_notification(int p_what) {
112 switch (p_what) {
113 case NOTIFICATION_ENTER_TREE: {
114 _update_cache();
115 } break;
116
117 case NOTIFICATION_TRANSFORM_CHANGED: {
118 if (!is_inside_tree()) {
119 break;
120 }
121
122 if (cache.is_valid()) {
123 _update_remote();
124 }
125 } break;
126 }
127}
128
129void RemoteTransform2D::set_remote_node(const NodePath &p_remote_node) {
130 remote_node = p_remote_node;
131 if (is_inside_tree()) {
132 _update_cache();
133 _update_remote();
134 }
135
136 update_configuration_warnings();
137}
138
139NodePath RemoteTransform2D::get_remote_node() const {
140 return remote_node;
141}
142
143void RemoteTransform2D::set_use_global_coordinates(const bool p_enable) {
144 use_global_coordinates = p_enable;
145 _update_remote();
146}
147
148bool RemoteTransform2D::get_use_global_coordinates() const {
149 return use_global_coordinates;
150}
151
152void RemoteTransform2D::set_update_position(const bool p_update) {
153 update_remote_position = p_update;
154 _update_remote();
155}
156
157bool RemoteTransform2D::get_update_position() const {
158 return update_remote_position;
159}
160
161void RemoteTransform2D::set_update_rotation(const bool p_update) {
162 update_remote_rotation = p_update;
163 _update_remote();
164}
165
166bool RemoteTransform2D::get_update_rotation() const {
167 return update_remote_rotation;
168}
169
170void RemoteTransform2D::set_update_scale(const bool p_update) {
171 update_remote_scale = p_update;
172 _update_remote();
173}
174
175bool RemoteTransform2D::get_update_scale() const {
176 return update_remote_scale;
177}
178
179void RemoteTransform2D::force_update_cache() {
180 _update_cache();
181}
182
183PackedStringArray RemoteTransform2D::get_configuration_warnings() const {
184 PackedStringArray warnings = Node::get_configuration_warnings();
185
186 if (!has_node(remote_node) || !Object::cast_to<Node2D>(get_node(remote_node))) {
187 warnings.push_back(RTR("Path property must point to a valid Node2D node to work."));
188 }
189
190 return warnings;
191}
192
193void RemoteTransform2D::_bind_methods() {
194 ClassDB::bind_method(D_METHOD("set_remote_node", "path"), &RemoteTransform2D::set_remote_node);
195 ClassDB::bind_method(D_METHOD("get_remote_node"), &RemoteTransform2D::get_remote_node);
196 ClassDB::bind_method(D_METHOD("force_update_cache"), &RemoteTransform2D::force_update_cache);
197
198 ClassDB::bind_method(D_METHOD("set_use_global_coordinates", "use_global_coordinates"), &RemoteTransform2D::set_use_global_coordinates);
199 ClassDB::bind_method(D_METHOD("get_use_global_coordinates"), &RemoteTransform2D::get_use_global_coordinates);
200
201 ClassDB::bind_method(D_METHOD("set_update_position", "update_remote_position"), &RemoteTransform2D::set_update_position);
202 ClassDB::bind_method(D_METHOD("get_update_position"), &RemoteTransform2D::get_update_position);
203 ClassDB::bind_method(D_METHOD("set_update_rotation", "update_remote_rotation"), &RemoteTransform2D::set_update_rotation);
204 ClassDB::bind_method(D_METHOD("get_update_rotation"), &RemoteTransform2D::get_update_rotation);
205 ClassDB::bind_method(D_METHOD("set_update_scale", "update_remote_scale"), &RemoteTransform2D::set_update_scale);
206 ClassDB::bind_method(D_METHOD("get_update_scale"), &RemoteTransform2D::get_update_scale);
207
208 ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "remote_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Node2D"), "set_remote_node", "get_remote_node");
209 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_global_coordinates"), "set_use_global_coordinates", "get_use_global_coordinates");
210
211 ADD_GROUP("Update", "update_");
212 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_position"), "set_update_position", "get_update_position");
213 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_rotation"), "set_update_rotation", "get_update_rotation");
214 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "update_scale"), "set_update_scale", "get_update_scale");
215}
216
217RemoteTransform2D::RemoteTransform2D() {
218 set_notify_transform(true);
219 set_hide_clip_children(true);
220}
221