1 /*************************************************************************/
2 /* parallax_layer.cpp */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* https://godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
9 /* Copyright (c) 2014-2019 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 #include "parallax_layer.h"
31 #include "parallax_background.h"
32
set_motion_scale(const Size2 & p_scale)33 void ParallaxLayer::set_motion_scale(const Size2 &p_scale) {
34
35 motion_scale = p_scale;
36
37 if (!get_parent())
38 return;
39
40 ParallaxBackground *pb = get_parent()->cast_to<ParallaxBackground>();
41 if (is_inside_tree() && pb) {
42 Vector2 ofs = pb->get_final_offset();
43 float scale = pb->get_scroll_scale();
44 set_base_offset_and_scale(ofs, scale);
45 }
46 }
47
get_motion_scale() const48 Size2 ParallaxLayer::get_motion_scale() const {
49
50 return motion_scale;
51 }
52
set_motion_offset(const Size2 & p_offset)53 void ParallaxLayer::set_motion_offset(const Size2 &p_offset) {
54
55 motion_offset = p_offset;
56
57 if (!get_parent())
58 return;
59
60 ParallaxBackground *pb = get_parent()->cast_to<ParallaxBackground>();
61 if (is_inside_tree() && pb) {
62 Vector2 ofs = pb->get_final_offset();
63 float scale = pb->get_scroll_scale();
64 set_base_offset_and_scale(ofs, scale);
65 }
66 }
67
get_motion_offset() const68 Size2 ParallaxLayer::get_motion_offset() const {
69
70 return motion_offset;
71 }
72
_update_mirroring()73 void ParallaxLayer::_update_mirroring() {
74
75 if (!get_parent())
76 return;
77
78 ParallaxBackground *pb = get_parent()->cast_to<ParallaxBackground>();
79 if (pb) {
80
81 RID c = pb->get_world_2d()->get_canvas();
82 RID ci = get_canvas_item();
83 VisualServer::get_singleton()->canvas_set_item_mirroring(c, ci, mirroring);
84 }
85 }
86
set_mirroring(const Size2 & p_mirroring)87 void ParallaxLayer::set_mirroring(const Size2 &p_mirroring) {
88
89 mirroring = p_mirroring;
90 if (mirroring.x < 0)
91 mirroring.x = 0;
92 if (mirroring.y < 0)
93 mirroring.y = 0;
94
95 _update_mirroring();
96 }
97
get_mirroring() const98 Size2 ParallaxLayer::get_mirroring() const {
99
100 return mirroring;
101 }
102
_notification(int p_what)103 void ParallaxLayer::_notification(int p_what) {
104
105 switch (p_what) {
106
107 case NOTIFICATION_ENTER_TREE: {
108
109 orig_offset = get_pos();
110 orig_scale = get_scale();
111 _update_mirroring();
112 } break;
113 }
114 }
115
set_base_offset_and_scale(const Point2 & p_offset,float p_scale)116 void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale) {
117
118 if (!is_inside_tree())
119 return;
120 if (get_tree()->is_editor_hint())
121 return;
122 Point2 new_ofs = ((orig_offset + p_offset) * motion_scale) * p_scale + motion_offset;
123
124 if (mirroring.x) {
125 double den = mirroring.x * p_scale;
126 new_ofs.x -= den * ceil(new_ofs.x / den);
127 }
128
129 if (mirroring.y) {
130 double den = mirroring.y * p_scale;
131 new_ofs.y -= den * ceil(new_ofs.y / den);
132 }
133
134 set_pos(new_ofs);
135 set_scale(Vector2(1, 1) * p_scale);
136 }
137
get_configuration_warning() const138 String ParallaxLayer::get_configuration_warning() const {
139
140 if (!get_parent() || !get_parent()->cast_to<ParallaxBackground>()) {
141 return TTR("ParallaxLayer node only works when set as child of a ParallaxBackground node.");
142 }
143
144 return String();
145 }
146
_bind_methods()147 void ParallaxLayer::_bind_methods() {
148
149 ObjectTypeDB::bind_method(_MD("set_motion_scale", "scale"), &ParallaxLayer::set_motion_scale);
150 ObjectTypeDB::bind_method(_MD("get_motion_scale"), &ParallaxLayer::get_motion_scale);
151 ObjectTypeDB::bind_method(_MD("set_motion_offset", "offset"), &ParallaxLayer::set_motion_offset);
152 ObjectTypeDB::bind_method(_MD("get_motion_offset"), &ParallaxLayer::get_motion_offset);
153 ObjectTypeDB::bind_method(_MD("set_mirroring", "mirror"), &ParallaxLayer::set_mirroring);
154 ObjectTypeDB::bind_method(_MD("get_mirroring"), &ParallaxLayer::get_mirroring);
155
156 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion/scale"), _SCS("set_motion_scale"), _SCS("get_motion_scale"));
157 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion/offset"), _SCS("set_motion_offset"), _SCS("get_motion_offset"));
158 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion/mirroring"), _SCS("set_mirroring"), _SCS("get_mirroring"));
159 }
160
ParallaxLayer()161 ParallaxLayer::ParallaxLayer() {
162 motion_scale = Size2(1, 1);
163 }
164