From acb43b2f3a44dcc0144d2191498b4bf4494b82d6 Mon Sep 17 00:00:00 2001 From: Eric Myllyoja Date: Mon, 18 Jul 2022 00:52:38 -0400 Subject: [PATCH 01/11] Added first working iteration of FlxRuntimeShader. --- flixel/addons/display/FlxRuntimeShader.hx | 712 ++++++++++++++++++++++ 1 file changed, 712 insertions(+) create mode 100644 flixel/addons/display/FlxRuntimeShader.hx diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx new file mode 100644 index 00000000..ca97537b --- /dev/null +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -0,0 +1,712 @@ +package flixel.addons.display; + +import flixel.system.FlxAssets.FlxShader; +import lime.utils.Float32Array; +import openfl.display.BitmapData; +import openfl.display.ShaderInput; +import openfl.display.ShaderParameter; +import openfl.display.ShaderParameterType; + +/** + * An wrapper for Flixel/OpenFL's shaders, which takes fragment and vertex source + * in the constructor instead of using macros, so it can be provided data + * at runtime (for example, when using mods). + * + * HOW TO USE: + * 1. Create an instance of this class, passing the text of the `.frag` and `.vert` files. + * Note that you can set either of these to null (making them both null would make the shader do nothing???). + * 2. Use `flxSprite.shader = runtimeShader` to apply the shader to the sprite. + * 3. Use `runtimeShader.setFloat()`, `setBool()`, etc. to modify any uniforms. + * + * @author MasterEric + * @see https://github.com/openfl/openfl/blob/develop/src/openfl/utils/_internal/ShaderMacro.hx + * @see https://dixonary.co.uk/blog/shadertoy + */ +class FlxRuntimeShader extends FlxShader +{ + #if FLX_DRAW_QUADS + // We need to add stuff from FlxGraphicsShader too! + #else + // Only stuff from openfl.display.Shader is needed + #end + // These variables got copied from openfl.display.GraphicsShader + // and from flixel.graphics.tile.FlxGraphicsShader, + // and probably won't change ever. + static final BASE_VERTEX_HEADER:String = " + #pragma version + + #pragma precision + + attribute float openfl_Alpha; + attribute vec4 openfl_ColorMultiplier; + attribute vec4 openfl_ColorOffset; + attribute vec4 openfl_Position; + attribute vec2 openfl_TextureCoord; + varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform mat4 openfl_Matrix; + uniform bool openfl_HasColorTransform; + uniform vec2 openfl_TextureSize; + "; + static final BASE_VERTEX_BODY:String = " + openfl_Alphav = openfl_Alpha; + openfl_TextureCoordv = openfl_TextureCoord; + if (openfl_HasColorTransform) { + openfl_ColorMultiplierv = openfl_ColorMultiplier; + openfl_ColorOffsetv = openfl_ColorOffset / 255.0; + } + gl_Position = openfl_Matrix * openfl_Position; + "; + + static final BASE_FRAGMENT_HEADER:String = " + #pragma version + + #pragma precision + + varying float openfl_Alphav; + varying vec4 openfl_ColorMultiplierv; + varying vec4 openfl_ColorOffsetv; + varying vec2 openfl_TextureCoordv; + uniform bool openfl_HasColorTransform; + uniform vec2 openfl_TextureSize; + uniform sampler2D bitmap; + " + + #if FLX_DRAW_QUADS + // Add on more stuff! + + " + uniform bool hasTransform; + uniform bool hasColorTransform; + vec4 flixel_texture2D(sampler2D bitmap, vec2 coord) + { + vec4 color = texture2D(bitmap, coord); + if (!hasTransform) + { + return color; + } + if (color.a == 0.0) + { + return vec4(0.0, 0.0, 0.0, 0.0); + } + if (!hasColorTransform) + { + return color * openfl_Alphav; + } + color = vec4(color.rgb / color.a, color.a); + mat4 colorMultiplier = mat4(0); + colorMultiplier[0][0] = openfl_ColorMultiplierv.x; + colorMultiplier[1][1] = openfl_ColorMultiplierv.y; + colorMultiplier[2][2] = openfl_ColorMultiplierv.z; + colorMultiplier[3][3] = openfl_ColorMultiplierv.w; + color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); + if (color.a > 0.0) + { + return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + } + return vec4(0.0, 0.0, 0.0, 0.0); + } + "; + #else + // No additional data. + ; + #end + static final BASE_FRAGMENT_BODY:String = " + vec4 color = texture2D (bitmap, openfl_TextureCoordv); + if (color.a == 0.0) { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } else if (openfl_HasColorTransform) { + color = vec4 (color.rgb / color.a, color.a); + mat4 colorMultiplier = mat4 (0); + colorMultiplier[0][0] = openfl_ColorMultiplierv.x; + colorMultiplier[1][1] = openfl_ColorMultiplierv.y; + colorMultiplier[2][2] = openfl_ColorMultiplierv.z; + colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w; + color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); + if (color.a > 0.0) { + gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); + } else { + gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); + } + } else { + gl_FragColor = color * openfl_Alphav; + } + "; + + #if FLX_DRAW_QUADS + static final DEFAULT_FRAGMENT_SOURCE:String = " + #pragma header + + void main(void) + { + gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); + } + "; + #else + static final DEFAULT_FRAGMENT_SOURCE:String = " + #pragma header + void main(void) { + #pragma body + } + "; + #end + + #if FLX_DRAW_QUADS + static final DEFAULT_VERTEX_SOURCE:String = " + #pragma header + + attribute float alpha; + attribute vec4 colorMultiplier; + attribute vec4 colorOffset; + uniform bool hasColorTransform; + + void main(void) + { + #pragma body + + openfl_Alphav = openfl_Alpha * alpha; + + if (hasColorTransform) + { + openfl_ColorOffsetv = colorOffset / 255.0; + openfl_ColorMultiplierv = colorMultiplier; + } + } + "; + #else + static final DEFAULT_VERTEX_SOURCE:String = " + #pragma header + void main(void) { + #pragma body + } + "; + #end + + static final PRAGMA_HEADER:String = "#pragma header"; + static final PRAGMA_BODY:String = "#pragma body"; + static final PRAGMA_PRECISION:String = "#pragma precision"; + static final PRAGMA_VERSION:String = "#pragma version"; + + private var _glslVersion:Int; + + /** + * Constructs a GLSL shader. + * @param fragmentSource The fragment shader source. + * @param vertexSource The vertex shader source. + * Note you also need to `initialize()` the shader MANUALLY! It can't be done automatically. + */ + public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:Int = 120):Void + { + _glslVersion = glslVersion; + + if (fragmentSource == null) + { + trace('Loading default fragment source...'); + glFragmentSource = processFragmentSource(DEFAULT_FRAGMENT_SOURCE); + } + else + { + trace('Loading fragment source from argument...'); + glFragmentSource = processFragmentSource(fragmentSource); + } + + if (vertexSource == null) + { + var s = processVertexSource(DEFAULT_VERTEX_SOURCE); + glVertexSource = s; + } + else + { + var s = processVertexSource(vertexSource); + glVertexSource = s; + } + + @:privateAccess { + // This tells the shader that the glVertexSource/glFragmentSource have been updated. + __glSourceDirty = true; + // This tells the shader that the shader properties are NOT reflected on this class automatically. + __isGenerated = false; + } + + super(); + } + + /** + * Replace the `#pragma header` and `#pragma body` with the fragment shader header and body. + */ + function processFragmentSource(input:String):String + { + var result = StringTools.replace(input, PRAGMA_HEADER, BASE_FRAGMENT_HEADER); + result = StringTools.replace(result, PRAGMA_BODY, BASE_FRAGMENT_BODY); + return result; + } + + /** + * Replace the `#pragma header` and `#pragma body` with the vertex shader header and body. + */ + function processVertexSource(input:String):String + { + var result = StringTools.replace(input, PRAGMA_HEADER, BASE_VERTEX_HEADER); + result = StringTools.replace(result, PRAGMA_BODY, BASE_VERTEX_BODY); + return result; + } + + function buildPrecisionHeaders():String { + return "#ifdef GL_ES + " + (precisionHint == FULL ? "#ifdef GL_FRAGMENT_PRECISION_HIGH + precision highp float; + #else + precision mediump float; + #endif" : "precision lowp float;") + + " + #endif + "; + } + + /** + * The parent function that initializes the shader. + * This is done to add the `#version` shader directive. + */ + private override function __initGL():Void + { + if (__glSourceDirty || __paramBool == null) + { + __glSourceDirty = false; + program = null; + + __inputBitmapData = new Array(); + __paramBool = new Array(); + __paramFloat = new Array(); + __paramInt = new Array(); + + __processGLData(glVertexSource, "attribute"); + __processGLData(glVertexSource, "uniform"); + __processGLData(glFragmentSource, "uniform"); + } + + @:privateAccess + if (__context != null && program == null) + { + var gl = __context.gl; + + var precisionHeaders = buildPrecisionHeaders(); + var versionHeader = '#version ${_glslVersion}\n'; + + var vertex = StringTools.replace(glVertexSource, PRAGMA_PRECISION, precisionHeaders); + vertex = StringTools.replace(vertex, PRAGMA_VERSION, versionHeader); + var fragment = StringTools.replace(glFragmentSource, PRAGMA_PRECISION, precisionHeaders); + fragment = StringTools.replace(fragment, PRAGMA_VERSION, versionHeader); + + var id = vertex + fragment; + + if (__context.__programs.exists(id)) { + // Use the existing program if it has been compiled. + program = __context.__programs.get(id); + } else { + // Build the program. + program = __context.createProgram(GLSL); + program.__glProgram = __createGLProgram(vertex, fragment); + __context.__programs.set(id, program); + } + + if (program != null) { + glProgram = program.__glProgram; + + // Map attributes for each type. + + for (input in __inputBitmapData) { + if (input.__isUniform) { + input.index = gl.getUniformLocation(glProgram, input.name); + } else { + input.index = gl.getAttribLocation(glProgram, input.name); + } + } + + for (parameter in __paramBool) { + if (parameter.__isUniform) { + parameter.index = gl.getUniformLocation(glProgram, parameter.name); + } else { + parameter.index = gl.getAttribLocation(glProgram, parameter.name); + } + } + + for (parameter in __paramFloat) { + if (parameter.__isUniform) { + parameter.index = gl.getUniformLocation(glProgram, parameter.name); + } else { + parameter.index = gl.getAttribLocation(glProgram, parameter.name); + } + } + + for (parameter in __paramInt) { + if (parameter.__isUniform) { + parameter.index = gl.getUniformLocation(glProgram, parameter.name); + } else { + parameter.index = gl.getAttribLocation(glProgram, parameter.name); + } + } + } + } + } + + private var __fieldList:Array = null; + private function thisHasField(name:String) { + // Reflect.hasField(this, name) is REALLY expensive so we use a cache. + if (__fieldList == null) { + __fieldList = Reflect.fields(this) + .concat(Type.getInstanceFields(Type.getClass(this))); + } + return __fieldList.indexOf(name) != -1; + } + + /** + * The parent function that initializes the shader. + * This is done because some shader fields (such as `bitmap`) have to automatically propagate from the shader, + * but others may not exist or be properties rather than fields. + */ + private override function __processGLData(source:String, storageType:String):Void + { + var position; + var name; + var type; + + var regex = (storageType == "uniform") + ? ~/uniform ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/ + : ~/attribute ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/; + + var lastMatch = 0; + + @:privateAccess + while (regex.matchSub(source, lastMatch)) { + type = regex.matched(1); + name = regex.matched(2); + + if (StringTools.startsWith(name, "gl_")) { + continue; + } + + var isUniform = (storageType == "uniform"); + + if (StringTools.startsWith(type, "sampler")) { + var input = new ShaderInput(); + input.name = name; + input.__isUniform = isUniform; + __inputBitmapData.push(input); + + switch (name) { + case "openfl_Texture": + __texture = input; + case "bitmap": + __bitmap = input; + default: + } + + Reflect.setField(__data, name, input); + if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, input); + } else if (!Reflect.hasField(__data, name) || Reflect.field(__data, name) == null) { + var parameterType:ShaderParameterType = switch (type) + { + case "bool": BOOL; + case "double", "float": FLOAT; + case "int", "uint": INT; + case "bvec2": BOOL2; + case "bvec3": BOOL3; + case "bvec4": BOOL4; + case "ivec2", "uvec2": INT2; + case "ivec3", "uvec3": INT3; + case "ivec4", "uvec4": INT4; + case "vec2", "dvec2": FLOAT2; + case "vec3", "dvec3": FLOAT3; + case "vec4", "dvec4": FLOAT4; + case "mat2", "mat2x2": MATRIX2X2; + case "mat2x3": MATRIX2X3; + case "mat2x4": MATRIX2X4; + case "mat3x2": MATRIX3X2; + case "mat3", "mat3x3": MATRIX3X3; + case "mat3x4": MATRIX3X4; + case "mat4x2": MATRIX4X2; + case "mat4x3": MATRIX4X3; + case "mat4", "mat4x4": MATRIX4X4; + default: null; + } + + var length = switch (parameterType) + { + case BOOL2, INT2, FLOAT2: 2; + case BOOL3, INT3, FLOAT3: 3; + case BOOL4, INT4, FLOAT4, MATRIX2X2: 4; + case MATRIX3X3: 9; + case MATRIX4X4: 16; + default: 1; + } + + var arrayLength = switch (parameterType) + { + case MATRIX2X2: 2; + case MATRIX3X3: 3; + case MATRIX4X4: 4; + default: 1; + } + + switch (parameterType) + { + case BOOL, BOOL2, BOOL3, BOOL4: + var parameter = new ShaderParameter(); + parameter.name = name; + parameter.type = parameterType; + parameter.__arrayLength = arrayLength; + parameter.__isBool = true; + parameter.__isUniform = isUniform; + parameter.__length = length; + __paramBool.push(parameter); + + if (name == "openfl_HasColorTransform") + { + __hasColorTransform = parameter; + } + + Reflect.setField(__data, name, parameter); + if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); + + case INT, INT2, INT3, INT4: + var parameter = new ShaderParameter(); + parameter.name = name; + parameter.type = parameterType; + parameter.__arrayLength = arrayLength; + parameter.__isInt = true; + parameter.__isUniform = isUniform; + parameter.__length = length; + __paramInt.push(parameter); + Reflect.setField(__data, name, parameter); + if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); + + default: + var parameter = new ShaderParameter(); + parameter.name = name; + parameter.type = parameterType; + parameter.__arrayLength = arrayLength; + #if lime + if (arrayLength > 0) parameter.__uniformMatrix = new Float32Array(arrayLength * arrayLength); + #end + parameter.__isFloat = true; + parameter.__isUniform = isUniform; + parameter.__length = length; + __paramFloat.push(parameter); + + if (StringTools.startsWith(name, "openfl_")) + { + switch (name) + { + case "openfl_Alpha": __alpha = parameter; + case "openfl_ColorMultiplier": __colorMultiplier = parameter; + case "openfl_ColorOffset": __colorOffset = parameter; + case "openfl_Matrix": __matrix = parameter; + case "openfl_Position": __position = parameter; + case "openfl_TextureCoord": __textureCoord = parameter; + case "openfl_TextureSize": __textureSize = parameter; + default: + } + } + + Reflect.setField(__data, name, parameter); + if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); + } + } + + position = regex.matchedPos(); + lastMatch = position.pos + position.len; + } + } + /** + * Modify a float parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setFloat(name:String, value:Float):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + @:privateAccess + if (prop == null) + { + trace('[WARN] Shader float property ${name} not found.'); + return; + } + prop.value = [value]; + } + + /** + * Modify a float array parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setFloatArray(name:String, value:Array):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader float[] property ${name} not found.'); + return; + } + prop.value = value; + } + + /** + * Modify an integer parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setInt(name:String, value:Int):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader int property ${name} not found.'); + return; + } + prop.value = [value]; + } + + /** + * Modify an integer array parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setIntArray(name:String, value:Array):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader int[] property ${name} not found.'); + return; + } + prop.value = value; + } + + /** + * Modify a boolean parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setBool(name:String, value:Bool):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader bool property ${name} not found.'); + return; + } + prop.value = [value]; + } + + /** + * Modify a boolean array parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setBoolArray(name:String, value:Array):Void + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader bool[] property ${name} not found.'); + return; + } + prop.value = value; + } + + /** + * Retrieve a float parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getFloat(name:String):Null + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) + { + trace('[WARN] Shader float property ${name} not found.'); + return null; + } + return prop.value[0]; + } + + /** + * Retrieve a float array parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getFloatArray(name:String):Null> + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader float[] property ${name} not found.'); + return null; + } + return prop.value; + } + + /** + * Retrieve an integer parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getInt(name:String):Null + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) + { + trace('[WARN] Shader int property ${name} not found.'); + return null; + } + return prop.value[0]; + } + + /** + * Retrieve an integer array parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getIntArray(name:String):Null> + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader int[] property ${name} not found.'); + return null; + } + return prop.value; + } + + /** + * Retrieve a boolean parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getBool(name:String):Null + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) + { + trace('[WARN] Shader bool property ${name} not found.'); + return null; + } + return prop.value[0]; + } + + /** + * Retrieve a boolean array parameter of the shader. + * @param name The name of the parameter to retrieve. + */ + public function getBoolArray(name:String):Null> + { + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader bool[] property ${name} not found.'); + return null; + } + return prop.value; + } + + public function toString():String + { + return 'FlxRuntimeShader'; + } +} From dd3157a772579564007aede37c71fca11b7f8320 Mon Sep 17 00:00:00 2001 From: Eric Myllyoja Date: Fri, 29 Jul 2022 19:35:40 -0400 Subject: [PATCH 02/11] getBitmapData/setBitmapData, reduced code duplication --- flixel/addons/display/FlxRuntimeShader.hx | 504 +++------------------- 1 file changed, 60 insertions(+), 444 deletions(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index ca97537b..c3357de0 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -1,11 +1,9 @@ package flixel.addons.display; import flixel.system.FlxAssets.FlxShader; -import lime.utils.Float32Array; import openfl.display.BitmapData; import openfl.display.ShaderInput; import openfl.display.ShaderParameter; -import openfl.display.ShaderParameterType; /** * An wrapper for Flixel/OpenFL's shaders, which takes fragment and vertex source @@ -16,7 +14,8 @@ import openfl.display.ShaderParameterType; * 1. Create an instance of this class, passing the text of the `.frag` and `.vert` files. * Note that you can set either of these to null (making them both null would make the shader do nothing???). * 2. Use `flxSprite.shader = runtimeShader` to apply the shader to the sprite. - * 3. Use `runtimeShader.setFloat()`, `setBool()`, etc. to modify any uniforms. + * 3. Use `runtimeShader.setFloat()`, `setBool()` etc. to modify any uniforms. + * 4. Use `setBitmapData()` to add additional textures as `sampler2D` uniforms * * @author MasterEric * @see https://github.com/openfl/openfl/blob/develop/src/openfl/utils/_internal/ShaderMacro.hx @@ -27,168 +26,13 @@ class FlxRuntimeShader extends FlxShader #if FLX_DRAW_QUADS // We need to add stuff from FlxGraphicsShader too! #else - // Only stuff from openfl.display.Shader is needed + // Only stuff from openfl.display.GraphicsShader is needed #end // These variables got copied from openfl.display.GraphicsShader - // and from flixel.graphics.tile.FlxGraphicsShader, - // and probably won't change ever. - static final BASE_VERTEX_HEADER:String = " - #pragma version - - #pragma precision - - attribute float openfl_Alpha; - attribute vec4 openfl_ColorMultiplier; - attribute vec4 openfl_ColorOffset; - attribute vec4 openfl_Position; - attribute vec2 openfl_TextureCoord; - varying float openfl_Alphav; - varying vec4 openfl_ColorMultiplierv; - varying vec4 openfl_ColorOffsetv; - varying vec2 openfl_TextureCoordv; - uniform mat4 openfl_Matrix; - uniform bool openfl_HasColorTransform; - uniform vec2 openfl_TextureSize; - "; - static final BASE_VERTEX_BODY:String = " - openfl_Alphav = openfl_Alpha; - openfl_TextureCoordv = openfl_TextureCoord; - if (openfl_HasColorTransform) { - openfl_ColorMultiplierv = openfl_ColorMultiplier; - openfl_ColorOffsetv = openfl_ColorOffset / 255.0; - } - gl_Position = openfl_Matrix * openfl_Position; - "; - - static final BASE_FRAGMENT_HEADER:String = " - #pragma version - - #pragma precision - - varying float openfl_Alphav; - varying vec4 openfl_ColorMultiplierv; - varying vec4 openfl_ColorOffsetv; - varying vec2 openfl_TextureCoordv; - uniform bool openfl_HasColorTransform; - uniform vec2 openfl_TextureSize; - uniform sampler2D bitmap; - " - - #if FLX_DRAW_QUADS - // Add on more stuff! - + " - uniform bool hasTransform; - uniform bool hasColorTransform; - vec4 flixel_texture2D(sampler2D bitmap, vec2 coord) - { - vec4 color = texture2D(bitmap, coord); - if (!hasTransform) - { - return color; - } - if (color.a == 0.0) - { - return vec4(0.0, 0.0, 0.0, 0.0); - } - if (!hasColorTransform) - { - return color * openfl_Alphav; - } - color = vec4(color.rgb / color.a, color.a); - mat4 colorMultiplier = mat4(0); - colorMultiplier[0][0] = openfl_ColorMultiplierv.x; - colorMultiplier[1][1] = openfl_ColorMultiplierv.y; - colorMultiplier[2][2] = openfl_ColorMultiplierv.z; - colorMultiplier[3][3] = openfl_ColorMultiplierv.w; - color = clamp(openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); - if (color.a > 0.0) - { - return vec4(color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); - } - return vec4(0.0, 0.0, 0.0, 0.0); - } - "; - #else - // No additional data. - ; - #end - static final BASE_FRAGMENT_BODY:String = " - vec4 color = texture2D (bitmap, openfl_TextureCoordv); - if (color.a == 0.0) { - gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); - } else if (openfl_HasColorTransform) { - color = vec4 (color.rgb / color.a, color.a); - mat4 colorMultiplier = mat4 (0); - colorMultiplier[0][0] = openfl_ColorMultiplierv.x; - colorMultiplier[1][1] = openfl_ColorMultiplierv.y; - colorMultiplier[2][2] = openfl_ColorMultiplierv.z; - colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w; - color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0); - if (color.a > 0.0) { - gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav); - } else { - gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0); - } - } else { - gl_FragColor = color * openfl_Alphav; - } - "; - - #if FLX_DRAW_QUADS - static final DEFAULT_FRAGMENT_SOURCE:String = " - #pragma header - - void main(void) - { - gl_FragColor = flixel_texture2D(bitmap, openfl_TextureCoordv); - } - "; - #else - static final DEFAULT_FRAGMENT_SOURCE:String = " - #pragma header - void main(void) { - #pragma body - } - "; - #end - - #if FLX_DRAW_QUADS - static final DEFAULT_VERTEX_SOURCE:String = " - #pragma header - - attribute float alpha; - attribute vec4 colorMultiplier; - attribute vec4 colorOffset; - uniform bool hasColorTransform; - - void main(void) - { - #pragma body - - openfl_Alphav = openfl_Alpha * alpha; - - if (hasColorTransform) - { - openfl_ColorOffsetv = colorOffset / 255.0; - openfl_ColorMultiplierv = colorMultiplier; - } - } - "; - #else - static final DEFAULT_VERTEX_SOURCE:String = " - #pragma header - void main(void) { - #pragma body - } - "; - #end + // and from flixel.graphics.tile.FlxGraphicsShader. static final PRAGMA_HEADER:String = "#pragma header"; static final PRAGMA_BODY:String = "#pragma body"; - static final PRAGMA_PRECISION:String = "#pragma precision"; - static final PRAGMA_VERSION:String = "#pragma version"; - - private var _glslVersion:Int; /** * Constructs a GLSL shader. @@ -198,35 +42,31 @@ class FlxRuntimeShader extends FlxShader */ public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:Int = 120):Void { - _glslVersion = glslVersion; + this.glVersion = glslVersion; if (fragmentSource == null) { - trace('Loading default fragment source...'); - glFragmentSource = processFragmentSource(DEFAULT_FRAGMENT_SOURCE); + this.glFragmentSource = __processFragmentSource(glFragmentSourceRaw); } else { - trace('Loading fragment source from argument...'); - glFragmentSource = processFragmentSource(fragmentSource); + this.glFragmentSource = __processFragmentSource(fragmentSource); } if (vertexSource == null) { - var s = processVertexSource(DEFAULT_VERTEX_SOURCE); - glVertexSource = s; + var s = __processVertexSource(glVertexSourceRaw); + this.glVertexSource = s; } else { - var s = processVertexSource(vertexSource); - glVertexSource = s; + var s = __processVertexSource(vertexSource); + this.glVertexSource = s; } @:privateAccess { // This tells the shader that the glVertexSource/glFragmentSource have been updated. - __glSourceDirty = true; - // This tells the shader that the shader properties are NOT reflected on this class automatically. - __isGenerated = false; + this.__glSourceDirty = true; } super(); @@ -235,291 +75,26 @@ class FlxRuntimeShader extends FlxShader /** * Replace the `#pragma header` and `#pragma body` with the fragment shader header and body. */ - function processFragmentSource(input:String):String + @:noCompletion private function __processFragmentSource(input:String):String { - var result = StringTools.replace(input, PRAGMA_HEADER, BASE_FRAGMENT_HEADER); - result = StringTools.replace(result, PRAGMA_BODY, BASE_FRAGMENT_BODY); + var result = StringTools.replace(input, PRAGMA_HEADER, glFragmentHeaderRaw); + result = StringTools.replace(result, PRAGMA_BODY, glFragmentBodyRaw); return result; } /** * Replace the `#pragma header` and `#pragma body` with the vertex shader header and body. */ - function processVertexSource(input:String):String + @:noCompletion private function __processVertexSource(input:String):String { - var result = StringTools.replace(input, PRAGMA_HEADER, BASE_VERTEX_HEADER); - result = StringTools.replace(result, PRAGMA_BODY, BASE_VERTEX_BODY); + var result = StringTools.replace(input, PRAGMA_HEADER, glVertexHeaderRaw); + result = StringTools.replace(result, PRAGMA_BODY, glVertexBodyRaw); return result; } - function buildPrecisionHeaders():String { - return "#ifdef GL_ES - " + (precisionHint == FULL ? "#ifdef GL_FRAGMENT_PRECISION_HIGH - precision highp float; - #else - precision mediump float; - #endif" : "precision lowp float;") - + " - #endif - "; - } - - /** - * The parent function that initializes the shader. - * This is done to add the `#version` shader directive. - */ - private override function __initGL():Void - { - if (__glSourceDirty || __paramBool == null) - { - __glSourceDirty = false; - program = null; - - __inputBitmapData = new Array(); - __paramBool = new Array(); - __paramFloat = new Array(); - __paramInt = new Array(); - - __processGLData(glVertexSource, "attribute"); - __processGLData(glVertexSource, "uniform"); - __processGLData(glFragmentSource, "uniform"); - } - - @:privateAccess - if (__context != null && program == null) - { - var gl = __context.gl; - - var precisionHeaders = buildPrecisionHeaders(); - var versionHeader = '#version ${_glslVersion}\n'; - - var vertex = StringTools.replace(glVertexSource, PRAGMA_PRECISION, precisionHeaders); - vertex = StringTools.replace(vertex, PRAGMA_VERSION, versionHeader); - var fragment = StringTools.replace(glFragmentSource, PRAGMA_PRECISION, precisionHeaders); - fragment = StringTools.replace(fragment, PRAGMA_VERSION, versionHeader); - - var id = vertex + fragment; - - if (__context.__programs.exists(id)) { - // Use the existing program if it has been compiled. - program = __context.__programs.get(id); - } else { - // Build the program. - program = __context.createProgram(GLSL); - program.__glProgram = __createGLProgram(vertex, fragment); - __context.__programs.set(id, program); - } - - if (program != null) { - glProgram = program.__glProgram; - - // Map attributes for each type. - - for (input in __inputBitmapData) { - if (input.__isUniform) { - input.index = gl.getUniformLocation(glProgram, input.name); - } else { - input.index = gl.getAttribLocation(glProgram, input.name); - } - } - - for (parameter in __paramBool) { - if (parameter.__isUniform) { - parameter.index = gl.getUniformLocation(glProgram, parameter.name); - } else { - parameter.index = gl.getAttribLocation(glProgram, parameter.name); - } - } - - for (parameter in __paramFloat) { - if (parameter.__isUniform) { - parameter.index = gl.getUniformLocation(glProgram, parameter.name); - } else { - parameter.index = gl.getAttribLocation(glProgram, parameter.name); - } - } - - for (parameter in __paramInt) { - if (parameter.__isUniform) { - parameter.index = gl.getUniformLocation(glProgram, parameter.name); - } else { - parameter.index = gl.getAttribLocation(glProgram, parameter.name); - } - } - } - } - } - - private var __fieldList:Array = null; - private function thisHasField(name:String) { - // Reflect.hasField(this, name) is REALLY expensive so we use a cache. - if (__fieldList == null) { - __fieldList = Reflect.fields(this) - .concat(Type.getInstanceFields(Type.getClass(this))); - } - return __fieldList.indexOf(name) != -1; - } - - /** - * The parent function that initializes the shader. - * This is done because some shader fields (such as `bitmap`) have to automatically propagate from the shader, - * but others may not exist or be properties rather than fields. - */ - private override function __processGLData(source:String, storageType:String):Void - { - var position; - var name; - var type; - - var regex = (storageType == "uniform") - ? ~/uniform ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/ - : ~/attribute ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/; - - var lastMatch = 0; - - @:privateAccess - while (regex.matchSub(source, lastMatch)) { - type = regex.matched(1); - name = regex.matched(2); - - if (StringTools.startsWith(name, "gl_")) { - continue; - } - - var isUniform = (storageType == "uniform"); - - if (StringTools.startsWith(type, "sampler")) { - var input = new ShaderInput(); - input.name = name; - input.__isUniform = isUniform; - __inputBitmapData.push(input); - - switch (name) { - case "openfl_Texture": - __texture = input; - case "bitmap": - __bitmap = input; - default: - } - - Reflect.setField(__data, name, input); - if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, input); - } else if (!Reflect.hasField(__data, name) || Reflect.field(__data, name) == null) { - var parameterType:ShaderParameterType = switch (type) - { - case "bool": BOOL; - case "double", "float": FLOAT; - case "int", "uint": INT; - case "bvec2": BOOL2; - case "bvec3": BOOL3; - case "bvec4": BOOL4; - case "ivec2", "uvec2": INT2; - case "ivec3", "uvec3": INT3; - case "ivec4", "uvec4": INT4; - case "vec2", "dvec2": FLOAT2; - case "vec3", "dvec3": FLOAT3; - case "vec4", "dvec4": FLOAT4; - case "mat2", "mat2x2": MATRIX2X2; - case "mat2x3": MATRIX2X3; - case "mat2x4": MATRIX2X4; - case "mat3x2": MATRIX3X2; - case "mat3", "mat3x3": MATRIX3X3; - case "mat3x4": MATRIX3X4; - case "mat4x2": MATRIX4X2; - case "mat4x3": MATRIX4X3; - case "mat4", "mat4x4": MATRIX4X4; - default: null; - } - - var length = switch (parameterType) - { - case BOOL2, INT2, FLOAT2: 2; - case BOOL3, INT3, FLOAT3: 3; - case BOOL4, INT4, FLOAT4, MATRIX2X2: 4; - case MATRIX3X3: 9; - case MATRIX4X4: 16; - default: 1; - } - - var arrayLength = switch (parameterType) - { - case MATRIX2X2: 2; - case MATRIX3X3: 3; - case MATRIX4X4: 4; - default: 1; - } - - switch (parameterType) - { - case BOOL, BOOL2, BOOL3, BOOL4: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - parameter.__isBool = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramBool.push(parameter); - - if (name == "openfl_HasColorTransform") - { - __hasColorTransform = parameter; - } - - Reflect.setField(__data, name, parameter); - if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); - - case INT, INT2, INT3, INT4: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - parameter.__isInt = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramInt.push(parameter); - Reflect.setField(__data, name, parameter); - if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); - - default: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - #if lime - if (arrayLength > 0) parameter.__uniformMatrix = new Float32Array(arrayLength * arrayLength); - #end - parameter.__isFloat = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramFloat.push(parameter); - - if (StringTools.startsWith(name, "openfl_")) - { - switch (name) - { - case "openfl_Alpha": __alpha = parameter; - case "openfl_ColorMultiplier": __colorMultiplier = parameter; - case "openfl_ColorOffset": __colorOffset = parameter; - case "openfl_Matrix": __matrix = parameter; - case "openfl_Position": __position = parameter; - case "openfl_TextureCoord": __textureCoord = parameter; - case "openfl_TextureSize": __textureSize = parameter; - default: - } - } - - Reflect.setField(__data, name, parameter); - if (__isGenerated && thisHasField(name)) Reflect.setProperty(this, name, parameter); - } - } - - position = regex.matchedPos(); - lastMatch = position.pos + position.len; - } - } /** * Modify a float parameter of the shader. + * * @param name The name of the parameter to modify. * @param value The new value to use. */ @@ -537,6 +112,7 @@ class FlxRuntimeShader extends FlxShader /** * Modify a float array parameter of the shader. + * * @param name The name of the parameter to modify. * @param value The new value to use. */ @@ -553,6 +129,7 @@ class FlxRuntimeShader extends FlxShader /** * Modify an integer parameter of the shader. + * * @param name The name of the parameter to modify. * @param value The new value to use. */ @@ -569,6 +146,7 @@ class FlxRuntimeShader extends FlxShader /** * Modify an integer array parameter of the shader. + * * @param name The name of the parameter to modify. * @param value The new value to use. */ @@ -615,9 +193,26 @@ class FlxRuntimeShader extends FlxShader prop.value = value; } + /** + * Modify a bitmap data parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. + */ + public function setBitmapData(name:String, value:openfl.display.BitmapData):Void + { + var prop:ShaderInput = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader sampler2D property ${name} not found.'); + return; + } + prop.input = value; + } + /** * Retrieve a float parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getFloat(name:String):Null { @@ -633,6 +228,7 @@ class FlxRuntimeShader extends FlxShader /** * Retrieve a float array parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getFloatArray(name:String):Null> { @@ -648,6 +244,7 @@ class FlxRuntimeShader extends FlxShader /** * Retrieve an integer parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getInt(name:String):Null { @@ -663,6 +260,7 @@ class FlxRuntimeShader extends FlxShader /** * Retrieve an integer array parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getIntArray(name:String):Null> { @@ -678,6 +276,7 @@ class FlxRuntimeShader extends FlxShader /** * Retrieve a boolean parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getBool(name:String):Null { @@ -693,6 +292,7 @@ class FlxRuntimeShader extends FlxShader /** * Retrieve a boolean array parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ public function getBoolArray(name:String):Null> { @@ -705,6 +305,22 @@ class FlxRuntimeShader extends FlxShader return prop.value; } + /** + * Retrieve a bitmap data parameter of the shader. + * @param name The name of the parameter to retrieve. + * @return The value of the parameter. + */ + public function getBitmapData(name:String):Null + { + var prop:ShaderInput = Reflect.field(this.data, name); + if (prop == null) + { + trace('[WARN] Shader sampler2D property ${name} not found.'); + return null; + } + return prop.input; + } + public function toString():String { return 'FlxRuntimeShader'; From 752c3d72076ef38207eb04d7efd73c53e0818d3a Mon Sep 17 00:00:00 2001 From: Eric Myllyoja Date: Fri, 9 Dec 2022 04:04:12 -0500 Subject: [PATCH 03/11] Change glVersion to a string --- flixel/addons/display/FlxRuntimeShader.hx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index c3357de0..ad5e9bbf 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -40,9 +40,10 @@ class FlxRuntimeShader extends FlxShader * @param vertexSource The vertex shader source. * Note you also need to `initialize()` the shader MANUALLY! It can't be done automatically. */ - public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:Int = 120):Void + public function new(fragmentSource:String = null, vertexSource:String = null, glVersion:String = null):Void { - this.glVersion = glslVersion; + if (glVersion != null) + this.glVersion = glVersion; if (fragmentSource == null) { From 0d9022ac4e4784665110657bb4005e6ff18fbc1f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 1 Sep 2023 22:00:06 -0400 Subject: [PATCH 04/11] Fix bad merge --- flixel/addons/display/FlxRuntimeShader.hx | 207 ---------------------- 1 file changed, 207 deletions(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index 0fa5bd10..7e83c9a8 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -101,7 +101,6 @@ class FlxRuntimeShader extends FlxShader */ public function setFloat(name:String, value:Float):Void { -<<<<<<< HEAD var prop:ShaderParameter = Reflect.field(this.data, name); @:privateAccess if (prop == null) @@ -109,22 +108,10 @@ class FlxRuntimeShader extends FlxShader trace('[WARN] Shader float property ${name} not found.'); return; } -======= - var prop:ShaderParameter = Reflect.field(data, name); - - if (prop == null) - { - FlxG.log.warn('Shader float property "$name" not found.'); - return; - } - ->>>>>>> flixel/dev prop.value = [value]; } /** -<<<<<<< HEAD -======= * Retrieve a float parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -143,7 +130,6 @@ class FlxRuntimeShader extends FlxShader } /** ->>>>>>> flixel/dev * Modify a float array parameter of the shader. * * @param name The name of the parameter to modify. @@ -151,14 +137,6 @@ class FlxRuntimeShader extends FlxShader */ public function setFloatArray(name:String, value:Array):Void { -<<<<<<< HEAD - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader float[] property ${name} not found.'); - return; - } -======= var prop:ShaderParameter = Reflect.field(data, name); if (prop == null) @@ -167,13 +145,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.value = value; } /** -<<<<<<< HEAD -======= * Retrieve a float array parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -192,7 +167,6 @@ class FlxRuntimeShader extends FlxShader } /** ->>>>>>> flixel/dev * Modify an integer parameter of the shader. * * @param name The name of the parameter to modify. @@ -200,14 +174,6 @@ class FlxRuntimeShader extends FlxShader */ public function setInt(name:String, value:Int):Void { -<<<<<<< HEAD - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader int property ${name} not found.'); - return; - } -======= var prop:ShaderParameter = Reflect.field(data, name); if (prop == null) @@ -216,13 +182,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.value = [value]; } /** -<<<<<<< HEAD -======= * Retrieve an integer parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -241,7 +204,6 @@ class FlxRuntimeShader extends FlxShader } /** ->>>>>>> flixel/dev * Modify an integer array parameter of the shader. * * @param name The name of the parameter to modify. @@ -249,14 +211,6 @@ class FlxRuntimeShader extends FlxShader */ public function setIntArray(name:String, value:Array):Void { -<<<<<<< HEAD - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader int[] property ${name} not found.'); - return; - } -======= var prop:ShaderParameter = Reflect.field(data, name); if (prop == null) @@ -265,14 +219,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.value = value; } /** -<<<<<<< HEAD - * Modify a boolean parameter of the shader. -======= * Retrieve an integer array parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -293,20 +243,11 @@ class FlxRuntimeShader extends FlxShader /** * Modify a bool parameter of the shader. * ->>>>>>> flixel/dev * @param name The name of the parameter to modify. * @param value The new value to use. */ public function setBool(name:String, value:Bool):Void { -<<<<<<< HEAD - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader bool property ${name} not found.'); - return; - } -======= var prop:ShaderParameter = Reflect.field(data, name); if (prop == null) @@ -315,14 +256,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.value = [value]; } /** -<<<<<<< HEAD - * Modify a boolean array parameter of the shader. -======= * Retrieve a bool parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -343,20 +280,11 @@ class FlxRuntimeShader extends FlxShader /** * Modify a bool array parameter of the shader. * ->>>>>>> flixel/dev * @param name The name of the parameter to modify. * @param value The new value to use. */ public function setBoolArray(name:String, value:Array):Void { -<<<<<<< HEAD - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader bool[] property ${name} not found.'); - return; - } -======= var prop:ShaderParameter = Reflect.field(data, name); if (prop == null) @@ -365,25 +293,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.value = value; } /** -<<<<<<< HEAD - * Modify a bitmap data parameter of the shader. - * @param name The name of the parameter to modify. - * @param value The new value to use. - */ - public function setBitmapData(name:String, value:openfl.display.BitmapData):Void - { - var prop:ShaderInput = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader sampler2D property ${name} not found.'); - return; - } -======= * Retrieve a bool array parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -417,129 +330,10 @@ class FlxRuntimeShader extends FlxShader return; } ->>>>>>> flixel/dev prop.input = value; } /** -<<<<<<< HEAD - * Retrieve a float parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getFloat(name:String):Null - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null || prop.value.length == 0) - { - trace('[WARN] Shader float property ${name} not found.'); - return null; - } - return prop.value[0]; - } - - /** - * Retrieve a float array parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getFloatArray(name:String):Null> - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader float[] property ${name} not found.'); - return null; - } - return prop.value; - } - - /** - * Retrieve an integer parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getInt(name:String):Null - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null || prop.value.length == 0) - { - trace('[WARN] Shader int property ${name} not found.'); - return null; - } - return prop.value[0]; - } - - /** - * Retrieve an integer array parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getIntArray(name:String):Null> - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader int[] property ${name} not found.'); - return null; - } - return prop.value; - } - - /** - * Retrieve a boolean parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getBool(name:String):Null - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null || prop.value.length == 0) - { - trace('[WARN] Shader bool property ${name} not found.'); - return null; - } - return prop.value[0]; - } - - /** - * Retrieve a boolean array parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getBoolArray(name:String):Null> - { - var prop:ShaderParameter = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader bool[] property ${name} not found.'); - return null; - } - return prop.value; - } - - /** - * Retrieve a bitmap data parameter of the shader. - * @param name The name of the parameter to retrieve. - * @return The value of the parameter. - */ - public function getBitmapData(name:String):Null - { - var prop:ShaderInput = Reflect.field(this.data, name); - if (prop == null) - { - trace('[WARN] Shader sampler2D property ${name} not found.'); - return null; - } - return prop.input; - } - - public function toString():String - { - return 'FlxRuntimeShader'; - } -} -======= * Retrieve a bitmap data parameter of the shader. * * @param name The name of the parameter to retrieve. @@ -767,4 +561,3 @@ class FlxRuntimeShader extends FlxShader } } #end ->>>>>>> flixel/dev From c8c41e26d463aaf2edc0582fb23b6e228235bd16 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 2 Sep 2023 00:52:01 -0400 Subject: [PATCH 05/11] ACTUALLY fix merge --- flixel/addons/display/FlxRuntimeShader.hx | 413 +++++----------------- 1 file changed, 89 insertions(+), 324 deletions(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index 7e83c9a8..77c33905 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -40,10 +40,9 @@ class FlxRuntimeShader extends FlxShader * @param vertexSource The vertex shader source. * Note you also need to `initialize()` the shader MANUALLY! It can't be done automatically. */ - public function new(fragmentSource:String = null, vertexSource:String = null, glVersion:String = null):Void + public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:String = "120"):Void { - if (glVersion != null) - this.glVersion = glVersion; + this.glVersion = glslVersion; if (fragmentSource == null) { @@ -112,452 +111,218 @@ class FlxRuntimeShader extends FlxShader } /** - * Retrieve a float parameter of the shader. + * Modify a float array parameter of the shader. * - * @param name The name of the parameter to retrieve. + * @param name The name of the parameter to modify. + * @param value The new value to use. */ - public function getFloat(name:String):Null + public function setFloatArray(name:String, value:Array):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader float property "$name" not found.'); - return null; + trace('[WARN] Shader float[] property ${name} not found.'); + return; } - - return prop.value[0]; + prop.value = value; } /** - * Modify a float array parameter of the shader. + * Modify an integer parameter of the shader. * * @param name The name of the parameter to modify. * @param value The new value to use. */ - public function setFloatArray(name:String, value:Array):Void + public function setInt(name:String, value:Int):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader float[] property "$name" not found.'); + trace('[WARN] Shader int property ${name} not found.'); return; } - - prop.value = value; + prop.value = [value]; } /** - * Retrieve a float array parameter of the shader. + * Modify an integer array parameter of the shader. * - * @param name The name of the parameter to retrieve. + * @param name The name of the parameter to modify. + * @param value The new value to use. */ - public function getFloatArray(name:String):Null> + public function setIntArray(name:String, value:Array):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader float[] property "$name" not found.'); - return null; + trace('[WARN] Shader int[] property ${name} not found.'); + return; } - - return prop.value; + prop.value = value; } /** - * Modify an integer parameter of the shader. - * + * Modify a boolean parameter of the shader. * @param name The name of the parameter to modify. * @param value The new value to use. */ - public function setInt(name:String, value:Int):Void + public function setBool(name:String, value:Bool):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader int property "$name" not found.'); + trace('[WARN] Shader bool property ${name} not found.'); return; } - prop.value = [value]; } /** - * Retrieve an integer parameter of the shader. - * - * @param name The name of the parameter to retrieve. + * Modify a boolean array parameter of the shader. + * @param name The name of the parameter to modify. + * @param value The new value to use. */ - public function getInt(name:String):Null + public function setBoolArray(name:String, value:Array):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader int property "$name" not found.'); - return null; + trace('[WARN] Shader bool[] property ${name} not found.'); + return; } - - return prop.value[0]; + prop.value = value; } /** - * Modify an integer array parameter of the shader. - * + * Modify a bitmap data parameter of the shader. * @param name The name of the parameter to modify. * @param value The new value to use. */ - public function setIntArray(name:String, value:Array):Void + public function setBitmapData(name:String, value:openfl.display.BitmapData):Void { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderInput = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader int[] property "$name" not found.'); + trace('[WARN] Shader sampler2D property ${name} not found.'); return; } - - prop.value = value; + prop.input = value; } /** - * Retrieve an integer array parameter of the shader. - * + * Retrieve a float parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function getIntArray(name:String):Null> + public function getFloat(name:String):Null { - var prop:ShaderParameter = Reflect.field(data, name); - - if (prop == null) + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) { - FlxG.log.warn('Shader int[] property "$name" not found.'); + trace('[WARN] Shader float property ${name} not found.'); return null; } - - return prop.value; + return prop.value[0]; } /** - * Modify a bool parameter of the shader. - * - * @param name The name of the parameter to modify. - * @param value The new value to use. + * Retrieve a float array parameter of the shader. + * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function setBool(name:String, value:Bool):Void + public function getFloatArray(name:String):Null> { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader bool property "$name" not found.'); - return; + trace('[WARN] Shader float[] property ${name} not found.'); + return null; } - - prop.value = [value]; + return prop.value; } /** - * Retrieve a bool parameter of the shader. - * + * Retrieve an integer parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function getBool(name:String):Null + public function getInt(name:String):Null { - var prop:ShaderParameter = Reflect.field(data, name); - - if (prop == null) + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) { - FlxG.log.warn('Shader bool property "$name" not found.'); + trace('[WARN] Shader int property ${name} not found.'); return null; } - return prop.value[0]; } /** - * Modify a bool array parameter of the shader. - * - * @param name The name of the parameter to modify. - * @param value The new value to use. + * Retrieve an integer array parameter of the shader. + * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function setBoolArray(name:String, value:Array):Void + public function getIntArray(name:String):Null> { - var prop:ShaderParameter = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader bool[] property "$name" not found.'); - return; + trace('[WARN] Shader int[] property ${name} not found.'); + return null; } - - prop.value = value; + return prop.value; } /** - * Retrieve a bool array parameter of the shader. - * + * Retrieve a boolean parameter of the shader. * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function getBoolArray(name:String):Null> + public function getBool(name:String):Null { - var prop:ShaderParameter = Reflect.field(data, name); - - if (prop == null) + var prop:ShaderParameter = Reflect.field(this.data, name); + if (prop == null || prop.value.length == 0) { - FlxG.log.warn('Shader bool[] property "$name" not found.'); + trace('[WARN] Shader bool property ${name} not found.'); return null; } - - return prop.value; + return prop.value[0]; } /** - * Modify a bitmap data parameter of the shader. - * - * @param name The name of the parameter to modify. - * @param value The new value to use. + * Retrieve a boolean array parameter of the shader. + * @param name The name of the parameter to retrieve. + * @return The value of the parameter. */ - public function setSampler2D(name:String, value:BitmapData):Void + public function getBoolArray(name:String):Null> { - var prop:ShaderInput = Reflect.field(data, name); - + var prop:ShaderParameter = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader sampler2D property "$name" not found.'); - return; + trace('[WARN] Shader bool[] property ${name} not found.'); + return null; } - - prop.input = value; + return prop.value; } /** * Retrieve a bitmap data parameter of the shader. - * * @param name The name of the parameter to retrieve. * @return The value of the parameter. */ - public function getSampler2D(name:String):Null + public function getBitmapData(name:String):Null { - var prop:ShaderInput = Reflect.field(data, name); - + var prop:ShaderInput = Reflect.field(this.data, name); if (prop == null) { - FlxG.log.warn('Shader sampler2D property "$name" not found.'); + trace('[WARN] Shader sampler2D property ${name} not found.'); return null; } - return prop.input; } - // Overrides - @:noCompletion private override function __processGLData(source:String, storageType:String):Void - { - var lastMatch = 0, position, regex, name, type; - - if (storageType == "uniform") - { - regex = ~/uniform ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/; - } - else - { - regex = ~/attribute ([A-Za-z0-9]+) ([A-Za-z0-9_]+)/; - } - - @:privateAccess - while (regex.matchSub(source, lastMatch)) - { - type = regex.matched(1); - name = regex.matched(2); - - if (StringTools.startsWith(name, "gl_")) - continue; - - var isUniform = (storageType == "uniform"); - - if (StringTools.startsWith(type, "sampler")) - { - var input = new ShaderInput(); - input.name = name; - input.__isUniform = isUniform; - __inputBitmapData.push(input); - - switch (name) - { - case "openfl_Texture": - __texture = input; - case "bitmap": - __bitmap = input; - default: - } - - Reflect.setField(__data, name, input); - - try - { - if (__isGenerated) - Reflect.setField(this, name, input); - } - catch (e:Dynamic) {} - } - else if (!Reflect.hasField(__data, name) || Reflect.field(__data, name) == null) - { - var parameterType:ShaderParameterType = switch (type) - { - case "bool": BOOL; - case "double", "float": FLOAT; - case "int", "uint": INT; - case "bvec2": BOOL2; - case "bvec3": BOOL3; - case "bvec4": BOOL4; - case "ivec2", "uvec2": INT2; - case "ivec3", "uvec3": INT3; - case "ivec4", "uvec4": INT4; - case "vec2", "dvec2": FLOAT2; - case "vec3", "dvec3": FLOAT3; - case "vec4", "dvec4": FLOAT4; - case "mat2", "mat2x2": MATRIX2X2; - case "mat2x3": MATRIX2X3; - case "mat2x4": MATRIX2X4; - case "mat3x2": MATRIX3X2; - case "mat3", "mat3x3": MATRIX3X3; - case "mat3x4": MATRIX3X4; - case "mat4x2": MATRIX4X2; - case "mat4x3": MATRIX4X3; - case "mat4", "mat4x4": MATRIX4X4; - default: null; - } - - var length = switch (parameterType) - { - case BOOL2, INT2, FLOAT2: 2; - case BOOL3, INT3, FLOAT3: 3; - case BOOL4, INT4, FLOAT4, MATRIX2X2: 4; - case MATRIX3X3: 9; - case MATRIX4X4: 16; - default: 1; - } - - var arrayLength = switch (parameterType) - { - case MATRIX2X2: 2; - case MATRIX3X3: 3; - case MATRIX4X4: 4; - default: 1; - } - - switch (parameterType) - { - case BOOL, BOOL2, BOOL3, BOOL4: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - parameter.__isBool = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramBool.push(parameter); - - if (name == "openfl_HasColorTransform") - { - __hasColorTransform = parameter; - } - - Reflect.setField(__data, name, parameter); - - try - { - if (__isGenerated) - Reflect.setField(this, name, parameter); - } - catch (e:Dynamic) {} - - case INT, INT2, INT3, INT4: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - parameter.__isInt = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramInt.push(parameter); - - Reflect.setField(__data, name, parameter); - - try - { - if (__isGenerated) - Reflect.setField(this, name, parameter); - } - catch (e:Dynamic) {} - - default: - var parameter = new ShaderParameter(); - parameter.name = name; - parameter.type = parameterType; - parameter.__arrayLength = arrayLength; - #if lime - if (arrayLength > 0) - parameter.__uniformMatrix = new Float32Array(arrayLength * arrayLength); - #end - parameter.__isFloat = true; - parameter.__isUniform = isUniform; - parameter.__length = length; - __paramFloat.push(parameter); - - if (StringTools.startsWith(name, "openfl_")) - { - switch (name) - { - case "openfl_Alpha": __alpha = parameter; - case "openfl_ColorMultiplier": __colorMultiplier = parameter; - case "openfl_ColorOffset": __colorOffset = parameter; - case "openfl_Matrix": __matrix = parameter; - case "openfl_Position": __position = parameter; - case "openfl_TextureCoord": __textureCoord = parameter; - case "openfl_TextureSize": __textureSize = parameter; - default: - } - } - - Reflect.setField(__data, name, parameter); - - try - { - if (__isGenerated) - Reflect.setField(this, name, parameter); - } - catch (e:Dynamic) {} - } - } - - position = regex.matchedPos(); - lastMatch = position.pos + position.len; - } - } - - @:noCompletion private override function set_glFragmentSource(value:String):String + public function toString():String { - if (value != null) - value = value.replace("#pragma header", BASE_FRAGMENT_HEADER).replace("#pragma body", BASE_FRAGMENT_BODY); - - if (value != __glFragmentSource) - __glSourceDirty = true; - - return __glFragmentSource = value; - } - - @:noCompletion private override function set_glVertexSource(value:String):String - { - if (value != null) - value = value.replace("#pragma header", BASE_VERTEX_HEADER).replace("#pragma body", BASE_VERTEX_BODY); - - if (value != __glVertexSource) - __glSourceDirty = true; - - return __glVertexSource = value; + return 'FlxRuntimeShader'; } } -#end From 56ff32074211eb7c10971c3eb1c3f94e7fe43c7f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 15 Dec 2023 02:28:26 -0500 Subject: [PATCH 06/11] Fall back to per-platform default shader --- flixel/addons/display/FlxRuntimeShader.hx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index 77c33905..6d56fa15 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -40,9 +40,12 @@ class FlxRuntimeShader extends FlxShader * @param vertexSource The vertex shader source. * Note you also need to `initialize()` the shader MANUALLY! It can't be done automatically. */ - public function new(fragmentSource:String = null, vertexSource:String = null, glslVersion:String = "120"):Void + public function new(?fragmentSource:String, ?vertexSource:String, ?glslVersion:String):Void { - this.glVersion = glslVersion; + if (glslVersion != null) { + // Don't set the value (use getDefaultGLVersion) if it's null. + this.glVersion = glslVersion; + } if (fragmentSource == null) { From a523c3b56622f0640933944171efed46929e360e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 2 Feb 2024 21:56:55 -0500 Subject: [PATCH 07/11] Add support for clipRects to FlxTiledSprite. --- flixel/addons/display/FlxTiledSprite.hx | 81 +++++++++++++------------ 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/flixel/addons/display/FlxTiledSprite.hx b/flixel/addons/display/FlxTiledSprite.hx index b47b8efe..74961a5f 100644 --- a/flixel/addons/display/FlxTiledSprite.hx +++ b/flixel/addons/display/FlxTiledSprite.hx @@ -8,6 +8,7 @@ import flixel.math.FlxMath; import flixel.system.FlxAssets.FlxGraphicAsset; import flixel.util.FlxColor; import flixel.util.FlxDestroyUtil; +import flixel.math.FlxRect; import flixel.util.FlxSpriteUtil; /** @@ -106,6 +107,14 @@ class FlxTiledSprite extends FlxStrip return this; } + override function set_clipRect(Value:FlxRect):FlxRect + { + if (Value != clipRect) + regen = true; + + return super.set_clipRect(Value); + } + override function set_graphic(Value:FlxGraphic):FlxGraphic { if (graphic != Value) @@ -216,51 +225,47 @@ class FlxTiledSprite extends FlxStrip var frame:FlxFrame = graphic.imageFrame.frame; graphicVisible = true; - if (repeatX) - { - vertices[0] = vertices[6] = 0.0; - vertices[2] = vertices[4] = width; + var rectX:Float = (repeatX ? 0 : scrollX); + rectX = FlxMath.bound(rectX, 0, width); + if (clipRect != null) rectX += clipRect.x; - uvtData[0] = uvtData[6] = -scrollX / frame.sourceSize.x; - uvtData[2] = uvtData[4] = uvtData[0] + width / frame.sourceSize.x; - } - else - { - vertices[0] = vertices[6] = FlxMath.bound(scrollX, 0, width); - vertices[2] = vertices[4] = FlxMath.bound(scrollX + frame.sourceSize.x, 0, width); + var rectWidth:Float = (repeatX ? rectX + width : scrollX + frame.sourceSize.x); + if (clipRect != null) rectWidth = FlxMath.bound(rectWidth, clipRect.x, clipRect.x + clipRect.width); - if (vertices[2] - vertices[0] <= 0) - { - graphicVisible = false; - return; - } + // Texture coordinates (UVs) + var rectUX:Float = (rectX - scrollX) / frame.sourceSize.x; + var rectVX:Float = rectUX + (rectWidth-rectX) / frame.sourceSize.x; - uvtData[0] = uvtData[6] = (vertices[0] - scrollX) / frame.sourceSize.x; - uvtData[2] = uvtData[4] = uvtData[0] + (vertices[2] - vertices[0]) / frame.sourceSize.x; - } + vertices[0] = rectX; + vertices[2] = rectWidth; + vertices[4] = rectWidth; + vertices[6] = rectX; - if (repeatY) - { - vertices[1] = vertices[3] = 0.0; - vertices[5] = vertices[7] = height; + uvtData[0] = rectUX; + uvtData[2] = rectVX; + uvtData[4] = rectVX; + uvtData[6] = rectUX; - uvtData[1] = uvtData[3] = -scrollY / frame.sourceSize.y; - uvtData[5] = uvtData[7] = uvtData[1] + height / frame.sourceSize.y; - } - else - { - vertices[1] = vertices[3] = FlxMath.bound(scrollY, 0, height); - vertices[5] = vertices[7] = FlxMath.bound(scrollY + frame.sourceSize.y, 0, height); + var rectY:Float = (repeatY ? 0 : scrollY); + rectY = FlxMath.bound(rectY, 0, height); + if (clipRect != null) rectY += clipRect.y; - if (vertices[5] - vertices[1] <= 0) - { - graphicVisible = false; - return; - } + var rectHeight:Float = (repeatY ? rectY + height : scrollY + frame.sourceSize.y); + if (clipRect != null) rectHeight = FlxMath.bound(rectHeight, clipRect.y, clipRect.y + clipRect.height); - uvtData[1] = uvtData[3] = (vertices[1] - scrollY) / frame.sourceSize.y; - uvtData[5] = uvtData[7] = uvtData[1] + (vertices[5] - vertices[1]) / frame.sourceSize.y; - } + // Texture coordinates (UVs) + var rectUY:Float = (rectY - scrollY) / frame.sourceSize.y; + var rectVY:Float = rectUY + (rectHeight-rectY) / frame.sourceSize.y; + + vertices[1] = rectY; + vertices[3] = rectY; + vertices[5] = rectHeight; + vertices[7] = rectHeight; + + uvtData[1] = rectUY; + uvtData[3] = rectUY; + uvtData[5] = rectVY; + uvtData[7] = rectVY; } override function set_width(Width:Float):Float From df575b00b6bb697642f9b66601ff6d044dfcaa87 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Mon, 10 Jun 2024 19:00:18 -0400 Subject: [PATCH 08/11] fix for FlxShader thingie --- flixel/addons/display/FlxRuntimeShader.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flixel/addons/display/FlxRuntimeShader.hx b/flixel/addons/display/FlxRuntimeShader.hx index 971eac00..bd385e46 100644 --- a/flixel/addons/display/FlxRuntimeShader.hx +++ b/flixel/addons/display/FlxRuntimeShader.hx @@ -30,7 +30,7 @@ import openfl.display.ShaderParameter; * @see https://github.com/openfl/openfl/blob/develop/src/openfl/utils/_internal/ShaderMacro.hx * @see https://dixonary.co.uk/blog/shadertoy */ -class FlxRuntimeShader extends FlxShader +class FlxRuntimeShader extends FlxGraphicsShader { #if FLX_DRAW_QUADS // We need to add stuff from FlxGraphicsShader too! From f1522a706a182b5413e2ab2eed05405da459dd23 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Wed, 12 Jun 2024 10:49:43 -0500 Subject: [PATCH 09/11] regen whenever cliprect is set --- flixel/addons/display/FlxTiledSprite.hx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/flixel/addons/display/FlxTiledSprite.hx b/flixel/addons/display/FlxTiledSprite.hx index da8004fe..76c44400 100644 --- a/flixel/addons/display/FlxTiledSprite.hx +++ b/flixel/addons/display/FlxTiledSprite.hx @@ -107,12 +107,11 @@ class FlxTiledSprite extends FlxStrip return this; } - override function set_clipRect(Value:FlxRect):FlxRect + override function set_clipRect(value:FlxRect):FlxRect { - if (Value != clipRect) - regen = true; + regen = true; - return super.set_clipRect(Value); + return super.set_clipRect(value); } override function set_graphic(Value:FlxGraphic):FlxGraphic From bb62c1e4d1cff9ff57d93b08c8d2fab2d688ee90 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Wed, 12 Jun 2024 12:51:16 -0500 Subject: [PATCH 10/11] fix cliprect on tiled sprites --- flixel/addons/display/FlxTiledSprite.hx | 206 +++++++++++++++--------- 1 file changed, 132 insertions(+), 74 deletions(-) diff --git a/flixel/addons/display/FlxTiledSprite.hx b/flixel/addons/display/FlxTiledSprite.hx index 76c44400..e2137643 100644 --- a/flixel/addons/display/FlxTiledSprite.hx +++ b/flixel/addons/display/FlxTiledSprite.hx @@ -143,61 +143,84 @@ class FlxTiledSprite extends FlxStrip { if (regen) regenGraphic(); - - if (!graphicVisible) - return; - - if (FlxG.renderBlit) + + if (graphicVisible) { - renderSprite.x = x; - renderSprite.y = y; - renderSprite.scrollFactor.set(scrollFactor.x, scrollFactor.y); - renderSprite._cameras = _cameras; - renderSprite.draw(); + if (FlxG.renderBlit) + { + renderSprite.x = x; + renderSprite.y = y; + renderSprite.scrollFactor.set(scrollFactor.x, scrollFactor.y); + renderSprite._cameras = _cameras; + renderSprite.draw(); + } + else + { + super.draw(); + } } - else + + #if FLX_DEBUG + if (FlxG.debugger.drawDebug) + drawDebug(); + #end + } + + #if FLX_DEBUG + /** + * Copied exactly from `FlxObject`, to avoid any future changes to `FlxStrip`'s debug drawing + */ + override function drawDebug() + { + if (ignoreDrawDebug) + return; + + final drawPath = path != null && !path.ignoreDrawDebug; + + for (camera in getCamerasLegacy()) { - super.draw(); + drawDebugOnCamera(camera); + + if (drawPath) + { + path.drawDebugOnCamera(camera); + } } } - + #end + function updateRenderSprite():Void { graphicVisible = true; - + if (renderSprite == null) renderSprite = new FlxSprite(); - - var rectX:Float = repeatX ? 0 : scrollX; - var rectWidth:Float = repeatX ? width : graphic.bitmap.width; - - if (!repeatX && (rectX > width || rectX + rectWidth < 0)) + + final drawRect = getDrawRect(); + drawRect.x = Std.int(drawRect.x); + drawRect.y = Std.int(drawRect.y); + drawRect.width = Std.int(drawRect.width); + drawRect.height = Std.int(drawRect.height); + //TODO: rect.int() or smth + + if (drawRect.width * drawRect.height == 0) { graphicVisible = false; + drawRect.put(); return; } - - var rectY:Float = repeatY ? 0 : scrollY; - var rectHeight:Float = repeatY ? height : graphic.bitmap.height; - - if (!repeatY && (rectY > height || rectY + rectHeight < 0)) + + if (renderSprite.width != drawRect.width || renderSprite.height != drawRect.height) { - graphicVisible = false; - return; - } - - if (renderSprite.width != width || renderSprite.height != height) - { - renderSprite.makeGraphic(Std.int(width), Std.int(height), FlxColor.TRANSPARENT, true); + renderSprite.makeGraphic(Std.int(drawRect.width), Std.int(drawRect.height), FlxColor.TRANSPARENT, true); } else { - _flashRect2.setTo(0, 0, width, height); - renderSprite.pixels.fillRect(_flashRect2, FlxColor.TRANSPARENT); + renderSprite.pixels.fillRect(renderSprite.pixels.rect, FlxColor.TRANSPARENT); } - + FlxSpriteUtil.flashGfx.clear(); - + if (scrollX != 0 || scrollY != 0) { _matrix.identity(); @@ -209,64 +232,99 @@ class FlxTiledSprite extends FlxStrip { FlxSpriteUtil.flashGfx.beginBitmapFill(graphic.bitmap); } - - FlxSpriteUtil.flashGfx.drawRect(rectX, rectY, rectWidth, rectHeight); + + FlxSpriteUtil.flashGfx.drawRect(drawRect.x, drawRect.y, drawRect.width, drawRect.height); renderSprite.pixels.draw(FlxSpriteUtil.flashGfxSprite, null, colorTransform); FlxSpriteUtil.flashGfx.clear(); renderSprite.dirty = true; } - + function updateVerticesData():Void { if (graphic == null) return; - - var frame:FlxFrame = graphic.imageFrame.frame; + + final frame:FlxFrame = graphic.imageFrame.frame; graphicVisible = true; - - var rectX:Float = (repeatX ? 0 : scrollX); - rectX = FlxMath.bound(rectX, 0, width); - if (clipRect != null) rectX += clipRect.x; - - var rectWidth:Float = (repeatX ? rectX + width : scrollX + frame.sourceSize.x); - if (clipRect != null) rectWidth = FlxMath.bound(rectWidth, clipRect.x, clipRect.x + clipRect.width); - + + final drawRect = getDrawRect(); + + if (drawRect.width * drawRect.height == 0) + { + graphicVisible = false; + drawRect.put(); + return; + } + // Texture coordinates (UVs) - var rectUX:Float = (rectX - scrollX) / frame.sourceSize.x; - var rectVX:Float = rectUX + (rectWidth-rectX) / frame.sourceSize.x; - - vertices[0] = rectX; - vertices[2] = rectWidth; - vertices[4] = rectWidth; - vertices[6] = rectX; - + final rectUX:Float = (drawRect.x - scrollX) / frame.sourceSize.x; + final rectVX:Float = rectUX + (drawRect.width-drawRect.x) / frame.sourceSize.x; + final rectUY:Float = (drawRect.y - scrollY) / frame.sourceSize.y; + final rectVY:Float = rectUY + (drawRect.height - drawRect.y) / frame.sourceSize.y; + + vertices[0] = drawRect.x; + vertices[2] = drawRect.width; + vertices[4] = drawRect.width; + vertices[6] = drawRect.x; + uvtData[0] = rectUX; uvtData[2] = rectVX; uvtData[4] = rectVX; uvtData[6] = rectUX; - - var rectY:Float = (repeatY ? 0 : scrollY); - rectY = FlxMath.bound(rectY, 0, height); - if (clipRect != null) rectY += clipRect.y; - - var rectHeight:Float = (repeatY ? rectY + height : scrollY + frame.sourceSize.y); - if (clipRect != null) rectHeight = FlxMath.bound(rectHeight, clipRect.y, clipRect.y + clipRect.height); - - // Texture coordinates (UVs) - var rectUY:Float = (rectY - scrollY) / frame.sourceSize.y; - var rectVY:Float = rectUY + (rectHeight-rectY) / frame.sourceSize.y; - - vertices[1] = rectY; - vertices[3] = rectY; - vertices[5] = rectHeight; - vertices[7] = rectHeight; - + + vertices[1] = drawRect.y; + vertices[3] = drawRect.y; + vertices[5] = drawRect.height; + vertices[7] = drawRect.height; + uvtData[1] = rectUY; uvtData[3] = rectUY; uvtData[5] = rectVY; uvtData[7] = rectVY; + + drawRect.put(); } - + + function getDrawRect(?result:FlxRect):FlxRect + { + if (result == null) + result = FlxRect.get(); + + final frame:FlxFrame = graphic.imageFrame.frame; + final sourceSizeX = FlxG.renderBlit ? graphic.bitmap.width : frame.sourceSize.x; + final sourceSizeY = FlxG.renderBlit ? graphic.bitmap.height : frame.sourceSize.y; + + result.x = (repeatX ? 0 : scrollX); + if (clipRect != null) + { + result.x += clipRect.x; + } + result.x = FlxMath.bound(result.x, 0, width); + + result.width = (repeatX ? result.x + width : scrollX + sourceSizeX); + if (clipRect != null) + { + result.width = FlxMath.bound(result.width, clipRect.x, clipRect.right); + } + result.width = FlxMath.bound(result.width, 0, width); + + result.y = (repeatY ? 0 : scrollY); + if (clipRect != null) + { + result.y += clipRect.y; + } + result.y = FlxMath.bound(result.y, 0, height); + + result.height = (repeatY ? result.y + height : scrollY + sourceSizeY); + if (clipRect != null) + { + result.height = FlxMath.bound(result.height, clipRect.y, clipRect.bottom); + } + result.height = FlxMath.bound(result.height, 0, height); + + return result; + } + override function set_width(Width:Float):Float { if (Width <= 0) From 9734937d863750c635cd87d9eb977683777797d8 Mon Sep 17 00:00:00 2001 From: George FunBook Date: Wed, 12 Jun 2024 12:51:29 -0500 Subject: [PATCH 11/11] style stuff --- flixel/addons/display/FlxTiledSprite.hx | 161 ++++++++++++------------ 1 file changed, 80 insertions(+), 81 deletions(-) diff --git a/flixel/addons/display/FlxTiledSprite.hx b/flixel/addons/display/FlxTiledSprite.hx index e2137643..738699fb 100644 --- a/flixel/addons/display/FlxTiledSprite.hx +++ b/flixel/addons/display/FlxTiledSprite.hx @@ -22,44 +22,44 @@ class FlxTiledSprite extends FlxStrip * The x-offset of the texture */ public var scrollX(default, set):Float = 0; - + /** * The y-offset of the texture. */ public var scrollY(default, set):Float = 0; - + /** * Repeat texture on x axis. Default is true */ public var repeatX(default, set):Bool = true; - + /** * Repeat texture on y axis. Default is true */ public var repeatY(default, set):Bool = true; - + /** * Helper sprite, which does actual rendering in blit render mode. */ var renderSprite:FlxSprite; - + var regen:Bool = true; - + var graphicVisible:Bool = true; - - public function new(?Graphic:FlxGraphicAsset, Width:Float, Height:Float, RepeatX:Bool = true, RepeatY:Bool = true) + + public function new(?graphic:FlxGraphicAsset, width:Float, height:Float, repeatX = true, repeatY = true) { super(); - + repeat = true; - + indices[0] = 0; indices[1] = 1; indices[2] = 2; indices[3] = 2; indices[4] = 3; indices[5] = 0; - + uvtData[0] = 0; uvtData[1] = 0; uvtData[2] = 1; @@ -68,65 +68,64 @@ class FlxTiledSprite extends FlxStrip uvtData[5] = 1; uvtData[6] = 0; uvtData[7] = 1; - + vertices[0] = 0; vertices[1] = 0; - vertices[2] = Width; + vertices[2] = width; vertices[3] = 0; - vertices[4] = Width; - vertices[5] = Height; + vertices[4] = width; + vertices[5] = height; vertices[6] = 0; - vertices[7] = Height; - - width = Width; - height = Height; - - repeatX = RepeatX; - repeatY = RepeatY; - - if (Graphic != null) - loadGraphic(Graphic); + vertices[7] = height; + + this.width = width; + this.height = height; + + this.repeatX = repeatX; + this.repeatY = repeatY; + + if (graphic != null) + loadGraphic(graphic); } - - override public function destroy():Void + + override function destroy():Void { renderSprite = FlxDestroyUtil.destroy(renderSprite); super.destroy(); } - - override public function loadGraphic(Graphic:FlxGraphicAsset, Animated:Bool = false, Width:Int = 0, Height:Int = 0, Unique:Bool = false, - ?Key:String):FlxSprite + + override function loadGraphic(graphic, animated = false, width = 0, height = 0, unique = false, ?key:String):FlxSprite { - graphic = FlxG.bitmap.add(Graphic); + this.graphic = FlxG.bitmap.add(graphic); return this; } - - public function loadFrame(Frame:FlxFrame):FlxTiledSprite + + public function loadFrame(frame:FlxFrame):FlxTiledSprite { - graphic = FlxGraphic.fromFrame(Frame); + graphic = FlxGraphic.fromFrame(frame); return this; } - + override function set_clipRect(value:FlxRect):FlxRect { regen = true; - + return super.set_clipRect(value); } - - override function set_graphic(Value:FlxGraphic):FlxGraphic + + override function set_graphic(value:FlxGraphic):FlxGraphic { - if (graphic != Value) + if (graphic != value) regen = true; - - return super.set_graphic(Value); + + return super.set_graphic(value); } - + function regenGraphic():Void { if (!regen || graphic == null) return; - + if (FlxG.renderBlit) { updateRenderSprite(); @@ -135,11 +134,11 @@ class FlxTiledSprite extends FlxStrip { updateVerticesData(); } - + regen = false; } - - override public function draw():Void + + override function draw():Void { if (regen) regenGraphic(); @@ -325,57 +324,57 @@ class FlxTiledSprite extends FlxStrip return result; } - override function set_width(Width:Float):Float + override function set_width(value:Float):Float { - if (Width <= 0) - return Width; - - if (Width != width) + if (value <= 0) + return value; + + if (value != width) regen = true; - - return super.set_width(Width); + + return super.set_width(value); } - - override function set_height(Height:Float):Float + + override function set_height(value:Float):Float { - if (Height <= 0) - return Height; - - if (Height != height) + if (value <= 0) + return value; + + if (value != height) regen = true; - - return super.set_height(Height); + + return super.set_height(value); } - - function set_scrollX(Value:Float):Float + + function set_scrollX(value:Float):Float { - if (Value != scrollX) + if (value != scrollX) regen = true; - - return scrollX = Value; + + return scrollX = value; } - - function set_scrollY(Value:Float):Float + + function set_scrollY(value:Float):Float { - if (Value != scrollY) + if (value != scrollY) regen = true; - - return scrollY = Value; + + return scrollY = value; } - - function set_repeatX(Value:Bool):Bool + + function set_repeatX(value:Bool):Bool { - if (Value != repeatX) + if (value != repeatX) regen = true; - - return repeatX = Value; + + return repeatX = value; } - - function set_repeatY(Value:Bool):Bool + + function set_repeatY(value:Bool):Bool { - if (Value != repeatY) + if (value != repeatY) regen = true; - - return repeatY = Value; + + return repeatY = value; } }