diff --git a/image.jpg b/image.jpg new file mode 100644 index 0000000..cf9169f Binary files /dev/null and b/image.jpg differ diff --git a/scrMaterial.gml b/scrMaterial.gml new file mode 100644 index 0000000..8a1bca7 --- /dev/null +++ b/scrMaterial.gml @@ -0,0 +1,239 @@ +enum MaterialUniformType {Float, Vec2, Vec3, Vec4, ColorNoAlpha, Color} + +///@param {Asset.GMShader} shader +function Material(shader) constructor { + self.uniforms = {}; + self.names = []; + self.shader = shader; +} + +///@param {Any} value +///@param {Real} type +function MaterialUniform(value, type) constructor { + self.value = value; + self.type = type; + self.debug_display_info = new MaterialUniformValueDisplayInfo(MaterialUniformValueDisplayType.Slider, 0.0, 1.0); +} + +enum MaterialUniformValueDisplayType { + Slider, + ColorNoAlpha, + Color, +} +///@param {real} type +///@param {real} [range_min = 0.0] +///@param {real} [range_max = 1.0] +function MaterialUniformValueDisplayInfo(type, range_min = 0.0, range_max = 1.0) constructor { + self.type = type; + self.range_min = range_min; + self.range_max = range_max; +} + +///@param {Struct.Material} mat +function shader_set_from_material(mat) { + shader_set(mat.shader); + material_apply(mat); +} + +///@param {Struct.Material} mat +///@param {String} key +///@return {Struct} +function material_get_uniform(mat, key) { + return mat.uniforms[$key]; +} + +///@param {Struct.Material} material +///@param {String} key +///@param {Real} type +///@param {Real} [range_min = 0.0] +///@param {Real} [range_max = 1.0] +function material_uniform_set_display_info(material, key, type, range_min = 0.0, range_max = 1.0) { + var _u = material.uniforms[$key]; + switch (type) { + case MaterialUniformValueDisplayType.ColorNoAlpha: + if (_u.type != MaterialUniformType.ColorNoAlpha) { + printerr($"Cannot change debug display type of uniform '{key}' to ColorNoAlpha because it's type doesn't support it ({_u.type})", ERROR_LOC); + return; + } + break; + case MaterialUniformValueDisplayType.Color: + if (_u.type != MaterialUniformType.Color) { + printerr($"Cannot change debug display type of uniform '{key}' to Color because it's type doesn't support it ({_u.type})", ERROR_LOC); + return; + } + break; + } + material.uniforms[$key].debug_display_info.type = type; + material.uniforms[$key].debug_display_info.range_min = range_min; + material.uniforms[$key].debug_display_info.range_max = range_max; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Real} val +///@return {Struct} +function material_add_float(mat, key, val) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec1(val), MaterialUniformType.Float); + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Real} x +///@param {Real} y +///@return {Struct} +function material_add_vec2(mat, key, x, y) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec2(x, y), MaterialUniformType.Vec2); + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Real} x +///@param {Real} y +///@param {Real} z +///@return {Struct} +function material_add_vec3(mat, key, x, y, z) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec3(x, y, z), MaterialUniformType.Vec3); + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Real} x +///@param {Real} y +///@param {Real} z +///@param {Real} w +///@return {Struct} +function material_add_vec4(mat, key, x, y, z, w) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec4(x, y, z, w), MaterialUniformType.Vec4); + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Constant.Color} color +///@return {Struct} +function material_add_color_rgb(mat, key, color) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec1(color), MaterialUniformType.ColorNoAlpha); + _uniform.debug_display_info.type = MaterialUniformValueDisplayType.ColorNoAlpha; + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +///@param {String} key +///@param {Constant.Color} color +///@param {Real} alpha +///@return {Struct} +function material_add_color_rgba(mat, key, color, alpha) { + if (variable_struct_exists(mat.uniforms, key)) { + printerr($"Material already has uniform '{key}'", ERROR_LOC); + return; + } + var _uniform = new MaterialUniform(new Vec2(color, alpha), MaterialUniformType.Color); + _uniform.debug_display_info.type = MaterialUniformValueDisplayType.Color; + array_push(mat.names, key); + variable_struct_set(mat.uniforms, key, _uniform); + return _uniform; +} + +///@param {Struct.Material} mat +function material_apply(mat) { + var _names = variable_struct_get_names(mat.uniforms); + var _sh = shader_current(); + for (var i = 0, n = array_length(_names); i < n; i++) { + var _uniform = variable_struct_get(mat.uniforms, _names[i]); + switch (_uniform.type) { + case MaterialUniformType.Float: + shader_set_uniform_f(shader_get_uniform(_sh, _names[i]), _uniform.value.x); + break; + case MaterialUniformType.Vec2: + shader_set_uniform_f(shader_get_uniform(_sh, _names[i]), _uniform.value.x, _uniform.value.y); + break; + case MaterialUniformType.Vec3: + shader_set_uniform_f(shader_get_uniform(_sh, _names[i]), _uniform.value.x, _uniform.value.y, _uniform.value.z); + break; + case MaterialUniformType.Vec4: + shader_set_uniform_f(shader_get_uniform(_sh, _names[i]), _uniform.value.x, _uniform.value.y, _uniform.value.z, _uniform.value.w); + break; + case MaterialUniformType.ColorNoAlpha: + shader_set_uniform_f( + shader_get_uniform(_sh, _names[i]), + color_get_red(_uniform.value.x) / 255, + color_get_green(_uniform.value.x) / 255, + color_get_blue(_uniform.value.x) / 255); + break; + case MaterialUniformType.Color: + shader_set_uniform_f( + shader_get_uniform(_sh, _names[i]), + color_get_red(_uniform.value.x) / 255, + color_get_green(_uniform.value.x) / 255, + color_get_blue(_uniform.value.x) / 255, + _uniform.value.y); + break; + } + } +} + +///@param {Struct.Material} mat +function material_add_to_debug_view(mat, name) { + if (!DEBUG_MODE) { + return; + } + dbg_set_view(global.debug_views.materials.view); + array_push(global.debug_views.materials.sections, dbg_section(name, false)); + for (var i = 0, n = array_length(mat.names); i < n; i++) { + _material_uniform_add_to_current_debug_view_section(mat.uniforms[$mat.names[i]], mat.names[i]); + } +} + +///@param {Struct.MaterialUniform} uniform +///@param {string} name +function _material_uniform_add_to_current_debug_view_section(uniform, name) { + dbg_text_separator(name); + switch (uniform.debug_display_info.type) { + case MaterialUniformValueDisplayType.Slider: + var _names = struct_get_names(uniform.value); + for (var i = 0, n = array_length(_names); i < n; i++) { + dbg_slider(ref_create(uniform.value, _names[i]), uniform.debug_display_info.range_min, uniform.debug_display_info.range_max); + } + break; + case MaterialUniformValueDisplayType.ColorNoAlpha: + dbg_color(ref_create(uniform.value, "x"), "Color"); + break; + case MaterialUniformValueDisplayType.Color: + dbg_color(ref_create(uniform.value, "x"), "Color"); + dbg_slider(ref_create(uniform.value, "y"), 0.0, 1.0, "Alpha"); + break; + } +}