1 /*************************************************************************/
2 /* parallax_layer.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 "parallax_layer.h"
32
33 #include "core/engine.h"
34 #include "parallax_background.h"
35
set_motion_scale(const Size2 & p_scale)36 void ParallaxLayer::set_motion_scale(const Size2 &p_scale) {
37
38 motion_scale = p_scale;
39
40 ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
41 if (pb && is_inside_tree()) {
42 Vector2 ofs = pb->get_final_offset();
43 float scale = pb->get_scroll_scale();
44 set_base_offset_and_scale(ofs, scale, screen_offset);
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 ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
58 if (pb && is_inside_tree()) {
59 Vector2 ofs = pb->get_final_offset();
60 float scale = pb->get_scroll_scale();
61 set_base_offset_and_scale(ofs, scale, screen_offset);
62 }
63 }
64
get_motion_offset() const65 Size2 ParallaxLayer::get_motion_offset() const {
66
67 return motion_offset;
68 }
69
_update_mirroring()70 void ParallaxLayer::_update_mirroring() {
71
72 if (!is_inside_tree())
73 return;
74
75 ParallaxBackground *pb = Object::cast_to<ParallaxBackground>(get_parent());
76 if (pb) {
77
78 RID c = pb->get_canvas();
79 RID ci = get_canvas_item();
80 Point2 mirrorScale = mirroring * get_scale();
81 VisualServer::get_singleton()->canvas_set_item_mirroring(c, ci, mirrorScale);
82 }
83 }
84
set_mirroring(const Size2 & p_mirroring)85 void ParallaxLayer::set_mirroring(const Size2 &p_mirroring) {
86
87 mirroring = p_mirroring;
88 if (mirroring.x < 0)
89 mirroring.x = 0;
90 if (mirroring.y < 0)
91 mirroring.y = 0;
92
93 _update_mirroring();
94 }
95
get_mirroring() const96 Size2 ParallaxLayer::get_mirroring() const {
97
98 return mirroring;
99 }
100
_notification(int p_what)101 void ParallaxLayer::_notification(int p_what) {
102
103 switch (p_what) {
104
105 case NOTIFICATION_ENTER_TREE: {
106
107 orig_offset = get_position();
108 orig_scale = get_scale();
109 _update_mirroring();
110 } break;
111 case NOTIFICATION_EXIT_TREE: {
112
113 set_position(orig_offset);
114 set_scale(orig_scale);
115 } break;
116 }
117 }
118
set_base_offset_and_scale(const Point2 & p_offset,float p_scale,const Point2 & p_screen_offset)119 void ParallaxLayer::set_base_offset_and_scale(const Point2 &p_offset, float p_scale, const Point2 &p_screen_offset) {
120 screen_offset = p_screen_offset;
121
122 if (!is_inside_tree())
123 return;
124 if (Engine::get_singleton()->is_editor_hint())
125 return;
126
127 Point2 new_ofs = (screen_offset + (p_offset - screen_offset) * motion_scale) + motion_offset * p_scale + orig_offset * p_scale;
128
129 if (mirroring.x) {
130 double den = mirroring.x * p_scale;
131 new_ofs.x -= den * ceil(new_ofs.x / den);
132 }
133
134 if (mirroring.y) {
135 double den = mirroring.y * p_scale;
136 new_ofs.y -= den * ceil(new_ofs.y / den);
137 }
138
139 set_position(new_ofs);
140 set_scale(Vector2(1, 1) * p_scale * orig_scale);
141
142 _update_mirroring();
143 }
144
get_configuration_warning() const145 String ParallaxLayer::get_configuration_warning() const {
146
147 if (!Object::cast_to<ParallaxBackground>(get_parent())) {
148 return TTR("ParallaxLayer node only works when set as child of a ParallaxBackground node.");
149 }
150
151 return String();
152 }
153
_bind_methods()154 void ParallaxLayer::_bind_methods() {
155
156 ClassDB::bind_method(D_METHOD("set_motion_scale", "scale"), &ParallaxLayer::set_motion_scale);
157 ClassDB::bind_method(D_METHOD("get_motion_scale"), &ParallaxLayer::get_motion_scale);
158 ClassDB::bind_method(D_METHOD("set_motion_offset", "offset"), &ParallaxLayer::set_motion_offset);
159 ClassDB::bind_method(D_METHOD("get_motion_offset"), &ParallaxLayer::get_motion_offset);
160 ClassDB::bind_method(D_METHOD("set_mirroring", "mirror"), &ParallaxLayer::set_mirroring);
161 ClassDB::bind_method(D_METHOD("get_mirroring"), &ParallaxLayer::get_mirroring);
162
163 ADD_GROUP("Motion", "motion_");
164 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_scale"), "set_motion_scale", "get_motion_scale");
165 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_offset"), "set_motion_offset", "get_motion_offset");
166 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_mirroring"), "set_mirroring", "get_mirroring");
167 }
168
ParallaxLayer()169 ParallaxLayer::ParallaxLayer() {
170 motion_scale = Size2(1, 1);
171 }
172