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