1 /*************************************************************************/
2 /* camera_2d.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
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 "camera_2d.h"
32
33 #include "core/engine.h"
34 #include "core/math/math_funcs.h"
35 #include "scene/scene_string_names.h"
36 #include "servers/visual_server.h"
37
_update_scroll()38 void Camera2D::_update_scroll() {
39
40 if (!is_inside_tree())
41 return;
42
43 if (Engine::get_singleton()->is_editor_hint()) {
44 update(); //will just be drawn
45 return;
46 }
47
48 if (!viewport)
49 return;
50
51 if (current) {
52
53 ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
54
55 Transform2D xform = get_camera_transform();
56
57 viewport->set_canvas_transform(xform);
58
59 Size2 screen_size = viewport->get_visible_rect().size;
60 Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5) : Point2());
61
62 get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_camera_moved", xform, screen_offset);
63 };
64 }
65
_update_process_mode()66 void Camera2D::_update_process_mode() {
67
68 if (Engine::get_singleton()->is_editor_hint()) {
69 set_process_internal(false);
70 set_physics_process_internal(false);
71 } else if (process_mode == CAMERA2D_PROCESS_IDLE) {
72 set_process_internal(true);
73 set_physics_process_internal(false);
74 } else {
75 set_process_internal(false);
76 set_physics_process_internal(true);
77 }
78 }
79
set_zoom(const Vector2 & p_zoom)80 void Camera2D::set_zoom(const Vector2 &p_zoom) {
81
82 zoom = p_zoom;
83 Point2 old_smoothed_camera_pos = smoothed_camera_pos;
84 _update_scroll();
85 smoothed_camera_pos = old_smoothed_camera_pos;
86 };
87
get_zoom() const88 Vector2 Camera2D::get_zoom() const {
89
90 return zoom;
91 };
92
get_camera_transform()93 Transform2D Camera2D::get_camera_transform() {
94
95 if (!get_tree())
96 return Transform2D();
97
98 ERR_FAIL_COND_V(custom_viewport && !ObjectDB::get_instance(custom_viewport_id), Transform2D());
99
100 Size2 screen_size = viewport->get_visible_rect().size;
101
102 Point2 new_camera_pos = get_global_transform().get_origin();
103 Point2 ret_camera_pos;
104
105 if (!first) {
106
107 if (anchor_mode == ANCHOR_MODE_DRAG_CENTER) {
108
109 if (h_drag_enabled && !Engine::get_singleton()->is_editor_hint() && !h_offset_changed) {
110 camera_pos.x = MIN(camera_pos.x, (new_camera_pos.x + screen_size.x * 0.5 * zoom.x * drag_margin[MARGIN_LEFT]));
111 camera_pos.x = MAX(camera_pos.x, (new_camera_pos.x - screen_size.x * 0.5 * zoom.x * drag_margin[MARGIN_RIGHT]));
112 } else {
113
114 if (h_ofs < 0) {
115 camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs;
116 } else {
117 camera_pos.x = new_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs;
118 }
119
120 h_offset_changed = false;
121 }
122
123 if (v_drag_enabled && !Engine::get_singleton()->is_editor_hint() && !v_offset_changed) {
124
125 camera_pos.y = MIN(camera_pos.y, (new_camera_pos.y + screen_size.y * 0.5 * zoom.y * drag_margin[MARGIN_TOP]));
126 camera_pos.y = MAX(camera_pos.y, (new_camera_pos.y - screen_size.y * 0.5 * zoom.y * drag_margin[MARGIN_BOTTOM]));
127
128 } else {
129
130 if (v_ofs < 0) {
131 camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs;
132 } else {
133 camera_pos.y = new_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs;
134 }
135
136 v_offset_changed = false;
137 }
138
139 } else if (anchor_mode == ANCHOR_MODE_FIXED_TOP_LEFT) {
140
141 camera_pos = new_camera_pos;
142 }
143
144 Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
145 Rect2 screen_rect(-screen_offset + camera_pos, screen_size * zoom);
146
147 if (limit_smoothing_enabled) {
148 if (screen_rect.position.x < limit[MARGIN_LEFT])
149 camera_pos.x -= screen_rect.position.x - limit[MARGIN_LEFT];
150
151 if (screen_rect.position.x + screen_rect.size.x > limit[MARGIN_RIGHT])
152 camera_pos.x -= screen_rect.position.x + screen_rect.size.x - limit[MARGIN_RIGHT];
153
154 if (screen_rect.position.y + screen_rect.size.y > limit[MARGIN_BOTTOM])
155 camera_pos.y -= screen_rect.position.y + screen_rect.size.y - limit[MARGIN_BOTTOM];
156
157 if (screen_rect.position.y < limit[MARGIN_TOP])
158 camera_pos.y -= screen_rect.position.y - limit[MARGIN_TOP];
159 }
160
161 if (smoothing_enabled && !Engine::get_singleton()->is_editor_hint()) {
162
163 float c = smoothing * (process_mode == CAMERA2D_PROCESS_PHYSICS ? get_physics_process_delta_time() : get_process_delta_time());
164 smoothed_camera_pos = ((camera_pos - smoothed_camera_pos) * c) + smoothed_camera_pos;
165 ret_camera_pos = smoothed_camera_pos;
166 //camera_pos=camera_pos*(1.0-smoothing)+new_camera_pos*smoothing;
167 } else {
168
169 ret_camera_pos = smoothed_camera_pos = camera_pos;
170 }
171
172 } else {
173 ret_camera_pos = smoothed_camera_pos = camera_pos = new_camera_pos;
174 first = false;
175 }
176
177 Point2 screen_offset = (anchor_mode == ANCHOR_MODE_DRAG_CENTER ? (screen_size * 0.5 * zoom) : Point2());
178
179 float angle = get_global_transform().get_rotation();
180 if (rotating) {
181 screen_offset = screen_offset.rotated(angle);
182 }
183
184 Rect2 screen_rect(-screen_offset + ret_camera_pos, screen_size * zoom);
185 if (screen_rect.position.x < limit[MARGIN_LEFT])
186 screen_rect.position.x = limit[MARGIN_LEFT];
187
188 if (screen_rect.position.x + screen_rect.size.x > limit[MARGIN_RIGHT])
189 screen_rect.position.x = limit[MARGIN_RIGHT] - screen_rect.size.x;
190
191 if (screen_rect.position.y + screen_rect.size.y > limit[MARGIN_BOTTOM])
192 screen_rect.position.y = limit[MARGIN_BOTTOM] - screen_rect.size.y;
193
194 if (screen_rect.position.y < limit[MARGIN_TOP])
195 screen_rect.position.y = limit[MARGIN_TOP];
196
197 if (offset != Vector2())
198 screen_rect.position += offset;
199
200 camera_screen_center = screen_rect.position + screen_rect.size * 0.5;
201
202 Transform2D xform;
203 if (rotating) {
204 xform.set_rotation(angle);
205 }
206 xform.scale_basis(zoom);
207 xform.set_origin(screen_rect.position /*.floor()*/);
208
209 /*
210 if (0) {
211 xform = get_global_transform() * xform;
212 } else {
213 xform.elements[2]+=get_global_transform().get_origin();
214 }
215 */
216
217 return (xform).affine_inverse();
218 }
219
_notification(int p_what)220 void Camera2D::_notification(int p_what) {
221
222 switch (p_what) {
223
224 case NOTIFICATION_INTERNAL_PROCESS:
225 case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {
226
227 _update_scroll();
228
229 } break;
230 case NOTIFICATION_TRANSFORM_CHANGED: {
231
232 if (!is_processing_internal() && !is_physics_processing_internal())
233 _update_scroll();
234
235 } break;
236 case NOTIFICATION_ENTER_TREE: {
237
238 if (custom_viewport && ObjectDB::get_instance(custom_viewport_id)) {
239 viewport = custom_viewport;
240 } else {
241 viewport = get_viewport();
242 }
243
244 canvas = get_canvas();
245
246 RID vp = viewport->get_viewport_rid();
247
248 group_name = "__cameras_" + itos(vp.get_id());
249 canvas_group_name = "__cameras_c" + itos(canvas.get_id());
250 add_to_group(group_name);
251 add_to_group(canvas_group_name);
252
253 _update_process_mode();
254 _update_scroll();
255 first = true;
256
257 } break;
258 case NOTIFICATION_EXIT_TREE: {
259
260 if (is_current()) {
261 if (viewport && !(custom_viewport && !ObjectDB::get_instance(custom_viewport_id))) {
262 viewport->set_canvas_transform(Transform2D());
263 }
264 }
265 remove_from_group(group_name);
266 remove_from_group(canvas_group_name);
267 viewport = NULL;
268
269 } break;
270 case NOTIFICATION_DRAW: {
271
272 if (!is_inside_tree() || !Engine::get_singleton()->is_editor_hint())
273 break;
274
275 if (screen_drawing_enabled) {
276 Color area_axis_color(0.5, 0.42, 0.87, 0.63);
277 float area_axis_width = 1;
278 if (is_current()) {
279 area_axis_width = 3;
280 area_axis_color.a = 0.83;
281 }
282
283 Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
284 Size2 screen_size = get_viewport_rect().size;
285
286 Vector2 screen_endpoints[4] = {
287 inv_camera_transform.xform(Vector2(0, 0)),
288 inv_camera_transform.xform(Vector2(screen_size.width, 0)),
289 inv_camera_transform.xform(Vector2(screen_size.width, screen_size.height)),
290 inv_camera_transform.xform(Vector2(0, screen_size.height))
291 };
292
293 Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space
294
295 for (int i = 0; i < 4; i++) {
296 draw_line(inv_transform.xform(screen_endpoints[i]), inv_transform.xform(screen_endpoints[(i + 1) % 4]), area_axis_color, area_axis_width);
297 }
298 }
299
300 if (limit_drawing_enabled) {
301 Color limit_drawing_color(1, 1, 0, 0.63);
302 float limit_drawing_width = 1;
303 if (is_current()) {
304 limit_drawing_color.a = 0.83;
305 limit_drawing_width = 3;
306 }
307
308 Vector2 camera_origin = get_global_transform().get_origin();
309 Vector2 camera_scale = get_global_transform().get_scale().abs();
310 Vector2 limit_points[4] = {
311 (Vector2(limit[MARGIN_LEFT], limit[MARGIN_TOP]) - camera_origin) / camera_scale,
312 (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_TOP]) - camera_origin) / camera_scale,
313 (Vector2(limit[MARGIN_RIGHT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale,
314 (Vector2(limit[MARGIN_LEFT], limit[MARGIN_BOTTOM]) - camera_origin) / camera_scale
315 };
316
317 for (int i = 0; i < 4; i++) {
318 draw_line(limit_points[i], limit_points[(i + 1) % 4], limit_drawing_color, limit_drawing_width);
319 }
320 }
321
322 if (margin_drawing_enabled) {
323 Color margin_drawing_color(0, 1, 1, 0.63);
324 float margin_drawing_width = 1;
325 if (is_current()) {
326 margin_drawing_width = 3;
327 margin_drawing_color.a = 0.83;
328 }
329
330 Transform2D inv_camera_transform = get_camera_transform().affine_inverse();
331 Size2 screen_size = get_viewport_rect().size;
332
333 Vector2 margin_endpoints[4] = {
334 inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))),
335 inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) - ((screen_size.height / 2) * drag_margin[MARGIN_TOP]))),
336 inv_camera_transform.xform(Vector2((screen_size.width / 2) + ((screen_size.width / 2) * drag_margin[MARGIN_RIGHT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM]))),
337 inv_camera_transform.xform(Vector2((screen_size.width / 2) - ((screen_size.width / 2) * drag_margin[MARGIN_LEFT]), (screen_size.height / 2) + ((screen_size.height / 2) * drag_margin[MARGIN_BOTTOM])))
338 };
339
340 Transform2D inv_transform = get_global_transform().affine_inverse(); // undo global space
341
342 for (int i = 0; i < 4; i++) {
343 draw_line(inv_transform.xform(margin_endpoints[i]), inv_transform.xform(margin_endpoints[(i + 1) % 4]), margin_drawing_color, margin_drawing_width);
344 }
345 }
346
347 } break;
348 }
349 }
350
set_offset(const Vector2 & p_offset)351 void Camera2D::set_offset(const Vector2 &p_offset) {
352
353 offset = p_offset;
354 Point2 old_smoothed_camera_pos = smoothed_camera_pos;
355 _update_scroll();
356 smoothed_camera_pos = old_smoothed_camera_pos;
357 }
358
get_offset() const359 Vector2 Camera2D::get_offset() const {
360
361 return offset;
362 }
363
set_anchor_mode(AnchorMode p_anchor_mode)364 void Camera2D::set_anchor_mode(AnchorMode p_anchor_mode) {
365
366 anchor_mode = p_anchor_mode;
367 _update_scroll();
368 }
369
get_anchor_mode() const370 Camera2D::AnchorMode Camera2D::get_anchor_mode() const {
371
372 return anchor_mode;
373 }
374
set_rotating(bool p_rotating)375 void Camera2D::set_rotating(bool p_rotating) {
376
377 rotating = p_rotating;
378 Point2 old_smoothed_camera_pos = smoothed_camera_pos;
379 _update_scroll();
380 smoothed_camera_pos = old_smoothed_camera_pos;
381 }
382
is_rotating() const383 bool Camera2D::is_rotating() const {
384
385 return rotating;
386 }
387
set_process_mode(Camera2DProcessMode p_mode)388 void Camera2D::set_process_mode(Camera2DProcessMode p_mode) {
389
390 if (process_mode == p_mode)
391 return;
392
393 process_mode = p_mode;
394 _update_process_mode();
395 }
396
get_process_mode() const397 Camera2D::Camera2DProcessMode Camera2D::get_process_mode() const {
398
399 return process_mode;
400 }
401
_make_current(Object * p_which)402 void Camera2D::_make_current(Object *p_which) {
403
404 if (p_which == this) {
405
406 current = true;
407 } else {
408 current = false;
409 }
410 }
411
_set_current(bool p_current)412 void Camera2D::_set_current(bool p_current) {
413
414 if (p_current)
415 make_current();
416
417 current = p_current;
418 update();
419 }
420
is_current() const421 bool Camera2D::is_current() const {
422
423 return current;
424 }
425
make_current()426 void Camera2D::make_current() {
427
428 if (!is_inside_tree()) {
429 current = true;
430 } else {
431 get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", this);
432 }
433 _update_scroll();
434 }
435
clear_current()436 void Camera2D::clear_current() {
437
438 current = false;
439 if (is_inside_tree()) {
440 get_tree()->call_group_flags(SceneTree::GROUP_CALL_REALTIME, group_name, "_make_current", (Object *)(NULL));
441 }
442 }
443
set_limit(Margin p_margin,int p_limit)444 void Camera2D::set_limit(Margin p_margin, int p_limit) {
445
446 ERR_FAIL_INDEX((int)p_margin, 4);
447 limit[p_margin] = p_limit;
448 update();
449 }
450
get_limit(Margin p_margin) const451 int Camera2D::get_limit(Margin p_margin) const {
452
453 ERR_FAIL_INDEX_V((int)p_margin, 4, 0);
454 return limit[p_margin];
455 }
456
set_limit_smoothing_enabled(bool enable)457 void Camera2D::set_limit_smoothing_enabled(bool enable) {
458
459 limit_smoothing_enabled = enable;
460 _update_scroll();
461 }
462
is_limit_smoothing_enabled() const463 bool Camera2D::is_limit_smoothing_enabled() const {
464
465 return limit_smoothing_enabled;
466 }
467
set_drag_margin(Margin p_margin,float p_drag_margin)468 void Camera2D::set_drag_margin(Margin p_margin, float p_drag_margin) {
469
470 ERR_FAIL_INDEX((int)p_margin, 4);
471 drag_margin[p_margin] = p_drag_margin;
472 update();
473 }
474
get_drag_margin(Margin p_margin) const475 float Camera2D::get_drag_margin(Margin p_margin) const {
476
477 ERR_FAIL_INDEX_V((int)p_margin, 4, 0);
478 return drag_margin[p_margin];
479 }
480
get_camera_position() const481 Vector2 Camera2D::get_camera_position() const {
482
483 return camera_pos;
484 }
485
force_update_scroll()486 void Camera2D::force_update_scroll() {
487
488 _update_scroll();
489 }
490
reset_smoothing()491 void Camera2D::reset_smoothing() {
492
493 smoothed_camera_pos = camera_pos;
494 _update_scroll();
495 }
496
align()497 void Camera2D::align() {
498
499 ERR_FAIL_COND(custom_viewport && !ObjectDB::get_instance(custom_viewport_id));
500
501 Size2 screen_size = viewport->get_visible_rect().size;
502
503 Point2 current_camera_pos = get_global_transform().get_origin();
504 if (anchor_mode == ANCHOR_MODE_DRAG_CENTER) {
505 if (h_ofs < 0) {
506 camera_pos.x = current_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_RIGHT] * h_ofs;
507 } else {
508 camera_pos.x = current_camera_pos.x + screen_size.x * 0.5 * drag_margin[MARGIN_LEFT] * h_ofs;
509 }
510 if (v_ofs < 0) {
511 camera_pos.y = current_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_TOP] * v_ofs;
512 } else {
513 camera_pos.y = current_camera_pos.y + screen_size.y * 0.5 * drag_margin[MARGIN_BOTTOM] * v_ofs;
514 }
515 } else if (anchor_mode == ANCHOR_MODE_FIXED_TOP_LEFT) {
516
517 camera_pos = current_camera_pos;
518 }
519
520 _update_scroll();
521 }
522
set_follow_smoothing(float p_speed)523 void Camera2D::set_follow_smoothing(float p_speed) {
524
525 smoothing = p_speed;
526 if (smoothing > 0 && !(is_inside_tree() && Engine::get_singleton()->is_editor_hint()))
527 set_process_internal(true);
528 else
529 set_process_internal(false);
530 }
531
get_follow_smoothing() const532 float Camera2D::get_follow_smoothing() const {
533
534 return smoothing;
535 }
536
get_camera_screen_center() const537 Point2 Camera2D::get_camera_screen_center() const {
538
539 return camera_screen_center;
540 }
541
set_h_drag_enabled(bool p_enabled)542 void Camera2D::set_h_drag_enabled(bool p_enabled) {
543
544 h_drag_enabled = p_enabled;
545 }
546
is_h_drag_enabled() const547 bool Camera2D::is_h_drag_enabled() const {
548
549 return h_drag_enabled;
550 }
551
set_v_drag_enabled(bool p_enabled)552 void Camera2D::set_v_drag_enabled(bool p_enabled) {
553
554 v_drag_enabled = p_enabled;
555 }
556
is_v_drag_enabled() const557 bool Camera2D::is_v_drag_enabled() const {
558
559 return v_drag_enabled;
560 }
561
set_v_offset(float p_offset)562 void Camera2D::set_v_offset(float p_offset) {
563
564 v_ofs = p_offset;
565 v_offset_changed = true;
566 Point2 old_smoothed_camera_pos = smoothed_camera_pos;
567 _update_scroll();
568 smoothed_camera_pos = old_smoothed_camera_pos;
569 }
570
get_v_offset() const571 float Camera2D::get_v_offset() const {
572
573 return v_ofs;
574 }
575
set_h_offset(float p_offset)576 void Camera2D::set_h_offset(float p_offset) {
577
578 h_ofs = p_offset;
579 h_offset_changed = true;
580 Point2 old_smoothed_camera_pos = smoothed_camera_pos;
581 _update_scroll();
582 smoothed_camera_pos = old_smoothed_camera_pos;
583 }
get_h_offset() const584 float Camera2D::get_h_offset() const {
585
586 return h_ofs;
587 }
588
_set_old_smoothing(float p_enable)589 void Camera2D::_set_old_smoothing(float p_enable) {
590 //compatibility
591 if (p_enable > 0) {
592 smoothing_enabled = true;
593 set_follow_smoothing(p_enable);
594 }
595 }
596
set_enable_follow_smoothing(bool p_enabled)597 void Camera2D::set_enable_follow_smoothing(bool p_enabled) {
598
599 smoothing_enabled = p_enabled;
600 }
601
is_follow_smoothing_enabled() const602 bool Camera2D::is_follow_smoothing_enabled() const {
603
604 return smoothing_enabled;
605 }
606
set_custom_viewport(Node * p_viewport)607 void Camera2D::set_custom_viewport(Node *p_viewport) {
608 ERR_FAIL_NULL(p_viewport);
609 if (is_inside_tree()) {
610 remove_from_group(group_name);
611 remove_from_group(canvas_group_name);
612 }
613
614 custom_viewport = Object::cast_to<Viewport>(p_viewport);
615
616 if (custom_viewport) {
617 custom_viewport_id = custom_viewport->get_instance_id();
618 } else {
619 custom_viewport_id = 0;
620 }
621
622 if (is_inside_tree()) {
623
624 if (custom_viewport)
625 viewport = custom_viewport;
626 else
627 viewport = get_viewport();
628
629 RID vp = viewport->get_viewport_rid();
630 group_name = "__cameras_" + itos(vp.get_id());
631 canvas_group_name = "__cameras_c" + itos(canvas.get_id());
632 add_to_group(group_name);
633 add_to_group(canvas_group_name);
634 }
635 }
636
get_custom_viewport() const637 Node *Camera2D::get_custom_viewport() const {
638
639 return custom_viewport;
640 }
641
set_screen_drawing_enabled(bool enable)642 void Camera2D::set_screen_drawing_enabled(bool enable) {
643 screen_drawing_enabled = enable;
644 update();
645 }
646
is_screen_drawing_enabled() const647 bool Camera2D::is_screen_drawing_enabled() const {
648 return screen_drawing_enabled;
649 }
650
set_limit_drawing_enabled(bool enable)651 void Camera2D::set_limit_drawing_enabled(bool enable) {
652 limit_drawing_enabled = enable;
653 update();
654 }
655
is_limit_drawing_enabled() const656 bool Camera2D::is_limit_drawing_enabled() const {
657 return limit_drawing_enabled;
658 }
659
set_margin_drawing_enabled(bool enable)660 void Camera2D::set_margin_drawing_enabled(bool enable) {
661 margin_drawing_enabled = enable;
662 update();
663 }
664
is_margin_drawing_enabled() const665 bool Camera2D::is_margin_drawing_enabled() const {
666 return margin_drawing_enabled;
667 }
668
_bind_methods()669 void Camera2D::_bind_methods() {
670
671 ClassDB::bind_method(D_METHOD("set_offset", "offset"), &Camera2D::set_offset);
672 ClassDB::bind_method(D_METHOD("get_offset"), &Camera2D::get_offset);
673
674 ClassDB::bind_method(D_METHOD("set_anchor_mode", "anchor_mode"), &Camera2D::set_anchor_mode);
675 ClassDB::bind_method(D_METHOD("get_anchor_mode"), &Camera2D::get_anchor_mode);
676
677 ClassDB::bind_method(D_METHOD("set_rotating", "rotating"), &Camera2D::set_rotating);
678 ClassDB::bind_method(D_METHOD("is_rotating"), &Camera2D::is_rotating);
679
680 ClassDB::bind_method(D_METHOD("make_current"), &Camera2D::make_current);
681 ClassDB::bind_method(D_METHOD("clear_current"), &Camera2D::clear_current);
682 ClassDB::bind_method(D_METHOD("_make_current"), &Camera2D::_make_current);
683
684 ClassDB::bind_method(D_METHOD("_update_scroll"), &Camera2D::_update_scroll);
685
686 ClassDB::bind_method(D_METHOD("set_process_mode", "mode"), &Camera2D::set_process_mode);
687 ClassDB::bind_method(D_METHOD("get_process_mode"), &Camera2D::get_process_mode);
688
689 ClassDB::bind_method(D_METHOD("_set_current", "current"), &Camera2D::_set_current);
690 ClassDB::bind_method(D_METHOD("is_current"), &Camera2D::is_current);
691
692 ClassDB::bind_method(D_METHOD("set_limit", "margin", "limit"), &Camera2D::set_limit);
693 ClassDB::bind_method(D_METHOD("get_limit", "margin"), &Camera2D::get_limit);
694
695 ClassDB::bind_method(D_METHOD("set_limit_smoothing_enabled", "limit_smoothing_enabled"), &Camera2D::set_limit_smoothing_enabled);
696 ClassDB::bind_method(D_METHOD("is_limit_smoothing_enabled"), &Camera2D::is_limit_smoothing_enabled);
697
698 ClassDB::bind_method(D_METHOD("set_v_drag_enabled", "enabled"), &Camera2D::set_v_drag_enabled);
699 ClassDB::bind_method(D_METHOD("is_v_drag_enabled"), &Camera2D::is_v_drag_enabled);
700
701 ClassDB::bind_method(D_METHOD("set_h_drag_enabled", "enabled"), &Camera2D::set_h_drag_enabled);
702 ClassDB::bind_method(D_METHOD("is_h_drag_enabled"), &Camera2D::is_h_drag_enabled);
703
704 ClassDB::bind_method(D_METHOD("set_v_offset", "ofs"), &Camera2D::set_v_offset);
705 ClassDB::bind_method(D_METHOD("get_v_offset"), &Camera2D::get_v_offset);
706
707 ClassDB::bind_method(D_METHOD("set_h_offset", "ofs"), &Camera2D::set_h_offset);
708 ClassDB::bind_method(D_METHOD("get_h_offset"), &Camera2D::get_h_offset);
709
710 ClassDB::bind_method(D_METHOD("set_drag_margin", "margin", "drag_margin"), &Camera2D::set_drag_margin);
711 ClassDB::bind_method(D_METHOD("get_drag_margin", "margin"), &Camera2D::get_drag_margin);
712
713 ClassDB::bind_method(D_METHOD("get_camera_position"), &Camera2D::get_camera_position);
714 ClassDB::bind_method(D_METHOD("get_camera_screen_center"), &Camera2D::get_camera_screen_center);
715
716 ClassDB::bind_method(D_METHOD("set_zoom", "zoom"), &Camera2D::set_zoom);
717 ClassDB::bind_method(D_METHOD("get_zoom"), &Camera2D::get_zoom);
718
719 ClassDB::bind_method(D_METHOD("set_custom_viewport", "viewport"), &Camera2D::set_custom_viewport);
720 ClassDB::bind_method(D_METHOD("get_custom_viewport"), &Camera2D::get_custom_viewport);
721
722 ClassDB::bind_method(D_METHOD("set_follow_smoothing", "follow_smoothing"), &Camera2D::set_follow_smoothing);
723 ClassDB::bind_method(D_METHOD("get_follow_smoothing"), &Camera2D::get_follow_smoothing);
724
725 ClassDB::bind_method(D_METHOD("set_enable_follow_smoothing", "follow_smoothing"), &Camera2D::set_enable_follow_smoothing);
726 ClassDB::bind_method(D_METHOD("is_follow_smoothing_enabled"), &Camera2D::is_follow_smoothing_enabled);
727
728 ClassDB::bind_method(D_METHOD("force_update_scroll"), &Camera2D::force_update_scroll);
729 ClassDB::bind_method(D_METHOD("reset_smoothing"), &Camera2D::reset_smoothing);
730 ClassDB::bind_method(D_METHOD("align"), &Camera2D::align);
731
732 ClassDB::bind_method(D_METHOD("_set_old_smoothing", "follow_smoothing"), &Camera2D::_set_old_smoothing);
733
734 ClassDB::bind_method(D_METHOD("set_screen_drawing_enabled", "screen_drawing_enabled"), &Camera2D::set_screen_drawing_enabled);
735 ClassDB::bind_method(D_METHOD("is_screen_drawing_enabled"), &Camera2D::is_screen_drawing_enabled);
736
737 ClassDB::bind_method(D_METHOD("set_limit_drawing_enabled", "limit_drawing_enabled"), &Camera2D::set_limit_drawing_enabled);
738 ClassDB::bind_method(D_METHOD("is_limit_drawing_enabled"), &Camera2D::is_limit_drawing_enabled);
739
740 ClassDB::bind_method(D_METHOD("set_margin_drawing_enabled", "margin_drawing_enabled"), &Camera2D::set_margin_drawing_enabled);
741 ClassDB::bind_method(D_METHOD("is_margin_drawing_enabled"), &Camera2D::is_margin_drawing_enabled);
742
743 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset"), "set_offset", "get_offset");
744 ADD_PROPERTY(PropertyInfo(Variant::INT, "anchor_mode", PROPERTY_HINT_ENUM, "Fixed TopLeft,Drag Center"), "set_anchor_mode", "get_anchor_mode");
745 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "rotating"), "set_rotating", "is_rotating");
746 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "current"), "_set_current", "is_current");
747 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "zoom"), "set_zoom", "get_zoom");
748 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport");
749 ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Physics,Idle"), "set_process_mode", "get_process_mode");
750
751 ADD_GROUP("Limit", "limit_");
752 ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_left"), "set_limit", "get_limit", MARGIN_LEFT);
753 ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_top"), "set_limit", "get_limit", MARGIN_TOP);
754 ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_right"), "set_limit", "get_limit", MARGIN_RIGHT);
755 ADD_PROPERTYI(PropertyInfo(Variant::INT, "limit_bottom"), "set_limit", "get_limit", MARGIN_BOTTOM);
756 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "limit_smoothed"), "set_limit_smoothing_enabled", "is_limit_smoothing_enabled");
757
758 ADD_GROUP("Draw Margin", "draw_margin_");
759 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_margin_h_enabled"), "set_h_drag_enabled", "is_h_drag_enabled");
760 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_margin_v_enabled"), "set_v_drag_enabled", "is_v_drag_enabled");
761
762 ADD_GROUP("Smoothing", "smoothing_");
763 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "smoothing_enabled"), "set_enable_follow_smoothing", "is_follow_smoothing_enabled");
764 ADD_PROPERTY(PropertyInfo(Variant::REAL, "smoothing_speed"), "set_follow_smoothing", "get_follow_smoothing");
765
766 ADD_GROUP("Offset", "offset_");
767 ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset_h", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_h_offset", "get_h_offset");
768 ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset_v", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_v_offset", "get_v_offset");
769
770 ADD_GROUP("Drag Margin", "drag_margin_");
771 ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_left", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_LEFT);
772 ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_top", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_TOP);
773 ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_right", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_RIGHT);
774 ADD_PROPERTYI(PropertyInfo(Variant::REAL, "drag_margin_bottom", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_drag_margin", "get_drag_margin", MARGIN_BOTTOM);
775
776 ADD_GROUP("Editor", "editor_");
777 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_screen"), "set_screen_drawing_enabled", "is_screen_drawing_enabled");
778 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_limits"), "set_limit_drawing_enabled", "is_limit_drawing_enabled");
779 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editor_draw_drag_margin"), "set_margin_drawing_enabled", "is_margin_drawing_enabled");
780
781 BIND_ENUM_CONSTANT(ANCHOR_MODE_FIXED_TOP_LEFT);
782 BIND_ENUM_CONSTANT(ANCHOR_MODE_DRAG_CENTER);
783 BIND_ENUM_CONSTANT(CAMERA2D_PROCESS_PHYSICS);
784 BIND_ENUM_CONSTANT(CAMERA2D_PROCESS_IDLE);
785 }
786
Camera2D()787 Camera2D::Camera2D() {
788
789 anchor_mode = ANCHOR_MODE_DRAG_CENTER;
790 rotating = false;
791 current = false;
792 limit[MARGIN_LEFT] = -10000000;
793 limit[MARGIN_TOP] = -10000000;
794 limit[MARGIN_RIGHT] = 10000000;
795 limit[MARGIN_BOTTOM] = 10000000;
796
797 drag_margin[MARGIN_LEFT] = 0.2;
798 drag_margin[MARGIN_TOP] = 0.2;
799 drag_margin[MARGIN_RIGHT] = 0.2;
800 drag_margin[MARGIN_BOTTOM] = 0.2;
801 camera_pos = Vector2();
802 first = true;
803 smoothing_enabled = false;
804 limit_smoothing_enabled = false;
805 custom_viewport = NULL;
806 custom_viewport_id = 0;
807 process_mode = CAMERA2D_PROCESS_IDLE;
808
809 smoothing = 5.0;
810 zoom = Vector2(1, 1);
811
812 screen_drawing_enabled = true;
813 limit_drawing_enabled = false;
814 margin_drawing_enabled = false;
815
816 h_drag_enabled = false;
817 v_drag_enabled = false;
818 h_ofs = 0;
819 v_ofs = 0;
820 h_offset_changed = false;
821 v_offset_changed = false;
822
823 set_notify_transform(true);
824 }
825