/*************************************************************************/ /* texture.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "texture.h" #include "io/image_loader.h" #include "core/os/os.h" Size2 Texture::get_size() const { return Size2(get_width(),get_height()); } void Texture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, get_size()),get_rid(),false,p_modulate,p_transpose); } void Texture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,get_rid(),p_tile,p_modulate,p_transpose); } 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{ VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,get_rid(),p_src_rect,p_modulate,p_transpose); } bool Texture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { r_rect=p_rect; r_src_rect=p_src_rect; return true; } void Texture::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_width"),&Texture::get_width); ObjectTypeDB::bind_method(_MD("get_height"),&Texture::get_height); ObjectTypeDB::bind_method(_MD("get_size"),&Texture::get_size); ObjectTypeDB::bind_method(_MD("get_rid"),&Texture::get_rid); ObjectTypeDB::bind_method(_MD("has_alpha"),&Texture::has_alpha); ObjectTypeDB::bind_method(_MD("set_flags","flags"),&Texture::set_flags); ObjectTypeDB::bind_method(_MD("get_flags"),&Texture::get_flags); ObjectTypeDB::bind_method(_MD("draw","canvas_item","pos","modulate","transpose"),&Texture::draw,DEFVAL(Color(1,1,1)),DEFVAL(false)); ObjectTypeDB::bind_method(_MD("draw_rect","canvas_item","rect","tile","modulate","transpose"),&Texture::draw_rect,DEFVAL(Color(1,1,1)),DEFVAL(false)); 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)); BIND_CONSTANT( FLAG_MIPMAPS ); BIND_CONSTANT( FLAG_REPEAT ); BIND_CONSTANT( FLAG_FILTER ); BIND_CONSTANT( FLAG_VIDEO_SURFACE ); BIND_CONSTANT( FLAGS_DEFAULT ); BIND_CONSTANT( FLAG_ANISOTROPIC_FILTER ); BIND_CONSTANT( FLAG_CONVERT_TO_LINEAR ); BIND_CONSTANT( FLAG_MIRRORED_REPEAT ); } Texture::Texture() { } ///////////////////// void ImageTexture::reload_from_file() { String path=get_path(); if (!path.is_resource_file()) return; uint32_t flags = get_flags(); Image img; Error err = ImageLoader::load_image(path,&img); ERR_FAIL_COND(err!=OK); create_from_image(img,flags); } bool ImageTexture::_set(const StringName& p_name, const Variant& p_value) { if (p_name=="image" && p_value.get_type()==Variant::IMAGE) create_from_image( p_value,flags ); else if (p_name=="flags") if (w*h==0) flags=p_value; else set_flags(p_value); else if (p_name=="size") { Size2 s = p_value; w=s.width; h=s.height; VisualServer::get_singleton()->texture_set_size_override(texture,w,h); } else if (p_name=="storage") { storage=Storage(p_value.operator int()); } else if (p_name=="lossy_quality") { lossy_storage_quality=p_value; } else if (p_name=="_data") { _set_data(p_value); } else return false; return true; } bool ImageTexture::_get(const StringName& p_name,Variant &r_ret) const { if (p_name=="image_data") { } else if (p_name=="image") r_ret= get_data(); else if (p_name=="flags") r_ret= flags; else if (p_name=="size") r_ret=Size2(w,h); else if (p_name=="storage") r_ret= storage; else if (p_name=="lossy_quality") r_ret= lossy_storage_quality; else return false; return true; } void ImageTexture::_get_property_list( List *p_list) const { PropertyHint img_hint=PROPERTY_HINT_NONE; if (storage==STORAGE_COMPRESS_LOSSY) { img_hint=PROPERTY_HINT_IMAGE_COMPRESS_LOSSY; } else if (storage==STORAGE_COMPRESS_LOSSLESS) { img_hint=PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS; } p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter,Anisotropic,sRGB,Mirrored Repeat") ); p_list->push_back( PropertyInfo( Variant::IMAGE, "image", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::VECTOR2, "size",PROPERTY_HINT_NONE, "")); p_list->push_back( PropertyInfo( Variant::INT, "storage", PROPERTY_HINT_ENUM,"Uncompressed,Compress Lossy,Compress Lossless")); p_list->push_back( PropertyInfo( Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" )); } void ImageTexture::_reload_hook(const RID& p_hook) { String path=get_path(); if (!path.is_resource_file()) return; Image img; Error err = ImageLoader::load_image(path,&img); ERR_FAIL_COND(err!=OK); VisualServer::get_singleton()->texture_set_data(texture,img); _change_notify(); } void ImageTexture::create(int p_width, int p_height,Image::Format p_format,uint32_t p_flags) { flags=p_flags; VisualServer::get_singleton()->texture_allocate(texture,p_width, p_height, p_format, p_flags); format=p_format; w=p_width; h=p_height; } void ImageTexture::create_from_image(const Image& p_image, uint32_t p_flags) { flags=p_flags; w=p_image.get_width(); h=p_image.get_height(); format=p_image.get_format(); VisualServer::get_singleton()->texture_allocate(texture,p_image.get_width(),p_image.get_height(), p_image.get_format(), p_flags); VisualServer::get_singleton()->texture_set_data(texture,p_image); _change_notify(); } void ImageTexture::set_flags(uint32_t p_flags) { /* uint32_t cube = flags & FLAG_CUBEMAP; if (flags == p_flags&cube) return; flags=p_flags|cube; */ flags=p_flags; VisualServer::get_singleton()->texture_set_flags(texture,p_flags); } uint32_t ImageTexture::get_flags() const { return ImageTexture::flags; } Image::Format ImageTexture::get_format() const { return format; } void ImageTexture::load(const String& p_path) { Image img; img.load(p_path); create_from_image(img); } void ImageTexture::set_data(const Image& p_image) { VisualServer::get_singleton()->texture_set_data(texture,p_image); VisualServer::get_singleton()->texture_set_reload_hook(texture,0,StringName()); //hook is erased if data is changed _change_notify(); } void ImageTexture::_resource_path_changed() { String path=get_path(); if (VS::get_singleton()->has_feature(VS::FEATURE_NEEDS_RELOAD_HOOK)) { //this needs to be done much better, but probably will end up being deprecated as technology advances if (path.is_resource_file() && ImageLoader::recognize(path.extension())) { //hook is set only if path is hookable VisualServer::get_singleton()->texture_set_reload_hook(texture,get_instance_ID(),"_reload_hook"); } else { VisualServer::get_singleton()->texture_set_reload_hook(texture,0,StringName()); } } } Image ImageTexture::get_data() const { return VisualServer::get_singleton()->texture_get_data(texture); } int ImageTexture::get_width() const { return w; } int ImageTexture::get_height() const { return h; } RID ImageTexture::get_rid() const { return texture; } void ImageTexture::fix_alpha_edges() { if (format==Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) { Image img = get_data(); img.fix_alpha_edges(); set_data(img); } } void ImageTexture::premultiply_alpha() { if (format==Image::FORMAT_RGBA /*&& !(flags&FLAG_CUBEMAP)*/) { Image img = get_data(); img.premultiply_alpha(); set_data(img); } } void ImageTexture::normal_to_xy() { Image img = get_data(); img.normalmap_to_xy(); create_from_image(img,flags); } void ImageTexture::shrink_x2_and_keep_size() { Size2 sizeov=get_size(); Image img = get_data(); img.resize(img.get_width()/2,img.get_height()/2,Image::INTERPOLATE_BILINEAR); create_from_image(img,flags); set_size_override(sizeov); } bool ImageTexture::has_alpha() const { return ( format==Image::FORMAT_GRAYSCALE_ALPHA || format==Image::FORMAT_INDEXED_ALPHA || format==Image::FORMAT_RGBA ); } void ImageTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { if ((w|h)==0) return; VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,Rect2( p_pos, Size2(w,h)),texture,false,p_modulate,p_transpose); } void ImageTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { if ((w|h)==0) return; VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item,p_rect,texture,p_tile,p_modulate,p_transpose); } 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{ if ((w|h)==0) return; VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,p_rect,texture,p_src_rect,p_modulate,p_transpose); } void ImageTexture::set_size_override(const Size2& p_size) { Size2 s=p_size; if (s.x!=0) w=s.x; if (s.y!=0) h=s.y; VisualServer::get_singleton()->texture_set_size_override(texture,w,h); } void ImageTexture::set_path(const String& p_path,bool p_take_over) { if (texture.is_valid()) { VisualServer::get_singleton()->texture_set_path(texture,p_path); } Resource::set_path(p_path,p_take_over); } void ImageTexture::set_storage(Storage p_storage) { storage=p_storage; } ImageTexture::Storage ImageTexture::get_storage() const { return storage; } void ImageTexture::set_lossy_storage_quality(float p_lossy_storage_quality) { lossy_storage_quality=p_lossy_storage_quality; } float ImageTexture::get_lossy_storage_quality() const { return lossy_storage_quality; } void ImageTexture::_set_data(Dictionary p_data) { Image img = p_data["image"]; uint32_t flags = p_data["flags"]; create_from_image(img, flags); set_storage(Storage(p_data["storage"].operator int())); set_lossy_storage_quality(p_data["lossy_quality"]); set_size_override(p_data["size"]); }; void ImageTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("create","width","height","format","flags"),&ImageTexture::create,DEFVAL(FLAGS_DEFAULT)); ObjectTypeDB::bind_method(_MD("create_from_image","image","flags"),&ImageTexture::create_from_image,DEFVAL(FLAGS_DEFAULT)); ObjectTypeDB::bind_method(_MD("get_format"),&ImageTexture::get_format); ObjectTypeDB::bind_method(_MD("load","path"),&ImageTexture::load); ObjectTypeDB::bind_method(_MD("set_data","image"),&ImageTexture::set_data); ObjectTypeDB::bind_method(_MD("get_data","cube_side"),&ImageTexture::get_data); ObjectTypeDB::bind_method(_MD("set_storage","mode"),&ImageTexture::set_storage); ObjectTypeDB::bind_method(_MD("get_storage"),&ImageTexture::get_storage); ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality","quality"),&ImageTexture::set_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&ImageTexture::get_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("fix_alpha_edges"),&ImageTexture::fix_alpha_edges); ObjectTypeDB::bind_method(_MD("premultiply_alpha"),&ImageTexture::premultiply_alpha); ObjectTypeDB::bind_method(_MD("normal_to_xy"),&ImageTexture::normal_to_xy); ObjectTypeDB::bind_method(_MD("shrink_x2_and_keep_size"),&ImageTexture::shrink_x2_and_keep_size); ObjectTypeDB::bind_method(_MD("set_size_override","size"),&ImageTexture::set_size_override); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("fix_alpha_edges"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("premultiply_alpha"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("normal_to_xy"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::set_method_flags(get_type_static(),_SCS("shrink_x2_and_keep_size"),METHOD_FLAGS_DEFAULT|METHOD_FLAG_EDITOR); ObjectTypeDB::bind_method(_MD("_reload_hook","rid"),&ImageTexture::_reload_hook); BIND_CONSTANT( STORAGE_RAW ); BIND_CONSTANT( STORAGE_COMPRESS_LOSSY ); BIND_CONSTANT( STORAGE_COMPRESS_LOSSLESS ); } ImageTexture::ImageTexture() { w=h=0; flags=FLAGS_DEFAULT; texture = VisualServer::get_singleton()->texture_create(); storage = STORAGE_RAW; lossy_storage_quality=0.7; } ImageTexture::~ImageTexture() { VisualServer::get_singleton()->free( texture ); } ////////////////////////////////////////// int AtlasTexture::get_width() const { if (region.size.width==0) { if (atlas.is_valid()) return atlas->get_width(); return 1; } else { return region.size.width+margin.size.width; } } int AtlasTexture::get_height() const { if (region.size.height==0) { if (atlas.is_valid()) return atlas->get_height(); return 1; } else { return region.size.height+margin.size.height; } } RID AtlasTexture::get_rid() const { if (atlas.is_valid()) return atlas->get_rid(); return RID(); } bool AtlasTexture::has_alpha() const { if (atlas.is_valid()) return atlas->has_alpha(); return false; } void AtlasTexture::set_flags(uint32_t p_flags) { if (atlas.is_valid()) atlas->set_flags(p_flags); } uint32_t AtlasTexture::get_flags() const{ if (atlas.is_valid()) return atlas->get_flags(); return 0; } void AtlasTexture::set_atlas(const Ref& p_atlas){ if (atlas==p_atlas) return; atlas=p_atlas; emit_changed(); emit_signal("atlas_changed"); } Ref AtlasTexture::get_atlas() const{ return atlas; } void AtlasTexture::set_region(const Rect2& p_region) { region=p_region; emit_changed(); } Rect2 AtlasTexture::get_region() const { return region; } void AtlasTexture::set_margin(const Rect2& p_margin) { margin=p_margin; emit_changed(); } Rect2 AtlasTexture::get_margin() const { return margin; } void AtlasTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_atlas","atlas:Texture"),&AtlasTexture::set_atlas); ObjectTypeDB::bind_method(_MD("get_atlas:Texture"),&AtlasTexture::get_atlas); ObjectTypeDB::bind_method(_MD("set_region","region"),&AtlasTexture::set_region); ObjectTypeDB::bind_method(_MD("get_region"),&AtlasTexture::get_region); ObjectTypeDB::bind_method(_MD("set_margin","margin"),&AtlasTexture::set_margin); ObjectTypeDB::bind_method(_MD("get_margin"),&AtlasTexture::get_margin); ADD_SIGNAL(MethodInfo("atlas_changed")); ADD_PROPERTY( PropertyInfo( Variant::OBJECT, "atlas", PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_atlas"),_SCS("get_atlas") ); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "region"), _SCS("set_region"),_SCS("get_region") ); ADD_PROPERTY( PropertyInfo( Variant::RECT2, "margin"), _SCS("set_margin"),_SCS("get_margin") ); } void AtlasTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { Rect2 rc=region; if (!atlas.is_valid()) return; if (rc.size.width==0) { rc.size.width=atlas->get_width(); } if (rc.size.height==0) { rc.size.height=atlas->get_height(); } 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); } void AtlasTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { Rect2 rc=region; if (!atlas.is_valid()) return; if (rc.size.width==0) { rc.size.width=atlas->get_width(); } if (rc.size.height==0) { rc.size.height=atlas->get_height(); } Vector2 scale = p_rect.size / (region.size+margin.size); Rect2 dr( p_rect.pos+margin.pos*scale,rc.size*scale ); VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),rc,p_modulate,p_transpose); } 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 { //this might not necesarily work well if using a rect, needs to be fixed properly Rect2 rc=region; if (!atlas.is_valid()) return; Rect2 src=p_src_rect; src.pos+=(rc.pos-margin.pos); Rect2 src_c = rc.clip(src); if (src_c.size==Size2()) return; Vector2 ofs = (src_c.pos-src.pos); Vector2 scale = p_rect.size / p_src_rect.size; if(scale.x < 0) { float mx = (margin.size.width - margin.pos.x); mx -= margin.pos.x; ofs.x = -(ofs.x + mx); } if(scale.y < 0) { float my = margin.size.height - margin.pos.y; my -= margin.pos.y; ofs.y = -(ofs.y + my); } Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale ); VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item,dr,atlas->get_rid(),src_c,p_modulate,p_transpose); } bool AtlasTexture::get_rect_region(const Rect2& p_rect, const Rect2& p_src_rect,Rect2& r_rect,Rect2& r_src_rect) const { Rect2 rc=region; if (!atlas.is_valid()) return false; Rect2 src=p_src_rect; src.pos+=(rc.pos-margin.pos); Rect2 src_c = rc.clip(src); if (src_c.size==Size2()) return false; Vector2 ofs = (src_c.pos-src.pos); Vector2 scale = p_rect.size / p_src_rect.size; if(scale.x < 0) { float mx = (margin.size.width - margin.pos.x); mx -= margin.pos.x; ofs.x = -(ofs.x + mx); } if(scale.y < 0) { float my = margin.size.height - margin.pos.y; my -= margin.pos.y; ofs.y = -(ofs.y + my); } Rect2 dr( p_rect.pos+ofs*scale,src_c.size*scale ); r_rect=dr; r_src_rect=src_c; return true; } AtlasTexture::AtlasTexture() { } ////////////////////////////////////////// int LargeTexture::get_width() const { return size.width; } int LargeTexture::get_height() const { return size.height; } RID LargeTexture::get_rid() const { return RID(); } bool LargeTexture::has_alpha() const { for(int i=0;ihas_alpha()) return true; } return false; } void LargeTexture::set_flags(uint32_t p_flags) { for(int i=0;iset_flags(p_flags); } } uint32_t LargeTexture::get_flags() const{ if (pieces.size()) return pieces[0].texture->get_flags(); return 0; } int LargeTexture::add_piece(const Point2& p_offset,const Ref& p_texture) { ERR_FAIL_COND_V(p_texture.is_null(), -1); Piece p; p.offset=p_offset; p.texture=p_texture; pieces.push_back(p); return pieces.size() - 1; } void LargeTexture::set_piece_offset(int p_idx, const Point2& p_offset) { ERR_FAIL_INDEX(p_idx, pieces.size()); pieces[p_idx].offset = p_offset; }; void LargeTexture::set_piece_texture(int p_idx, const Ref& p_texture) { ERR_FAIL_INDEX(p_idx, pieces.size()); pieces[p_idx].texture = p_texture; }; void LargeTexture::set_size(const Size2& p_size){ size=p_size; } void LargeTexture::clear(){ pieces.clear(); size=Size2i(); } Array LargeTexture::_get_data() const { Array arr; for(int i=0;i LargeTexture::get_piece_texture(int p_idx) const{ ERR_FAIL_INDEX_V(p_idx,pieces.size(),Ref()); return pieces[p_idx].texture; } void LargeTexture::_bind_methods() { ObjectTypeDB::bind_method(_MD("add_piece","ofs","texture:Texture"),&LargeTexture::add_piece); ObjectTypeDB::bind_method(_MD("set_piece_offset", "idx", "ofs"),&LargeTexture::set_piece_offset); ObjectTypeDB::bind_method(_MD("set_piece_texture","idx", "texture:Texture"),&LargeTexture::set_piece_texture); ObjectTypeDB::bind_method(_MD("set_size","size"),&LargeTexture::set_size); ObjectTypeDB::bind_method(_MD("clear"),&LargeTexture::clear); ObjectTypeDB::bind_method(_MD("get_piece_count"),&LargeTexture::get_piece_count); ObjectTypeDB::bind_method(_MD("get_piece_offset","idx"),&LargeTexture::get_piece_offset); ObjectTypeDB::bind_method(_MD("get_piece_texture:Texture","idx"),&LargeTexture::get_piece_texture); ObjectTypeDB::bind_method(_MD("_set_data","data"),&LargeTexture::_set_data); ObjectTypeDB::bind_method(_MD("_get_data"),&LargeTexture::_get_data); ADD_PROPERTY( PropertyInfo( Variant::ARRAY, "_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data") ); } void LargeTexture::draw(RID p_canvas_item, const Point2& p_pos, const Color& p_modulate, bool p_transpose) const { for(int i=0;idraw(p_canvas_item,pieces[i].offset+p_pos,p_modulate,p_transpose); } } void LargeTexture::draw_rect(RID p_canvas_item,const Rect2& p_rect, bool p_tile,const Color& p_modulate, bool p_transpose) const { //tiling not supported for this if (size.x==0 || size.y==0) return; Size2 scale = p_rect.size/size; for(int i=0;idraw_rect(p_canvas_item,Rect2(pieces[i].offset*scale+p_rect.pos,pieces[i].texture->get_size()*scale),false,p_modulate,p_transpose); } } 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 { //tiling not supported for this if (p_src_rect.size.x==0 || p_src_rect.size.y==0) return; Size2 scale = p_rect.size/p_src_rect.size; for(int i=0;iget_size()); if (!p_src_rect.intersects(rect)) continue; Rect2 local = p_src_rect.clip(rect); Rect2 target = local; target.size*=scale; target.pos=p_rect.pos+(p_src_rect.pos+rect.pos)*scale; local.pos-=rect.pos; pieces[i].texture->draw_rect_region(p_canvas_item,target,local,p_modulate,p_transpose); } } LargeTexture::LargeTexture() { } /////////////////////////////////////////////// void CubeMap::set_flags(uint32_t p_flags) { flags=p_flags; if (_is_valid()) VS::get_singleton()->texture_set_flags(cubemap,flags|VS::TEXTURE_FLAG_CUBEMAP); } uint32_t CubeMap::get_flags() const { return flags; } void CubeMap::set_side(Side p_side,const Image& p_image) { ERR_FAIL_COND(p_image.empty()); ERR_FAIL_INDEX(p_side,6); if (!_is_valid()) { format = p_image.get_format(); w=p_image.get_width(); h=p_image.get_height(); VS::get_singleton()->texture_allocate(cubemap,w,h,p_image.get_format(),flags|VS::TEXTURE_FLAG_CUBEMAP); } VS::get_singleton()->texture_set_data(cubemap,p_image,VS::CubeMapSide(p_side)); valid[p_side]=true; } Image CubeMap::get_side(Side p_side) const { if (!valid[p_side]) return Image(); return VS::get_singleton()->texture_get_data(cubemap,VS::CubeMapSide(p_side)); } Image::Format CubeMap::get_format() const { return format; } int CubeMap::get_width() const { return w; } int CubeMap::get_height() const { return h; } RID CubeMap::get_rid() const { return cubemap; } void CubeMap::set_storage(Storage p_storage) { storage=p_storage; } CubeMap::Storage CubeMap::get_storage() const { return storage; } void CubeMap::set_lossy_storage_quality(float p_lossy_storage_quality) { lossy_storage_quality=p_lossy_storage_quality; } float CubeMap::get_lossy_storage_quality() const { return lossy_storage_quality; } void CubeMap::set_path(const String& p_path,bool p_take_over) { if (cubemap.is_valid()) { VisualServer::get_singleton()->texture_set_path(cubemap,p_path); } Resource::set_path(p_path,p_take_over); } bool CubeMap::_set(const StringName& p_name, const Variant& p_value) { if (p_name=="side/left") { set_side(SIDE_LEFT,p_value); } else if (p_name=="side/right") { set_side(SIDE_RIGHT,p_value); } else if (p_name=="side/bottom") { set_side(SIDE_BOTTOM,p_value); } else if (p_name=="side/top") { set_side(SIDE_TOP,p_value); } else if (p_name=="side/front") { set_side(SIDE_FRONT,p_value); } else if (p_name=="side/back") { set_side(SIDE_BACK,p_value); } else if (p_name=="flags") { set_flags(p_value); } else if (p_name=="storage") { storage=Storage(p_value.operator int()); } else if (p_name=="lossy_quality") { lossy_storage_quality=p_value; } else return false; return true; } bool CubeMap::_get(const StringName& p_name,Variant &r_ret) const { if (p_name=="side/left") { r_ret=get_side(SIDE_LEFT); } else if (p_name=="side/right") { r_ret=get_side(SIDE_RIGHT); } else if (p_name=="side/bottom") { r_ret=get_side(SIDE_BOTTOM); } else if (p_name=="side/top") { r_ret=get_side(SIDE_TOP); } else if (p_name=="side/front") { r_ret=get_side(SIDE_FRONT); } else if (p_name=="side/back") { r_ret=get_side(SIDE_BACK); } else if (p_name=="flags") { r_ret= flags; } else if (p_name=="storage") { r_ret= storage; } else if (p_name=="lossy_quality") { r_ret= lossy_storage_quality; } else return false; return true; } void CubeMap::_get_property_list( List *p_list) const { PropertyHint img_hint=PROPERTY_HINT_NONE; if (storage==STORAGE_COMPRESS_LOSSY) { img_hint=PROPERTY_HINT_IMAGE_COMPRESS_LOSSY; } else if (storage==STORAGE_COMPRESS_LOSSLESS) { img_hint=PROPERTY_HINT_IMAGE_COMPRESS_LOSSLESS; } p_list->push_back( PropertyInfo( Variant::INT, "flags", PROPERTY_HINT_FLAGS,"Mipmaps,Repeat,Filter" ) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/left", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/right", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/bottom", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/top", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/front", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::IMAGE, "side/back", img_hint,String::num(lossy_storage_quality)) ); p_list->push_back( PropertyInfo( Variant::INT, "storage", PROPERTY_HINT_ENUM,"Uncompressed,Compress Lossy,Compress Lossless",PROPERTY_USAGE_EDITOR)); p_list->push_back( PropertyInfo( Variant::REAL, "lossy_quality", PROPERTY_HINT_RANGE,"0.0,1.0,0.01" ) ); } void CubeMap::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_width"),&CubeMap::get_width); ObjectTypeDB::bind_method(_MD("get_height"),&CubeMap::get_height); ObjectTypeDB::bind_method(_MD("get_rid"),&CubeMap::get_rid); ObjectTypeDB::bind_method(_MD("set_flags","flags"),&CubeMap::set_flags); ObjectTypeDB::bind_method(_MD("get_flags"),&CubeMap::get_flags); ObjectTypeDB::bind_method(_MD("set_side","side","image"),&CubeMap::set_side); ObjectTypeDB::bind_method(_MD("get_side","side"),&CubeMap::get_side); ObjectTypeDB::bind_method(_MD("set_storage","mode"),&CubeMap::set_storage); ObjectTypeDB::bind_method(_MD("get_storage"),&CubeMap::get_storage); ObjectTypeDB::bind_method(_MD("set_lossy_storage_quality","quality"),&CubeMap::set_lossy_storage_quality); ObjectTypeDB::bind_method(_MD("get_lossy_storage_quality"),&CubeMap::get_lossy_storage_quality); BIND_CONSTANT( STORAGE_RAW ); BIND_CONSTANT( STORAGE_COMPRESS_LOSSY ); BIND_CONSTANT( STORAGE_COMPRESS_LOSSLESS ); BIND_CONSTANT( SIDE_LEFT ); BIND_CONSTANT( SIDE_RIGHT ); BIND_CONSTANT( SIDE_BOTTOM ); BIND_CONSTANT( SIDE_TOP ); BIND_CONSTANT( SIDE_FRONT ); BIND_CONSTANT( SIDE_BACK ); BIND_CONSTANT( FLAG_MIPMAPS ); BIND_CONSTANT( FLAG_REPEAT ); BIND_CONSTANT( FLAG_FILTER ); BIND_CONSTANT( FLAGS_DEFAULT ); } CubeMap::CubeMap() { w=h=0; flags=FLAGS_DEFAULT; for(int i=0;i<6;i++) valid[i]=false; cubemap = VisualServer::get_singleton()->texture_create(); storage = STORAGE_RAW; lossy_storage_quality=0.7; } CubeMap::~CubeMap() { VisualServer::get_singleton()->free( cubemap ); } /* BIND_CONSTANT( FLAG_CUBEMAP ); BIND_CONSTANT( CUBEMAP_LEFT ); BIND_CONSTANT( CUBEMAP_RIGHT ); BIND_CONSTANT( CUBEMAP_BOTTOM ); BIND_CONSTANT( CUBEMAP_TOP ); BIND_CONSTANT( CUBEMAP_FRONT ); BIND_CONSTANT( CUBEMAP_BACK ); */