1 /*************************************************************************/
2 /* sprite.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 "sprite.h"
31 #include "core/core_string_names.h"
32 #include "os/os.h"
33 #include "scene/main/viewport.h"
34 #include "scene/scene_string_names.h"
35
edit_set_pivot(const Point2 & p_pivot)36 void Sprite::edit_set_pivot(const Point2 &p_pivot) {
37
38 set_offset(p_pivot);
39 }
40
edit_get_pivot() const41 Point2 Sprite::edit_get_pivot() const {
42
43 return get_offset();
44 }
edit_has_pivot() const45 bool Sprite::edit_has_pivot() const {
46
47 return true;
48 }
49
_notification(int p_what)50 void Sprite::_notification(int p_what) {
51
52 switch (p_what) {
53
54 case NOTIFICATION_DRAW: {
55
56 if (texture.is_null())
57 return;
58
59 RID ci = get_canvas_item();
60
61 /*
62 texture->draw(ci,Point2());
63 break;
64 */
65
66 Size2 s;
67 Rect2 src_rect;
68
69 if (region) {
70
71 s = region_rect.size;
72 src_rect = region_rect;
73 } else {
74 s = Size2(texture->get_size());
75 s = s / Size2(hframes, vframes);
76
77 src_rect.size = s;
78 src_rect.pos.x += float(frame % hframes) * s.x;
79 src_rect.pos.y += float(frame / hframes) * s.y;
80 }
81
82 Point2 ofs = offset;
83 if (centered)
84 ofs -= s / 2;
85 if (OS::get_singleton()->get_use_pixel_snap()) {
86 ofs = ofs.floor();
87 }
88
89 Rect2 dst_rect(ofs, s);
90
91 if (hflip)
92 dst_rect.size.x = -dst_rect.size.x;
93 if (vflip)
94 dst_rect.size.y = -dst_rect.size.y;
95
96 texture->draw_rect_region(ci, dst_rect, src_rect, modulate);
97
98 } break;
99 }
100 }
101
set_texture(const Ref<Texture> & p_texture)102 void Sprite::set_texture(const Ref<Texture> &p_texture) {
103
104 if (p_texture == texture)
105 return;
106 #ifdef DEBUG_ENABLED
107 if (texture.is_valid()) {
108 texture->disconnect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update);
109 }
110 #endif
111 texture = p_texture;
112 #ifdef DEBUG_ENABLED
113 if (texture.is_valid()) {
114 texture->set_flags(texture->get_flags()); //remove repeat from texture, it looks bad in sprites
115 texture->connect(CoreStringNames::get_singleton()->changed, this, SceneStringNames::get_singleton()->update);
116 }
117 #endif
118 update();
119 emit_signal("texture_changed");
120 item_rect_changed();
121 }
122
get_texture() const123 Ref<Texture> Sprite::get_texture() const {
124
125 return texture;
126 }
127
set_centered(bool p_center)128 void Sprite::set_centered(bool p_center) {
129
130 centered = p_center;
131 update();
132 item_rect_changed();
133 }
134
is_centered() const135 bool Sprite::is_centered() const {
136
137 return centered;
138 }
139
set_offset(const Point2 & p_offset)140 void Sprite::set_offset(const Point2 &p_offset) {
141
142 offset = p_offset;
143 update();
144 item_rect_changed();
145 _change_notify("offset");
146 }
get_offset() const147 Point2 Sprite::get_offset() const {
148
149 return offset;
150 }
151
set_flip_h(bool p_flip)152 void Sprite::set_flip_h(bool p_flip) {
153
154 hflip = p_flip;
155 update();
156 }
is_flipped_h() const157 bool Sprite::is_flipped_h() const {
158
159 return hflip;
160 }
161
set_flip_v(bool p_flip)162 void Sprite::set_flip_v(bool p_flip) {
163
164 vflip = p_flip;
165 update();
166 }
is_flipped_v() const167 bool Sprite::is_flipped_v() const {
168
169 return vflip;
170 }
171
set_region(bool p_region)172 void Sprite::set_region(bool p_region) {
173
174 if (p_region == region)
175 return;
176
177 region = p_region;
178 update();
179 }
180
is_region() const181 bool Sprite::is_region() const {
182
183 return region;
184 }
185
set_region_rect(const Rect2 & p_region_rect)186 void Sprite::set_region_rect(const Rect2 &p_region_rect) {
187
188 if (region_rect == p_region_rect)
189 return;
190
191 region_rect = p_region_rect;
192
193 if (region)
194 item_rect_changed();
195
196 _change_notify("region_rect");
197 }
198
get_region_rect() const199 Rect2 Sprite::get_region_rect() const {
200
201 return region_rect;
202 }
203
set_frame(int p_frame)204 void Sprite::set_frame(int p_frame) {
205
206 ERR_FAIL_INDEX(p_frame, vframes * hframes);
207
208 if (frame != p_frame)
209 item_rect_changed();
210
211 frame = p_frame;
212
213 _change_notify("frame");
214 emit_signal(SceneStringNames::get_singleton()->frame_changed);
215 }
216
get_frame() const217 int Sprite::get_frame() const {
218
219 return frame;
220 }
221
set_vframes(int p_amount)222 void Sprite::set_vframes(int p_amount) {
223
224 ERR_FAIL_COND(p_amount < 1);
225 vframes = p_amount;
226 update();
227 item_rect_changed();
228 _change_notify();
229 }
get_vframes() const230 int Sprite::get_vframes() const {
231
232 return vframes;
233 }
234
set_hframes(int p_amount)235 void Sprite::set_hframes(int p_amount) {
236
237 ERR_FAIL_COND(p_amount < 1);
238 hframes = p_amount;
239 update();
240 item_rect_changed();
241 _change_notify();
242 }
get_hframes() const243 int Sprite::get_hframes() const {
244
245 return hframes;
246 }
247
set_modulate(const Color & p_color)248 void Sprite::set_modulate(const Color &p_color) {
249
250 modulate = p_color;
251 update();
252 }
253
get_modulate() const254 Color Sprite::get_modulate() const {
255
256 return modulate;
257 }
258
get_item_rect() const259 Rect2 Sprite::get_item_rect() const {
260
261 if (texture.is_null())
262 return Rect2(0, 0, 1, 1);
263 //if (texture.is_null())
264 // return CanvasItem::get_item_rect();
265
266 Size2i s;
267
268 if (region) {
269
270 s = region_rect.size;
271 } else {
272 s = texture->get_size();
273 s = s / Point2(hframes, vframes);
274 }
275
276 Point2 ofs = offset;
277 if (centered)
278 ofs -= s / 2;
279
280 if (s == Size2(0, 0))
281 s = Size2(1, 1);
282
283 return Rect2(ofs, s);
284 }
285
_validate_property(PropertyInfo & property) const286 void Sprite::_validate_property(PropertyInfo &property) const {
287
288 if (property.name == "frame") {
289
290 property.hint = PROPERTY_HINT_SPRITE_FRAME;
291
292 property.hint_string = "0," + itos(vframes * hframes - 1) + ",1";
293 }
294 }
295
_bind_methods()296 void Sprite::_bind_methods() {
297
298 ObjectTypeDB::bind_method(_MD("set_texture", "texture:Texture"), &Sprite::set_texture);
299 ObjectTypeDB::bind_method(_MD("get_texture:Texture"), &Sprite::get_texture);
300
301 ObjectTypeDB::bind_method(_MD("set_centered", "centered"), &Sprite::set_centered);
302 ObjectTypeDB::bind_method(_MD("is_centered"), &Sprite::is_centered);
303
304 ObjectTypeDB::bind_method(_MD("set_offset", "offset"), &Sprite::set_offset);
305 ObjectTypeDB::bind_method(_MD("get_offset"), &Sprite::get_offset);
306
307 ObjectTypeDB::bind_method(_MD("set_flip_h", "flip_h"), &Sprite::set_flip_h);
308 ObjectTypeDB::bind_method(_MD("is_flipped_h"), &Sprite::is_flipped_h);
309
310 ObjectTypeDB::bind_method(_MD("set_flip_v", "flip_v"), &Sprite::set_flip_v);
311 ObjectTypeDB::bind_method(_MD("is_flipped_v"), &Sprite::is_flipped_v);
312
313 ObjectTypeDB::bind_method(_MD("set_region", "enabled"), &Sprite::set_region);
314 ObjectTypeDB::bind_method(_MD("is_region"), &Sprite::is_region);
315
316 ObjectTypeDB::bind_method(_MD("set_region_rect", "rect"), &Sprite::set_region_rect);
317 ObjectTypeDB::bind_method(_MD("get_region_rect"), &Sprite::get_region_rect);
318
319 ObjectTypeDB::bind_method(_MD("set_frame", "frame"), &Sprite::set_frame);
320 ObjectTypeDB::bind_method(_MD("get_frame"), &Sprite::get_frame);
321
322 ObjectTypeDB::bind_method(_MD("set_vframes", "vframes"), &Sprite::set_vframes);
323 ObjectTypeDB::bind_method(_MD("get_vframes"), &Sprite::get_vframes);
324
325 ObjectTypeDB::bind_method(_MD("set_hframes", "hframes"), &Sprite::set_hframes);
326 ObjectTypeDB::bind_method(_MD("get_hframes"), &Sprite::get_hframes);
327
328 ObjectTypeDB::bind_method(_MD("set_modulate", "modulate"), &Sprite::set_modulate);
329 ObjectTypeDB::bind_method(_MD("get_modulate"), &Sprite::get_modulate);
330
331 ADD_SIGNAL(MethodInfo("frame_changed"));
332 ADD_SIGNAL(MethodInfo("texture_changed"));
333
334 ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"), _SCS("get_texture"));
335 ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), _SCS("set_centered"), _SCS("is_centered"));
336 ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), _SCS("set_offset"), _SCS("get_offset"));
337 ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_h"), _SCS("set_flip_h"), _SCS("is_flipped_h"));
338 ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "flip_v"), _SCS("set_flip_v"), _SCS("is_flipped_v"));
339 ADD_PROPERTYNO(PropertyInfo(Variant::INT, "vframes", PROPERTY_HINT_RANGE, "1,16384,1"), _SCS("set_vframes"), _SCS("get_vframes"));
340 ADD_PROPERTYNO(PropertyInfo(Variant::INT, "hframes", PROPERTY_HINT_RANGE, "1,16384,1"), _SCS("set_hframes"), _SCS("get_hframes"));
341 ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "frame", PROPERTY_HINT_SPRITE_FRAME), _SCS("set_frame"), _SCS("get_frame"));
342 ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "modulate"), _SCS("set_modulate"), _SCS("get_modulate"));
343 ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "region"), _SCS("set_region"), _SCS("is_region"));
344 ADD_PROPERTYNZ(PropertyInfo(Variant::RECT2, "region_rect"), _SCS("set_region_rect"), _SCS("get_region_rect"));
345 }
346
Sprite()347 Sprite::Sprite() {
348
349 centered = true;
350 hflip = false;
351 vflip = false;
352 region = false;
353
354 frame = 0;
355
356 vframes = 1;
357 hframes = 1;
358
359 modulate = Color(1, 1, 1, 1);
360 }
361
362 //////////////////////////// VPSPRITE
363 ///
364 ///
365 ///
366
edit_set_pivot(const Point2 & p_pivot)367 void ViewportSprite::edit_set_pivot(const Point2 &p_pivot) {
368
369 set_offset(p_pivot);
370 }
371
edit_get_pivot() const372 Point2 ViewportSprite::edit_get_pivot() const {
373
374 return get_offset();
375 }
edit_has_pivot() const376 bool ViewportSprite::edit_has_pivot() const {
377
378 return true;
379 }
380
_notification(int p_what)381 void ViewportSprite::_notification(int p_what) {
382
383 switch (p_what) {
384
385 case NOTIFICATION_ENTER_TREE: {
386
387 if (!viewport_path.is_empty()) {
388
389 Node *n = get_node(viewport_path);
390 ERR_FAIL_COND(!n);
391 Viewport *vp = n->cast_to<Viewport>();
392 ERR_FAIL_COND(!vp);
393
394 Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
395 texture = rtt;
396 texture->connect("changed", this, "update");
397 item_rect_changed();
398 }
399 } break;
400 case NOTIFICATION_EXIT_TREE: {
401
402 if (texture.is_valid()) {
403
404 texture->disconnect("changed", this, "update");
405 texture = Ref<Texture>();
406 }
407 } break;
408 case NOTIFICATION_DRAW: {
409
410 if (texture.is_null())
411 return;
412
413 RID ci = get_canvas_item();
414
415 /*
416 texture->draw(ci,Point2());
417 break;
418 */
419
420 Size2i s;
421 Rect2i src_rect;
422
423 s = texture->get_size();
424
425 src_rect.size = s;
426
427 Point2 ofs = offset;
428 if (centered)
429 ofs -= s / 2;
430
431 if (OS::get_singleton()->get_use_pixel_snap()) {
432 ofs = ofs.floor();
433 }
434 Rect2 dst_rect(ofs, s);
435 texture->draw_rect_region(ci, dst_rect, src_rect, modulate);
436
437 } break;
438 }
439 }
440
set_viewport_path(const NodePath & p_viewport)441 void ViewportSprite::set_viewport_path(const NodePath &p_viewport) {
442
443 viewport_path = p_viewport;
444 update();
445 if (!is_inside_tree())
446 return;
447
448 if (texture.is_valid()) {
449 texture->disconnect("changed", this, "update");
450 texture = Ref<Texture>();
451 }
452
453 if (viewport_path.is_empty())
454 return;
455
456 Node *n = get_node(viewport_path);
457 ERR_FAIL_COND(!n);
458 Viewport *vp = n->cast_to<Viewport>();
459 ERR_FAIL_COND(!vp);
460
461 Ref<RenderTargetTexture> rtt = vp->get_render_target_texture();
462 texture = rtt;
463
464 if (texture.is_valid()) {
465 texture->connect("changed", this, "update");
466 }
467
468 item_rect_changed();
469 }
470
get_viewport_path() const471 NodePath ViewportSprite::get_viewport_path() const {
472
473 return viewport_path;
474 }
475
set_centered(bool p_center)476 void ViewportSprite::set_centered(bool p_center) {
477
478 centered = p_center;
479 update();
480 item_rect_changed();
481 }
482
is_centered() const483 bool ViewportSprite::is_centered() const {
484
485 return centered;
486 }
487
set_offset(const Point2 & p_offset)488 void ViewportSprite::set_offset(const Point2 &p_offset) {
489
490 offset = p_offset;
491 update();
492 item_rect_changed();
493 }
get_offset() const494 Point2 ViewportSprite::get_offset() const {
495
496 return offset;
497 }
set_modulate(const Color & p_color)498 void ViewportSprite::set_modulate(const Color &p_color) {
499
500 modulate = p_color;
501 update();
502 }
503
get_modulate() const504 Color ViewportSprite::get_modulate() const {
505
506 return modulate;
507 }
508
get_item_rect() const509 Rect2 ViewportSprite::get_item_rect() const {
510
511 if (texture.is_null())
512 return Rect2(0, 0, 1, 1);
513 //if (texture.is_null())
514 // return CanvasItem::get_item_rect();
515
516 Size2i s;
517
518 s = texture->get_size();
519 Point2 ofs = offset;
520 if (centered)
521 ofs -= s / 2;
522
523 if (s == Size2(0, 0))
524 s = Size2(1, 1);
525
526 return Rect2(ofs, s);
527 }
528
get_configuration_warning() const529 String ViewportSprite::get_configuration_warning() const {
530
531 if (!has_node(viewport_path) || !get_node(viewport_path) || !get_node(viewport_path)->cast_to<Viewport>()) {
532 return TTR("Path property must point to a valid Viewport node to work. Such Viewport must be set to 'render target' mode.");
533 } else {
534
535 Node *n = get_node(viewport_path);
536 if (n) {
537 Viewport *vp = n->cast_to<Viewport>();
538 if (!vp->is_set_as_render_target()) {
539
540 return TTR("The Viewport set in the path property must be set as 'render target' in order for this sprite to work.");
541 }
542 }
543 }
544
545 return String();
546 }
547
_bind_methods()548 void ViewportSprite::_bind_methods() {
549
550 ObjectTypeDB::bind_method(_MD("set_viewport_path", "path"), &ViewportSprite::set_viewport_path);
551 ObjectTypeDB::bind_method(_MD("get_viewport_path"), &ViewportSprite::get_viewport_path);
552
553 ObjectTypeDB::bind_method(_MD("set_centered", "centered"), &ViewportSprite::set_centered);
554 ObjectTypeDB::bind_method(_MD("is_centered"), &ViewportSprite::is_centered);
555
556 ObjectTypeDB::bind_method(_MD("set_offset", "offset"), &ViewportSprite::set_offset);
557 ObjectTypeDB::bind_method(_MD("get_offset"), &ViewportSprite::get_offset);
558
559 ObjectTypeDB::bind_method(_MD("set_modulate", "modulate"), &ViewportSprite::set_modulate);
560 ObjectTypeDB::bind_method(_MD("get_modulate"), &ViewportSprite::get_modulate);
561
562 ADD_PROPERTYNZ(PropertyInfo(Variant::NODE_PATH, "viewport"), _SCS("set_viewport_path"), _SCS("get_viewport_path"));
563 ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "centered"), _SCS("set_centered"), _SCS("is_centered"));
564 ADD_PROPERTYNZ(PropertyInfo(Variant::VECTOR2, "offset"), _SCS("set_offset"), _SCS("get_offset"));
565 ADD_PROPERTYNO(PropertyInfo(Variant::COLOR, "modulate"), _SCS("set_modulate"), _SCS("get_modulate"));
566 }
567
ViewportSprite()568 ViewportSprite::ViewportSprite() {
569
570 centered = true;
571 modulate = Color(1, 1, 1, 1);
572 }
573