mirror of https://github.com/godotengine/godot
242 lines
9.6 KiB
C++
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);
|
|
}
|