[WIP] Scores can be saved. Screen filter blocks out video on scorescreen.
This commit is contained in:
parent
1a9a5c5eac
commit
92b83416a3
11
GameTheme.gd
11
GameTheme.gd
|
@ -64,13 +64,22 @@ var COLOR_ARRAY_DOUBLE_MISS_8 := PoolColorArray([
|
||||||
COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS
|
COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS, COLOR_DOUBLE_MISS
|
||||||
])
|
])
|
||||||
|
|
||||||
var screen_filter := Color(0.0, 0.0, 0.0, 0.2)
|
var screen_filter_min_alpha := 0.2
|
||||||
|
var screen_filter := Color(0.0, 0.0, 0.0, screen_filter_min_alpha)
|
||||||
|
signal screen_filter_changed()
|
||||||
var receptor_color := Color.blue
|
var receptor_color := Color.blue
|
||||||
var bezel_color := Color.black
|
var bezel_color := Color.black
|
||||||
|
|
||||||
var RADIAL_COL_ANGLES := PoolRealArray() # ideally const
|
var RADIAL_COL_ANGLES := PoolRealArray() # ideally const
|
||||||
var RADIAL_UNIT_VECTORS := PoolVector2Array() # ideally const
|
var RADIAL_UNIT_VECTORS := PoolVector2Array() # ideally const
|
||||||
|
|
||||||
|
func set_screen_filter_alpha(alpha: float):
|
||||||
|
# Scale to minimum alpha
|
||||||
|
var new_alpha = lerp(screen_filter_min_alpha, 1.0, alpha)
|
||||||
|
if new_alpha != screen_filter.a:
|
||||||
|
screen_filter = Color(screen_filter.r, screen_filter.g, screen_filter.b, new_alpha)
|
||||||
|
emit_signal("screen_filter_changed")
|
||||||
|
|
||||||
func init_radial_values():
|
func init_radial_values():
|
||||||
for i in range(Rules.COLS):
|
for i in range(Rules.COLS):
|
||||||
var angle = deg2rad(fposmod(Rules.FIRST_COLUMN_ANGLE_DEG + (i * Rules.COLS_ANGLE_DEG), 360.0))
|
var angle = deg2rad(fposmod(Rules.FIRST_COLUMN_ANGLE_DEG + (i * Rules.COLS_ANGLE_DEG), 360.0))
|
||||||
|
|
92
Menu.gd
92
Menu.gd
|
@ -21,11 +21,14 @@ var currently_playing := false
|
||||||
|
|
||||||
var scorescreen_song_key := ""
|
var scorescreen_song_key := ""
|
||||||
var scorescreen_score_data := {}
|
var scorescreen_score_data := {}
|
||||||
|
var scorescreen_datetime := {}
|
||||||
|
var scorescreen_saved := false
|
||||||
|
|
||||||
var touch_rects = []
|
var touch_rects = []
|
||||||
|
|
||||||
var TitleFont := preload("res://assets/MenuTitleFont.tres")
|
var TitleFont := preload("res://assets/MenuTitleFont.tres")
|
||||||
var GenreFont := preload("res://assets/MenuGenreFont.tres")
|
var GenreFont := preload("res://assets/MenuGenreFont.tres")
|
||||||
|
var ScoreFont := preload("res://assets/MenuScoreFont.tres")
|
||||||
var snd_interact := preload("res://assets/softclap.wav")
|
var snd_interact := preload("res://assets/softclap.wav")
|
||||||
|
|
||||||
func scan_library():
|
func scan_library():
|
||||||
|
@ -55,6 +58,23 @@ func scan_library():
|
||||||
else:
|
else:
|
||||||
print("An error occurred when trying to access the songs directory: ", err)
|
print("An error occurred when trying to access the songs directory: ", err)
|
||||||
|
|
||||||
|
func save_score():
|
||||||
|
var rootdir = "user://scores"
|
||||||
|
var dir = Directory.new()
|
||||||
|
dir.make_dir_recursive(rootdir)
|
||||||
|
var data = {}
|
||||||
|
data.score_data = scorescreen_score_data
|
||||||
|
data.song_key = scorescreen_song_key
|
||||||
|
var json = JSON.print(data)
|
||||||
|
var file = File.new()
|
||||||
|
var err = file.open(rootdir + "/{year}{month}{day}T{hour}{minute}{second}.json".format(scorescreen_datetime), File.WRITE)
|
||||||
|
if err != OK:
|
||||||
|
print(err)
|
||||||
|
return err
|
||||||
|
file.store_string(json)
|
||||||
|
file.close()
|
||||||
|
scorescreen_saved = true
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
scan_library()
|
scan_library()
|
||||||
$"/root/main/NoteHandler".connect("finished_song", self, "finished_song")
|
$"/root/main/NoteHandler".connect("finished_song", self, "finished_song")
|
||||||
|
@ -175,26 +195,37 @@ func _draw_score_screen(center: Vector2) -> Array:
|
||||||
var song_key = scorescreen_song_key
|
var song_key = scorescreen_song_key
|
||||||
var x = center.x
|
var x = center.x
|
||||||
var y = center.y - 200
|
var y = center.y - 200
|
||||||
|
var x_songtile = x - 120
|
||||||
|
var x_score = x + 120
|
||||||
var x2 = x - 360
|
var x2 = x - 360
|
||||||
var x_spacing = 116
|
var x_spacing = 116
|
||||||
var y_spacing = 48
|
var y_spacing = 48
|
||||||
var y1 = y + size + y_spacing
|
var y1 = y
|
||||||
var y2 = y1 + 120
|
var y2 = y + size + y_spacing*2
|
||||||
|
|
||||||
draw_songtile(song_key, Vector2(x-size/2.0, y), size, false, selected_difficulty, 3)
|
var tex_judgement_text = $"/root/main/NoteHandler".tex_judgement_text
|
||||||
draw_string_centered(TitleFont, Vector2(x, y+size), song_defs[song_key]["title"], Color(0.95, 0.95, 1.0))
|
var judgement_text_scale = 0.667
|
||||||
|
var judgement_text_width = 256 * judgement_text_scale
|
||||||
|
var judgement_text_height = 64 * judgement_text_scale
|
||||||
|
|
||||||
|
draw_songtile(song_key, Vector2(x_songtile-size/2.0, y), size, false, selected_difficulty, 3)
|
||||||
|
draw_string_centered(TitleFont, Vector2(x_songtile, y+size), song_defs[song_key]["title"], Color(0.95, 0.95, 1.0))
|
||||||
var notestrs = ["Tap", "Hold", "Slide"]
|
var notestrs = ["Tap", "Hold", "Slide"]
|
||||||
var judgestrs = Array(Rules.JUDGEMENT_STRINGS + ["Miss"])
|
var judgestrs = Array(Rules.JUDGEMENT_STRINGS + ["Miss"])
|
||||||
var judge_scores = [1.0, 0.9, 0.75, 0.5, 0.0]
|
var judge_scores = [1.0, 0.9, 0.75, 0.5, 0.0]
|
||||||
var notetype_weights = [1.0, 2.0, 2.0]
|
var notetype_weights = [1.0, 2.0, 2.0]
|
||||||
var notetype_scores = []
|
var notecount_total = 0
|
||||||
var notetype_counts = []
|
var notecount_early = 0
|
||||||
|
var notecount_late = 0
|
||||||
var total_score = 0.0
|
var total_score = 0.0
|
||||||
var total_scoremax = 0.0
|
var total_scoremax = 0.0
|
||||||
|
|
||||||
for i in len(judgestrs):
|
for i in len(judgestrs):
|
||||||
# For each judgement type, print a column header
|
# For each judgement type, print a column header
|
||||||
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(i+1), y2), judgestrs[i], Color(0.95, 0.95, 1.0))
|
# draw_string_centered(TitleFont, Vector2(x2+x_spacing*(i+1), y2), judgestrs[i], Color(0.95, 0.95, 1.0))
|
||||||
|
draw_texture_rect_region(tex_judgement_text, Rect2(x2+x_spacing*(i+1)-judgement_text_width/2.0, y2, judgement_text_width, judgement_text_height), Rect2(0, 128*(i+3), 512, 128))
|
||||||
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2), "Score", Color(0.95, 0.95, 1.0))
|
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2), "Score", Color(0.95, 0.95, 1.0))
|
||||||
|
|
||||||
for i in len(notestrs):
|
for i in len(notestrs):
|
||||||
# For each note type, make a row and print scores
|
# For each note type, make a row and print scores
|
||||||
draw_string_centered(TitleFont, Vector2(x2, y2+y_spacing*(i+1)), notestrs[i]+"s:", Color(0.95, 0.95, 1.0))
|
draw_string_centered(TitleFont, Vector2(x2, y2+y_spacing*(i+1)), notestrs[i]+"s:", Color(0.95, 0.95, 1.0))
|
||||||
|
@ -208,14 +239,16 @@ func _draw_score_screen(center: Vector2) -> Array:
|
||||||
score = scorescreen_score_data[i]["MISS"]
|
score = scorescreen_score_data[i]["MISS"]
|
||||||
else:
|
else:
|
||||||
score = scorescreen_score_data[i][j] + scorescreen_score_data[i][-j]
|
score = scorescreen_score_data[i][j] + scorescreen_score_data[i][-j]
|
||||||
|
notecount_early += scorescreen_score_data[i][-j]
|
||||||
|
notecount_late += scorescreen_score_data[i][j]
|
||||||
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(j+1), y2+y_spacing*(i+1)), str(score), Color(0.95, 0.95, 1.0))
|
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(j+1), y2+y_spacing*(i+1)), str(score), Color(0.95, 0.95, 1.0))
|
||||||
|
notecount_total += score # Kinda redundant, will probably refactor eventually
|
||||||
note_count += score
|
note_count += score
|
||||||
note_score += score * judge_scores[j]
|
note_score += score * judge_scores[j]
|
||||||
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2+y_spacing*(i+1)), "%2.2f%%"%(note_score/note_count*100.0), Color(0.95, 0.95, 1.0))
|
draw_string_centered(TitleFont, Vector2(x2+x_spacing*(len(judgestrs)+1), y2+y_spacing*(i+1)), "%2.2f%%"%(note_score/note_count*100.0), Color(0.95, 0.95, 1.0))
|
||||||
notetype_counts.append(note_count)
|
|
||||||
notetype_scores.append(note_score)
|
|
||||||
total_score += note_score * notetype_weights[i]
|
total_score += note_score * notetype_weights[i]
|
||||||
total_scoremax += note_count * notetype_weights[i]
|
total_scoremax += note_count * notetype_weights[i]
|
||||||
|
|
||||||
var overall_score = total_score/total_scoremax
|
var overall_score = total_score/total_scoremax
|
||||||
var score_idx = 0
|
var score_idx = 0
|
||||||
for cutoff in Rules.SCORE_CUTOFFS:
|
for cutoff in Rules.SCORE_CUTOFFS:
|
||||||
|
@ -223,10 +256,27 @@ func _draw_score_screen(center: Vector2) -> Array:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
score_idx += 1
|
score_idx += 1
|
||||||
draw_string_centered(TitleFont, Vector2(x, y1), Rules.SCORE_STRINGS[score_idx], Color(0.95, 0.95, 1.0))
|
# $ScoreText.draw_string_centered(ScoreFont, Vector2(x_score, y1), Rules.SCORE_STRINGS[score_idx], Color(1.0, 1.0, 1.0))
|
||||||
draw_string_centered(TitleFont, Vector2(x, y1+y_spacing), "%2.3f%%"%(overall_score*100.0), Color(0.95, 0.95, 1.0))
|
# $ScoreText.draw_string_centered(TitleFont, Vector2(x_score, y1+y_spacing*3), "%2.3f%%"%(overall_score*100.0), Color(1.0, 1.0, 1.0))
|
||||||
# touchrects.append({rect=r, chart_idx=diff})
|
draw_string_centered(ScoreFont, Vector2(x_score, y1), Rules.SCORE_STRINGS[score_idx], Color(1.0, 1.0, 1.0))
|
||||||
touchrects.append({rect=Rect2(-450.0, 150.0, 900.0, 300.0), next_menu=MenuMode.SONG_SELECT})
|
draw_string_centered(TitleFont, Vector2(x_score, y1+y_spacing*3), "%2.3f%%"%(overall_score*100.0), Color(1.0, 1.0, 1.0))
|
||||||
|
|
||||||
|
draw_string_centered(TitleFont, Vector2(x, y2+y_spacing*4), "Early : Late", Color(0.95, 0.95, 1.0))
|
||||||
|
draw_string_centered(TitleFont, Vector2(x, y2+y_spacing*5), "%3d%% : %3d%%"%[notecount_early*100/notecount_total, notecount_late*100/notecount_total], Color(0.95, 0.95, 1.0))
|
||||||
|
|
||||||
|
var rect_songselect := Rect2(-100.0, 300.0, 400.0, 100.0)
|
||||||
|
draw_rect(rect_songselect, Color.red)
|
||||||
|
draw_string_centered(TitleFont, Vector2(x+100, 320), "Song Select", Color(0.95, 0.95, 1.0))
|
||||||
|
touchrects.append({rect=rect_songselect, next_menu=MenuMode.SONG_SELECT})
|
||||||
|
|
||||||
|
var rect_save := Rect2(-300.0, 300.0, 180.0, 100.0)
|
||||||
|
if not scorescreen_saved:
|
||||||
|
draw_rect(rect_save, Color.blue)
|
||||||
|
draw_string_centered(TitleFont, Vector2(x-210, 320), "Save", Color(0.95, 0.95, 1.0))
|
||||||
|
touchrects.append({rect=rect_save, action="save"})
|
||||||
|
else:
|
||||||
|
draw_rect(rect_save, Color.darkgray)
|
||||||
|
draw_string_centered(TitleFont, Vector2(x-210, 320), "Saved", Color(0.95, 0.95, 1.0))
|
||||||
return touchrects
|
return touchrects
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,7 +301,7 @@ func _draw():
|
||||||
MenuMode.OPTIONS:
|
MenuMode.OPTIONS:
|
||||||
pass
|
pass
|
||||||
MenuMode.GAMEPLAY:
|
MenuMode.GAMEPLAY:
|
||||||
pass
|
GameTheme.set_screen_filter_alpha(progress)
|
||||||
MenuMode.SCORE_SCREEN:
|
MenuMode.SCORE_SCREEN:
|
||||||
_draw_score_screen(center_prev)
|
_draw_score_screen(center_prev)
|
||||||
match menu_mode:
|
match menu_mode:
|
||||||
|
@ -262,20 +312,23 @@ func _draw():
|
||||||
MenuMode.OPTIONS:
|
MenuMode.OPTIONS:
|
||||||
pass
|
pass
|
||||||
MenuMode.GAMEPLAY:
|
MenuMode.GAMEPLAY:
|
||||||
pass
|
GameTheme.set_screen_filter_alpha(1.0 - progress)
|
||||||
MenuMode.SCORE_SCREEN:
|
MenuMode.SCORE_SCREEN:
|
||||||
_draw_score_screen(center_next)
|
_draw_score_screen(center_next)
|
||||||
else:
|
else:
|
||||||
match menu_mode:
|
match menu_mode:
|
||||||
MenuMode.SONG_SELECT:
|
MenuMode.SONG_SELECT:
|
||||||
|
GameTheme.set_screen_filter_alpha(1.0)
|
||||||
touch_rects[menu_mode] = _draw_song_select(center)
|
touch_rects[menu_mode] = _draw_song_select(center)
|
||||||
MenuMode.CHART_SELECT:
|
MenuMode.CHART_SELECT:
|
||||||
|
GameTheme.set_screen_filter_alpha(1.0)
|
||||||
touch_rects[menu_mode] = _draw_chart_select(center)
|
touch_rects[menu_mode] = _draw_chart_select(center)
|
||||||
MenuMode.OPTIONS:
|
MenuMode.OPTIONS:
|
||||||
pass
|
pass
|
||||||
MenuMode.GAMEPLAY:
|
MenuMode.GAMEPLAY:
|
||||||
pass
|
GameTheme.set_screen_filter_alpha(0.0)
|
||||||
MenuMode.SCORE_SCREEN:
|
MenuMode.SCORE_SCREEN:
|
||||||
|
GameTheme.set_screen_filter_alpha(1.0)
|
||||||
touch_rects[menu_mode] = _draw_score_screen(center)
|
touch_rects[menu_mode] = _draw_score_screen(center)
|
||||||
|
|
||||||
func set_menu_mode(mode):
|
func set_menu_mode(mode):
|
||||||
|
@ -305,11 +358,18 @@ func touch_select_chart(touchdict):
|
||||||
|
|
||||||
func touch_score_screen(touchdict):
|
func touch_score_screen(touchdict):
|
||||||
if touchdict.has("next_menu"):
|
if touchdict.has("next_menu"):
|
||||||
|
SFXPlayer.play(SFXPlayer.Type.NON_POSITIONAL, self, snd_interact, 0.0)
|
||||||
set_menu_mode(touchdict.next_menu)
|
set_menu_mode(touchdict.next_menu)
|
||||||
|
elif touchdict.has("action"):
|
||||||
|
SFXPlayer.play(SFXPlayer.Type.NON_POSITIONAL, self, snd_interact, 0.0)
|
||||||
|
if touchdict.action == "save":
|
||||||
|
save_score()
|
||||||
|
|
||||||
func finished_song(song_key, score_data):
|
func finished_song(song_key, score_data):
|
||||||
scorescreen_song_key = song_key
|
scorescreen_song_key = song_key
|
||||||
scorescreen_score_data = score_data
|
scorescreen_score_data = score_data
|
||||||
|
scorescreen_datetime = OS.get_datetime()
|
||||||
|
scorescreen_saved = false
|
||||||
set_menu_mode(MenuMode.SCORE_SCREEN)
|
set_menu_mode(MenuMode.SCORE_SCREEN)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,3 +26,5 @@ func _draw():
|
||||||
for i in range(len(receptor_centers)):
|
for i in range(len(receptor_centers)):
|
||||||
draw_circle(receptor_centers[i], receptor_px/2, GameTheme.receptor_color)
|
draw_circle(receptor_centers[i], receptor_px/2, GameTheme.receptor_color)
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
GameTheme.connect("screen_filter_changed", self, "update")
|
2
Rules.gd
2
Rules.gd
|
@ -16,5 +16,5 @@ const JUDGEMENT_TIMES_RELEASE_POST := [0.090, 0.140, 0.175, 0.200] # Small grac
|
||||||
const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.140, 0.175, 0.200] # Small grace period, sort-of
|
const JUDGEMENT_TIMES_SLIDE_PRE := [0.090, 0.140, 0.175, 0.200] # Small grace period, sort-of
|
||||||
const JUDGEMENT_TIMES_SLIDE_POST := [0.090, 0.140, 0.175, 0.200]
|
const JUDGEMENT_TIMES_SLIDE_POST := [0.090, 0.140, 0.175, 0.200]
|
||||||
|
|
||||||
const SCORE_STRINGS = ["SSS", "SS", "S", "A+", "A", "B+", "B", "C+", "C", "F"]
|
const SCORE_STRINGS = ["SSS", "SS", "S", "A⁺", "A", "B⁺", "B", "C⁺", "C", "F"]
|
||||||
const SCORE_CUTOFFS = [1.0, 0.975, 0.95, 0.9, 0.85, 0.8, 0.7, 0.6, 0.5]
|
const SCORE_CUTOFFS = [1.0, 0.975, 0.95, 0.9, 0.85, 0.8, 0.7, 0.6, 0.5]
|
|
@ -76,6 +76,8 @@ material = SubResource( 2 )
|
||||||
[node name="Menu" type="Node2D" parent="."]
|
[node name="Menu" type="Node2D" parent="."]
|
||||||
script = ExtResource( 8 )
|
script = ExtResource( 8 )
|
||||||
|
|
||||||
|
[node name="ScoreText" type="Node2D" parent="Menu"]
|
||||||
|
|
||||||
[node name="Bezel" type="Node2D" parent="."]
|
[node name="Bezel" type="Node2D" parent="."]
|
||||||
script = ExtResource( 9 )
|
script = ExtResource( 9 )
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
[gd_resource type="ShaderMaterial" load_steps=2 format=2]
|
||||||
|
|
||||||
|
[sub_resource type="Shader" id=1]
|
||||||
|
code = "shader_type canvas_item;
|
||||||
|
//render_mode unshaded;
|
||||||
|
|
||||||
|
uniform float bps;
|
||||||
|
uniform vec4 star_color : hint_color;
|
||||||
|
uniform vec4 held_color : hint_color;
|
||||||
|
uniform vec2 screen_size;
|
||||||
|
|
||||||
|
//void vertex() {
|
||||||
|
//}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec4 sample = texture(TEXTURE, UV);
|
||||||
|
|
||||||
|
float color_scale = sample.r;
|
||||||
|
float bright_scale = (sample.g+sample.b)/2.0;
|
||||||
|
float dist = distance(FRAGCOORD.xy, screen_size/2.0);
|
||||||
|
float dist_norm = dist*1.8 / screen_size.y;
|
||||||
|
if (COLOR.rgb == star_color.rgb){
|
||||||
|
// Star ripple
|
||||||
|
COLOR.rg += dist_norm*0.33;
|
||||||
|
COLOR.rgb *= mix(abs(0.5-mod(TIME*bps*2.0+dist_norm, 1.0)), 1.0, 0.75);
|
||||||
|
COLOR.rgb *= color_scale; // Preserve black outlines
|
||||||
|
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), bright_scale); // Preserve white outlines
|
||||||
|
} else if (COLOR.rgb == held_color.rgb){
|
||||||
|
// Hold note being held, flashy effects
|
||||||
|
COLOR.b *= mix(2.0*abs(0.5-mod(TIME*bps*2.0+dist_norm, 1.0)), 1.0, 0.35);
|
||||||
|
COLOR.g *= mix(1.0 - 2.0*abs(0.5-mod(TIME*bps*0.5+dist_norm, 1.0)), 0.0, 0.35);
|
||||||
|
COLOR.r *= mix(abs(0.5-mod(TIME*bps, 1.0)), 1.0, 0.85);
|
||||||
|
if (color_scale < 0.5){ // Make black outlines shine
|
||||||
|
COLOR.rgb = mix(COLOR.rgb, vec3(mix(dist_norm, abs(0.5-mod(TIME*bps*8.0, 1.0)), 0.33)), 1.0-(color_scale*2.0));
|
||||||
|
}
|
||||||
|
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), 0.33); // brighten overall
|
||||||
|
COLOR.rgb = mix(COLOR.rgb, vec3(0.25), bright_scale); // Invert white outlines
|
||||||
|
} else {
|
||||||
|
COLOR.gb += 0.1;
|
||||||
|
COLOR.rgb *= mix(abs(0.5-mod(TIME*bps, 1.0)), 1.0, 0.85);
|
||||||
|
COLOR.rgb *= color_scale; // Preserve black outlines
|
||||||
|
COLOR.rgb = mix(COLOR.rgb, vec3(1.0), bright_scale); // Preserve white outlines
|
||||||
|
}
|
||||||
|
|
||||||
|
COLOR.a = clamp(COLOR.a*texture(TEXTURE, UV).a, 0.0, 1.0);
|
||||||
|
}"
|
||||||
|
|
||||||
|
[resource]
|
||||||
|
shader = SubResource( 1 )
|
||||||
|
shader_param/bps = null
|
||||||
|
shader_param/star_color = null
|
||||||
|
shader_param/held_color = null
|
||||||
|
shader_param/screen_size = null
|
Loading…
Reference in New Issue