# RoundedCorners() rounds the corners of a displayable you give it python early: def normalize_color(col): a = col[3] / 255.0 r = a * col[0] / 255.0 g = a * col[1] / 255.0 b = a * col[2] / 255.0 return (r, g, b, a) _rounded_corners_relative = { None: 0.0, "min": 1.0, "max": 2.0, "width": 3.0, "height": 4.0, } def RoundedCorners(child, radius, relative=None, outline_width=0.0, outline_color="#fff", **kwargs): if not isinstance(radius, tuple): radius = (radius,) * 4 relative = _rounded_corners_relative[relative] outline_color = normalize_color(Color(outline_color)) return Transform(child, mesh=True, shader="shader.rounded_corners", u_radius=radius, u_relative=relative, u_outline_color=outline_color, u_outline_width=outline_width, **kwargs) CurriedRoundedCorners = renpy.curry(RoundedCorners) renpy.register_shader("shader.rounded_corners", variables=""" uniform vec4 u_radius; uniform float u_outline_width; uniform vec4 u_outline_color; uniform float u_relative; uniform sampler2D tex0; attribute vec2 a_tex_coord; varying vec2 v_tex_coord; uniform vec2 u_model_size; """, vertex_200=""" v_tex_coord = a_tex_coord; """, fragment_functions=""" float rounded_rectangle(vec2 p, vec2 b, float r) { return length(max(abs(p) - b + r, 0.0)) - r; } float get_radius(vec2 uv_minus_center, vec4 radius) { vec2 xy = (uv_minus_center.x > 0.0) ? radius.xy : radius.zw; float r = (uv_minus_center.y > 0.0) ? xy.x : xy.y; return r; } """, fragment_200=""" vec2 center = u_model_size.xy / 2.0; vec2 uv = (v_tex_coord.xy * u_model_size.xy); vec2 uv_minus_center = uv - center; float radius = get_radius(uv_minus_center, u_radius); vec4 color = texture2D(tex0, v_tex_coord); if (u_relative != 0.0) { float side_size; if (u_relative == 1.0) { side_size = u_model_size.x; } else if (u_relative == 2.0) { side_size = u_model_size.y; } else if (u_relative == 3.0) { side_size = min(u_model_size.x, u_model_size.y); } else { side_size = max(u_model_size.x, u_model_size.y); } radius *= side_size; } if (u_outline_width > 0.0) { vec2 center_outline = center - u_outline_width; float crop1 = rounded_rectangle(uv - center, center, radius); float crop2 = rounded_rectangle(uv - center, center_outline, radius - u_outline_width); float coeff1 = smoothstep(1.0, -1.0, crop1); float coeff2 = smoothstep(1.0, -1.0, crop2); float outline_coeff = (coeff1 - coeff2); gl_FragColor = mix(vec4(0.0), mix(color, u_outline_color, outline_coeff), coeff1); } else { float crop = rounded_rectangle(uv_minus_center, center, radius); gl_FragColor = mix(color, vec4(0.0), smoothstep(0.0, 1.0, crop)); } """)