1 /*************************************************************************/
2 /* light_occluder_2d.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 "light_occluder_2d.h"
31
set_polygon(const DVector<Vector2> & p_polygon)32 void OccluderPolygon2D::set_polygon(const DVector<Vector2> &p_polygon) {
33
34 polygon = p_polygon;
35 VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, p_polygon, closed);
36 emit_changed();
37 }
38
get_polygon() const39 DVector<Vector2> OccluderPolygon2D::get_polygon() const {
40
41 return polygon;
42 }
43
set_closed(bool p_closed)44 void OccluderPolygon2D::set_closed(bool p_closed) {
45
46 if (closed == p_closed)
47 return;
48 closed = p_closed;
49 if (polygon.size())
50 VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, polygon, closed);
51 emit_changed();
52 }
53
is_closed() const54 bool OccluderPolygon2D::is_closed() const {
55
56 return closed;
57 }
58
set_cull_mode(CullMode p_mode)59 void OccluderPolygon2D::set_cull_mode(CullMode p_mode) {
60
61 cull = p_mode;
62 VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon, VS::CanvasOccluderPolygonCullMode(p_mode));
63 }
64
get_cull_mode() const65 OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const {
66
67 return cull;
68 }
69
get_rid() const70 RID OccluderPolygon2D::get_rid() const {
71
72 return occ_polygon;
73 }
74
_bind_methods()75 void OccluderPolygon2D::_bind_methods() {
76
77 ObjectTypeDB::bind_method(_MD("set_closed", "closed"), &OccluderPolygon2D::set_closed);
78 ObjectTypeDB::bind_method(_MD("is_closed"), &OccluderPolygon2D::is_closed);
79
80 ObjectTypeDB::bind_method(_MD("set_cull_mode", "cull_mode"), &OccluderPolygon2D::set_cull_mode);
81 ObjectTypeDB::bind_method(_MD("get_cull_mode"), &OccluderPolygon2D::get_cull_mode);
82
83 ObjectTypeDB::bind_method(_MD("set_polygon", "polygon"), &OccluderPolygon2D::set_polygon);
84 ObjectTypeDB::bind_method(_MD("get_polygon"), &OccluderPolygon2D::get_polygon);
85
86 ADD_PROPERTY(PropertyInfo(Variant::BOOL, "closed"), _SCS("set_closed"), _SCS("is_closed"));
87 ADD_PROPERTY(PropertyInfo(Variant::INT, "cull_mode", PROPERTY_HINT_ENUM, "Disabled,ClockWise,CounterClockWise"), _SCS("set_cull_mode"), _SCS("get_cull_mode"));
88 ADD_PROPERTY(PropertyInfo(Variant::VECTOR2_ARRAY, "polygon"), _SCS("set_polygon"), _SCS("get_polygon"));
89
90 BIND_CONSTANT(CULL_DISABLED);
91 BIND_CONSTANT(CULL_CLOCKWISE);
92 BIND_CONSTANT(CULL_COUNTER_CLOCKWISE);
93 }
94
OccluderPolygon2D()95 OccluderPolygon2D::OccluderPolygon2D() {
96
97 occ_polygon = VS::get_singleton()->canvas_occluder_polygon_create();
98 closed = true;
99 cull = CULL_DISABLED;
100 }
101
~OccluderPolygon2D()102 OccluderPolygon2D::~OccluderPolygon2D() {
103
104 VS::get_singleton()->free(occ_polygon);
105 }
106
107 #ifdef DEBUG_ENABLED
_poly_changed()108 void LightOccluder2D::_poly_changed() {
109
110 update();
111 }
112 #endif
113
_notification(int p_what)114 void LightOccluder2D::_notification(int p_what) {
115
116 if (p_what == NOTIFICATION_ENTER_CANVAS) {
117
118 VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, get_canvas());
119 VS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
120 VS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible());
121 }
122 if (p_what == NOTIFICATION_TRANSFORM_CHANGED) {
123
124 VS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform());
125 }
126 if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
127
128 VS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible());
129 }
130
131 if (p_what == NOTIFICATION_DRAW) {
132
133 if (get_tree()->is_editor_hint()) {
134
135 if (occluder_polygon.is_valid()) {
136
137 DVector<Vector2> poly = occluder_polygon->get_polygon();
138
139 if (poly.size()) {
140 if (occluder_polygon->is_closed()) {
141 Vector<Color> color;
142 color.push_back(Color(0, 0, 0, 0.6));
143 draw_polygon(Variant(poly), color);
144 } else {
145
146 int ps = poly.size();
147 DVector<Vector2>::Read r = poly.read();
148 for (int i = 0; i < ps - 1; i++) {
149
150 draw_line(r[i], r[i + 1], Color(0, 0, 0, 0.6), 3);
151 }
152 }
153 }
154 }
155 }
156 }
157
158 if (p_what == NOTIFICATION_EXIT_CANVAS) {
159
160 VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, RID());
161 }
162 }
163
set_occluder_polygon(const Ref<OccluderPolygon2D> & p_polygon)164 void LightOccluder2D::set_occluder_polygon(const Ref<OccluderPolygon2D> &p_polygon) {
165
166 #ifdef DEBUG_ENABLED
167 if (occluder_polygon.is_valid())
168 occluder_polygon->disconnect("changed", this, "_poly_changed");
169 #endif
170 occluder_polygon = p_polygon;
171
172 if (occluder_polygon.is_valid())
173 VS::get_singleton()->canvas_light_occluder_set_polygon(occluder, occluder_polygon->get_rid());
174 else
175 VS::get_singleton()->canvas_light_occluder_set_polygon(occluder, RID());
176
177 #ifdef DEBUG_ENABLED
178 if (occluder_polygon.is_valid())
179 occluder_polygon->connect("changed", this, "_poly_changed");
180 update();
181 #endif
182 }
183
get_occluder_polygon() const184 Ref<OccluderPolygon2D> LightOccluder2D::get_occluder_polygon() const {
185
186 return occluder_polygon;
187 }
188
set_occluder_light_mask(int p_mask)189 void LightOccluder2D::set_occluder_light_mask(int p_mask) {
190
191 mask = p_mask;
192 VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder, mask);
193 }
194
get_occluder_light_mask() const195 int LightOccluder2D::get_occluder_light_mask() const {
196
197 return mask;
198 }
199
get_configuration_warning() const200 String LightOccluder2D::get_configuration_warning() const {
201
202 if (!occluder_polygon.is_valid()) {
203 return TTR("An occluder polygon must be set (or drawn) for this occluder to take effect.");
204 }
205
206 if (occluder_polygon.is_valid() && occluder_polygon->get_polygon().size() == 0) {
207 return TTR("The occluder polygon for this occluder is empty. Please draw a polygon!");
208 }
209
210 return String();
211 }
212
_bind_methods()213 void LightOccluder2D::_bind_methods() {
214
215 ObjectTypeDB::bind_method(_MD("set_occluder_polygon", "polygon:OccluderPolygon2D"), &LightOccluder2D::set_occluder_polygon);
216 ObjectTypeDB::bind_method(_MD("get_occluder_polygon:OccluderPolygon2D"), &LightOccluder2D::get_occluder_polygon);
217
218 ObjectTypeDB::bind_method(_MD("set_occluder_light_mask", "mask"), &LightOccluder2D::set_occluder_light_mask);
219 ObjectTypeDB::bind_method(_MD("get_occluder_light_mask"), &LightOccluder2D::get_occluder_light_mask);
220
221 #ifdef DEBUG_ENABLED
222 ObjectTypeDB::bind_method("_poly_changed", &LightOccluder2D::_poly_changed);
223 #endif
224
225 ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "occluder", PROPERTY_HINT_RESOURCE_TYPE, "OccluderPolygon2D"), _SCS("set_occluder_polygon"), _SCS("get_occluder_polygon"));
226 ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_ALL_FLAGS), _SCS("set_occluder_light_mask"), _SCS("get_occluder_light_mask"));
227 }
228
LightOccluder2D()229 LightOccluder2D::LightOccluder2D() {
230
231 occluder = VS::get_singleton()->canvas_light_occluder_create();
232 mask = 1;
233 }
234
~LightOccluder2D()235 LightOccluder2D::~LightOccluder2D() {
236
237 VS::get_singleton()->free(occluder);
238 }
239