texture.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. /*************************************************************************/
  2. /* texture.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. #include "texture.h"
  31. #include "core/os/os.h"
  32. #include "io/image_loader.h"
  33. Size2 Texture::get_size() const {
  34. return Size2(get_width(), get_height());
  35. }
  36. void Texture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
  37. VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose);
  38. }
  39. void Texture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
  40. VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose);
  41. }
  42. void Texture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const {
  43. VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose);
  44. }
  45. bool Texture::get_rect_region_uv_rect(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_uv_rect) const {
  46. Size2 size = get_size();
  47. if (size.width == 0 || size.height == 0)
  48. return false;
  49. r_rect = p_rect;
  50. r_uv_rect = Rect2(p_src_rect.get_pos() / size, p_src_rect.get_size() / size);
  51. return true;
  52. }
  53. void Texture::_bind_methods() {
  54. ObjectTypeDB::bind_method(_MD("get_width"), &Texture::get_width);
  55. ObjectTypeDB::bind_method(_MD("get_height"), &Texture::get_height);
  56. ObjectTypeDB::bind_method(_MD("get_size"), &Texture::get_size);
  57. ObjectTypeDB::bind_method(_MD("get_rid"), &Texture::get_rid);
  58. ObjectTypeDB::bind_method(_MD("has_alpha"), &Texture::has_alpha);
  59. ObjectTypeDB::bind_method(_MD("set_flags", "flags"), &Texture::set_flags);
  60. ObjectTypeDB::bind_method(_MD("get_flags"), &Texture::get_flags);
  61. ObjectTypeDB::bind_method(_MD("draw", "canvas_item", "pos", "modulate", "transpose"), &Texture::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
  62. ObjectTypeDB::bind_method(_MD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose"), &Texture::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
  63. ObjectTypeDB::bind_method(_MD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose"), &Texture::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false));
  64. BIND_CONSTANT(FLAG_MIPMAPS);
  65. BIND_CONSTANT(FLAG_REPEAT);
  66. BIND_CONSTANT(FLAG_FILTER);
  67. BIND_CONSTANT(FLAG_VIDEO_SURFACE);
  68. BIND_CONSTANT(FLAGS_DEFAULT);
  69. BIND_CONSTANT(FLAG_ANISOTROPIC_FILTER);
  70. BIND_CONSTANT(FLAG_CONVERT_TO_LINEAR);
  71. BIND_CONSTANT(FLAG_MIRRORED_REPEAT);
  72. }
  73. Texture::Texture() {
  74. }
  75. /////////////////////
  76. void ImageTexture::reload_from_file() {
  77. String path = get_path();
  78. if (!path.is_resource_file())
  79. return;
  80. uint32_t flags = get_flags();
  81. Image img;
  82. Error err = ImageLoader::load_image(path, &img);
  83. ERR_FAIL_COND(err != OK);
  84. create_from_image(img, flags);
  85. }
  86. bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) {
  87. if (p_name == "image" && p_value.get_type() == Variant::IMAGE)
  88. create_from_image(p_value, flags);
  89. else if (p_name == "flags")
  90. if (w * h == 0)
  91. flags = p_value;
  92. else
  93. set_flags(p_value);
  94. else if (p_name == "size") {
  95. Size2 s = p_value;
  96. w = s.width;
  97. h = s.height;
  98. VisualServer::get_singleton()->texture_set_size_override(texture, w, h);
  99. } else if (p_name == "storage") {
  100. storage = Storage(p_value.operator int());
  101. } else if (p_name == "lossy_quality") {
  102. lossy_storage_quality = p_value;
  103. } else if (p_name == "_data") {
  104. _set_data(p_value);
  105. } else
  106. return false;
  107. return true;
  108. }
  109. bool ImageTexture::_get(const StringName &p_name, Variant &r_ret) const {
  110. if (p_name == "image_data") {
  111. } else if (p_name == "image")
  112. r_ret = get_data();
  113. else if (p_name == "flags")
  114. r_ret = flags;
  115. else if (p_name == "size")
  116. r_ret = Size2(w, h);
  117. else if (p_name == "storage")
  118. r_ret = storage;
  119. else if (p_name == "lossy_quality")
  120. r_ret = lossy_storage_quality;
  121. else
  122. return false;
  123. return true;
  124. }
  125. void ImageTexture::_get_property_list(List<PropertyInfo> *p_list) const {
  126. PropertyHint img_hint = PROPERTY_HINT_NONE;
  127. if (storage == STORAGE_COMPRESS_LOSSY) {
  128. img_hint = PROPERTY_HINT_IMAGE_COMPRESS_LOSSY;
  129. } else if (storage == STORAGE_COMPRESS_LOSSLESS) {
  130. img_hint = PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS;
  131. }
  132. p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat"));
  133. p_list->push_back(PropertyInfo(Variant::IMAGE, "image", img_hint, String::num(lossy_storage_quality)));
  134. p_list->push_back(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, ""));
  135. p_list->push_back(PropertyInfo(Variant::INT, "storage", PROPERTY_HINT_ENUM, "Uncompressed,Compress Lossy,Compress Lossless"));
  136. p_list->push_back(PropertyInfo(Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
  137. }
  138. void ImageTexture::_reload_hook(const RID &p_hook) {
  139. String path = get_path();
  140. if (!path.is_resource_file())
  141. return;
  142. Image img;
  143. Error err = ImageLoader::load_image(path, &img);
  144. ERR_FAIL_COND(err != OK);
  145. VisualServer::get_singleton()->texture_set_data(texture, img);
  146. _change_notify();
  147. }
  148. void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) {
  149. flags = p_flags;
  150. VisualServer::get_singleton()->texture_allocate(texture, p_width, p_height, p_format, p_flags);
  151. format = p_format;
  152. w = p_width;
  153. h = p_height;
  154. }
  155. void ImageTexture::create_from_image(const Image &p_image, uint32_t p_flags) {
  156. ERR_FAIL_COND(p_image.empty());
  157. flags = p_flags;
  158. w = p_image.get_width();
  159. h = p_image.get_height();
  160. format = p_image.get_format();
  161. VisualServer::get_singleton()->texture_allocate(texture, p_image.get_width(), p_image.get_height(), p_image.get_format(), p_flags);
  162. VisualServer::get_singleton()->texture_set_data(texture, p_image);
  163. _change_notify();
  164. }
  165. void ImageTexture::set_flags(uint32_t p_flags) {
  166. /* uint32_t cube = flags & FLAG_CUBEMAP;
  167. if (flags == p_flags&cube)
  168. return;
  169. flags=p_flags|cube; */
  170. flags = p_flags;
  171. VisualServer::get_singleton()->texture_set_flags(texture, p_flags);
  172. }
  173. uint32_t ImageTexture::get_flags() const {
  174. return ImageTexture::flags;
  175. }
  176. Image::Format ImageTexture::get_format() const {
  177. return format;
  178. }
  179. void ImageTexture::load(const String &p_path) {
  180. Image img;
  181. img.load(p_path);
  182. create_from_image(img);
  183. }
  184. void ImageTexture::set_data(const Image &p_image) {
  185. VisualServer::get_singleton()->texture_set_data(texture, p_image);
  186. VisualServer::get_singleton()->texture_set_reload_hook(texture, 0, StringName()); //hook is erased if data is changed
  187. _change_notify();
  188. }
  189. void ImageTexture::_resource_path_changed() {
  190. String path = get_path();
  191. if (VS::get_singleton()->has_feature(VS::FEATURE_NEEDS_RELOAD_HOOK)) {
  192. //this needs to be done much better, but probably will end up being deprecated as technology advances
  193. if (path.is_resource_file() && ImageLoader::recognize(path.extension())) {
  194. //hook is set only if path is hookable
  195. VisualServer::get_singleton()->texture_set_reload_hook(texture, get_instance_ID(), "_reload_hook");
  196. } else {
  197. VisualServer::get_singleton()->texture_set_reload_hook(texture, 0, StringName());
  198. }
  199. }
  200. }
  201. Image ImageTexture::get_data() const {
  202. return VisualServer::get_singleton()->texture_get_data(texture);
  203. }
  204. int ImageTexture::get_width() const {
  205. return w;
  206. }
  207. int ImageTexture::get_height() const {
  208. return h;
  209. }
  210. RID ImageTexture::get_rid() const {
  211. return texture;
  212. }
  213. void ImageTexture::fix_alpha_edges() {
  214. if (format == Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) {
  215. Image img = get_data();
  216. img.fix_alpha_edges();
  217. set_data(img);
  218. }
  219. }
  220. void ImageTexture::premultiply_alpha() {
  221. if (format == Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) {
  222. Image img = get_data();
  223. img.premultiply_alpha();
  224. set_data(img);
  225. }
  226. }
  227. void ImageTexture::normal_to_xy() {
  228. Image img = get_data();
  229. img.normalmap_to_xy();
  230. create_from_image(img, flags);
  231. }
  232. void ImageTexture::shrink_x2_and_keep_size() {
  233. Size2 sizeov = get_size();
  234. Image img = get_data();
  235. img.resize(img.get_width() / 2, img.get_height() / 2, Image::INTERPOLATE_BILINEAR);
  236. create_from_image(img, flags);
  237. set_size_override(sizeov);
  238. }
  239. bool ImageTexture::has_alpha() const {
  240. return (format == Image::FORMAT_GRAYSCALE_ALPHA || format == Image::FORMAT_INDEXED_ALPHA || format == Image::FORMAT_RGBA);
  241. }
  242. void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
  243. if ((w | h) == 0)
  244. return;
  245. VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose);
  246. }
  247. void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
  248. if ((w | h) == 0)
  249. return;
  250. VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose);
  251. }
  252. void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const {
  253. if ((w | h) == 0)
  254. return;
  255. VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose);
  256. }
  257. void ImageTexture::set_size_override(const Size2 &p_size) {
  258. Size2 s = p_size;
  259. if (s.x != 0)
  260. w = s.x;
  261. if (s.y != 0)
  262. h = s.y;
  263. VisualServer::get_singleton()->texture_set_size_override(texture, w, h);
  264. }
  265. void ImageTexture::set_path(const String &p_path, bool p_take_over) {
  266. if (texture.is_valid()) {
  267. VisualServer::get_singleton()->texture_set_path(texture, p_path);
  268. }
  269. Resource::set_path(p_path, p_take_over);
  270. }
  271. void ImageTexture::set_storage(Storage p_storage) {
  272. storage = p_storage;
  273. }
  274. ImageTexture::Storage ImageTexture::get_storage() const {
  275. return storage;
  276. }
  277. void ImageTexture::set_lossy_storage_quality(float p_lossy_storage_quality) {
  278. lossy_storage_quality = p_lossy_storage_quality;
  279. }
  280. float ImageTexture::get_lossy_storage_quality() const {
  281. return lossy_storage_quality;
  282. }
  283. void ImageTexture::_set_data(Dictionary p_data) {
  284. Image img = p_data["image"];
  285. uint32_t flags = p_data["flags"];
  286. create_from_image(img, flags);
  287. set_storage(Storage(p_data["storage"].operator int()));
  288. set_lossy_storage_quality(p_data["lossy_quality"]);
  289. set_size_override(p_data["size"]);
  290. };
  291. void ImageTexture::_bind_methods() {
  292. ObjectTypeDB::bind_method(_MD("create", "width", "height", "format", "flags"), &ImageTexture::create, DEFVAL(FLAGS_DEFAULT));
  293. ObjectTypeDB::bind_method(_MD("create_from_image", "image", "flags"), &ImageTexture::create_from_image, DEFVAL(FLAGS_DEFAULT));
  294. ObjectTypeDB::bind_method(_MD("get_format"), &ImageTexture::get_format);
  295. ObjectTypeDB::bind_method(_MD("load", "path"), &ImageTexture::load);
  296. ObjectTypeDB::bind_method(_MD("set_data", "image"), &ImageTexture::set_data);
  297. ObjectTypeDB::bind_method(_MD("get_data", "cube_side"), &ImageTexture::get_data);
  298. ObjectTypeDB::bind_method(_MD("set_storage", "mode"), &ImageTexture::set_storage);
  299. ObjectTypeDB::bind_method(_MD("get_storage"), &ImageTexture::get_storage);
  300. ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality", "quality"), &ImageTexture::set_lossy_storage_quality);
  301. ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"), &ImageTexture::get_lossy_storage_quality);
  302. ObjectTypeDB::bind_method(_MD("fix_alpha_edges"), &ImageTexture::fix_alpha_edges);
  303. ObjectTypeDB::bind_method(_MD("premultiply_alpha"), &ImageTexture::premultiply_alpha);
  304. ObjectTypeDB::bind_method(_MD("normal_to_xy"), &ImageTexture::normal_to_xy);
  305. ObjectTypeDB::bind_method(_MD("shrink_x2_and_keep_size"), &ImageTexture::shrink_x2_and_keep_size);
  306. ObjectTypeDB::bind_method(_MD("set_size_override", "size"), &ImageTexture::set_size_override);
  307. ObjectTypeDB::set_method_flags(get_type_static(), _SCS("fix_alpha_edges"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
  308. ObjectTypeDB::set_method_flags(get_type_static(), _SCS("premultiply_alpha"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
  309. ObjectTypeDB::set_method_flags(get_type_static(), _SCS("normal_to_xy"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
  310. ObjectTypeDB::set_method_flags(get_type_static(), _SCS("shrink_x2_and_keep_size"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
  311. ObjectTypeDB::bind_method(_MD("_reload_hook", "rid"), &ImageTexture::_reload_hook);
  312. BIND_CONSTANT(STORAGE_RAW);
  313. BIND_CONSTANT(STORAGE_COMPRESS_LOSSY);
  314. BIND_CONSTANT(STORAGE_COMPRESS_LOSSLESS);
  315. }
  316. ImageTexture::ImageTexture() {
  317. w = h = 0;
  318. flags = FLAGS_DEFAULT;
  319. texture = VisualServer::get_singleton()->texture_create();
  320. storage = STORAGE_RAW;
  321. lossy_storage_quality = 0.7;
  322. }
  323. ImageTexture::~ImageTexture() {
  324. VisualServer::get_singleton()->free(texture);
  325. }
  326. //////////////////////////////////////////
  327. int AtlasTexture::get_width() const {
  328. if (region.size.width == 0) {
  329. if (atlas.is_valid())
  330. return atlas->get_width();
  331. return 1;
  332. } else {
  333. return region.size.width + margin.size.width;
  334. }
  335. }
  336. int AtlasTexture::get_height() const {
  337. if (region.size.height == 0) {
  338. if (atlas.is_valid())
  339. return atlas->get_height();
  340. return 1;
  341. } else {
  342. return region.size.height + margin.size.height;
  343. }
  344. }
  345. RID AtlasTexture::get_rid() const {
  346. if (atlas.is_valid())
  347. return atlas->get_rid();
  348. return RID();
  349. }
  350. bool AtlasTexture::has_alpha() const {
  351. if (atlas.is_valid())
  352. return atlas->has_alpha();
  353. return false;
  354. }
  355. void AtlasTexture::set_flags(uint32_t p_flags) {
  356. if (atlas.is_valid())
  357. atlas->set_flags(p_flags);
  358. }
  359. uint32_t AtlasTexture::get_flags() const {
  360. if (atlas.is_valid())
  361. return atlas->get_flags();
  362. return 0;
  363. }
  364. void AtlasTexture::set_atlas(const Ref<Texture> &p_atlas) {
  365. if (atlas == p_atlas)
  366. return;
  367. atlas = p_atlas;
  368. emit_changed();
  369. emit_signal("atlas_changed");
  370. }
  371. Ref<Texture> AtlasTexture::get_atlas() const {
  372. return atlas;
  373. }
  374. void AtlasTexture::set_region(const Rect2 &p_region) {
  375. region = p_region;
  376. emit_changed();
  377. }
  378. Rect2 AtlasTexture::get_region() const {
  379. return region;
  380. }
  381. void AtlasTexture::set_margin(const Rect2 &p_margin) {
  382. margin = p_margin;
  383. emit_changed();
  384. }
  385. Rect2 AtlasTexture::get_margin() const {
  386. return margin;
  387. }
  388. void AtlasTexture::_bind_methods() {
  389. ObjectTypeDB::bind_method(_MD("set_atlas", "atlas:Texture"), &AtlasTexture::set_atlas);
  390. ObjectTypeDB::bind_method(_MD("get_atlas:Texture"), &AtlasTexture::get_atlas);
  391. ObjectTypeDB::bind_method(_MD("set_region", "region"), &AtlasTexture::set_region);
  392. ObjectTypeDB::bind_method(_MD("get_region"), &AtlasTexture::get_region);
  393. ObjectTypeDB::bind_method(_MD("set_margin", "margin"), &AtlasTexture::set_margin);
  394. ObjectTypeDB::bind_method(_MD("get_margin"), &AtlasTexture::get_margin);
  395. ADD_SIGNAL(MethodInfo("atlas_changed"));
  396. ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_atlas"), _SCS("get_atlas"));
  397. ADD_PROPERTY(PropertyInfo(Variant::RECT2, "region"), _SCS("set_region"), _SCS("get_region"));
  398. ADD_PROPERTY(PropertyInfo(Variant::RECT2, "margin"), _SCS("set_margin"), _SCS("get_margin"));
  399. }
  400. void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
  401. Rect2 rc = region;
  402. if (!atlas.is_valid())
  403. return;
  404. if (rc.size.width == 0) {
  405. rc.size.width = atlas->get_width();
  406. }
  407. if (rc.size.height == 0) {
  408. rc.size.height = atlas->get_height();
  409. }
  410. VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.pos, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose);
  411. }
  412. void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
  413. Rect2 rc = region;
  414. if (!atlas.is_valid())
  415. return;
  416. if (rc.size.width == 0) {
  417. rc.size.width = atlas->get_width();
  418. }
  419. if (rc.size.height == 0) {
  420. rc.size.height = atlas->get_height();
  421. }
  422. Vector2 scale = p_rect.size / (region.size + margin.size);
  423. Rect2 dr(p_rect.pos + margin.pos * scale, rc.size * scale);
  424. VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose);
  425. }
  426. void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const {
  427. //this might not necesarily work well if using a rect, needs to be fixed properly
  428. Rect2 rc = region;
  429. if (!atlas.is_valid())
  430. return;
  431. Rect2 src = p_src_rect;
  432. src.pos += (rc.pos - margin.pos);
  433. Rect2 src_c = rc.clip(src);
  434. if (src_c.size == Size2())
  435. return;
  436. Vector2 ofs = (src_c.pos - src.pos);
  437. Vector2 scale = p_rect.size / p_src_rect.size;
  438. if (scale.x < 0) {
  439. float mx = (margin.size.width - margin.pos.x);
  440. mx -= margin.pos.x;
  441. ofs.x = -(ofs.x + mx);
  442. }
  443. if (scale.y < 0) {
  444. float my = margin.size.height - margin.pos.y;
  445. my -= margin.pos.y;
  446. ofs.y = -(ofs.y + my);
  447. }
  448. Rect2 dr(p_rect.pos + ofs * scale, src_c.size * scale);
  449. VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose);
  450. }
  451. bool AtlasTexture::get_rect_region_uv_rect(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_uv_rect) const {
  452. Rect2 rc = region;
  453. if (!atlas.is_valid())
  454. return false;
  455. Size2 atlas_size = atlas->get_size();
  456. if (atlas_size.width == 0 || atlas_size.height == 0)
  457. return false;
  458. Rect2 src = p_src_rect;
  459. src.pos += (rc.pos - margin.pos);
  460. Rect2 src_c = rc.clip(src);
  461. if (src_c.size == Size2())
  462. return false;
  463. Vector2 ofs = (src_c.pos - src.pos);
  464. Vector2 scale = p_rect.size / p_src_rect.size;
  465. if (scale.x < 0) {
  466. float mx = (margin.size.width - margin.pos.x);
  467. mx -= margin.pos.x;
  468. ofs.x = -(ofs.x + mx);
  469. }
  470. if (scale.y < 0) {
  471. float my = margin.size.height - margin.pos.y;
  472. my -= margin.pos.y;
  473. ofs.y = -(ofs.y + my);
  474. }
  475. Rect2 dr(p_rect.pos + ofs * scale, src_c.size * scale);
  476. r_rect = dr;
  477. r_uv_rect = Rect2(src_c.get_pos() / atlas_size, src_c.get_size() / atlas_size);
  478. return true;
  479. }
  480. AtlasTexture::AtlasTexture() {
  481. }
  482. //////////////////////////////////////////
  483. int LargeTexture::get_width() const {
  484. return size.width;
  485. }
  486. int LargeTexture::get_height() const {
  487. return size.height;
  488. }
  489. RID LargeTexture::get_rid() const {
  490. return RID();
  491. }
  492. bool LargeTexture::has_alpha() const {
  493. for (int i = 0; i < pieces.size(); i++) {
  494. if (pieces[i].texture->has_alpha())
  495. return true;
  496. }
  497. return false;
  498. }
  499. void LargeTexture::set_flags(uint32_t p_flags) {
  500. for (int i = 0; i < pieces.size(); i++) {
  501. pieces[i].texture->set_flags(p_flags);
  502. }
  503. }
  504. uint32_t LargeTexture::get_flags() const {
  505. if (pieces.size())
  506. return pieces[0].texture->get_flags();
  507. return 0;
  508. }
  509. int LargeTexture::add_piece(const Point2 &p_offset, const Ref<Texture> &p_texture) {
  510. ERR_FAIL_COND_V(p_texture.is_null(), -1);
  511. Piece p;
  512. p.offset = p_offset;
  513. p.texture = p_texture;
  514. pieces.push_back(p);
  515. return pieces.size() - 1;
  516. }
  517. void LargeTexture::set_piece_offset(int p_idx, const Point2 &p_offset) {
  518. ERR_FAIL_INDEX(p_idx, pieces.size());
  519. pieces[p_idx].offset = p_offset;
  520. };
  521. void LargeTexture::set_piece_texture(int p_idx, const Ref<Texture> &p_texture) {
  522. ERR_FAIL_INDEX(p_idx, pieces.size());
  523. pieces[p_idx].texture = p_texture;
  524. };
  525. void LargeTexture::set_size(const Size2 &p_size) {
  526. size = p_size;
  527. }
  528. void LargeTexture::clear() {
  529. pieces.clear();
  530. size = Size2i();
  531. }
  532. Array LargeTexture::_get_data() const {
  533. Array arr;
  534. for (int i = 0; i < pieces.size(); i++) {
  535. arr.push_back(pieces[i].offset);
  536. arr.push_back(pieces[i].texture);
  537. }
  538. arr.push_back(Size2(size));
  539. return arr;
  540. }
  541. void LargeTexture::_set_data(const Array &p_array) {
  542. ERR_FAIL_COND(p_array.size() < 1);
  543. ERR_FAIL_COND(!(p_array.size() & 1));
  544. clear();
  545. for (int i = 0; i < p_array.size() - 1; i += 2) {
  546. add_piece(p_array[i], p_array[i + 1]);
  547. }
  548. size = Size2(p_array[p_array.size() - 1]);
  549. }
  550. int LargeTexture::get_piece_count() const {
  551. return pieces.size();
  552. }
  553. Vector2 LargeTexture::get_piece_offset(int p_idx) const {
  554. ERR_FAIL_INDEX_V(p_idx, pieces.size(), Vector2());
  555. return pieces[p_idx].offset;
  556. }
  557. Ref<Texture> LargeTexture::get_piece_texture(int p_idx) const {
  558. ERR_FAIL_INDEX_V(p_idx, pieces.size(), Ref<Texture>());
  559. return pieces[p_idx].texture;
  560. }
  561. void LargeTexture::_bind_methods() {
  562. ObjectTypeDB::bind_method(_MD("add_piece", "ofs", "texture:Texture"), &LargeTexture::add_piece);
  563. ObjectTypeDB::bind_method(_MD("set_piece_offset", "idx", "ofs"), &LargeTexture::set_piece_offset);
  564. ObjectTypeDB::bind_method(_MD("set_piece_texture", "idx", "texture:Texture"), &LargeTexture::set_piece_texture);
  565. ObjectTypeDB::bind_method(_MD("set_size", "size"), &LargeTexture::set_size);
  566. ObjectTypeDB::bind_method(_MD("clear"), &LargeTexture::clear);
  567. ObjectTypeDB::bind_method(_MD("get_piece_count"), &LargeTexture::get_piece_count);
  568. ObjectTypeDB::bind_method(_MD("get_piece_offset", "idx"), &LargeTexture::get_piece_offset);
  569. ObjectTypeDB::bind_method(_MD("get_piece_texture:Texture", "idx"), &LargeTexture::get_piece_texture);
  570. ObjectTypeDB::bind_method(_MD("_set_data", "data"), &LargeTexture::_set_data);
  571. ObjectTypeDB::bind_method(_MD("_get_data"), &LargeTexture::_get_data);
  572. ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"), _SCS("_get_data"));
  573. }
  574. void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const {
  575. for (int i = 0; i < pieces.size(); i++) {
  576. // TODO
  577. pieces[i].texture->draw(p_canvas_item, pieces[i].offset + p_pos, p_modulate, p_transpose);
  578. }
  579. }
  580. void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const {
  581. //tiling not supported for this
  582. if (size.x == 0 || size.y == 0)
  583. return;
  584. Size2 scale = p_rect.size / size;
  585. for (int i = 0; i < pieces.size(); i++) {
  586. // TODO
  587. pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.pos, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose);
  588. }
  589. }
  590. void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose) const {
  591. //tiling not supported for this
  592. if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0)
  593. return;
  594. Size2 scale = p_rect.size / p_src_rect.size;
  595. for (int i = 0; i < pieces.size(); i++) {
  596. // TODO
  597. Rect2 rect(pieces[i].offset, pieces[i].texture->get_size());
  598. if (!p_src_rect.intersects(rect))
  599. continue;
  600. Rect2 local = p_src_rect.clip(rect);
  601. Rect2 target = local;
  602. target.size *= scale;
  603. target.pos = p_rect.pos + (p_src_rect.pos + rect.pos) * scale;
  604. local.pos -= rect.pos;
  605. pieces[i].texture->draw_rect_region(p_canvas_item, target, local, p_modulate, p_transpose);
  606. }
  607. }
  608. LargeTexture::LargeTexture() {
  609. }
  610. ///////////////////////////////////////////////
  611. void CubeMap::set_flags(uint32_t p_flags) {
  612. flags = p_flags;
  613. if (_is_valid())
  614. VS::get_singleton()->texture_set_flags(cubemap, flags | VS::TEXTURE_FLAG_CUBEMAP);
  615. }
  616. uint32_t CubeMap::get_flags() const {
  617. return flags;
  618. }
  619. void CubeMap::set_side(Side p_side, const Image &p_image) {
  620. ERR_FAIL_COND(p_image.empty());
  621. ERR_FAIL_INDEX(p_side, 6);
  622. if (!_is_valid()) {
  623. format = p_image.get_format();
  624. w = p_image.get_width();
  625. h = p_image.get_height();
  626. VS::get_singleton()->texture_allocate(cubemap, w, h, p_image.get_format(), flags | VS::TEXTURE_FLAG_CUBEMAP);
  627. }
  628. VS::get_singleton()->texture_set_data(cubemap, p_image, VS::CubeMapSide(p_side));
  629. valid[p_side] = true;
  630. }
  631. Image CubeMap::get_side(Side p_side) const {
  632. if (!valid[p_side])
  633. return Image();
  634. return VS::get_singleton()->texture_get_data(cubemap, VS::CubeMapSide(p_side));
  635. }
  636. Image::Format CubeMap::get_format() const {
  637. return format;
  638. }
  639. int CubeMap::get_width() const {
  640. return w;
  641. }
  642. int CubeMap::get_height() const {
  643. return h;
  644. }
  645. RID CubeMap::get_rid() const {
  646. return cubemap;
  647. }
  648. void CubeMap::set_storage(Storage p_storage) {
  649. storage = p_storage;
  650. }
  651. CubeMap::Storage CubeMap::get_storage() const {
  652. return storage;
  653. }
  654. void CubeMap::set_lossy_storage_quality(float p_lossy_storage_quality) {
  655. lossy_storage_quality = p_lossy_storage_quality;
  656. }
  657. float CubeMap::get_lossy_storage_quality() const {
  658. return lossy_storage_quality;
  659. }
  660. void CubeMap::set_path(const String &p_path, bool p_take_over) {
  661. if (cubemap.is_valid()) {
  662. VisualServer::get_singleton()->texture_set_path(cubemap, p_path);
  663. }
  664. Resource::set_path(p_path, p_take_over);
  665. }
  666. bool CubeMap::_set(const StringName &p_name, const Variant &p_value) {
  667. if (p_name == "side/left") {
  668. set_side(SIDE_LEFT, p_value);
  669. } else if (p_name == "side/right") {
  670. set_side(SIDE_RIGHT, p_value);
  671. } else if (p_name == "side/bottom") {
  672. set_side(SIDE_BOTTOM, p_value);
  673. } else if (p_name == "side/top") {
  674. set_side(SIDE_TOP, p_value);
  675. } else if (p_name == "side/front") {
  676. set_side(SIDE_FRONT, p_value);
  677. } else if (p_name == "side/back") {
  678. set_side(SIDE_BACK, p_value);
  679. } else if (p_name == "flags") {
  680. set_flags(p_value);
  681. } else if (p_name == "storage") {
  682. storage = Storage(p_value.operator int());
  683. } else if (p_name == "lossy_quality") {
  684. lossy_storage_quality = p_value;
  685. } else
  686. return false;
  687. return true;
  688. }
  689. bool CubeMap::_get(const StringName &p_name, Variant &r_ret) const {
  690. if (p_name == "side/left") {
  691. r_ret = get_side(SIDE_LEFT);
  692. } else if (p_name == "side/right") {
  693. r_ret = get_side(SIDE_RIGHT);
  694. } else if (p_name == "side/bottom") {
  695. r_ret = get_side(SIDE_BOTTOM);
  696. } else if (p_name == "side/top") {
  697. r_ret = get_side(SIDE_TOP);
  698. } else if (p_name == "side/front") {
  699. r_ret = get_side(SIDE_FRONT);
  700. } else if (p_name == "side/back") {
  701. r_ret = get_side(SIDE_BACK);
  702. } else if (p_name == "flags") {
  703. r_ret = flags;
  704. } else if (p_name == "storage") {
  705. r_ret = storage;
  706. } else if (p_name == "lossy_quality") {
  707. r_ret = lossy_storage_quality;
  708. } else
  709. return false;
  710. return true;
  711. }
  712. void CubeMap::_get_property_list(List<PropertyInfo> *p_list) const {
  713. PropertyHint img_hint = PROPERTY_HINT_NONE;
  714. if (storage == STORAGE_COMPRESS_LOSSY) {
  715. img_hint = PROPERTY_HINT_IMAGE_COMPRESS_LOSSY;
  716. } else if (storage == STORAGE_COMPRESS_LOSSLESS) {
  717. img_hint = PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS;
  718. }
  719. p_list->push_back(PropertyInfo(Variant::INT, "flags", PROPERTY_HINT_FLAGS, "Mipmaps,Repeat,Filter"));
  720. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/left", img_hint, String::num(lossy_storage_quality)));
  721. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/right", img_hint, String::num(lossy_storage_quality)));
  722. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/bottom", img_hint, String::num(lossy_storage_quality)));
  723. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/top", img_hint, String::num(lossy_storage_quality)));
  724. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/front", img_hint, String::num(lossy_storage_quality)));
  725. p_list->push_back(PropertyInfo(Variant::IMAGE, "side/back", img_hint, String::num(lossy_storage_quality)));
  726. p_list->push_back(PropertyInfo(Variant::INT, "storage", PROPERTY_HINT_ENUM, "Uncompressed,Compress Lossy,Compress Lossless", PROPERTY_USAGE_EDITOR));
  727. p_list->push_back(PropertyInfo(Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"));
  728. }
  729. void CubeMap::_bind_methods() {
  730. ObjectTypeDB::bind_method(_MD("get_width"), &CubeMap::get_width);
  731. ObjectTypeDB::bind_method(_MD("get_height"), &CubeMap::get_height);
  732. ObjectTypeDB::bind_method(_MD("get_rid"), &CubeMap::get_rid);
  733. ObjectTypeDB::bind_method(_MD("set_flags", "flags"), &CubeMap::set_flags);
  734. ObjectTypeDB::bind_method(_MD("get_flags"), &CubeMap::get_flags);
  735. ObjectTypeDB::bind_method(_MD("set_side", "side", "image"), &CubeMap::set_side);
  736. ObjectTypeDB::bind_method(_MD("get_side", "side"), &CubeMap::get_side);
  737. ObjectTypeDB::bind_method(_MD("set_storage", "mode"), &CubeMap::set_storage);
  738. ObjectTypeDB::bind_method(_MD("get_storage"), &CubeMap::get_storage);
  739. ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality", "quality"), &CubeMap::set_lossy_storage_quality);
  740. ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"), &CubeMap::get_lossy_storage_quality);
  741. BIND_CONSTANT(STORAGE_RAW);
  742. BIND_CONSTANT(STORAGE_COMPRESS_LOSSY);
  743. BIND_CONSTANT(STORAGE_COMPRESS_LOSSLESS);
  744. BIND_CONSTANT(SIDE_LEFT);
  745. BIND_CONSTANT(SIDE_RIGHT);
  746. BIND_CONSTANT(SIDE_BOTTOM);
  747. BIND_CONSTANT(SIDE_TOP);
  748. BIND_CONSTANT(SIDE_FRONT);
  749. BIND_CONSTANT(SIDE_BACK);
  750. BIND_CONSTANT(FLAG_MIPMAPS);
  751. BIND_CONSTANT(FLAG_REPEAT);
  752. BIND_CONSTANT(FLAG_FILTER);
  753. BIND_CONSTANT(FLAGS_DEFAULT);
  754. }
  755. CubeMap::CubeMap() {
  756. w = h = 0;
  757. flags = FLAGS_DEFAULT;
  758. for (int i = 0; i < 6; i++)
  759. valid[i] = false;
  760. cubemap = VisualServer::get_singleton()->texture_create();
  761. storage = STORAGE_RAW;
  762. lossy_storage_quality = 0.7;
  763. }
  764. CubeMap::~CubeMap() {
  765. VisualServer::get_singleton()->free(cubemap);
  766. }
  767. /* BIND_CONSTANT( FLAG_CUBEMAP );
  768. BIND_CONSTANT( CUBEMAP_LEFT );
  769. BIND_CONSTANT( CUBEMAP_RIGHT );
  770. BIND_CONSTANT( CUBEMAP_BOTTOM );
  771. BIND_CONSTANT( CUBEMAP_TOP );
  772. BIND_CONSTANT( CUBEMAP_FRONT );
  773. BIND_CONSTANT( CUBEMAP_BACK );
  774. */