1
0
Fork 0
godot/scene/resources/drawable_texture_2d.cpp

242 lines
9.6 KiB
C++

/**************************************************************************/
/* 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<Texture2D> &p_source, const Color &p_modulate, int p_mipmap, const Ref<Material> &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<AtlasTexture>(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<Texture2D> &p_sources, const TypedArray<DrawableTexture2D> &p_extra_targets, const Color &p_modulate, int p_mipmap, const Ref<Material> &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<AtlasTexture>(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<Image> DrawableTexture2D::get_image() const {
if (texture.is_valid()) {
return RS::get_singleton()->texture_2d_get(texture);
} else {
return Ref<Image>();
}
}
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<Material>()));
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<Material>()));
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);
}