From c759458581a7365e8bf836a05523ac7aac0f8016 Mon Sep 17 00:00:00 2001 From: davesmith00000 Date: Thu, 21 Nov 2024 09:42:46 +0000 Subject: [PATCH] Sending data to the nineslice shader --- .../effectmaterials/LegacyEffects.scala | 41 +++++++--- .../effectmaterials/Refraction.scala | 30 +++++-- .../shaders/LegacyEffectsShaders.scala | 16 ++-- .../shaders/RefractionShaders.scala | 22 +++-- .../indigo/shared/materials/FillType.scala | 16 ++++ .../indigo/shared/materials/Material.scala | 80 +++++++++++++------ .../indigo/shared/shader/library/Blit.scala | 22 +++-- .../shared/shader/library/ImageEffects.scala | 16 ++-- .../shader/library/TileAndStretch.scala | 42 +++++----- .../shader/library/TileAndStretchTests.scala | 44 +++++----- .../sandbox/scenes/TextureTileScene.scala | 8 +- 11 files changed, 236 insertions(+), 101 deletions(-) create mode 100644 indigo/indigo/src/main/scala/indigo/shared/materials/FillType.scala diff --git a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/LegacyEffects.scala b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/LegacyEffects.scala index 5863d9d7f..43f058ae9 100644 --- a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/LegacyEffects.scala +++ b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/LegacyEffects.scala @@ -5,6 +5,7 @@ import indigo.shared.collections.Batch import indigo.shared.datatypes.Fill import indigo.shared.datatypes.RGB import indigo.shared.datatypes.RGBA +import indigo.shared.datatypes.Rectangle import indigo.shared.materials.FillType import indigo.shared.materials.Material import indigo.shared.shader.EntityShader @@ -60,6 +61,10 @@ final case class LegacyEffects( withFillType(FillType.Stretch) def tile: LegacyEffects = withFillType(FillType.Tile) + def nineSlice(center: Rectangle): LegacyEffects = + withFillType(FillType.NineSlice(center)) + def nineSlice(top: Int, right: Int, bottom: Int, left: Int): LegacyEffects = + withFillType(FillType.NineSlice(top, right, bottom, left)) lazy val toShaderData: ShaderData = val overlayType: Float = @@ -70,10 +75,23 @@ final case class LegacyEffects( val imageFillType: Float = fillType match - case FillType.Normal => 0.0 - case FillType.Stretch => 1.0 - case FillType.Tile => 2.0 - case FillType.NineSlice => 3.0 + case FillType.Normal => 0.0 + case FillType.Stretch => 1.0 + case FillType.Tile => 2.0 + case FillType.NineSlice(_) => 3.0 + + val nineSliceCenter: scalajs.js.Array[Float] = + fillType match + case FillType.NineSlice(center) => + scalajs.js.Array( + center.x.toFloat, + center.y.toFloat, + center.width.toFloat, + center.height.toFloat + ) + + case _ => + scalajs.js.Array(0.0f, 0.0f, 0.0f, 0.0f) ShaderData( LegacyEffects.entityShader.id, @@ -87,12 +105,15 @@ final case class LegacyEffects( alpha.toFloat, saturation.toFloat, overlayType, - imageFillType, - tint.r.toFloat, - tint.g.toFloat, - tint.b.toFloat, - tint.a.toFloat - ) + imageFillType + ) ++ + nineSliceCenter ++ + scalajs.js.Array( + tint.r.toFloat, + tint.g.toFloat, + tint.b.toFloat, + tint.a.toFloat + ) ) ) ++ overlay.toUniformData("LegacyEffects") ++ // BORDER_COLOR (vec4), GLOW_COLOR (vec4), EFFECT_AMOUNTS (vec4) diff --git a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/Refraction.scala b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/Refraction.scala index 4fdc123be..01f3ecff1 100644 --- a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/Refraction.scala +++ b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/Refraction.scala @@ -3,6 +3,7 @@ package indigoextras.effectmaterials import indigo.shared.assets.AssetName import indigo.shared.collections.Batch import indigo.shared.datatypes.RGBA +import indigo.shared.datatypes.Rectangle import indigo.shared.materials.BlendMaterial import indigo.shared.materials.FillType import indigo.shared.materials.Material @@ -13,6 +14,7 @@ import indigo.shared.shader.EntityShader import indigo.shared.shader.ShaderData import indigo.shared.shader.ShaderId import indigo.shared.shader.ShaderPrimitive.float +import indigo.shared.shader.ShaderPrimitive.rawJSArray import indigo.shared.shader.ShaderProgram import indigo.shared.shader.UltravioletShader import indigo.shared.shader.Uniform @@ -71,20 +73,38 @@ final case class RefractionEntity(diffuse: AssetName, fillType: FillType) extend withFillType(FillType.Stretch) def tile: RefractionEntity = withFillType(FillType.Tile) + def nineSlice(center: Rectangle): RefractionEntity = + withFillType(FillType.NineSlice(center)) + def nineSlice(top: Int, right: Int, bottom: Int, left: Int): RefractionEntity = + withFillType(FillType.NineSlice(top, right, bottom, left)) lazy val toShaderData: ShaderData = val imageFillType: Double = fillType match - case FillType.Normal => 0.0 - case FillType.Stretch => 1.0 - case FillType.Tile => 2.0 - case FillType.NineSlice => 3.0 + case FillType.Normal => 0.0 + case FillType.Stretch => 1.0 + case FillType.Tile => 2.0 + case FillType.NineSlice(_) => 3.0 + + val nineSliceCenter: scalajs.js.Array[Float] = + fillType match + case FillType.NineSlice(center) => + scalajs.js.Array( + center.x.toFloat, + center.y.toFloat, + center.width.toFloat, + center.height.toFloat + ) + + case _ => + scalajs.js.Array(0.0f, 0.0f, 0.0f, 0.0f) val uniformBlock: UniformBlock = UniformBlock( UniformBlockName("IndigoBitmapData"), Batch( - Uniform("FILLTYPE") -> float(imageFillType) + Uniform("FILLTYPE") -> float(imageFillType), + Uniform("NINE_SLICE_CENTER") -> rawJSArray(nineSliceCenter) ) ) diff --git a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/LegacyEffectsShaders.scala b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/LegacyEffectsShaders.scala index 8bfa2603c..863ee6236 100644 --- a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/LegacyEffectsShaders.scala +++ b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/LegacyEffectsShaders.scala @@ -65,6 +65,7 @@ object LegacyEffectsShaders: trait Env extends Lighting.LightEnv { val ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE: highp[vec4] = vec4(0.0f) + val NINE_SLICE_CENTER: highp[vec4] = vec4(0.0f) val TINT: vec4 = vec4(0.0f) val GRADIENT_FROM_TO: vec4 = vec4(0.0f) val GRADIENT_FROM_COLOR: vec4 = vec4(0.0f) @@ -78,6 +79,7 @@ object LegacyEffectsShaders: final case class IndigoLegacyEffectsData( ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE: highp[vec4], + NINE_SLICE_CENTER: highp[vec4], TINT: vec4, GRADIENT_FROM_TO: vec4, GRADIENT_FROM_COLOR: vec4, @@ -104,7 +106,7 @@ object LegacyEffectsShaders: calculateRadialGradientOverlay val _calculateSaturation: (vec4, Float) => vec4 = calculateSaturation - val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = tileAndStretchChannel @in val v_offsetTL: vec2 = null @@ -273,7 +275,8 @@ object LegacyEffectsShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_1 = _tileAndStretchChannel( fillType, @@ -283,7 +286,8 @@ object LegacyEffectsShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_2 = _tileAndStretchChannel( fillType, @@ -293,7 +297,8 @@ object LegacyEffectsShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_3 = _tileAndStretchChannel( fillType, @@ -303,7 +308,8 @@ object LegacyEffectsShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) val alpha: Float = env.ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE.x diff --git a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/RefractionShaders.scala b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/RefractionShaders.scala index 5c63ff531..f10f26a65 100644 --- a/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/RefractionShaders.scala +++ b/indigo/indigo-extras/src/main/scala/indigoextras/effectmaterials/shaders/RefractionShaders.scala @@ -14,7 +14,8 @@ object RefractionShaders: val reference: BlendEnv = new BlendEnv {} trait FragEnv extends Lighting.LightEnv { - val FILLTYPE: highp[Float] = 0.0f + val FILLTYPE: highp[Float] = 0.0f + val NINE_SLICE_CENTER: highp[vec4] = vec4(0.0f) } object FragEnv: val reference: FragEnv = new FragEnv {} @@ -32,14 +33,17 @@ object RefractionShaders: texture2D(env.DST_CHANNEL, offset) } - final case class IndigoBitmapData(FILLTYPE: highp[Float]) + final case class IndigoBitmapData( + FILLTYPE: highp[Float], + NINE_SLICE_CENTER: highp[vec4] + ) inline def normalMinusBlue = Shader[FragEnv] { env => import TileAndStretch.* // Delegates - val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = tileAndStretchChannel ubo[IndigoBitmapData] @@ -54,7 +58,8 @@ object RefractionShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_1 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -64,7 +69,8 @@ object RefractionShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_2 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -74,7 +80,8 @@ object RefractionShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_3 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -84,7 +91,8 @@ object RefractionShaders: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) val redGreen = vec3(env.CHANNEL_0.xy, 0.0f) diff --git a/indigo/indigo/src/main/scala/indigo/shared/materials/FillType.scala b/indigo/indigo/src/main/scala/indigo/shared/materials/FillType.scala new file mode 100644 index 000000000..0f0083b99 --- /dev/null +++ b/indigo/indigo/src/main/scala/indigo/shared/materials/FillType.scala @@ -0,0 +1,16 @@ +package indigo.shared.materials + +import indigo.shared.datatypes.Rectangle + +enum FillType derives CanEqual: + case Normal + case Stretch + case Tile + case NineSlice(center: Rectangle) + +object FillType: + object NineSlice: + def apply(top: Int, right: Int, bottom: Int, left: Int): FillType = + FillType.NineSlice( + Rectangle(left, top, right - left, bottom - top) + ) diff --git a/indigo/indigo/src/main/scala/indigo/shared/materials/Material.scala b/indigo/indigo/src/main/scala/indigo/shared/materials/Material.scala index 5eb513169..522859748 100644 --- a/indigo/indigo/src/main/scala/indigo/shared/materials/Material.scala +++ b/indigo/indigo/src/main/scala/indigo/shared/materials/Material.scala @@ -5,6 +5,7 @@ import indigo.shared.collections.Batch import indigo.shared.datatypes.Fill import indigo.shared.datatypes.RGB import indigo.shared.datatypes.RGBA +import indigo.shared.datatypes.Rectangle import indigo.shared.materials.LightingModel.Lit import indigo.shared.materials.LightingModel.Unlit import indigo.shared.shader.ShaderData @@ -48,8 +49,10 @@ object Material: withFillType(FillType.Stretch) def tile: Bitmap = withFillType(FillType.Tile) - def nineSlice: Bitmap = - withFillType(FillType.NineSlice) + def nineSlice(center: Rectangle): Bitmap = + withFillType(FillType.NineSlice(center)) + def nineSlice(top: Int, right: Int, bottom: Int, left: Int): Bitmap = + withFillType(FillType.NineSlice(top, right, bottom, left)) def toImageEffects: Material.ImageEffects = Material.ImageEffects( @@ -67,16 +70,32 @@ object Material: val imageFillType: Float = fillType match - case FillType.Normal => 0.0 - case FillType.Stretch => 1.0 - case FillType.Tile => 2.0 - case FillType.NineSlice => 3.0 + case FillType.Normal => 0.0 + case FillType.Stretch => 1.0 + case FillType.Tile => 2.0 + case FillType.NineSlice(_) => 3.0 + + val nineSliceCenter: scalajs.js.Array[Float] = + fillType match + case FillType.NineSlice(center) => + scalajs.js.Array( + center.x.toFloat, + center.y.toFloat, + center.width.toFloat, + center.height.toFloat + ) + + case _ => + scalajs.js.Array(0.0f, 0.0f, 0.0f, 0.0f) val uniformBlock: UniformBlock = UniformBlock( UniformBlockName("IndigoBitmapData"), Batch( - Uniform("Bitmap_FILLTYPE") -> rawJSArray(scalajs.js.Array(imageFillType)) + Uniform("Bitmap_FILLTYPE") -> + rawJSArray( + scalajs.js.Array(imageFillType, 0.0f, 0.0f, 0.0f) ++ nineSliceCenter + ) ) ) @@ -151,8 +170,10 @@ object Material: withFillType(FillType.Stretch) def tile: ImageEffects = withFillType(FillType.Tile) - def nineSlice: ImageEffects = - withFillType(FillType.NineSlice) + def nineSlice(center: Rectangle): ImageEffects = + withFillType(FillType.NineSlice(center)) + def nineSlice(top: Int, right: Int, bottom: Int, left: Int): ImageEffects = + withFillType(FillType.NineSlice(top, right, bottom, left)) def toBitmap: Material.Bitmap = Material.Bitmap(diffuse, lighting, shaderId, fillType) @@ -167,12 +188,25 @@ object Material: val imageFillType: Float = fillType match - case FillType.Normal => 0.0 - case FillType.Stretch => 1.0 - case FillType.Tile => 2.0 - case FillType.NineSlice => 3.0 + case FillType.Normal => 0.0 + case FillType.Stretch => 1.0 + case FillType.Tile => 2.0 + case FillType.NineSlice(_) => 3.0 - // ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE (vec4), TINT (vec4) + val nineSliceCenter: scalajs.js.Array[Float] = + fillType match + case FillType.NineSlice(center) => + scalajs.js.Array( + center.x.toFloat, + center.y.toFloat, + center.width.toFloat, + center.height.toFloat + ) + + case _ => + scalajs.js.Array(0.0f, 0.0f, 0.0f, 0.0f) + + // ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE (vec4), NINE_SLICE_CENTER (vec4), TINT (vec4) val effectsUniformBlock: UniformBlock = UniformBlock( UniformBlockName("IndigoImageEffectsData"), @@ -182,12 +216,15 @@ object Material: alpha.toFloat, saturation.toFloat, overlayType, - imageFillType, - tint.r.toFloat, - tint.g.toFloat, - tint.b.toFloat, - tint.a.toFloat - ) + imageFillType + ) ++ + nineSliceCenter ++ + scalajs.js.Array( + tint.r.toFloat, + tint.g.toFloat, + tint.b.toFloat, + tint.a.toFloat + ) ) ) ++ overlay.toUniformData("ImageEffects") ) @@ -222,6 +259,3 @@ object Material: def apply(diffuse: AssetName, lighting: LightingModel, shaderId: Option[ShaderId]): ImageEffects = ImageEffects(diffuse, 1.0, RGBA.None, Fill.Color.default, 1.0, lighting, shaderId, FillType.Normal) - -enum FillType derives CanEqual: - case Normal, Stretch, Tile, NineSlice diff --git a/indigo/indigo/src/main/scala/indigo/shared/shader/library/Blit.scala b/indigo/indigo/src/main/scala/indigo/shared/shader/library/Blit.scala index 77e213331..267cfd283 100644 --- a/indigo/indigo/src/main/scala/indigo/shared/shader/library/Blit.scala +++ b/indigo/indigo/src/main/scala/indigo/shared/shader/library/Blit.scala @@ -6,19 +6,23 @@ import ultraviolet.syntax.* object Blit: trait Env extends Lighting.LightEnv { - val FILLTYPE: highp[Float] = 0.0f + val FILLTYPE: highp[Float] = 0.0f + val NINE_SLICE_CENTER: highp[vec4] = vec4(0.0f) } object Env: val reference: Env = new Env {} - case class IndigoBitmapData(FILLTYPE: highp[Float]) + case class IndigoBitmapData( + FILLTYPE: highp[Float], + NINE_SLICE_CENTER: highp[vec4] + ) inline def fragment = Shader[Env] { env => import TileAndStretch.* // Delegates - val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = tileAndStretchChannel ubo[IndigoBitmapData] @@ -32,7 +36,8 @@ object Blit: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_1 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -42,7 +47,8 @@ object Blit: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_2 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -52,7 +58,8 @@ object Blit: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_3 = _tileAndStretchChannel( env.FILLTYPE.toInt, @@ -62,7 +69,8 @@ object Blit: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_0 diff --git a/indigo/indigo/src/main/scala/indigo/shared/shader/library/ImageEffects.scala b/indigo/indigo/src/main/scala/indigo/shared/shader/library/ImageEffects.scala index 83fa22415..7daff47b3 100644 --- a/indigo/indigo/src/main/scala/indigo/shared/shader/library/ImageEffects.scala +++ b/indigo/indigo/src/main/scala/indigo/shared/shader/library/ImageEffects.scala @@ -7,6 +7,7 @@ object ImageEffects: trait Env extends Lighting.LightEnv { val ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE: highp[vec4] = vec4(0.0f) + val NINE_SLICE_CENTER: highp[vec4] = vec4(0.0f) val TINT: vec4 = vec4(0.0f) val GRADIENT_FROM_TO: vec4 = vec4(0.0f) val GRADIENT_FROM_COLOR: vec4 = vec4(0.0f) @@ -17,6 +18,7 @@ object ImageEffects: case class IndigoImageEffectsData( ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE: highp[vec4], + NINE_SLICE_CENTER: highp[vec4], TINT: vec4, GRADIENT_FROM_TO: vec4, GRADIENT_FROM_COLOR: vec4, @@ -43,7 +45,7 @@ object ImageEffects: calculateRadialGradientOverlay val _calculateSaturation: (vec4, Float) => vec4 = calculateSaturation - val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = tileAndStretchChannel // 0 = normal 1 = stretch 2 = tile @@ -58,7 +60,8 @@ object ImageEffects: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_1 = _tileAndStretchChannel( fillType, @@ -68,7 +71,8 @@ object ImageEffects: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_2 = _tileAndStretchChannel( fillType, @@ -78,7 +82,8 @@ object ImageEffects: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) env.CHANNEL_3 = _tileAndStretchChannel( fillType, @@ -88,7 +93,8 @@ object ImageEffects: env.CHANNEL_0_SIZE, env.UV, env.SIZE, - env.TEXTURE_SIZE + env.TEXTURE_SIZE, + env.NINE_SLICE_CENTER ) val alpha: Float = env.ALPHA_SATURATION_OVERLAYTYPE_FILLTYPE.x diff --git a/indigo/indigo/src/main/scala/indigo/shared/shader/library/TileAndStretch.scala b/indigo/indigo/src/main/scala/indigo/shared/shader/library/TileAndStretch.scala index 99a0a7afa..1d46fcc51 100644 --- a/indigo/indigo/src/main/scala/indigo/shared/shader/library/TileAndStretch.scala +++ b/indigo/indigo/src/main/scala/indigo/shared/shader/library/TileAndStretch.scala @@ -4,7 +4,7 @@ import ultraviolet.syntax.* object TileAndStretch: - inline def tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + inline def tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = ( fillType: Int, fallback: vec4, @@ -13,8 +13,13 @@ object TileAndStretch: channelSize: vec2, uv: vec2, entitySize: vec2, - textureSize: vec2 + textureSize: vec2, + nineSliceCenter: vec4 ) => + def _nineSliceUVs: (vec2, vec2, vec2, vec2, vec2, vec4) => vec2 = + (originalUV, channelPos, channelSize, entitySize, textureSize, nineSliceCenter) => + nineSliceUVs(originalUV, channelPos, channelSize, entitySize, textureSize, nineSliceCenter) + fillType match case 1 => texture2D( @@ -31,7 +36,7 @@ object TileAndStretch: case 3 => texture2D( srcChannel, - nineSliceUVs(uv, channelPos, channelSize, entitySize, textureSize) + _nineSliceUVs(uv, channelPos, channelSize, entitySize, textureSize, nineSliceCenter) ) case _ => @@ -51,7 +56,8 @@ object TileAndStretch: channelPos: vec2, channelSize: vec2, entitySize: vec2, - textureSize: vec2 + textureSize: vec2, + nineSliceCenter: vec4 ): vec2 = // Delegates @@ -68,26 +74,26 @@ object TileAndStretch: def _regionContainsUV: (vec4, vec2) => Boolean = (region, uv) => regionContainsUV(region, uv) - // TODO: Should be passed in as UBO data - // texture is 64x64, slice lines at an even 16 pixels // A rectangle inside the texture that defines the center, from which we can work out the other regions. - val centerSquare = vec4(16.0f, 16.0f, 48.0f, 48.0f) + val centerSquare = nineSliceCenter // Work out all the texture regions in pixels as rectangles (x,y,w,h) val textureRegionTL = - vec4(0.0f, 0.0f, centerSquare.x - 0.0f, centerSquare.y - 0.0f) + vec4(0.0f, 0.0f, centerSquare.x, centerSquare.y) val textureRegionTM = - vec4(centerSquare.x, 0.0f, centerSquare.z - centerSquare.x, centerSquare.y - 0.0f) + vec4(centerSquare.x, 0.0f, centerSquare.z - centerSquare.x, centerSquare.y) val textureRegionTR = - vec4(centerSquare.z, 0.0f, textureSize.x - centerSquare.z, centerSquare.y - 0.0f) + vec4(centerSquare.z, 0.0f, textureSize.x - centerSquare.z, centerSquare.y) + val textureRegionML = - vec4(0.0f, centerSquare.y, centerSquare.x - 0.0f, centerSquare.w - centerSquare.y) + vec4(0.0f, centerSquare.y, centerSquare.x, centerSquare.w - centerSquare.y) val textureRegionMM = vec4(centerSquare.xy, centerSquare.zw - centerSquare.xy) val textureRegionMR = vec4(centerSquare.z, centerSquare.y, textureSize.x - centerSquare.z, centerSquare.w - centerSquare.y) + val textureRegionBL = - vec4(0.0f, centerSquare.w, centerSquare.x - 0.0f, textureSize.y - centerSquare.w) + vec4(0.0f, centerSquare.w, centerSquare.x, textureSize.y - centerSquare.w) val textureRegionBM = vec4(centerSquare.x, centerSquare.w, centerSquare.z - centerSquare.x, textureSize.y - centerSquare.w) val textureRegionBR = @@ -118,28 +124,28 @@ object TileAndStretch: vec4( 0.0f, 0.0f, - entityCenterSquare.x - 0.0f, - entityCenterSquare.y - 0.0f + entityCenterSquare.x, + entityCenterSquare.y ) val entityRegionTM = vec4( entityCenterSquare.x, 0.0f, entityCenterSquare.z - entityCenterSquare.x, - entityCenterSquare.y - 0.0f + entityCenterSquare.y ) val entityRegionTR = vec4( entityCenterSquare.z, 0.0f, entitySafeSize.x - entityCenterSquare.z, - entityCenterSquare.y - 0.0f + entityCenterSquare.y ) val entityRegionML = vec4( 0.0f, entityCenterSquare.y, - entityCenterSquare.x - 0.0f, + entityCenterSquare.x, entityCenterSquare.w - entityCenterSquare.y ) val entityRegionMM = @@ -155,7 +161,7 @@ object TileAndStretch: entityCenterSquare.w - entityCenterSquare.y ) val entityRegionBL = - vec4(0.0f, entityCenterSquare.w, entityCenterSquare.x - 0.0f, entitySafeSize.y - entityCenterSquare.w) + vec4(0.0f, entityCenterSquare.w, entityCenterSquare.x, entitySafeSize.y - entityCenterSquare.w) val entityRegionBM = vec4( entityCenterSquare.x, diff --git a/indigo/indigo/src/test/scala/indigo/shared/shader/library/TileAndStretchTests.scala b/indigo/indigo/src/test/scala/indigo/shared/shader/library/TileAndStretchTests.scala index bb6faeb7f..1cc5abd9d 100644 --- a/indigo/indigo/src/test/scala/indigo/shared/shader/library/TileAndStretchTests.scala +++ b/indigo/indigo/src/test/scala/indigo/shared/shader/library/TileAndStretchTests.scala @@ -85,7 +85,7 @@ class TileAndStretchTests extends munit.FunSuite { import TileAndStretch.* // Delegates - val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2) => vec4 = + val _tileAndStretchChannel: (Int, vec4, sampler2D.type, vec2, vec2, vec2, vec2, vec2, vec4) => vec4 = tileAndStretchChannel val fillType: Int = 0 @@ -96,16 +96,18 @@ class TileAndStretchTests extends munit.FunSuite { val uv: vec2 = vec2(4.0) val entitySize: vec2 = vec2(5.0) val textureSize: vec2 = vec2(6.0) + val nineSliceCenter: vec4 = vec4(7.0) _tileAndStretchChannel( - fillType, // env.FILLTYPE.toInt, - fallback, // env.CHANNEL_0, - srcChannel, // env.SRC_CHANNEL, - channelPos, // env.CHANNEL_0_POSITION, - channelSize, // env.CHANNEL_0_SIZE, - uv, // env.UV, - entitySize, // env.SIZE, - textureSize // env.TEXTURE_SIZE + fillType, // env.FILLTYPE.toInt, + fallback, // env.CHANNEL_0, + srcChannel, // env.SRC_CHANNEL, + channelPos, // env.CHANNEL_0_POSITION, + channelSize, // env.CHANNEL_0_SIZE, + uv, // env.UV, + entitySize, // env.SIZE, + textureSize, // env.TEXTURE_SIZE + nineSliceCenter // env.NINE_SLICE_CENTER ) } @@ -127,7 +129,7 @@ class TileAndStretchTests extends munit.FunSuite { | val0=texture(srcChannel,channelPos+((fract(uv*(entitySize/textureSize)))*channelSize)); | break; | case 3: - | // maddnes ensues + | // maddness ensues | break; | default: | val0=fallback; @@ -155,19 +157,21 @@ class TileAndStretchTests extends munit.FunSuite { Shader { import TileAndStretch.* - val uv: vec2 = vec2(1.0) - val channelPos: vec2 = vec2(2.0) - val channelSize: vec2 = vec2(3.0) - val entitySize: vec2 = vec2(128.0) - val textureSize: vec2 = vec2(64.0) + val uv: vec2 = vec2(1.0) + val channelPos: vec2 = vec2(2.0) + val channelSize: vec2 = vec2(3.0) + val entitySize: vec2 = vec2(128.0) + val textureSize: vec2 = vec2(64.0) + val nineSliceCenter: vec4 = vec4(16.0f, 16.0f, 32.0f, 32.0f) def doNineSlice(): vec2 = nineSliceUVs( - uv, // env.UV, - channelPos, // env.CHANNEL_0_POSITION, - channelSize, // env.CHANNEL_0_SIZE, - entitySize, // env.SIZE, - textureSize // env.TEXTURE_SIZE + uv, // env.UV, + channelPos, // env.CHANNEL_0_POSITION, + channelSize, // env.CHANNEL_0_SIZE, + entitySize, // env.SIZE, + textureSize, // env.TEXTURE_SIZE + nineSliceCenter // env.NINE_SLICE_CENTER ) doNineSlice() diff --git a/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/TextureTileScene.scala b/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/TextureTileScene.scala index 237e88b3c..73c9c4835 100644 --- a/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/TextureTileScene.scala +++ b/indigo/sandbox/src/main/scala/com/example/sandbox/scenes/TextureTileScene.scala @@ -44,6 +44,8 @@ object TextureTileScene extends Scene[SandboxStartupData, SandboxGameModel, Sand def fit(originalSize: Vector2, screenSize: Vector2): Vector2 = Vector2(Math.max(screenSize.x / originalSize.x, screenSize.y / originalSize.y)) + def boxSize(t: Seconds): Int = Signal.SmoothPulse.map(d => (d * 64) + 64).map(_.toInt).at(t) + def present( context: SceneContext[SandboxStartupData], model: SandboxGameModel, @@ -63,7 +65,11 @@ object TextureTileScene extends Scene[SandboxStartupData, SandboxGameModel, Sand Graphic(64, 64, Material.Bitmap(SandboxAssets.dots).normal).moveTo(10, 90), Graphic(200, 75, Material.Bitmap(SandboxAssets.dots).tile).moveTo(10, 10), Graphic(50, 75, Material.Bitmap(SandboxAssets.dots).stretch).moveTo(100, 75), - Graphic(128, 128, Material.Bitmap(SandboxAssets.nineSlice).nineSlice).moveTo(125, 125) + Graphic( + boxSize(context.frame.time.running), + boxSize(context.frame.time.running), + Material.Bitmap(SandboxAssets.nineSlice).nineSlice(Rectangle(16, 16, 32, 32)) + ).moveTo(125, 125) ) ) )