/**************************************************************************/ /* drawable_texture_2d.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* https://godotengine.org */ /**************************************************************************/ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ /* Copyright (c) 2007-2014 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 "drawable_texture_2d.h" DrawableTexture2D::DrawableTexture2D() { default_material = RS::get_singleton()->texture_drawable_get_default_material(); } DrawableTexture2D::~DrawableTexture2D() { if (texture.is_valid()) { ERR_FAIL_NULL(RenderingServer::get_singleton()); RenderingServer::get_singleton()->free_rid(texture); } } // Initialize Texture Resource with a call to rendering server. Overwrite existing. void DrawableTexture2D::_initialize() { if (texture.is_valid()) { RID new_texture = RS::get_singleton()->texture_drawable_create(width, height, (RS::TextureDrawableFormat)format, base_color, mipmaps); RS::get_singleton()->texture_replace(texture, new_texture); } else { texture = RS::get_singleton()->texture_drawable_create(width, height, (RS::TextureDrawableFormat)format, base_color, mipmaps); } } // Setup basic parameters on the Drawable Texture void DrawableTexture2D::setup(int p_width, int p_height, DrawableFormat p_format, const Color &p_color, bool p_use_mipmaps) { ERR_FAIL_COND_MSG(p_width <= 0 || p_width > 16384, "Texture dimensions have to be in the 1 to 16384 range."); ERR_FAIL_COND_MSG(p_height <= 0 || p_height > 16384, "Texture dimensions have to be in the 1 to 16384 range."); width = p_width; height = p_height; format = p_format; mipmaps = p_use_mipmaps; base_color = p_color; _initialize(); notify_property_list_changed(); emit_changed(); } void DrawableTexture2D::set_width(int p_width) { ERR_FAIL_COND_MSG(p_width <= 0 || p_width > 16384, "Texture dimensions have to be in the 1 to 16384 range."); if (width == p_width) { return; } width = p_width; notify_property_list_changed(); emit_changed(); } int DrawableTexture2D::get_width() const { return width; } void DrawableTexture2D::set_height(int p_height) { ERR_FAIL_COND_MSG(p_height <= 0 || p_height > 16384, "Texture dimensions have to be in the 1 to 16384 range."); if (height == p_height) { return; } height = p_height; notify_property_list_changed(); emit_changed(); } int DrawableTexture2D::get_height() const { return height; } void DrawableTexture2D::set_format(DrawableFormat p_format) { if (format == p_format) { return; } format = p_format; notify_property_list_changed(); emit_changed(); } DrawableTexture2D::DrawableFormat DrawableTexture2D::get_format() const { return format; } void DrawableTexture2D::set_use_mipmaps(bool p_mipmaps) { if (mipmaps == p_mipmaps) { return; } mipmaps = p_mipmaps; notify_property_list_changed(); emit_changed(); } bool DrawableTexture2D::get_use_mipmaps() const { return mipmaps; } RID DrawableTexture2D::get_rid() const { if (texture.is_null()) { // We are in trouble, create something temporary. // 4, 4, false, Image::FORMAT_RGBA8 texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); } return texture; } void DrawableTexture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose) const { if ((width | height) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(width, height)), texture, false, p_modulate, p_transpose); } void DrawableTexture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose) const { if ((width | height) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose); } void DrawableTexture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) const { if ((width | height) == 0) { return; } RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, p_clip_uv); } // Perform a blit operation from the given source to the given rect on self. void DrawableTexture2D::blit_rect(const Rect2i p_rect, const Ref &p_source, const Color &p_modulate, int p_mipmap, const Ref &p_material) { // Use user Shader if exists. RID material = default_material; if (p_material.is_valid()) { material = p_material->get_rid(); if (p_material->get_shader_mode() != Shader::MODE_TEXTURE_BLIT) { WARN_PRINT("ShaderMaterial passed to blit_rect() is not a texture_blit shader. Using default instead."); } } // Rendering server expects textureParameters as a TypedArray[RID] Array textures; textures.push_back(texture); if (p_source.is_valid()) { ERR_FAIL_COND_MSG(texture == p_source->get_rid(), "Cannot use self as a source."); } Array src_textures; if (Ref(p_source).is_valid()) { WARN_PRINT("AtlasTexture not supported as a source for blit_rect. Using default White."); src_textures.push_back(RID()); } else { src_textures.push_back(p_source); } RS::get_singleton()->texture_drawable_blit_rect(textures, p_rect, material, p_modulate, src_textures, p_mipmap); notify_property_list_changed(); } // Perform a blit operation from the given sources to the given rect on self and extra targets void DrawableTexture2D::blit_rect_multi(const Rect2i p_rect, const TypedArray &p_sources, const TypedArray &p_extra_targets, const Color &p_modulate, int p_mipmap, const Ref &p_material) { RID material = default_material; if (p_material.is_valid()) { material = p_material->get_rid(); if (p_material->get_shader_mode() != Shader::MODE_TEXTURE_BLIT) { WARN_PRINT("ShaderMaterial passed to blit_rect_multi() is not a texture_blit shader. Using default instead."); } } // Rendering server expects textureParameters as a TypedArray[RID] Array textures; textures.push_back(texture); int i = 0; while (i < p_extra_targets.size()) { textures.push_back(RID(p_extra_targets[i])); i += 1; } i = 0; Array src_textures; while (i < p_sources.size()) { if (Ref(p_sources[i]).is_valid()) { WARN_PRINT("AtlasTexture not supported as a source for blit_rect. Using default White."); src_textures.push_back(RID()); } else { src_textures.push_back(RID(p_sources[i])); } ERR_FAIL_COND_MSG(textures.has(RID(src_textures[i])), "Cannot use self as a source."); i += 1; } RS::get_singleton()->texture_drawable_blit_rect(textures, p_rect, material, p_modulate, src_textures, p_mipmap); notify_property_list_changed(); } Ref DrawableTexture2D::get_image() const { if (texture.is_valid()) { return RS::get_singleton()->texture_2d_get(texture); } else { return Ref(); } } void DrawableTexture2D::generate_mipmaps() { if (texture.is_valid()) { RS::get_singleton()->texture_drawable_generate_mipmaps(texture); } } void DrawableTexture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("setup", "width", "height", "format", "color", "use_mipmaps"), &DrawableTexture2D::setup, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("blit_rect", "rect", "source", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("blit_rect_multi", "rect", "sources", "extra_targets", "modulate", "mipmap", "material"), &DrawableTexture2D::blit_rect_multi, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0), DEFVAL(Ref())); ClassDB::bind_method(D_METHOD("generate_mipmaps"), &DrawableTexture2D::generate_mipmaps); BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBA8); BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBA8_SRGB); BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBAH); BIND_ENUM_CONSTANT(DRAWABLE_FORMAT_RGBAF); }