texture.cpp 28 KB

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