2017-03-05 15:47:28 +01:00
/*************************************************************************/
/* resource_importer_texture.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
2017-08-27 14:16:55 +02:00
/* https://godotengine.org */
2017-03-05 15:47:28 +01:00
/*************************************************************************/
2020-01-01 11:16:22 +01:00
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
2017-03-05 15:47:28 +01:00
/* */
/* 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. */
/*************************************************************************/
2018-01-05 00:50:27 +01:00
2017-02-03 04:08:50 +01:00
# include "resource_importer_texture.h"
2017-03-05 15:47:28 +01:00
2018-09-11 18:13:45 +02:00
# include "core/io/config_file.h"
# include "core/io/image_loader.h"
2019-09-27 04:16:44 +02:00
# include "core/version.h"
2017-03-05 14:21:25 +01:00
# include "editor/editor_file_system.h"
2017-09-13 09:13:23 +02:00
# include "editor/editor_node.h"
2019-06-11 20:43:37 +02:00
void ResourceImporterTexture : : _texture_reimport_roughness ( const Ref < StreamTexture > & p_tex , const String & p_normal_path , VS : : TextureDetectRoughnessChannel p_channel ) {
2017-02-06 04:38:39 +01:00
singleton - > mutex - > lock ( ) ;
StringName path = p_tex - > get_path ( ) ;
if ( ! singleton - > make_flags . has ( path ) ) {
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] = MakeInfo ( ) ;
2017-02-06 04:38:39 +01:00
}
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] . flags | = MAKE_ROUGHNESS_FLAG ;
singleton - > make_flags [ path ] . channel_for_roughness = p_channel ;
singleton - > make_flags [ path ] . normal_path_for_roughness = p_normal_path ;
2017-02-06 04:38:39 +01:00
singleton - > mutex - > unlock ( ) ;
}
2017-03-05 16:44:50 +01:00
void ResourceImporterTexture : : _texture_reimport_3d ( const Ref < StreamTexture > & p_tex ) {
2017-02-06 04:38:39 +01:00
singleton - > mutex - > lock ( ) ;
StringName path = p_tex - > get_path ( ) ;
if ( ! singleton - > make_flags . has ( path ) ) {
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] = MakeInfo ( ) ;
2017-02-06 04:38:39 +01:00
}
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] . flags | = MAKE_3D_FLAG ;
2017-02-06 04:38:39 +01:00
singleton - > mutex - > unlock ( ) ;
}
2017-06-17 02:47:28 +02:00
void ResourceImporterTexture : : _texture_reimport_normal ( const Ref < StreamTexture > & p_tex ) {
singleton - > mutex - > lock ( ) ;
StringName path = p_tex - > get_path ( ) ;
if ( ! singleton - > make_flags . has ( path ) ) {
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] = MakeInfo ( ) ;
2017-06-17 02:47:28 +02:00
}
2019-06-11 20:43:37 +02:00
singleton - > make_flags [ path ] . flags | = MAKE_NORMAL_FLAG ;
2017-06-17 02:47:28 +02:00
singleton - > mutex - > unlock ( ) ;
}
2017-02-06 04:38:39 +01:00
void ResourceImporterTexture : : update_imports ( ) {
if ( EditorFileSystem : : get_singleton ( ) - > is_scanning ( ) | | EditorFileSystem : : get_singleton ( ) - > is_importing ( ) ) {
2019-05-19 12:34:40 +02:00
return ; // do nothing for now
2017-02-06 04:38:39 +01:00
}
mutex - > lock ( ) ;
if ( make_flags . empty ( ) ) {
mutex - > unlock ( ) ;
return ;
}
Vector < String > to_reimport ;
2019-06-11 20:43:37 +02:00
for ( Map < StringName , MakeInfo > : : Element * E = make_flags . front ( ) ; E ; E = E - > next ( ) ) {
2017-02-06 04:38:39 +01:00
Ref < ConfigFile > cf ;
cf . instance ( ) ;
2017-03-05 16:44:50 +01:00
String src_path = String ( E - > key ( ) ) + " .import " ;
2017-02-06 04:38:39 +01:00
Error err = cf - > load ( src_path ) ;
2017-03-05 16:44:50 +01:00
ERR_CONTINUE ( err ! = OK ) ;
2017-02-06 04:38:39 +01:00
2017-03-05 16:44:50 +01:00
bool changed = false ;
2019-06-11 20:43:37 +02:00
if ( E - > get ( ) . flags & MAKE_NORMAL_FLAG & & int ( cf - > get_value ( " params " , " compress/normal_map " ) ) = = 0 ) {
cf - > set_value ( " params " , " compress/normal_map " , 1 ) ;
2017-03-05 16:44:50 +01:00
changed = true ;
2017-02-06 04:38:39 +01:00
}
2019-06-11 20:43:37 +02:00
if ( E - > get ( ) . flags & MAKE_ROUGHNESS_FLAG & & int ( cf - > get_value ( " params " , " roughness/mode " ) ) = = 0 ) {
cf - > set_value ( " params " , " roughness/mode " , E - > get ( ) . channel_for_roughness + 2 ) ;
cf - > set_value ( " params " , " roughness/src_normal " , E - > get ( ) . normal_path_for_roughness ) ;
2017-06-17 02:47:28 +02:00
changed = true ;
}
2019-09-27 04:16:44 +02:00
if ( E - > get ( ) . flags & MAKE_3D_FLAG & & bool ( cf - > get_value ( " params " , " detect_3d/compress_to " ) ) ) {
int compress_to = cf - > get_value ( " params " , " detect_3d/compress_to " ) ;
cf - > set_value ( " params " , " detect_3d/compress_to " , 0 ) ;
if ( compress_to = = 1 ) {
cf - > set_value ( " params " , " compress/mode " , COMPRESS_VRAM_COMPRESSED ) ;
} else if ( compress_to = = 2 ) {
cf - > set_value ( " params " , " compress/mode " , COMPRESS_BASIS_UNIVERSAL ) ;
}
cf - > set_value ( " params " , " mipmaps/generate " , true ) ;
2017-03-05 16:44:50 +01:00
changed = true ;
2017-02-06 04:38:39 +01:00
}
if ( changed ) {
cf - > save ( src_path ) ;
to_reimport . push_back ( E - > key ( ) ) ;
}
}
make_flags . clear ( ) ;
mutex - > unlock ( ) ;
if ( to_reimport . size ( ) ) {
EditorFileSystem : : get_singleton ( ) - > reimport_files ( to_reimport ) ;
}
}
2017-02-01 13:45:45 +01:00
String ResourceImporterTexture : : get_importer_name ( ) const {
return " texture " ;
}
2017-03-05 16:44:50 +01:00
String ResourceImporterTexture : : get_visible_name ( ) const {
2017-02-01 13:45:45 +01:00
2019-06-11 20:43:37 +02:00
return " Texture2D " ;
2017-02-01 13:45:45 +01:00
}
2017-03-05 16:44:50 +01:00
void ResourceImporterTexture : : get_recognized_extensions ( List < String > * p_extensions ) const {
2017-02-01 13:45:45 +01:00
ImageLoader : : get_recognized_extensions ( p_extensions ) ;
}
String ResourceImporterTexture : : get_save_extension ( ) const {
return " stex " ;
}
2017-03-05 16:44:50 +01:00
String ResourceImporterTexture : : get_resource_type ( ) const {
2017-02-01 13:45:45 +01:00
return " StreamTexture " ;
}
2017-03-05 16:44:50 +01:00
bool ResourceImporterTexture : : get_option_visibility ( const String & p_option , const Map < StringName , Variant > & p_options ) const {
2017-02-01 13:45:45 +01:00
2017-04-26 17:49:08 +02:00
if ( p_option = = " compress/lossy_quality " ) {
int compress_mode = int ( p_options [ " compress/mode " ] ) ;
2019-09-27 04:16:44 +02:00
if ( compress_mode ! = COMPRESS_LOSSY & & compress_mode ! = COMPRESS_VRAM_COMPRESSED ) {
2017-04-26 17:49:08 +02:00
return false ;
}
2018-08-27 18:47:13 +02:00
} else if ( p_option = = " compress/hdr_mode " ) {
2018-08-23 00:31:12 +02:00
int compress_mode = int ( p_options [ " compress/mode " ] ) ;
2019-09-27 04:16:44 +02:00
if ( compress_mode < COMPRESS_VRAM_COMPRESSED ) {
2018-08-23 00:31:12 +02:00
return false ;
}
2019-09-27 04:16:44 +02:00
} else if ( p_option = = " mipmaps/limit " ) {
return p_options [ " mipmaps/generate " ] ;
2018-08-28 05:05:04 +02:00
} else if ( p_option = = " compress/bptc_ldr " ) {
int compress_mode = int ( p_options [ " compress/mode " ] ) ;
2019-09-27 04:16:44 +02:00
if ( compress_mode < COMPRESS_VRAM_COMPRESSED ) {
2018-08-28 05:05:04 +02:00
return false ;
}
if ( ! ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_bptc " ) ) {
return false ;
}
2017-04-26 17:49:08 +02:00
}
2017-02-01 13:45:45 +01:00
return true ;
}
int ResourceImporterTexture : : get_preset_count ( ) const {
return 4 ;
}
String ResourceImporterTexture : : get_preset_name ( int p_idx ) const {
2017-03-05 16:44:50 +01:00
static const char * preset_names [ ] = {
2017-02-01 13:45:45 +01:00
" 2D, Detect 3D " ,
" 2D " ,
" 2D Pixel " ,
" 3D "
} ;
return preset_names [ p_idx ] ;
}
2017-03-05 16:44:50 +01:00
void ResourceImporterTexture : : get_import_options ( List < ImportOption > * r_options , int p_preset ) const {
2019-09-27 04:16:44 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/mode " , PROPERTY_HINT_ENUM , " Lossless,Lossy,VRAM Compressed,VRAM Uncompressed,Basis Universal " , PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED ) , p_preset = = PRESET_3D ? 2 : 0 ) ) ;
2017-03-05 16:44:50 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : REAL , " compress/lossy_quality " , PROPERTY_HINT_RANGE , " 0,1,0.01 " ) , 0.7 ) ) ;
2018-08-27 18:47:13 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/hdr_mode " , PROPERTY_HINT_ENUM , " Enabled,Force RGBE " ) , 0 ) ) ;
2018-08-28 05:05:04 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/bptc_ldr " , PROPERTY_HINT_ENUM , " Enabled,RGBA Only " ) , 0 ) ) ;
2017-06-17 02:47:28 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/normal_map " , PROPERTY_HINT_ENUM , " Detect,Enable,Disabled " ) , 0 ) ) ;
2019-06-11 20:43:37 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/channel_pack " , PROPERTY_HINT_ENUM , " sRGB Friendly,Optimized " ) , 0 ) ) ;
2019-09-27 04:16:44 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " compress/streamed " ) , false ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " mipmaps/generate " ) , ( p_preset = = PRESET_3D ? true : false ) ) ) ;
2019-09-27 14:05:22 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " mipmaps/limit " , PROPERTY_HINT_RANGE , " -1,256 " ) , - 1 ) ) ;
2019-06-11 20:43:37 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " roughness/mode " , PROPERTY_HINT_ENUM , " Detect,Disabled,Red,Green,Blue,Alpha,Gray " ) , 0 ) ) ;
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : STRING , " roughness/src_normal " , PROPERTY_HINT_FILE , " *.png,*.jpg " ) , " " ) ) ;
2019-06-26 15:08:25 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " process/fix_alpha_border " ) , p_preset ! = PRESET_3D ) ) ;
2017-06-25 13:01:15 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " process/premult_alpha " ) , false ) ) ;
2018-08-17 18:28:07 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " process/invert_color " ) , false ) ) ;
2019-06-26 20:11:52 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : BOOL , " process/HDR_as_SRGB " ) , false ) ) ;
2019-09-14 05:37:42 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " process/size_limit " , PROPERTY_HINT_RANGE , " 0,4096,1 " ) , 0 ) ) ;
2019-09-27 14:05:22 +02:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : INT , " detect_3d/compress_to " , PROPERTY_HINT_ENUM , " Disabled,VRAM Compressed,Basis Universal " ) , ( p_preset = = PRESET_DETECT ) ? 1 : 0 ) ) ;
2018-11-21 19:06:38 +01:00
r_options - > push_back ( ImportOption ( PropertyInfo ( Variant : : REAL , " svg/scale " , PROPERTY_HINT_RANGE , " 0.001,100,0.001 " ) , 1.0 ) ) ;
2017-02-01 13:45:45 +01:00
}
2019-09-27 04:16:44 +02:00
void ResourceImporterTexture : : save_to_stex_format ( FileAccess * f , const Ref < Image > & p_image , CompressMode p_compress_mode , Image : : UsedChannels p_channels , Image : : CompressMode p_compress_format , float p_lossy_quality , bool p_force_rgbe ) {
2017-05-27 02:49:49 +02:00
2017-02-01 13:45:45 +01:00
switch ( p_compress_mode ) {
case COMPRESS_LOSSLESS : {
2019-09-27 04:16:44 +02:00
f - > store_32 ( StreamTexture : : DATA_FORMAT_LOSSLESS ) ;
f - > store_16 ( p_image - > get_width ( ) ) ;
f - > store_16 ( p_image - > get_height ( ) ) ;
f - > store_32 ( p_image - > get_mipmap_count ( ) ) ;
f - > store_32 ( p_image - > get_format ( ) ) ;
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
for ( int i = 0 ; i < p_image - > get_mipmap_count ( ) + 1 ; i + + ) {
2017-02-01 13:45:45 +01:00
2020-02-17 22:06:54 +01:00
Vector < uint8_t > data = Image : : lossless_packer ( p_image - > get_image_from_mipmap ( i ) ) ;
2017-02-01 13:45:45 +01:00
int data_len = data . size ( ) ;
f - > store_32 ( data_len ) ;
2020-02-17 22:06:54 +01:00
const uint8_t * r = data . ptr ( ) ;
f - > store_buffer ( r , data_len ) ;
2017-02-01 13:45:45 +01:00
}
} break ;
case COMPRESS_LOSSY : {
2019-09-27 04:16:44 +02:00
f - > store_32 ( StreamTexture : : DATA_FORMAT_LOSSY ) ;
f - > store_16 ( p_image - > get_width ( ) ) ;
f - > store_16 ( p_image - > get_height ( ) ) ;
f - > store_32 ( p_image - > get_mipmap_count ( ) ) ;
f - > store_32 ( p_image - > get_format ( ) ) ;
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
for ( int i = 0 ; i < p_image - > get_mipmap_count ( ) + 1 ; i + + ) {
2017-02-01 13:45:45 +01:00
2020-02-17 22:06:54 +01:00
Vector < uint8_t > data = Image : : lossy_packer ( p_image - > get_image_from_mipmap ( i ) , p_lossy_quality ) ;
2017-02-01 13:45:45 +01:00
int data_len = data . size ( ) ;
f - > store_32 ( data_len ) ;
2020-02-17 22:06:54 +01:00
const uint8_t * r = data . ptr ( ) ;
f - > store_buffer ( r , data_len ) ;
2017-02-01 13:45:45 +01:00
}
} break ;
2019-09-27 04:16:44 +02:00
case COMPRESS_VRAM_COMPRESSED : {
2017-02-01 13:45:45 +01:00
2017-05-17 12:36:47 +02:00
Ref < Image > image = p_image - > duplicate ( ) ;
2017-05-27 02:49:49 +02:00
2019-09-27 04:16:44 +02:00
if ( p_force_rgbe & & image - > get_format ( ) > = Image : : FORMAT_RF & & image - > get_format ( ) < Image : : FORMAT_RGBE9995 ) {
2017-05-27 02:49:49 +02:00
image - > convert ( Image : : FORMAT_RGBE9995 ) ;
} else {
2019-09-27 04:16:44 +02:00
image - > compress_from_channels ( p_compress_format , p_channels , p_lossy_quality ) ;
2017-05-27 02:49:49 +02:00
}
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
f - > store_32 ( StreamTexture : : DATA_FORMAT_IMAGE ) ;
f - > store_16 ( image - > get_width ( ) ) ;
f - > store_16 ( image - > get_height ( ) ) ;
f - > store_32 ( image - > get_mipmap_count ( ) ) ;
f - > store_32 ( image - > get_format ( ) ) ;
2017-02-01 13:45:45 +01:00
2020-02-17 22:06:54 +01:00
Vector < uint8_t > data = image - > get_data ( ) ;
2017-02-01 13:45:45 +01:00
int dl = data . size ( ) ;
2020-02-17 22:06:54 +01:00
const uint8_t * r = data . ptr ( ) ;
f - > store_buffer ( r , dl ) ;
2017-02-01 13:45:45 +01:00
} break ;
2019-09-27 04:16:44 +02:00
case COMPRESS_VRAM_UNCOMPRESSED : {
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
f - > store_32 ( StreamTexture : : DATA_FORMAT_IMAGE ) ;
f - > store_16 ( p_image - > get_width ( ) ) ;
f - > store_16 ( p_image - > get_height ( ) ) ;
f - > store_32 ( p_image - > get_mipmap_count ( ) ) ;
f - > store_32 ( p_image - > get_format ( ) ) ;
2017-02-01 13:45:45 +01:00
2020-02-17 22:06:54 +01:00
Vector < uint8_t > data = p_image - > get_data ( ) ;
2017-02-01 13:45:45 +01:00
int dl = data . size ( ) ;
2020-02-17 22:06:54 +01:00
const uint8_t * r = data . ptr ( ) ;
2017-02-01 13:45:45 +01:00
2020-02-17 22:06:54 +01:00
f - > store_buffer ( r , dl ) ;
2017-02-01 13:45:45 +01:00
} break ;
2019-09-27 04:16:44 +02:00
case COMPRESS_BASIS_UNIVERSAL : {
f - > store_32 ( StreamTexture : : DATA_FORMAT_BASIS_UNIVERSAL ) ;
f - > store_16 ( p_image - > get_width ( ) ) ;
f - > store_16 ( p_image - > get_height ( ) ) ;
f - > store_32 ( p_image - > get_mipmap_count ( ) ) ;
f - > store_32 ( p_image - > get_format ( ) ) ;
for ( int i = 0 ; i < p_image - > get_mipmap_count ( ) + 1 ; i + + ) {
2020-02-17 22:06:54 +01:00
Vector < uint8_t > data = Image : : basis_universal_packer ( p_image - > get_image_from_mipmap ( i ) , p_channels ) ;
2019-09-27 04:16:44 +02:00
int data_len = data . size ( ) ;
f - > store_32 ( data_len ) ;
2020-02-17 22:06:54 +01:00
const uint8_t * r = data . ptr ( ) ;
f - > store_buffer ( r , data_len ) ;
2019-09-27 04:16:44 +02:00
}
} break ;
2017-02-01 13:45:45 +01:00
}
2019-09-27 04:16:44 +02:00
}
2020-01-27 00:09:40 +01:00
void ResourceImporterTexture : : _save_stex ( const Ref < Image > & p_image , const String & p_to_path , CompressMode p_compress_mode , float p_lossy_quality , Image : : CompressMode p_vram_compression , bool p_mipmaps , bool p_streamable , bool p_detect_3d , bool p_detect_roughness , bool p_force_rgbe , bool p_detect_normal , bool p_force_normal , bool p_srgb_friendly , bool p_force_po2_for_compressed , uint32_t p_limit_mipmap , const Ref < Image > & p_normal , Image : : RoughnessChannel p_roughness_channel ) {
2019-09-27 04:16:44 +02:00
FileAccess * f = FileAccess : : open ( p_to_path , FileAccess : : WRITE ) ;
f - > store_8 ( ' G ' ) ;
f - > store_8 ( ' S ' ) ;
f - > store_8 ( ' T ' ) ;
f - > store_8 ( ' 2 ' ) ; //godot streamable texture 2D
//format version
f - > store_32 ( StreamTexture : : FORMAT_VERSION ) ;
//texture may be resized later, so original size must be saved first
f - > store_32 ( p_image - > get_width ( ) ) ;
f - > store_32 ( p_image - > get_height ( ) ) ;
uint32_t flags = 0 ;
if ( p_streamable )
flags | = StreamTexture : : FORMAT_BIT_STREAM ;
if ( p_mipmaps )
flags | = StreamTexture : : FORMAT_BIT_HAS_MIPMAPS ; //mipmaps bit
if ( p_detect_3d )
flags | = StreamTexture : : FORMAT_BIT_DETECT_3D ;
if ( p_detect_roughness )
flags | = StreamTexture : : FORMAT_BIT_DETECT_ROUGNESS ;
if ( p_detect_normal )
flags | = StreamTexture : : FORMAT_BIT_DETECT_NORMAL ;
f - > store_32 ( flags ) ;
f - > store_32 ( p_limit_mipmap ) ;
//reserverd for future use
f - > store_32 ( 0 ) ;
f - > store_32 ( 0 ) ;
f - > store_32 ( 0 ) ;
/*
print_line ( " streamable " + itos ( p_streamable ) ) ;
print_line ( " mipmaps " + itos ( p_mipmaps ) ) ;
print_line ( " detect_3d " + itos ( p_detect_3d ) ) ;
print_line ( " roughness " + itos ( p_detect_roughness ) ) ;
print_line ( " normal " + itos ( p_detect_normal ) ) ;
*/
if ( ( p_compress_mode = = COMPRESS_LOSSLESS | | p_compress_mode = = COMPRESS_LOSSY ) & & p_image - > get_format ( ) > Image : : FORMAT_RGBA8 ) {
p_compress_mode = COMPRESS_VRAM_UNCOMPRESSED ; //these can't go as lossy
}
Ref < Image > image = p_image - > duplicate ( ) ;
if ( ( ( p_compress_mode = = COMPRESS_BASIS_UNIVERSAL ) | | ( p_compress_mode = = COMPRESS_VRAM_COMPRESSED & & p_force_po2_for_compressed ) ) & & p_mipmaps ) {
image - > resize_to_po2 ( ) ;
}
if ( p_mipmaps & & ( ! image - > has_mipmaps ( ) | | p_force_normal ) ) {
image - > generate_mipmaps ( p_force_normal ) ;
}
if ( ! p_mipmaps ) {
image - > clear_mipmaps ( ) ;
}
2020-01-27 00:09:40 +01:00
if ( image - > has_mipmaps ( ) & & p_normal . is_valid ( ) ) {
image - > generate_mipmap_roughness ( p_roughness_channel , p_normal ) ;
}
2019-09-27 04:16:44 +02:00
if ( p_force_rgbe & & image - > get_format ( ) > = Image : : FORMAT_RF & & image - > get_format ( ) < Image : : FORMAT_RGBE9995 ) {
image - > convert ( Image : : FORMAT_RGBE9995 ) ;
}
Image : : CompressSource csource = Image : : COMPRESS_SOURCE_GENERIC ;
if ( p_force_normal ) {
csource = Image : : COMPRESS_SOURCE_NORMAL ;
} else if ( p_srgb_friendly ) {
csource = Image : : COMPRESS_SOURCE_SRGB ;
}
Image : : UsedChannels used_channels = image - > detect_used_channels ( csource ) ;
save_to_stex_format ( f , image , p_compress_mode , used_channels , p_vram_compression , p_lossy_quality , p_force_rgbe ) ;
2017-02-01 13:45:45 +01:00
memdelete ( f ) ;
}
2019-02-26 22:43:37 +01:00
Error ResourceImporterTexture : : import ( const String & p_source_file , const String & p_save_path , const Map < StringName , Variant > & p_options , List < String > * r_platform_variants , List < String > * r_gen_files , Variant * r_metadata ) {
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
CompressMode compress_mode = CompressMode ( int ( p_options [ " compress/mode " ] ) ) ;
2017-03-05 16:44:50 +01:00
float lossy = p_options [ " compress/lossy_quality " ] ;
2019-06-11 20:43:37 +02:00
int pack_channels = p_options [ " compress/channel_pack " ] ;
2019-09-27 04:16:44 +02:00
bool mipmaps = p_options [ " mipmaps/generate " ] ;
uint32_t mipmap_limit = int ( mipmaps ? int ( p_options [ " mipmaps/limit " ] ) : int ( - 1 ) ) ;
2017-03-05 16:44:50 +01:00
bool fix_alpha_border = p_options [ " process/fix_alpha_border " ] ;
bool premult_alpha = p_options [ " process/premult_alpha " ] ;
2018-08-17 18:28:07 +02:00
bool invert_color = p_options [ " process/invert_color " ] ;
2019-09-27 04:16:44 +02:00
bool stream = p_options [ " compress/streamed " ] ;
2019-09-14 05:37:42 +02:00
int size_limit = p_options [ " process/size_limit " ] ;
2017-05-30 03:11:33 +02:00
bool hdr_as_srgb = p_options [ " process/HDR_as_SRGB " ] ;
2017-06-17 02:47:28 +02:00
int normal = p_options [ " compress/normal_map " ] ;
2017-08-31 18:52:07 +02:00
float scale = p_options [ " svg/scale " ] ;
2019-09-27 04:16:44 +02:00
bool force_rgbe = int ( p_options [ " compress/hdr_mode " ] ) = = 1 ;
2018-08-28 05:05:04 +02:00
int bptc_ldr = p_options [ " compress/bptc_ldr " ] ;
2019-06-11 20:43:37 +02:00
int roughness = p_options [ " roughness/mode " ] ;
2020-01-27 00:09:40 +01:00
String normal_map = p_options [ " roughness/src_normal " ] ;
Ref < Image > normal_image ;
Image : : RoughnessChannel roughness_channel ;
2017-02-01 13:45:45 +01:00
2020-01-27 00:09:40 +01:00
if ( mipmaps & & roughness > 1 & & FileAccess : : exists ( normal_map ) ) {
normal_image . instance ( ) ;
if ( ImageLoader : : load_image ( normal_map , normal_image ) = = OK ) {
roughness_channel = Image : : RoughnessChannel ( roughness - 2 ) ;
}
}
2017-05-17 12:36:47 +02:00
Ref < Image > image ;
image . instance ( ) ;
2017-08-19 04:21:24 +02:00
Error err = ImageLoader : : load_image ( p_source_file , image , NULL , hdr_as_srgb , scale ) ;
2017-03-05 16:44:50 +01:00
if ( err ! = OK )
2017-02-01 13:45:45 +01:00
return err ;
2019-02-26 22:43:37 +01:00
Array formats_imported ;
2017-05-17 12:36:47 +02:00
if ( size_limit > 0 & & ( image - > get_width ( ) > size_limit | | image - > get_height ( ) > size_limit ) ) {
2017-02-01 13:45:45 +01:00
//limit size
2017-05-17 12:36:47 +02:00
if ( image - > get_width ( ) > = image - > get_height ( ) ) {
2017-02-01 13:45:45 +01:00
int new_width = size_limit ;
2017-05-17 12:36:47 +02:00
int new_height = image - > get_height ( ) * new_width / image - > get_width ( ) ;
2017-02-01 13:45:45 +01:00
2017-05-17 12:36:47 +02:00
image - > resize ( new_width , new_height , Image : : INTERPOLATE_CUBIC ) ;
2017-02-01 13:45:45 +01:00
} else {
int new_height = size_limit ;
2017-05-17 12:36:47 +02:00
int new_width = image - > get_width ( ) * new_height / image - > get_height ( ) ;
2017-02-01 13:45:45 +01:00
2017-05-17 12:36:47 +02:00
image - > resize ( new_width , new_height , Image : : INTERPOLATE_CUBIC ) ;
2017-02-01 13:45:45 +01:00
}
2018-07-03 15:55:50 +02:00
2018-11-25 21:05:35 +01:00
if ( normal = = 1 ) {
2018-07-03 15:55:50 +02:00
image - > normalize ( ) ;
}
2017-02-01 13:45:45 +01:00
}
if ( fix_alpha_border ) {
2017-05-17 12:36:47 +02:00
image - > fix_alpha_edges ( ) ;
2017-02-01 13:45:45 +01:00
}
if ( premult_alpha ) {
2017-05-17 12:36:47 +02:00
image - > premultiply_alpha ( ) ;
2017-02-01 13:45:45 +01:00
}
2018-08-17 18:28:07 +02:00
if ( invert_color ) {
int height = image - > get_height ( ) ;
int width = image - > get_width ( ) ;
2018-09-02 15:13:19 +02:00
for ( int i = 0 ; i < width ; i + + ) {
for ( int j = 0 ; j < height ; j + + ) {
2018-08-17 18:28:07 +02:00
image - > set_pixel ( i , j , image - > get_pixel ( i , j ) . inverted ( ) ) ;
}
}
}
2019-09-27 04:16:44 +02:00
if ( compress_mode = = COMPRESS_BASIS_UNIVERSAL & & image - > get_format ( ) > = Image : : FORMAT_RF ) {
//basis universal does not support float formats, fall back
compress_mode = COMPRESS_VRAM_COMPRESSED ;
}
bool detect_3d = int ( p_options [ " detect_3d/compress_to " ] ) > 0 ;
2019-06-11 20:43:37 +02:00
bool detect_roughness = roughness = = 0 ;
2017-06-17 02:47:28 +02:00
bool detect_normal = normal = = 0 ;
bool force_normal = normal = = 1 ;
2019-06-11 20:43:37 +02:00
bool srgb_friendly_pack = pack_channels = = 0 ;
2017-02-01 13:45:45 +01:00
2019-09-27 04:16:44 +02:00
if ( compress_mode = = COMPRESS_VRAM_COMPRESSED ) {
2017-07-19 22:00:46 +02:00
//must import in all formats, in order of priority (so platform choses the best supported one. IE, etc2 over etc).
2017-02-01 13:45:45 +01:00
//Android, GLES 2.x
2017-09-06 01:17:26 +02:00
2017-09-13 09:13:23 +02:00
bool ok_on_pc = false ;
2018-08-28 05:05:04 +02:00
bool is_hdr = ( image - > get_format ( ) > = Image : : FORMAT_RF & & image - > get_format ( ) < = Image : : FORMAT_RGBE9995 ) ;
2019-09-27 04:16:44 +02:00
bool is_ldr = ( image - > get_format ( ) > = Image : : FORMAT_L8 & & image - > get_format ( ) < = Image : : FORMAT_RGB565 ) ;
2018-08-28 05:05:04 +02:00
bool can_bptc = ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_bptc " ) ;
bool can_s3tc = ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_s3tc " ) ;
2017-09-06 01:17:26 +02:00
2018-08-27 18:47:13 +02:00
if ( can_bptc ) {
2019-09-27 04:16:44 +02:00
Image : : UsedChannels channels = image - > detect_used_channels ( ) ;
2018-08-28 05:05:04 +02:00
if ( is_hdr ) {
2019-09-27 04:16:44 +02:00
if ( channels = = Image : : USED_CHANNELS_LA | | channels = = Image : : USED_CHANNELS_RGBA ) {
2018-08-28 05:05:04 +02:00
can_bptc = false ;
}
} else if ( is_ldr ) {
//handle "RGBA Only" setting
2019-09-27 04:16:44 +02:00
if ( bptc_ldr = = 1 & & channels ! = Image : : USED_CHANNELS_LA & & channels ! = Image : : USED_CHANNELS_RGBA ) {
2018-08-28 05:05:04 +02:00
can_bptc = false ;
}
2018-08-22 04:56:04 +02:00
}
2019-02-26 22:43:37 +01:00
formats_imported . push_back ( " bptc " ) ;
2018-08-22 04:56:04 +02:00
}
2018-08-28 05:05:04 +02:00
if ( ! can_bptc & & is_hdr & & ! force_rgbe ) {
//convert to ldr if this can't be stored hdr
image - > convert ( Image : : FORMAT_RGBA8 ) ;
}
2018-08-22 04:56:04 +02:00
2018-08-28 05:05:04 +02:00
if ( can_bptc | | can_s3tc ) {
2020-01-27 00:09:40 +01:00
_save_stex ( image , p_save_path + " .s3tc.stex " , compress_mode , lossy , can_bptc ? Image : : COMPRESS_BPTC : Image : : COMPRESS_S3TC , mipmaps , stream , detect_3d , detect_roughness , force_rgbe , detect_normal , force_normal , srgb_friendly_pack , false , mipmap_limit , normal_image , roughness_channel ) ;
2017-06-17 02:47:28 +02:00
r_platform_variants - > push_back ( " s3tc " ) ;
2019-02-26 22:43:37 +01:00
formats_imported . push_back ( " s3tc " ) ;
2017-09-13 09:13:23 +02:00
ok_on_pc = true ;
2017-06-17 02:47:28 +02:00
}
2018-08-27 18:47:13 +02:00
if ( ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_etc2 " ) ) {
2017-06-17 02:47:28 +02:00
2020-01-27 00:09:40 +01:00
_save_stex ( image , p_save_path + " .etc2.stex " , compress_mode , lossy , Image : : COMPRESS_ETC2 , mipmaps , stream , detect_3d , detect_roughness , force_rgbe , detect_normal , force_normal , srgb_friendly_pack , true , mipmap_limit , normal_image , roughness_channel ) ;
2017-06-17 02:47:28 +02:00
r_platform_variants - > push_back ( " etc2 " ) ;
2019-02-26 22:43:37 +01:00
formats_imported . push_back ( " etc2 " ) ;
2017-06-17 02:47:28 +02:00
}
2018-08-27 18:47:13 +02:00
if ( ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_etc " ) ) {
2020-01-27 00:09:40 +01:00
_save_stex ( image , p_save_path + " .etc.stex " , compress_mode , lossy , Image : : COMPRESS_ETC , mipmaps , stream , detect_3d , detect_roughness , force_rgbe , detect_normal , force_normal , srgb_friendly_pack , true , mipmap_limit , normal_image , roughness_channel ) ;
2017-07-19 22:00:46 +02:00
r_platform_variants - > push_back ( " etc " ) ;
2019-02-26 22:43:37 +01:00
formats_imported . push_back ( " etc " ) ;
2017-07-19 22:00:46 +02:00
}
2018-08-27 18:47:13 +02:00
if ( ProjectSettings : : get_singleton ( ) - > get ( " rendering/vram_compression/import_pvrtc " ) ) {
2017-06-17 02:47:28 +02:00
2020-01-27 00:09:40 +01:00
_save_stex ( image , p_save_path + " .pvrtc.stex " , compress_mode , lossy , Image : : COMPRESS_PVRTC4 , mipmaps , stream , detect_3d , detect_roughness , force_rgbe , detect_normal , force_normal , srgb_friendly_pack , true , mipmap_limit , normal_image , roughness_channel ) ;
2017-06-17 02:47:28 +02:00
r_platform_variants - > push_back ( " pvrtc " ) ;
2019-02-26 22:43:37 +01:00
formats_imported . push_back ( " pvrtc " ) ;
2017-06-17 02:47:28 +02:00
}
2017-02-01 13:45:45 +01:00
2017-09-06 01:17:26 +02:00
if ( ! ok_on_pc ) {
2018-09-13 03:38:39 +02:00
EditorNode : : add_io_error ( " Warning, no suitable PC VRAM compression enabled in Project Settings. This texture will not display correctly on PC. " ) ;
2017-09-06 01:17:26 +02:00
}
2017-02-01 13:45:45 +01:00
} else {
//import normally
2020-01-27 00:09:40 +01:00
_save_stex ( image , p_save_path + " .stex " , compress_mode , lossy , Image : : COMPRESS_S3TC /*this is ignored */ , mipmaps , stream , detect_3d , detect_roughness , force_rgbe , detect_normal , force_normal , srgb_friendly_pack , false , mipmap_limit , normal_image , roughness_channel ) ;
2017-02-01 13:45:45 +01:00
}
2019-02-26 22:43:37 +01:00
if ( r_metadata ) {
Dictionary metadata ;
2019-09-27 04:16:44 +02:00
metadata [ " vram_texture " ] = compress_mode = = COMPRESS_VRAM_COMPRESSED ;
2019-02-26 22:43:37 +01:00
if ( formats_imported . size ( ) ) {
metadata [ " imported_formats " ] = formats_imported ;
}
* r_metadata = metadata ;
}
2017-02-01 13:45:45 +01:00
return OK ;
}
2019-02-26 22:43:37 +01:00
const char * ResourceImporterTexture : : compression_formats [ ] = {
" bptc " ,
" s3tc " ,
" etc " ,
" etc2 " ,
" pvrtc " ,
NULL
} ;
String ResourceImporterTexture : : get_import_settings_string ( ) const {
String s ;
int index = 0 ;
while ( compression_formats [ index ] ) {
String setting_path = " rendering/vram_compression/import_ " + String ( compression_formats [ index ] ) ;
bool test = ProjectSettings : : get_singleton ( ) - > get ( setting_path ) ;
if ( test ) {
s + = String ( compression_formats [ index ] ) ;
}
index + + ;
}
return s ;
}
bool ResourceImporterTexture : : are_import_settings_valid ( const String & p_path ) const {
//will become invalid if formats are missing to import
Dictionary metadata = ResourceFormatImporter : : get_singleton ( ) - > get_resource_metadata ( p_path ) ;
if ( ! metadata . has ( " vram_texture " ) ) {
return false ;
}
bool vram = metadata [ " vram_texture " ] ;
if ( ! vram ) {
return true ; //do not care about non vram
}
Vector < String > formats_imported ;
if ( metadata . has ( " imported_formats " ) ) {
formats_imported = metadata [ " imported_formats " ] ;
}
int index = 0 ;
bool valid = true ;
while ( compression_formats [ index ] ) {
String setting_path = " rendering/vram_compression/import_ " + String ( compression_formats [ index ] ) ;
bool test = ProjectSettings : : get_singleton ( ) - > get ( setting_path ) ;
if ( test ) {
if ( formats_imported . find ( compression_formats [ index ] ) = = - 1 ) {
valid = false ;
break ;
}
}
index + + ;
}
return valid ;
}
2017-03-05 16:44:50 +01:00
ResourceImporterTexture * ResourceImporterTexture : : singleton = NULL ;
2017-02-06 04:38:39 +01:00
2017-03-05 16:44:50 +01:00
ResourceImporterTexture : : ResourceImporterTexture ( ) {
2017-02-01 13:45:45 +01:00
2017-03-05 16:44:50 +01:00
singleton = this ;
StreamTexture : : request_3d_callback = _texture_reimport_3d ;
2019-06-11 20:43:37 +02:00
StreamTexture : : request_roughness_callback = _texture_reimport_roughness ;
2017-06-17 02:47:28 +02:00
StreamTexture : : request_normal_callback = _texture_reimport_normal ;
2017-02-06 04:38:39 +01:00
mutex = Mutex : : create ( ) ;
2017-02-01 13:45:45 +01:00
}
2017-02-06 04:38:39 +01:00
2017-03-05 16:44:50 +01:00
ResourceImporterTexture : : ~ ResourceImporterTexture ( ) {
2017-02-06 04:38:39 +01:00
memdelete ( mutex ) ;
}