diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 2 | ||||
-rw-r--r-- | scene/resources/material.cpp | 547 | ||||
-rw-r--r-- | scene/resources/material.h | 88 | ||||
-rw-r--r-- | scene/resources/mesh.cpp | 74 | ||||
-rw-r--r-- | scene/resources/mesh.h | 16 | ||||
-rw-r--r-- | scene/resources/shader.cpp | 19 | ||||
-rw-r--r-- | scene/resources/shader.h | 29 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 468 | ||||
-rw-r--r-- | scene/resources/texture.h | 141 | ||||
-rw-r--r-- | scene/resources/tile_set.cpp | 12 | ||||
-rw-r--r-- | scene/resources/tile_set.h | 6 |
11 files changed, 1198 insertions, 204 deletions
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 3f19c2eafc..50f535fde9 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -120,7 +120,7 @@ static Ref<Texture> make_icon(T p_src) { } static Ref<Shader> make_shader(const char *vertex_code, const char *fragment_code, const char *lighting_code) { - Ref<Shader> shader = (memnew(Shader(Shader::MODE_CANVAS_ITEM))); + Ref<Shader> shader = (memnew(Shader())); //shader->set_code(vertex_code, fragment_code, lighting_code); return shader; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 90be6374ea..407357ea67 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -44,14 +44,132 @@ Material::~Material() { VisualServer::get_singleton()->free(material); } +/////////////////////////////////// + +bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { + + if (p_name == SceneStringNames::get_singleton()->shader_shader) { + set_shader(p_value); + return true; + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (!pr) { + String n = p_name; + if (n.find("param/") == 0) { //backwards compatibility + pr = n.substr(6, n.length()); + } + } + if (pr) { + VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + return true; + } + } + } + + return false; +} + +bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { + + if (p_name == SceneStringNames::get_singleton()->shader_shader) { + + r_ret = get_shader(); + return true; + + } else { + + if (shader.is_valid()) { + + StringName pr = shader->remap_param(p_name); + if (pr) { + r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); + return true; + } + } + } + + return false; +} + +void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { + + p_list->push_back(PropertyInfo(Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE, "Shader,ShaderGraph")); + + if (!shader.is_null()) { + + shader->get_param_list(p_list); + } +} + +void ShaderMaterial::set_shader(const Ref<Shader> &p_shader) { + + shader = p_shader; + + RID rid; + if (shader.is_valid()) + rid = shader->get_rid(); + + VS::get_singleton()->material_set_shader(_get_material(), rid); + _change_notify(); //properties for shader exposed + emit_changed(); +} + +Ref<Shader> ShaderMaterial::get_shader() const { + + return shader; +} + +void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { + + VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); +} + +Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { + + return VS::get_singleton()->material_get_param(_get_material(), p_param); +} + +void ShaderMaterial::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shader", "shader:Shader"), &ShaderMaterial::set_shader); + ClassDB::bind_method(D_METHOD("get_shader:Shader"), &ShaderMaterial::get_shader); + ClassDB::bind_method(D_METHOD("set_shader_param", "param", "value"), &ShaderMaterial::set_shader_param); + ClassDB::bind_method(D_METHOD("get_shader_param", "param"), &ShaderMaterial::get_shader_param); +} + +void ShaderMaterial::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const { + + String f = p_function.operator String(); + if ((f == "get_shader_param" || f == "set_shader_param") && p_idx == 0) { + + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E = pl.front(); E; E = E->next()) { + r_options->push_back("\"" + E->get().name.replace_first("shader_param/", "") + "\""); + } + } + } + Resource::get_argument_options(p_function, p_idx, r_options); +} + +ShaderMaterial::ShaderMaterial() { +} + +ShaderMaterial::~ShaderMaterial() { +} + ///////////////////////////////// -Mutex *FixedSpatialMaterial::material_mutex = NULL; -SelfList<FixedSpatialMaterial>::List FixedSpatialMaterial::dirty_materials; -Map<FixedSpatialMaterial::MaterialKey, FixedSpatialMaterial::ShaderData> FixedSpatialMaterial::shader_map; -FixedSpatialMaterial::ShaderNames *FixedSpatialMaterial::shader_names = NULL; +Mutex *SpatialMaterial::material_mutex = NULL; +SelfList<SpatialMaterial>::List SpatialMaterial::dirty_materials; +Map<SpatialMaterial::MaterialKey, SpatialMaterial::ShaderData> SpatialMaterial::shader_map; +SpatialMaterial::ShaderNames *SpatialMaterial::shader_names = NULL; -void FixedSpatialMaterial::init_shaders() { +void SpatialMaterial::init_shaders() { #ifndef NO_THREADS material_mutex = Mutex::create(); @@ -81,6 +199,10 @@ void FixedSpatialMaterial::init_shaders() { shader_names->uv2_scale = "uv2_scale"; shader_names->uv2_offset = "uv2_offset"; + shader_names->particle_h_frames = "particle_h_frames"; + shader_names->particle_v_frames = "particle_v_frames"; + shader_names->particles_anim_loop = "particles_anim_loop"; + shader_names->texture_names[TEXTURE_ALBEDO] = "texture_albedo"; shader_names->texture_names[TEXTURE_SPECULAR] = "texture_specular"; shader_names->texture_names[TEXTURE_EMISSION] = "texture_emission"; @@ -98,7 +220,7 @@ void FixedSpatialMaterial::init_shaders() { shader_names->texture_names[TEXTURE_DETAIL_NORMAL] = "texture_detail_normal"; } -void FixedSpatialMaterial::finish_shaders() { +void SpatialMaterial::finish_shaders() { #ifndef NO_THREADS memdelete(material_mutex); @@ -107,7 +229,7 @@ void FixedSpatialMaterial::finish_shaders() { memdelete(shader_names); } -void FixedSpatialMaterial::_update_shader() { +void SpatialMaterial::_update_shader() { dirty_materials.remove(&element); @@ -135,7 +257,7 @@ void FixedSpatialMaterial::_update_shader() { //must create a shader! - String code = "render_mode "; + String code = "shader_type spatial;\nrender_mode "; switch (blend_mode) { case BLEND_MODE_MIX: code += "blend_mix"; break; case BLEND_MODE_ADD: code += "blend_add"; break; @@ -180,6 +302,11 @@ void FixedSpatialMaterial::_update_shader() { code += "uniform vec2 uv1_offset;\n"; code += "uniform vec2 uv2_scale;\n"; code += "uniform vec2 uv2_offset;\n"; + if (billboard_mode == BILLBOARD_PARTICLES) { + code += "uniform int particles_anim_h_frames;\n"; + code += "uniform int particles_anim_v_frames;\n"; + code += "uniform bool particles_anim_loop;\n"; + } if (features[FEATURE_EMISSION]) { @@ -235,6 +362,58 @@ void FixedSpatialMaterial::_update_shader() { code += "\tPOINT_SIZE=point_size;\n"; } code += "\tUV=UV*uv1_scale+uv1_offset;\n"; + + switch (billboard_mode) { + case BILLBOARD_DISABLED: { + + } break; + case BILLBOARD_ENABLED: { + + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],CAMERA_MATRIX[1],CAMERA_MATRIX[2],WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_FIXED_Y: { + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat4(CAMERA_MATRIX[0],WORLD_MATRIX[1],vec4(normalize(cross(CAMERA_MATRIX[0].xyz,WORLD_MATRIX[1].xyz)),0.0),WORLD_MATRIX[3]);\n"; + } break; + case BILLBOARD_PARTICLES: { + + //make billboard + code += "\tmat4 mat_world = mat4(normalize(CAMERA_MATRIX[0])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[1])*length(WORLD_MATRIX[0]),normalize(CAMERA_MATRIX[2])*length(WORLD_MATRIX[2]),WORLD_MATRIX[3]);\n"; + //rotate by rotation + code += "\tmat_world = mat_world * mat4( vec4(cos(INSTANCE_CUSTOM.x),-sin(INSTANCE_CUSTOM.x),0.0,0.0), vec4(sin(INSTANCE_CUSTOM.x),cos(INSTANCE_CUSTOM.x),0.0,0.0),vec4(0.0,0.0,1.0,0.0),vec4(0.0,0.0,0.0,1.0));\n"; + //set modelview + code += "\tMODELVIEW_MATRIX = INV_CAMERA_MATRIX * mat_world;\n"; + + //handle animation + code += "\tint particle_total_frames = particles_anim_h_frames * particles_anim_v_frames;\n"; + code += "\tint particle_frame = int(INSTANCE_CUSTOM.y * float(particle_total_frames));\n"; + code += "\tif (particles_anim_loop) particle_frame=clamp(particle_frame,0,particle_total_frames-1); else particle_frame=abs(particle_frame)%particle_total_frames;\n"; + //code += "\tUV /= vec2(float(particles_anim_h_frames),float(particles_anim_v_frames));\n"; + //code += "\tUV+= UV * vec2(float(particle_frame % particles_anim_h_frames),float(particle_frame / particles_anim_v_frames));\n"; + //handle rotation + // code += "\tmat4 rotation = mat4(" + + } break; + } + + if (flags[FLAG_FIXED_SIZE]) { + + code += "\tif (PROJECTION_MATRIX[3][3] != 0.0) {\n"; + //orthogonal matrix, try to do about the same + //with viewport size + code += "\t\tfloat h = abs(1.0 / (2.0 * PROJECTION_MATRIX[1][1]));\n"; + code += "\t\tfloat sc = (h * 2.0); //consistent with Y-fov\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t} else {\n"; + //just scale by depth + code += "\t\tfloat sc = -(MODELVIEW_MATRIX)[3].z;\n"; + code += "\t\tMODELVIEW_MATRIX[0]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[1]*=sc;\n"; + code += "\t\tMODELVIEW_MATRIX[2]*=sc;\n"; + code += "\t}\n"; + } + if (detail_uv == DETAIL_UV_2) { code += "\tUV2=UV2*uv2_scale+uv2_offset;\n"; } @@ -336,7 +515,7 @@ void FixedSpatialMaterial::_update_shader() { code += "}\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(VS::SHADER_SPATIAL); + shader_data.shader = VS::get_singleton()->shader_create(); shader_data.users = 1; VS::get_singleton()->shader_set_code(shader_data.shader, code); @@ -346,7 +525,7 @@ void FixedSpatialMaterial::_update_shader() { VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void FixedSpatialMaterial::flush_changes() { +void SpatialMaterial::flush_changes() { if (material_mutex) material_mutex->lock(); @@ -360,7 +539,7 @@ void FixedSpatialMaterial::flush_changes() { material_mutex->unlock(); } -void FixedSpatialMaterial::_queue_shader_change() { +void SpatialMaterial::_queue_shader_change() { if (material_mutex) material_mutex->lock(); @@ -373,7 +552,7 @@ void FixedSpatialMaterial::_queue_shader_change() { material_mutex->unlock(); } -bool FixedSpatialMaterial::_is_shader_dirty() const { +bool SpatialMaterial::_is_shader_dirty() const { bool dirty = false; @@ -387,187 +566,187 @@ bool FixedSpatialMaterial::_is_shader_dirty() const { return dirty; } -void FixedSpatialMaterial::set_albedo(const Color &p_albedo) { +void SpatialMaterial::set_albedo(const Color &p_albedo) { albedo = p_albedo; VS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); } -Color FixedSpatialMaterial::get_albedo() const { +Color SpatialMaterial::get_albedo() const { return albedo; } -void FixedSpatialMaterial::set_specular_mode(SpecularMode p_mode) { +void SpatialMaterial::set_specular_mode(SpecularMode p_mode) { specular_mode = p_mode; _change_notify(); _queue_shader_change(); } -FixedSpatialMaterial::SpecularMode FixedSpatialMaterial::get_specular_mode() const { +SpatialMaterial::SpecularMode SpatialMaterial::get_specular_mode() const { return specular_mode; } -void FixedSpatialMaterial::set_specular(const Color &p_specular) { +void SpatialMaterial::set_specular(const Color &p_specular) { specular = p_specular; VS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); } -Color FixedSpatialMaterial::get_specular() const { +Color SpatialMaterial::get_specular() const { return specular; } -void FixedSpatialMaterial::set_roughness(float p_roughness) { +void SpatialMaterial::set_roughness(float p_roughness) { roughness = p_roughness; VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); } -float FixedSpatialMaterial::get_roughness() const { +float SpatialMaterial::get_roughness() const { return roughness; } -void FixedSpatialMaterial::set_metalness(float p_metalness) { +void SpatialMaterial::set_metalness(float p_metalness) { metalness = p_metalness; VS::get_singleton()->material_set_param(_get_material(), shader_names->metalness, p_metalness); } -float FixedSpatialMaterial::get_metalness() const { +float SpatialMaterial::get_metalness() const { return metalness; } -void FixedSpatialMaterial::set_emission(const Color &p_emission) { +void SpatialMaterial::set_emission(const Color &p_emission) { emission = p_emission; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); } -Color FixedSpatialMaterial::get_emission() const { +Color SpatialMaterial::get_emission() const { return emission; } -void FixedSpatialMaterial::set_emission_energy(float p_emission_energy) { +void SpatialMaterial::set_emission_energy(float p_emission_energy) { emission_energy = p_emission_energy; VS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); } -float FixedSpatialMaterial::get_emission_energy() const { +float SpatialMaterial::get_emission_energy() const { return emission_energy; } -void FixedSpatialMaterial::set_normal_scale(float p_normal_scale) { +void SpatialMaterial::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); } -float FixedSpatialMaterial::get_normal_scale() const { +float SpatialMaterial::get_normal_scale() const { return normal_scale; } -void FixedSpatialMaterial::set_rim(float p_rim) { +void SpatialMaterial::set_rim(float p_rim) { rim = p_rim; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); } -float FixedSpatialMaterial::get_rim() const { +float SpatialMaterial::get_rim() const { return rim; } -void FixedSpatialMaterial::set_rim_tint(float p_rim_tint) { +void SpatialMaterial::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; VS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); } -float FixedSpatialMaterial::get_rim_tint() const { +float SpatialMaterial::get_rim_tint() const { return rim_tint; } -void FixedSpatialMaterial::set_clearcoat(float p_clearcoat) { +void SpatialMaterial::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); } -float FixedSpatialMaterial::get_clearcoat() const { +float SpatialMaterial::get_clearcoat() const { return clearcoat; } -void FixedSpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { +void SpatialMaterial::set_clearcoat_gloss(float p_clearcoat_gloss) { clearcoat_gloss = p_clearcoat_gloss; VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); } -float FixedSpatialMaterial::get_clearcoat_gloss() const { +float SpatialMaterial::get_clearcoat_gloss() const { return clearcoat_gloss; } -void FixedSpatialMaterial::set_anisotropy(float p_anisotropy) { +void SpatialMaterial::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; VS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); } -float FixedSpatialMaterial::get_anisotropy() const { +float SpatialMaterial::get_anisotropy() const { return anisotropy; } -void FixedSpatialMaterial::set_height_scale(float p_height_scale) { +void SpatialMaterial::set_height_scale(float p_height_scale) { height_scale = p_height_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->height_scale, p_height_scale); } -float FixedSpatialMaterial::get_height_scale() const { +float SpatialMaterial::get_height_scale() const { return height_scale; } -void FixedSpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { +void SpatialMaterial::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { subsurface_scattering_strength = p_subsurface_scattering_strength; VS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } -float FixedSpatialMaterial::get_subsurface_scattering_strength() const { +float SpatialMaterial::get_subsurface_scattering_strength() const { return subsurface_scattering_strength; } -void FixedSpatialMaterial::set_refraction(float p_refraction) { +void SpatialMaterial::set_refraction(float p_refraction) { refraction = p_refraction; VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); } -float FixedSpatialMaterial::get_refraction() const { +float SpatialMaterial::get_refraction() const { return refraction; } -void FixedSpatialMaterial::set_refraction_roughness(float p_refraction_roughness) { +void SpatialMaterial::set_refraction_roughness(float p_refraction_roughness) { refraction_roughness = p_refraction_roughness; VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_roughness, refraction_roughness); } -float FixedSpatialMaterial::get_refraction_roughness() const { +float SpatialMaterial::get_refraction_roughness() const { return refraction_roughness; } -void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { +void SpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { if (detail_uv == p_detail_uv) return; @@ -575,12 +754,12 @@ void FixedSpatialMaterial::set_detail_uv(DetailUV p_detail_uv) { detail_uv = p_detail_uv; _queue_shader_change(); } -FixedSpatialMaterial::DetailUV FixedSpatialMaterial::get_detail_uv() const { +SpatialMaterial::DetailUV SpatialMaterial::get_detail_uv() const { return detail_uv; } -void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_blend_mode(BlendMode p_mode) { if (blend_mode == p_mode) return; @@ -588,22 +767,22 @@ void FixedSpatialMaterial::set_blend_mode(BlendMode p_mode) { blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_blend_mode() const { return blend_mode; } -void FixedSpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { +void SpatialMaterial::set_detail_blend_mode(BlendMode p_mode) { detail_blend_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::BlendMode FixedSpatialMaterial::get_detail_blend_mode() const { +SpatialMaterial::BlendMode SpatialMaterial::get_detail_blend_mode() const { return detail_blend_mode; } -void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { +void SpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { if (depth_draw_mode == p_mode) return; @@ -611,12 +790,12 @@ void FixedSpatialMaterial::set_depth_draw_mode(DepthDrawMode p_mode) { depth_draw_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DepthDrawMode FixedSpatialMaterial::get_depth_draw_mode() const { +SpatialMaterial::DepthDrawMode SpatialMaterial::get_depth_draw_mode() const { return depth_draw_mode; } -void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { +void SpatialMaterial::set_cull_mode(CullMode p_mode) { if (cull_mode == p_mode) return; @@ -624,12 +803,12 @@ void FixedSpatialMaterial::set_cull_mode(CullMode p_mode) { cull_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::CullMode FixedSpatialMaterial::get_cull_mode() const { +SpatialMaterial::CullMode SpatialMaterial::get_cull_mode() const { return cull_mode; } -void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { +void SpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { if (diffuse_mode == p_mode) return; @@ -637,12 +816,12 @@ void FixedSpatialMaterial::set_diffuse_mode(DiffuseMode p_mode) { diffuse_mode = p_mode; _queue_shader_change(); } -FixedSpatialMaterial::DiffuseMode FixedSpatialMaterial::get_diffuse_mode() const { +SpatialMaterial::DiffuseMode SpatialMaterial::get_diffuse_mode() const { return diffuse_mode; } -void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { +void SpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); @@ -653,13 +832,13 @@ void FixedSpatialMaterial::set_flag(Flags p_flag, bool p_enabled) { _queue_shader_change(); } -bool FixedSpatialMaterial::get_flag(Flags p_flag) const { +bool SpatialMaterial::get_flag(Flags p_flag) const { ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false); return flags[p_flag]; } -void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { +void SpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { ERR_FAIL_INDEX(p_feature, FEATURE_MAX); if (features[p_feature] == p_enabled) @@ -670,13 +849,13 @@ void FixedSpatialMaterial::set_feature(Feature p_feature, bool p_enabled) { _queue_shader_change(); } -bool FixedSpatialMaterial::get_feature(Feature p_feature) const { +bool SpatialMaterial::get_feature(Feature p_feature) const { ERR_FAIL_INDEX_V(p_feature, FEATURE_MAX, false); return features[p_feature]; } -void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { +void SpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> &p_texture) { ERR_FAIL_INDEX(p_param, TEXTURE_MAX); textures[p_param] = p_texture; @@ -684,19 +863,19 @@ void FixedSpatialMaterial::set_texture(TextureParam p_param, const Ref<Texture> VS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); } -Ref<Texture> FixedSpatialMaterial::get_texture(TextureParam p_param) const { +Ref<Texture> SpatialMaterial::get_texture(TextureParam p_param) const { ERR_FAIL_INDEX_V(p_param, TEXTURE_MAX, Ref<Texture>()); return textures[p_param]; } -void FixedSpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { +void SpatialMaterial::_validate_feature(const String &text, Feature feature, PropertyInfo &property) const { if (property.name.begins_with(text) && property.name != text + "_enabled" && !features[feature]) { property.usage = 0; } } -void FixedSpatialMaterial::_validate_property(PropertyInfo &property) const { +void SpatialMaterial::_validate_property(PropertyInfo &property) const { _validate_feature("normal", FEATURE_NORMAL_MAPPING, property); _validate_feature("emission", FEATURE_EMISSION, property); _validate_feature("rim", FEATURE_RIM, property); @@ -714,187 +893,253 @@ void FixedSpatialMaterial::_validate_property(PropertyInfo &property) const { if (property.name == "specular/metalness" && specular_mode == SPECULAR_MODE_SPECULAR) { property.usage = 0; } + + if (property.name.begins_with("particles_anim_") && billboard_mode != BILLBOARD_PARTICLES) { + property.usage = 0; + } } -void FixedSpatialMaterial::set_line_width(float p_line_width) { +void SpatialMaterial::set_line_width(float p_line_width) { line_width = p_line_width; VS::get_singleton()->material_set_line_width(_get_material(), line_width); } -float FixedSpatialMaterial::get_line_width() const { +float SpatialMaterial::get_line_width() const { return line_width; } -void FixedSpatialMaterial::set_point_size(float p_point_size) { +void SpatialMaterial::set_point_size(float p_point_size) { point_size = p_point_size; VS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); } -float FixedSpatialMaterial::get_point_size() const { +float SpatialMaterial::get_point_size() const { return point_size; } -void FixedSpatialMaterial::set_uv1_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv1_scale(const Vector2 &p_scale) { uv1_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv1_scale() const { +Vector2 SpatialMaterial::get_uv1_scale() const { return uv1_scale; } -void FixedSpatialMaterial::set_uv1_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv1_offset(const Vector2 &p_offset) { uv1_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv1_offset() const { +Vector2 SpatialMaterial::get_uv1_offset() const { return uv1_offset; } -void FixedSpatialMaterial::set_uv2_scale(const Vector2 &p_scale) { +void SpatialMaterial::set_uv2_scale(const Vector2 &p_scale) { uv2_scale = p_scale; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); } -Vector2 FixedSpatialMaterial::get_uv2_scale() const { +Vector2 SpatialMaterial::get_uv2_scale() const { return uv2_scale; } -void FixedSpatialMaterial::set_uv2_offset(const Vector2 &p_offset) { +void SpatialMaterial::set_uv2_offset(const Vector2 &p_offset) { uv2_offset = p_offset; VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); } -Vector2 FixedSpatialMaterial::get_uv2_offset() const { +Vector2 SpatialMaterial::get_uv2_offset() const { return uv2_offset; } -void FixedSpatialMaterial::_bind_methods() { +void SpatialMaterial::set_billboard_mode(BillboardMode p_mode) { + + billboard_mode = p_mode; + _queue_shader_change(); + _change_notify(); +} + +SpatialMaterial::BillboardMode SpatialMaterial::get_billboard_mode() const { + + return billboard_mode; +} + +void SpatialMaterial::set_particles_anim_h_frames(int p_frames) { + + particles_anim_h_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_h_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_h_frames() const { + + return particles_anim_h_frames; +} +void SpatialMaterial::set_particles_anim_v_frames(int p_frames) { + + particles_anim_v_frames = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particle_v_frames, p_frames); +} + +int SpatialMaterial::get_particles_anim_v_frames() const { - ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &FixedSpatialMaterial::set_albedo); - ClassDB::bind_method(D_METHOD("get_albedo"), &FixedSpatialMaterial::get_albedo); + return particles_anim_v_frames; +} - ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &FixedSpatialMaterial::set_specular_mode); - ClassDB::bind_method(D_METHOD("get_specular_mode"), &FixedSpatialMaterial::get_specular_mode); +void SpatialMaterial::set_particles_anim_loop(int p_frames) { - ClassDB::bind_method(D_METHOD("set_specular", "specular"), &FixedSpatialMaterial::set_specular); - ClassDB::bind_method(D_METHOD("get_specular"), &FixedSpatialMaterial::get_specular); + particles_anim_loop = p_frames; + VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, p_frames); +} - ClassDB::bind_method(D_METHOD("set_metalness", "metalness"), &FixedSpatialMaterial::set_metalness); - ClassDB::bind_method(D_METHOD("get_metalness"), &FixedSpatialMaterial::get_metalness); +int SpatialMaterial::get_particles_anim_loop() const { - ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &FixedSpatialMaterial::set_roughness); - ClassDB::bind_method(D_METHOD("get_roughness"), &FixedSpatialMaterial::get_roughness); + return particles_anim_loop; +} - ClassDB::bind_method(D_METHOD("set_emission", "emission"), &FixedSpatialMaterial::set_emission); - ClassDB::bind_method(D_METHOD("get_emission"), &FixedSpatialMaterial::get_emission); +void SpatialMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &FixedSpatialMaterial::set_emission_energy); - ClassDB::bind_method(D_METHOD("get_emission_energy"), &FixedSpatialMaterial::get_emission_energy); + ClassDB::bind_method(D_METHOD("set_albedo", "albedo"), &SpatialMaterial::set_albedo); + ClassDB::bind_method(D_METHOD("get_albedo"), &SpatialMaterial::get_albedo); - ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &FixedSpatialMaterial::set_normal_scale); - ClassDB::bind_method(D_METHOD("get_normal_scale"), &FixedSpatialMaterial::get_normal_scale); + ClassDB::bind_method(D_METHOD("set_specular_mode", "specular_mode"), &SpatialMaterial::set_specular_mode); + ClassDB::bind_method(D_METHOD("get_specular_mode"), &SpatialMaterial::get_specular_mode); - ClassDB::bind_method(D_METHOD("set_rim", "rim"), &FixedSpatialMaterial::set_rim); - ClassDB::bind_method(D_METHOD("get_rim"), &FixedSpatialMaterial::get_rim); + ClassDB::bind_method(D_METHOD("set_specular", "specular"), &SpatialMaterial::set_specular); + ClassDB::bind_method(D_METHOD("get_specular"), &SpatialMaterial::get_specular); - ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &FixedSpatialMaterial::set_rim_tint); - ClassDB::bind_method(D_METHOD("get_rim_tint"), &FixedSpatialMaterial::get_rim_tint); + ClassDB::bind_method(D_METHOD("set_metalness", "metalness"), &SpatialMaterial::set_metalness); + ClassDB::bind_method(D_METHOD("get_metalness"), &SpatialMaterial::get_metalness); - ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &FixedSpatialMaterial::set_clearcoat); - ClassDB::bind_method(D_METHOD("get_clearcoat"), &FixedSpatialMaterial::get_clearcoat); + ClassDB::bind_method(D_METHOD("set_roughness", "roughness"), &SpatialMaterial::set_roughness); + ClassDB::bind_method(D_METHOD("get_roughness"), &SpatialMaterial::get_roughness); - ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &FixedSpatialMaterial::set_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &FixedSpatialMaterial::get_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("set_emission", "emission"), &SpatialMaterial::set_emission); + ClassDB::bind_method(D_METHOD("get_emission"), &SpatialMaterial::get_emission); - ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &FixedSpatialMaterial::set_anisotropy); - ClassDB::bind_method(D_METHOD("get_anisotropy"), &FixedSpatialMaterial::get_anisotropy); + ClassDB::bind_method(D_METHOD("set_emission_energy", "emission_energy"), &SpatialMaterial::set_emission_energy); + ClassDB::bind_method(D_METHOD("get_emission_energy"), &SpatialMaterial::get_emission_energy); - ClassDB::bind_method(D_METHOD("set_height_scale", "height_scale"), &FixedSpatialMaterial::set_height_scale); - ClassDB::bind_method(D_METHOD("get_height_scale"), &FixedSpatialMaterial::get_height_scale); + ClassDB::bind_method(D_METHOD("set_normal_scale", "normal_scale"), &SpatialMaterial::set_normal_scale); + ClassDB::bind_method(D_METHOD("get_normal_scale"), &SpatialMaterial::get_normal_scale); - ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &FixedSpatialMaterial::set_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &FixedSpatialMaterial::get_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("set_rim", "rim"), &SpatialMaterial::set_rim); + ClassDB::bind_method(D_METHOD("get_rim"), &SpatialMaterial::get_rim); - ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &FixedSpatialMaterial::set_refraction); - ClassDB::bind_method(D_METHOD("get_refraction"), &FixedSpatialMaterial::get_refraction); + ClassDB::bind_method(D_METHOD("set_rim_tint", "rim_tint"), &SpatialMaterial::set_rim_tint); + ClassDB::bind_method(D_METHOD("get_rim_tint"), &SpatialMaterial::get_rim_tint); - ClassDB::bind_method(D_METHOD("set_refraction_roughness", "refraction_roughness"), &FixedSpatialMaterial::set_refraction_roughness); - ClassDB::bind_method(D_METHOD("get_refraction_roughness"), &FixedSpatialMaterial::get_refraction_roughness); + ClassDB::bind_method(D_METHOD("set_clearcoat", "clearcoat"), &SpatialMaterial::set_clearcoat); + ClassDB::bind_method(D_METHOD("get_clearcoat"), &SpatialMaterial::get_clearcoat); - ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &FixedSpatialMaterial::set_line_width); - ClassDB::bind_method(D_METHOD("get_line_width"), &FixedSpatialMaterial::get_line_width); + ClassDB::bind_method(D_METHOD("set_clearcoat_gloss", "clearcoat_gloss"), &SpatialMaterial::set_clearcoat_gloss); + ClassDB::bind_method(D_METHOD("get_clearcoat_gloss"), &SpatialMaterial::get_clearcoat_gloss); - ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &FixedSpatialMaterial::set_point_size); - ClassDB::bind_method(D_METHOD("get_point_size"), &FixedSpatialMaterial::get_point_size); + ClassDB::bind_method(D_METHOD("set_anisotropy", "anisotropy"), &SpatialMaterial::set_anisotropy); + ClassDB::bind_method(D_METHOD("get_anisotropy"), &SpatialMaterial::get_anisotropy); - ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &FixedSpatialMaterial::set_detail_uv); - ClassDB::bind_method(D_METHOD("get_detail_uv"), &FixedSpatialMaterial::get_detail_uv); + ClassDB::bind_method(D_METHOD("set_height_scale", "height_scale"), &SpatialMaterial::set_height_scale); + ClassDB::bind_method(D_METHOD("get_height_scale"), &SpatialMaterial::get_height_scale); - ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &FixedSpatialMaterial::set_blend_mode); - ClassDB::bind_method(D_METHOD("get_blend_mode"), &FixedSpatialMaterial::get_blend_mode); + ClassDB::bind_method(D_METHOD("set_subsurface_scattering_strength", "strength"), &SpatialMaterial::set_subsurface_scattering_strength); + ClassDB::bind_method(D_METHOD("get_subsurface_scattering_strength"), &SpatialMaterial::get_subsurface_scattering_strength); - ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &FixedSpatialMaterial::set_depth_draw_mode); - ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &FixedSpatialMaterial::get_depth_draw_mode); + ClassDB::bind_method(D_METHOD("set_refraction", "refraction"), &SpatialMaterial::set_refraction); + ClassDB::bind_method(D_METHOD("get_refraction"), &SpatialMaterial::get_refraction); - ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &FixedSpatialMaterial::set_cull_mode); - ClassDB::bind_method(D_METHOD("get_cull_mode"), &FixedSpatialMaterial::get_cull_mode); + ClassDB::bind_method(D_METHOD("set_refraction_roughness", "refraction_roughness"), &SpatialMaterial::set_refraction_roughness); + ClassDB::bind_method(D_METHOD("get_refraction_roughness"), &SpatialMaterial::get_refraction_roughness); - ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &FixedSpatialMaterial::set_diffuse_mode); - ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &FixedSpatialMaterial::get_diffuse_mode); + ClassDB::bind_method(D_METHOD("set_line_width", "line_width"), &SpatialMaterial::set_line_width); + ClassDB::bind_method(D_METHOD("get_line_width"), &SpatialMaterial::get_line_width); - ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &FixedSpatialMaterial::set_flag); - ClassDB::bind_method(D_METHOD("get_flag"), &FixedSpatialMaterial::get_flag); + ClassDB::bind_method(D_METHOD("set_point_size", "point_size"), &SpatialMaterial::set_point_size); + ClassDB::bind_method(D_METHOD("get_point_size"), &SpatialMaterial::get_point_size); - ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &FixedSpatialMaterial::set_feature); - ClassDB::bind_method(D_METHOD("get_feature", "feature"), &FixedSpatialMaterial::get_feature); + ClassDB::bind_method(D_METHOD("set_detail_uv", "detail_uv"), &SpatialMaterial::set_detail_uv); + ClassDB::bind_method(D_METHOD("get_detail_uv"), &SpatialMaterial::get_detail_uv); - ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &FixedSpatialMaterial::set_texture); - ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &FixedSpatialMaterial::get_texture); + ClassDB::bind_method(D_METHOD("set_blend_mode", "blend_mode"), &SpatialMaterial::set_blend_mode); + ClassDB::bind_method(D_METHOD("get_blend_mode"), &SpatialMaterial::get_blend_mode); - ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &FixedSpatialMaterial::set_detail_blend_mode); - ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &FixedSpatialMaterial::get_detail_blend_mode); + ClassDB::bind_method(D_METHOD("set_depth_draw_mode", "depth_draw_mode"), &SpatialMaterial::set_depth_draw_mode); + ClassDB::bind_method(D_METHOD("get_depth_draw_mode"), &SpatialMaterial::get_depth_draw_mode); - ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &FixedSpatialMaterial::set_uv1_scale); - ClassDB::bind_method(D_METHOD("get_uv1_scale"), &FixedSpatialMaterial::get_uv1_scale); + ClassDB::bind_method(D_METHOD("set_cull_mode", "cull_mode"), &SpatialMaterial::set_cull_mode); + ClassDB::bind_method(D_METHOD("get_cull_mode"), &SpatialMaterial::get_cull_mode); - ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &FixedSpatialMaterial::set_uv1_offset); - ClassDB::bind_method(D_METHOD("get_uv1_offset"), &FixedSpatialMaterial::get_uv1_offset); + ClassDB::bind_method(D_METHOD("set_diffuse_mode", "diffuse_mode"), &SpatialMaterial::set_diffuse_mode); + ClassDB::bind_method(D_METHOD("get_diffuse_mode"), &SpatialMaterial::get_diffuse_mode); - ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &FixedSpatialMaterial::set_uv2_scale); - ClassDB::bind_method(D_METHOD("get_uv2_scale"), &FixedSpatialMaterial::get_uv2_scale); + ClassDB::bind_method(D_METHOD("set_flag", "flag", "enable"), &SpatialMaterial::set_flag); + ClassDB::bind_method(D_METHOD("get_flag"), &SpatialMaterial::get_flag); - ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &FixedSpatialMaterial::set_uv2_offset); - ClassDB::bind_method(D_METHOD("get_uv2_offset"), &FixedSpatialMaterial::get_uv2_offset); + ClassDB::bind_method(D_METHOD("set_feature", "feature", "enable"), &SpatialMaterial::set_feature); + ClassDB::bind_method(D_METHOD("get_feature", "feature"), &SpatialMaterial::get_feature); + + ClassDB::bind_method(D_METHOD("set_texture", "param:Texture", "texture"), &SpatialMaterial::set_texture); + ClassDB::bind_method(D_METHOD("get_texture:Texture", "param:Texture"), &SpatialMaterial::get_texture); + + ClassDB::bind_method(D_METHOD("set_detail_blend_mode", "detail_blend_mode"), &SpatialMaterial::set_detail_blend_mode); + ClassDB::bind_method(D_METHOD("get_detail_blend_mode"), &SpatialMaterial::get_detail_blend_mode); + + ClassDB::bind_method(D_METHOD("set_uv1_scale", "scale"), &SpatialMaterial::set_uv1_scale); + ClassDB::bind_method(D_METHOD("get_uv1_scale"), &SpatialMaterial::get_uv1_scale); + + ClassDB::bind_method(D_METHOD("set_uv1_offset", "offset"), &SpatialMaterial::set_uv1_offset); + ClassDB::bind_method(D_METHOD("get_uv1_offset"), &SpatialMaterial::get_uv1_offset); + + ClassDB::bind_method(D_METHOD("set_uv2_scale", "scale"), &SpatialMaterial::set_uv2_scale); + ClassDB::bind_method(D_METHOD("get_uv2_scale"), &SpatialMaterial::get_uv2_scale); + + ClassDB::bind_method(D_METHOD("set_uv2_offset", "offset"), &SpatialMaterial::set_uv2_offset); + ClassDB::bind_method(D_METHOD("get_uv2_offset"), &SpatialMaterial::get_uv2_offset); + + ClassDB::bind_method(D_METHOD("set_billboard_mode", "mode"), &SpatialMaterial::set_billboard_mode); + ClassDB::bind_method(D_METHOD("get_billboard_mode"), &SpatialMaterial::get_billboard_mode); + + ClassDB::bind_method(D_METHOD("set_particles_anim_h_frames", "frames"), &SpatialMaterial::set_particles_anim_h_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_h_frames"), &SpatialMaterial::get_particles_anim_h_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_v_frames", "frames"), &SpatialMaterial::set_particles_anim_v_frames); + ClassDB::bind_method(D_METHOD("get_particles_anim_v_frames"), &SpatialMaterial::get_particles_anim_v_frames); + + ClassDB::bind_method(D_METHOD("set_particles_anim_loop", "frames"), &SpatialMaterial::set_particles_anim_loop); + ClassDB::bind_method(D_METHOD("get_particles_anim_loop"), &SpatialMaterial::get_particles_anim_loop); ADD_GROUP("Flags", "flags_"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_transparent"), "set_feature", "get_feature", FEATURE_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_unshaded"), "set_flag", "get_flag", FLAG_UNSHADED); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_on_top"), "set_flag", "get_flag", FLAG_ONTOP); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_use_point_size"), "set_flag", "get_flag", FLAG_USE_POINT_SIZE); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "flags_fixed_size"), "set_flag", "get_flag", FLAG_FIXED_SIZE); ADD_GROUP("Vertex Color", "vertex_color"); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_use_as_albedo"), "set_flag", "get_flag", FLAG_ALBEDO_FROM_VERTEX_COLOR); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "vertex_color_is_srgb"), "set_flag", "get_flag", FLAG_SRGB_VERTEX_COLOR); ADD_GROUP("Parameters", "params_"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Labert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_diffuse_mode", PROPERTY_HINT_ENUM, "Lambert,Lambert Wrap,Oren Nayar,Burley"), "set_diffuse_mode", "get_diffuse_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_blend_mode", PROPERTY_HINT_ENUM, "Mix,Add,Sub,Mul"), "set_blend_mode", "get_blend_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_cull_mode", PROPERTY_HINT_ENUM, "Back,Front,Disabled"), "set_cull_mode", "get_cull_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "params_depth_draw_mode", PROPERTY_HINT_ENUM, "Opaque Only,Always,Never,Opaque Pre-Pass"), "set_depth_draw_mode", "get_depth_draw_mode"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_line_width", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_line_width", "get_line_width"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "params_point_size", PROPERTY_HINT_RANGE, "0.1,128,0.1"), "set_point_size", "get_point_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "params_billboard_mode", PROPERTY_HINT_ENUM, "Disabled,Enabled,Y-Billboard,Particle Billboard"), "set_billboard_mode", "get_billboard_mode"); + ADD_GROUP("Particles Anim", "particles_anim_"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_h_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_h_frames", "get_particles_anim_h_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "particles_anim_v_frames", PROPERTY_HINT_RANGE, "1,128,1"), "set_particles_anim_v_frames", "get_particles_anim_v_frames"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "particles_anim_loop"), "set_particles_anim_loop", "get_particles_anim_loop"); ADD_GROUP("Albedo", "albedo_"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "albedo_color"), "set_albedo", "get_albedo"); @@ -1023,6 +1268,7 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(FLAG_ALBEDO_FROM_VERTEX_COLOR); BIND_CONSTANT(FLAG_SRGB_VERTEX_COLOR) BIND_CONSTANT(FLAG_USE_POINT_SIZE) + BIND_CONSTANT(FLAG_FIXED_SIZE) BIND_CONSTANT(FLAG_MAX); BIND_CONSTANT(DIFFUSE_LAMBERT); @@ -1032,9 +1278,14 @@ void FixedSpatialMaterial::_bind_methods() { BIND_CONSTANT(SPECULAR_MODE_METALLIC); BIND_CONSTANT(SPECULAR_MODE_SPECULAR); + + BIND_CONSTANT(BILLBOARD_DISABLED); + BIND_CONSTANT(BILLBOARD_ENABLED); + BIND_CONSTANT(BILLBOARD_FIXED_Y); + BIND_CONSTANT(BILLBOARD_PARTICLES); } -FixedSpatialMaterial::FixedSpatialMaterial() +SpatialMaterial::SpatialMaterial() : element(this) { //initialize to right values @@ -1061,6 +1312,10 @@ FixedSpatialMaterial::FixedSpatialMaterial() set_uv1_scale(Vector2(1, 1)); set_uv2_offset(Vector2(0, 0)); set_uv2_scale(Vector2(1, 1)); + set_billboard_mode(BILLBOARD_DISABLED); + set_particles_anim_h_frames(1); + set_particles_anim_v_frames(1); + set_particles_anim_loop(false); detail_uv = DETAIL_UV_1; blend_mode = BLEND_MODE_MIX; @@ -1081,7 +1336,7 @@ FixedSpatialMaterial::FixedSpatialMaterial() _queue_shader_change(); } -FixedSpatialMaterial::~FixedSpatialMaterial() { +SpatialMaterial::~SpatialMaterial() { if (material_mutex) material_mutex->lock(); diff --git a/scene/resources/material.h b/scene/resources/material.h index a8288153c3..147e7a46ba 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -56,9 +56,34 @@ public: virtual ~Material(); }; -class FixedSpatialMaterial : public Material { +class ShaderMaterial : public Material { - GDCLASS(FixedSpatialMaterial, Material) + GDCLASS(ShaderMaterial, Material); + Ref<Shader> shader; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + void _get_property_list(List<PropertyInfo> *p_list) const; + + static void _bind_methods(); + + void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const; + +public: + void set_shader(const Ref<Shader> &p_shader); + Ref<Shader> get_shader() const; + + void set_shader_param(const StringName &p_param, const Variant &p_value); + Variant get_shader_param(const StringName &p_param) const; + + ShaderMaterial(); + ~ShaderMaterial(); +}; + +class SpatialMaterial : public Material { + + GDCLASS(SpatialMaterial, Material) public: enum TextureParam { @@ -128,6 +153,7 @@ public: FLAG_ALBEDO_FROM_VERTEX_COLOR, FLAG_SRGB_VERTEX_COLOR, FLAG_USE_POINT_SIZE, + FLAG_FIXED_SIZE, FLAG_MAX }; @@ -143,20 +169,28 @@ public: SPECULAR_MODE_SPECULAR, }; + enum BillboardMode { + BILLBOARD_DISABLED, + BILLBOARD_ENABLED, + BILLBOARD_FIXED_Y, + BILLBOARD_PARTICLES, + }; + private: union MaterialKey { struct { - uint32_t feature_mask : 14; + uint32_t feature_mask : 11; uint32_t detail_uv : 1; uint32_t blend_mode : 2; uint32_t depth_draw_mode : 2; uint32_t cull_mode : 2; - uint32_t flags : 5; + uint32_t flags : 6; uint32_t detail_blend_mode : 2; uint32_t diffuse_mode : 2; uint32_t invalid_key : 1; uint32_t specular_mode : 1; + uint32_t billboard_mode : 2; }; uint32_t key; @@ -196,6 +230,7 @@ private: mk.detail_blend_mode = detail_blend_mode; mk.diffuse_mode = diffuse_mode; mk.specular_mode = specular_mode; + mk.billboard_mode = billboard_mode; return mk; } @@ -222,14 +257,17 @@ private: StringName uv1_offset; StringName uv2_scale; StringName uv2_offset; + StringName particle_h_frames; + StringName particle_v_frames; + StringName particles_anim_loop; StringName texture_names[TEXTURE_MAX]; }; static Mutex *material_mutex; - static SelfList<FixedSpatialMaterial>::List dirty_materials; + static SelfList<SpatialMaterial>::List dirty_materials; static ShaderNames *shader_names; - SelfList<FixedSpatialMaterial> element; + SelfList<SpatialMaterial> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); @@ -253,6 +291,9 @@ private: float refraction_roughness; float line_width; float point_size; + int particles_anim_h_frames; + int particles_anim_v_frames; + bool particles_anim_loop; Vector2 uv1_scale; Vector2 uv1_offset; @@ -269,6 +310,7 @@ private: bool flags[FLAG_MAX]; DiffuseMode diffuse_mode; SpecularMode specular_mode; + BillboardMode billboard_mode; bool features[FEATURE_MAX]; @@ -377,23 +419,35 @@ public: void set_uv2_offset(const Vector2 &p_offset); Vector2 get_uv2_offset() const; + void set_billboard_mode(BillboardMode p_mode); + BillboardMode get_billboard_mode() const; + + void set_particles_anim_h_frames(int p_frames); + int get_particles_anim_h_frames() const; + void set_particles_anim_v_frames(int p_frames); + int get_particles_anim_v_frames() const; + + void set_particles_anim_loop(int p_frames); + int get_particles_anim_loop() const; + static void init_shaders(); static void finish_shaders(); static void flush_changes(); - FixedSpatialMaterial(); - virtual ~FixedSpatialMaterial(); + SpatialMaterial(); + virtual ~SpatialMaterial(); }; -VARIANT_ENUM_CAST(FixedSpatialMaterial::TextureParam) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DetailUV) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Feature) -VARIANT_ENUM_CAST(FixedSpatialMaterial::BlendMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DepthDrawMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::CullMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::Flags) -VARIANT_ENUM_CAST(FixedSpatialMaterial::DiffuseMode) -VARIANT_ENUM_CAST(FixedSpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::TextureParam) +VARIANT_ENUM_CAST(SpatialMaterial::DetailUV) +VARIANT_ENUM_CAST(SpatialMaterial::Feature) +VARIANT_ENUM_CAST(SpatialMaterial::BlendMode) +VARIANT_ENUM_CAST(SpatialMaterial::DepthDrawMode) +VARIANT_ENUM_CAST(SpatialMaterial::CullMode) +VARIANT_ENUM_CAST(SpatialMaterial::Flags) +VARIANT_ENUM_CAST(SpatialMaterial::DiffuseMode) +VARIANT_ENUM_CAST(SpatialMaterial::SpecularMode) +VARIANT_ENUM_CAST(SpatialMaterial::BillboardMode) ////////////////////// diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index f951cf1620..8da8f09007 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -192,6 +192,9 @@ bool Mesh::_set(const StringName &p_name, const Variant &p_value) { bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { + if (_is_generated()) + return false; + String sname = p_name; if (p_name == "blend_shape/names") { @@ -268,6 +271,9 @@ bool Mesh::_get(const StringName &p_name, Variant &r_ret) const { void Mesh::_get_property_list(List<PropertyInfo> *p_list) const { + if (_is_generated()) + return; + if (blend_shapes.size()) { p_list->push_back(PropertyInfo(Variant::POOL_STRING_ARRAY, "blend_shape/names", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::INT, "blend_shape/mode", PROPERTY_HINT_ENUM, "Normalized,Relative")); @@ -1025,3 +1031,71 @@ Mesh::~Mesh() { VisualServer::get_singleton()->free(mesh); } + +//////////////////////// + +void QuadMesh::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_material", "material:Material"), &QuadMesh::set_material); + ClassDB::bind_method(D_METHOD("get_material:Material"), &QuadMesh::get_material); + + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "material", PROPERTY_HINT_RESOURCE_TYPE, "Material"), "set_material", "get_material"); +} + +void QuadMesh::set_material(const Ref<Material> &p_material) { + + surface_set_material(0, p_material); +} + +Ref<Material> QuadMesh::get_material() const { + + return surface_get_material(0); +} + +QuadMesh::QuadMesh() { + + PoolVector<Vector3> faces; + PoolVector<Vector3> normals; + PoolVector<float> tangents; + PoolVector<Vector2> uvs; + + faces.resize(4); + normals.resize(4); + tangents.resize(4 * 4); + uvs.resize(4); + + for (int i = 0; i < 4; i++) { + + static const Vector3 quad_faces[4] = { + Vector3(-1, -1, 0), + Vector3(-1, 1, 0), + Vector3(1, 1, 0), + Vector3(1, -1, 0), + }; + + faces.set(i, quad_faces[i]); + normals.set(i, Vector3(0, 0, 1)); + tangents.set(i * 4 + 0, 1.0); + tangents.set(i * 4 + 1, 0.0); + tangents.set(i * 4 + 2, 0.0); + tangents.set(i * 4 + 3, 1.0); + + static const Vector2 quad_uv[4] = { + Vector2(0, 1), + Vector2(0, 0), + Vector2(1, 0), + Vector2(1, 1), + }; + + uvs.set(i, quad_uv[i]); + } + + Array arr; + arr.resize(ARRAY_MAX); + arr[ARRAY_VERTEX] = faces; + arr[ARRAY_NORMAL] = normals; + arr[ARRAY_TANGENT] = tangents; + arr[ARRAY_TEX_UV] = uvs; + + add_surface_from_arrays(PRIMITIVE_TRIANGLE_FAN, arr); +} diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 8b1936ed06..77907ddbcd 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -128,6 +128,8 @@ private: void _recompute_aabb(); protected: + virtual bool _is_generated() const { return false; } + bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; @@ -189,6 +191,20 @@ public: ~Mesh(); }; +class QuadMesh : public Mesh { + + GDCLASS(QuadMesh, Mesh) + +protected: + virtual bool _is_generated() const { return true; } + static void _bind_methods(); + +public: + void set_material(const Ref<Material> &p_material); + Ref<Material> get_material() const; + QuadMesh(); +}; + VARIANT_ENUM_CAST(Mesh::ArrayType); VARIANT_ENUM_CAST(Mesh::PrimitiveType); VARIANT_ENUM_CAST(Mesh::BlendShapeMode); diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index fd058a4a6f..a0a8a9eca2 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -29,6 +29,7 @@ #include "shader.h" #include "os/file_access.h" #include "scene/scene_string_names.h" +#include "servers/visual/shader_language.h" #include "servers/visual_server.h" #include "texture.h" @@ -39,6 +40,18 @@ Shader::Mode Shader::get_mode() const { void Shader::set_code(const String &p_code) { + String type = ShaderLanguage::get_shader_type(p_code); + + print_line("mode: " + type); + + if (type == "canvas_item") { + mode = MODE_CANVAS_ITEM; + } else if (type == "particles") { + mode = MODE_PARTICLES; + } else { + mode = MODE_SPATIAL; + } + VisualServer::get_singleton()->shader_set_code(shader, p_code); params_cache_dirty = true; emit_signal(SceneStringNames::get_singleton()->changed); @@ -128,10 +141,10 @@ void Shader::_bind_methods() { BIND_CONSTANT(MODE_PARTICLES); } -Shader::Shader(Mode p_mode) { +Shader::Shader() { - mode = p_mode; - shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); + mode = MODE_SPATIAL; + shader = VisualServer::get_singleton()->shader_create(); params_cache_dirty = true; } diff --git a/scene/resources/shader.h b/scene/resources/shader.h index bc98fbf737..984ea84fb4 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -88,37 +88,10 @@ public: virtual RID get_rid() const; - Shader(Mode p_mode); + Shader(); ~Shader(); }; VARIANT_ENUM_CAST(Shader::Mode); -class SpatialShader : public Shader { - - GDCLASS(SpatialShader, Shader); - -public: - SpatialShader() - : Shader(MODE_SPATIAL){}; -}; - -class CanvasItemShader : public Shader { - - GDCLASS(CanvasItemShader, Shader); - -public: - CanvasItemShader() - : Shader(MODE_CANVAS_ITEM){}; -}; - -class ParticlesShader : public Shader { - - GDCLASS(ParticlesShader, Shader); - -public: - ParticlesShader() - : Shader(MODE_PARTICLES){}; -}; - #endif // SHADER_H diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index d08fc2634e..d4732281be 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1367,3 +1367,471 @@ CubeMap::~CubeMap() { BIND_CONSTANT( CUBEMAP_FRONT ); BIND_CONSTANT( CUBEMAP_BACK ); */ +/////////////////////////// + +void CurveTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_max", "max"), &CurveTexture::set_max); + ClassDB::bind_method(D_METHOD("get_max"), &CurveTexture::get_max); + + ClassDB::bind_method(D_METHOD("set_min", "min"), &CurveTexture::set_min); + ClassDB::bind_method(D_METHOD("get_min"), &CurveTexture::get_min); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); + + ClassDB::bind_method(D_METHOD("set_points", "points"), &CurveTexture::set_points); + ClassDB::bind_method(D_METHOD("get_points"), &CurveTexture::get_points); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min", PROPERTY_HINT_RANGE, "-1024,1024"), "set_min", "get_min"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max", PROPERTY_HINT_RANGE, "-1024,1024"), "set_max", "get_max"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "points"), "set_points", "get_points"); +} +void CurveTexture::set_max(float p_max) { + + max = p_max; + emit_changed(); +} +float CurveTexture::get_max() const { + + return max; +} + +void CurveTexture::set_min(float p_min) { + + min = p_min; + emit_changed(); +} +float CurveTexture::get_min() const { + + return min; +} +void CurveTexture::set_width(int p_width) { + + ERR_FAIL_COND(p_width < 32 || p_width > 4096); + width = p_width; + if (points.size()) + set_points(points); +} +int CurveTexture::get_width() const { + + return width; +} + +static void _plot_curve(const Vector2 &p_a, const Vector2 &p_b, const Vector2 &p_c, const Vector2 &p_d, float *p_heights, bool *p_useds, int p_width, float p_min, float p_max) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx; + int newx; + float lasty; + float newy; + int ntimes; + int i, j; + + int xmax = p_width; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } + + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1]); + geometry[1][1] = (p_b[1]); + geometry[2][1] = (p_c[1]); + geometry[3][1] = (p_d[1]); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; + tmp2[0][1] = 0; + tmp2[0][2] = 0; + tmp2[0][3] = 1; + tmp2[1][0] = d3; + tmp2[1][1] = d2; + tmp2[1][2] = d; + tmp2[1][3] = 0; + tmp2[2][0] = 6 * d3; + tmp2[2][1] = 2 * d2; + tmp2[2][2] = 0; + tmp2[2][3] = 0; + tmp2[3][0] = 6 * d3; + tmp2[3][1] = 0; + tmp2[3][2] = 0; + tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + lastx = CLAMP(x, 0, xmax); + lasty = y; + + p_heights[lastx] = lasty; + p_useds[lastx] = true; + + /* loop over the curve */ + for (i = 0; i < ntimes; i++) { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP((Math::round(x)), 0, xmax); + newy = CLAMP(y, p_min, p_max); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) { + p_useds[newx] = true; + p_heights[newx] = newy; + } + + lastx = newx; + lasty = newy; + } +} + +void CurveTexture::set_points(const PoolVector<Vector2> &p_points) { + + points = p_points; + + PoolVector<uint8_t> data; + PoolVector<bool> used; + data.resize(width * sizeof(float)); + used.resize(width); + { + PoolVector<uint8_t>::Write wd8 = data.write(); + float *wd = (float *)wd8.ptr(); + PoolVector<bool>::Write wu = used.write(); + int pc = p_points.size(); + PoolVector<Vector2>::Read pr = p_points.read(); + + for (int i = 0; i < width; i++) { + wd[i] = 0.0; + wu[i] = false; + } + + Vector2 prev = Vector2(0, 0); + Vector2 prev2 = Vector2(0, 0); + + for (int i = -1; i < pc; i++) { + + Vector2 next; + Vector2 next2; + if (i + 1 >= pc) { + next = Vector2(1, 0); + } else { + next = Vector2(pr[i + 1].x, pr[i + 1].y); + } + + if (i + 2 >= pc) { + next2 = Vector2(1, 0); + } else { + next2 = Vector2(pr[i + 2].x, pr[i + 2].y); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2, prev, next, next2, wd, wu.ptr(), width, min, max); + + prev2 = prev; + prev = next; + } + } + + Image image(width, 1, false, Image::FORMAT_RF, data); + + VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RF, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(texture, image); + + emit_changed(); +} + +PoolVector<Vector2> CurveTexture::get_points() const { + + return points; +} + +RID CurveTexture::get_rid() const { + + return texture; +} + +CurveTexture::CurveTexture() { + + max = 1; + min = 0; + width = 2048; + texture = VS::get_singleton()->texture_create(); +} +CurveTexture::~CurveTexture() { + VS::get_singleton()->free(texture); +} +////////////////// + +//setter and getter names for property serialization +#define COLOR_RAMP_GET_OFFSETS "get_offsets" +#define COLOR_RAMP_GET_COLORS "get_colors" +#define COLOR_RAMP_SET_OFFSETS "set_offsets" +#define COLOR_RAMP_SET_COLORS "set_colors" + +GradientTexture::GradientTexture() { + //Set initial color ramp transition from black to white + points.resize(2); + points[0].color = Color(0, 0, 0, 1); + points[0].offset = 0; + points[1].color = Color(1, 1, 1, 1); + points[1].offset = 1; + is_sorted = true; + update_pending = false; + width = 2048; + + texture = VS::get_singleton()->texture_create(); + _queue_update(); +} + +GradientTexture::~GradientTexture() { + VS::get_singleton()->free(texture); +} + +void GradientTexture::_bind_methods() { + + ClassDB::bind_method(D_METHOD("add_point", "offset", "color"), &GradientTexture::add_point); + ClassDB::bind_method(D_METHOD("remove_point", "offset", "color"), &GradientTexture::remove_point); + + ClassDB::bind_method(D_METHOD("set_offset", "point", "offset"), &GradientTexture::set_offset); + ClassDB::bind_method(D_METHOD("get_offset", "point"), &GradientTexture::get_offset); + + ClassDB::bind_method(D_METHOD("set_color", "point", "color"), &GradientTexture::set_color); + ClassDB::bind_method(D_METHOD("get_color", "point"), &GradientTexture::get_color); + + ClassDB::bind_method(D_METHOD("set_width", "width"), &GradientTexture::set_width); + + ClassDB::bind_method(D_METHOD("interpolate", "offset"), &GradientTexture::get_color_at_offset); + + ClassDB::bind_method(D_METHOD("get_point_count"), &GradientTexture::get_points_count); + + ClassDB::bind_method(D_METHOD("_update"), &GradientTexture::_update); + + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_OFFSETS, "offsets"), &GradientTexture::set_offsets); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_OFFSETS), &GradientTexture::get_offsets); + + ClassDB::bind_method(D_METHOD(COLOR_RAMP_SET_COLORS, "colors"), &GradientTexture::set_colors); + ClassDB::bind_method(D_METHOD(COLOR_RAMP_GET_COLORS), &GradientTexture::get_colors); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "width"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offsets"), COLOR_RAMP_SET_OFFSETS, COLOR_RAMP_GET_OFFSETS); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "colors"), COLOR_RAMP_SET_COLORS, COLOR_RAMP_GET_COLORS); +} + +void GradientTexture::_queue_update() { + + if (update_pending) + return; + + call_deferred("_update"); +} + +void GradientTexture::_update() { + + update_pending = false; + + PoolVector<uint8_t> data; + data.resize(width * 4); + { + PoolVector<uint8_t>::Write wd8 = data.write(); + for (int i = 0; i < width; i++) { + float ofs = float(i) / (width - 1); + + Color color = get_color_at_offset(ofs); + wd8[i * 4 + 0] = uint8_t(CLAMP(color.r * 255.0, 0, 255)); + wd8[i * 4 + 1] = uint8_t(CLAMP(color.g * 255.0, 0, 255)); + wd8[i * 4 + 2] = uint8_t(CLAMP(color.b * 255.0, 0, 255)); + wd8[i * 4 + 3] = uint8_t(CLAMP(color.a * 255.0, 0, 255)); + } + } + + Image image(width, 1, false, Image::FORMAT_RGBA8, data); + + VS::get_singleton()->texture_allocate(texture, width, 1, Image::FORMAT_RGBA8, VS::TEXTURE_FLAG_FILTER); + VS::get_singleton()->texture_set_data(texture, image); + + emit_changed(); +} + +void GradientTexture::set_width(int p_width) { + + width = p_width; + _queue_update(); +} +int GradientTexture::get_width() const { + + return width; +} + +Vector<float> GradientTexture::get_offsets() const { + Vector<float> offsets; + offsets.resize(points.size()); + for (int i = 0; i < points.size(); i++) { + offsets[i] = points[i].offset; + } + return offsets; +} + +Vector<Color> GradientTexture::get_colors() const { + Vector<Color> colors; + colors.resize(points.size()); + for (int i = 0; i < points.size(); i++) { + colors[i] = points[i].color; + } + return colors; +} + +void GradientTexture::set_offsets(const Vector<float> &p_offsets) { + points.resize(p_offsets.size()); + for (int i = 0; i < points.size(); i++) { + points[i].offset = p_offsets[i]; + } + is_sorted = false; + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_colors(const Vector<Color> &p_colors) { + if (points.size() < p_colors.size()) + is_sorted = false; + points.resize(p_colors.size()); + for (int i = 0; i < points.size(); i++) { + points[i].color = p_colors[i]; + } + emit_changed(); + _queue_update(); +} + +Vector<GradientTexture::Point> &GradientTexture::get_points() { + return points; +} + +void GradientTexture::add_point(float p_offset, const Color &p_color) { + + Point p; + p.offset = p_offset; + p.color = p_color; + is_sorted = false; + points.push_back(p); + + emit_changed(); + _queue_update(); +} + +void GradientTexture::remove_point(int p_index) { + + ERR_FAIL_INDEX(p_index, points.size()); + ERR_FAIL_COND(points.size() <= 2); + points.remove(p_index); + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_points(Vector<GradientTexture::Point> &p_points) { + points = p_points; + is_sorted = false; + emit_changed(); + _queue_update(); +} + +void GradientTexture::set_offset(int pos, const float offset) { + if (points.size() <= pos) + points.resize(pos + 1); + points[pos].offset = offset; + is_sorted = false; + emit_changed(); + _queue_update(); +} + +float GradientTexture::get_offset(int pos) const { + if (points.size() > pos) + return points[pos].offset; + return 0; //TODO: Maybe throw some error instead? +} + +void GradientTexture::set_color(int pos, const Color &color) { + if (points.size() <= pos) { + points.resize(pos + 1); + is_sorted = false; + } + points[pos].color = color; + emit_changed(); + _queue_update(); +} + +Color GradientTexture::get_color(int pos) const { + if (points.size() > pos) + return points[pos].color; + return Color(0, 0, 0, 1); //TODO: Maybe throw some error instead? +} + +int GradientTexture::get_points_count() const { + return points.size(); +} diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 0092fee836..52e5fdd161 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -394,6 +394,44 @@ VARIANT_ENUM_CAST(CubeMap::Flags); VARIANT_ENUM_CAST(CubeMap::Side); VARIANT_ENUM_CAST(CubeMap::Storage); +class CurveTexture : public Texture { + + GDCLASS(CurveTexture, Texture); + RES_BASE_EXTENSION("cvtex"); + +private: + RID texture; + PoolVector<Vector2> points; + float min, max; + int width; + +protected: + static void _bind_methods(); + +public: + void set_max(float p_max); + float get_max() const; + + void set_min(float p_min); + float get_min() const; + + void set_width(int p_width); + int get_width() const; + + void set_points(const PoolVector<Vector2> &p_points); + PoolVector<Vector2> get_points() const; + + virtual RID get_rid() const; + + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return false; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + CurveTexture(); + ~CurveTexture(); +}; /* enum CubeMapSide { @@ -408,4 +446,107 @@ VARIANT_ENUM_CAST(CubeMap::Storage); */ //VARIANT_ENUM_CAST( Texture::CubeMapSide ); +class GradientTexture : public Texture { + GDCLASS(GradientTexture, Texture); + +public: + struct Point { + + float offset; + Color color; + bool operator<(const Point &p_ponit) const { + return offset < p_ponit.offset; + } + }; + +private: + Vector<Point> points; + bool is_sorted; + bool update_pending; + RID texture; + int width; + + void _queue_update(); + void _update(); + +protected: + static void _bind_methods(); + +public: + void add_point(float p_offset, const Color &p_color); + void remove_point(int p_index); + + void set_points(Vector<Point> &points); + Vector<Point> &get_points(); + + void set_offset(int pos, const float offset); + float get_offset(int pos) const; + + void set_color(int pos, const Color &color); + Color get_color(int pos) const; + + void set_offsets(const Vector<float> &offsets); + Vector<float> get_offsets() const; + + void set_colors(const Vector<Color> &colors); + Vector<Color> get_colors() const; + + void set_width(int p_width); + int get_width() const; + + virtual RID get_rid() const { return texture; } + virtual int get_height() const { return 1; } + virtual bool has_alpha() const { return true; } + + virtual void set_flags(uint32_t p_flags) {} + virtual uint32_t get_flags() const { return FLAG_FILTER; } + + _FORCE_INLINE_ Color get_color_at_offset(float p_offset) { + + if (points.empty()) + return Color(0, 0, 0, 1); + + if (!is_sorted) { + points.sort(); + is_sorted = true; + } + + //binary search + int low = 0; + int high = points.size() - 1; + int middle; + + while (low <= high) { + middle = (low + high) / 2; + Point &point = points[middle]; + if (point.offset > p_offset) { + high = middle - 1; //search low end of array + } else if (point.offset < p_offset) { + low = middle + 1; //search high end of array + } else { + return point.color; + } + } + + //return interpolated value + if (points[middle].offset > p_offset) { + middle--; + } + int first = middle; + int second = middle + 1; + if (second >= points.size()) + return points[points.size() - 1].color; + if (first < 0) + return points[0].color; + Point &pointFirst = points[first]; + Point &pointSecond = points[second]; + return pointFirst.color.linear_interpolate(pointSecond.color, (p_offset - pointFirst.offset) / (pointSecond.offset - pointFirst.offset)); + } + + int get_points_count() const; + + GradientTexture(); + virtual ~GradientTexture(); +}; + #endif diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index 3e128379ae..13fbac3417 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -125,7 +125,7 @@ void TileSet::_get_property_list(List<PropertyInfo> *p_list) const { p_list->push_back(PropertyInfo(Variant::STRING, pre + "name")); p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "tex_offset")); - p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "CanvasItemMaterial")); + p_list->push_back(PropertyInfo(Variant::OBJECT, pre + "material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial")); p_list->push_back(PropertyInfo(Variant::COLOR, pre + "modulate")); p_list->push_back(PropertyInfo(Variant::RECT2, pre + "region")); p_list->push_back(PropertyInfo(Variant::VECTOR2, pre + "occluder_offset")); @@ -159,16 +159,16 @@ Ref<Texture> TileSet::tile_get_texture(int p_id) const { return tile_map[p_id].texture; } -void TileSet::tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material) { +void TileSet::tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material) { ERR_FAIL_COND(!tile_map.has(p_id)); tile_map[p_id].material = p_material; emit_changed(); } -Ref<CanvasItemMaterial> TileSet::tile_get_material(int p_id) const { +Ref<ShaderMaterial> TileSet::tile_get_material(int p_id) const { - ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<CanvasItemMaterial>()); + ERR_FAIL_COND_V(!tile_map.has(p_id), Ref<ShaderMaterial>()); return tile_map[p_id].material; } @@ -403,8 +403,8 @@ void TileSet::_bind_methods() { ClassDB::bind_method(D_METHOD("tile_get_name", "id"), &TileSet::tile_get_name); ClassDB::bind_method(D_METHOD("tile_set_texture", "id", "texture:Texture"), &TileSet::tile_set_texture); ClassDB::bind_method(D_METHOD("tile_get_texture:Texture", "id"), &TileSet::tile_get_texture); - ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material:CanvasItemMaterial"), &TileSet::tile_set_material); - ClassDB::bind_method(D_METHOD("tile_get_material:CanvasItemMaterial", "id"), &TileSet::tile_get_material); + ClassDB::bind_method(D_METHOD("tile_set_material", "id", "material:ShaderMaterial"), &TileSet::tile_set_material); + ClassDB::bind_method(D_METHOD("tile_get_material:ShaderMaterial", "id"), &TileSet::tile_get_material); ClassDB::bind_method(D_METHOD("tile_set_texture_offset", "id", "texture_offset"), &TileSet::tile_set_texture_offset); ClassDB::bind_method(D_METHOD("tile_get_texture_offset", "id"), &TileSet::tile_get_texture_offset); ClassDB::bind_method(D_METHOD("tile_set_shape_offset", "id", "shape_offset"), &TileSet::tile_set_shape_offset); diff --git a/scene/resources/tile_set.h b/scene/resources/tile_set.h index 53f68d00a5..4c8adb760f 100644 --- a/scene/resources/tile_set.h +++ b/scene/resources/tile_set.h @@ -51,7 +51,7 @@ class TileSet : public Resource { Ref<OccluderPolygon2D> occluder; Vector2 navigation_polygon_offset; Ref<NavigationPolygon> navigation_polygon; - Ref<CanvasItemMaterial> material; + Ref<ShaderMaterial> material; Color modulate; // Default modulate for back-compat @@ -92,8 +92,8 @@ public: void tile_set_shape(int p_id, const Ref<Shape2D> &p_shape); Ref<Shape2D> tile_get_shape(int p_id) const; - void tile_set_material(int p_id, const Ref<CanvasItemMaterial> &p_material); - Ref<CanvasItemMaterial> tile_get_material(int p_id) const; + void tile_set_material(int p_id, const Ref<ShaderMaterial> &p_material); + Ref<ShaderMaterial> tile_get_material(int p_id) const; void tile_set_modulate(int p_id, const Color &p_color); Color tile_get_modulate(int p_id) const; |