working updates
This commit is contained in:
189
scripts/visual/PlaymatRenderer.gd
Normal file
189
scripts/visual/PlaymatRenderer.gd
Normal file
@@ -0,0 +1,189 @@
|
||||
class_name PlaymatRenderer
|
||||
extends Node
|
||||
|
||||
## PlaymatRenderer - Generates a clean programmatic play mat texture using SubViewport
|
||||
## Layout matches FF-TCG official play mat zones:
|
||||
## Left: Damage Zone (top) / Turn Structure (bottom)
|
||||
## Center: Field (Forwards top, Backups bottom)
|
||||
## Right: Deck (top) / Break Zone (bottom)
|
||||
|
||||
const MAT_TEXTURE_WIDTH: int = 2048
|
||||
const MAT_TEXTURE_HEIGHT: int = 1024
|
||||
|
||||
# Color scheme - dark green felt table look
|
||||
const BG_COLOR := Color(0.12, 0.15, 0.12)
|
||||
const ZONE_BORDER_COLOR := Color(0.35, 0.40, 0.30)
|
||||
const ZONE_FILL_COLOR := Color(0.14, 0.18, 0.14)
|
||||
const LABEL_COLOR := Color(0.45, 0.50, 0.40)
|
||||
const FIELD_LINE_COLOR := Color(0.20, 0.25, 0.20)
|
||||
const TURN_TEXT_COLOR := Color(0.35, 0.40, 0.30)
|
||||
|
||||
# Zone regions as pixel rects in the texture
|
||||
# Left column: ~17% width
|
||||
const DAMAGE_RECT := Rect2(30, 30, 320, 460)
|
||||
const TURN_REF_RECT := Rect2(30, 520, 320, 474)
|
||||
# Center: ~66% width
|
||||
const FIELD_RECT := Rect2(380, 30, 1290, 964)
|
||||
# Right column: ~17% width
|
||||
const DECK_RECT := Rect2(1700, 30, 318, 440)
|
||||
const BREAK_RECT := Rect2(1700, 500, 318, 494)
|
||||
|
||||
# Border thickness
|
||||
const BORDER_WIDTH: int = 3
|
||||
|
||||
func render() -> ImageTexture:
|
||||
var viewport = SubViewport.new()
|
||||
viewport.size = Vector2i(MAT_TEXTURE_WIDTH, MAT_TEXTURE_HEIGHT)
|
||||
viewport.render_target_update_mode = SubViewport.UPDATE_ONCE
|
||||
viewport.transparent_bg = false
|
||||
|
||||
# Background
|
||||
var bg = ColorRect.new()
|
||||
bg.color = BG_COLOR
|
||||
bg.position = Vector2.ZERO
|
||||
bg.size = Vector2(MAT_TEXTURE_WIDTH, MAT_TEXTURE_HEIGHT)
|
||||
viewport.add_child(bg)
|
||||
|
||||
# Draw zone rectangles with borders and labels
|
||||
_draw_zone(viewport, DAMAGE_RECT, "DAMAGE ZONE")
|
||||
_draw_zone(viewport, DECK_RECT, "DECK")
|
||||
_draw_zone(viewport, BREAK_RECT, "BREAK ZONE")
|
||||
_draw_zone(viewport, FIELD_RECT, "FIELD")
|
||||
|
||||
# Divider line in Field (separating Forwards from Backups)
|
||||
var divider_y = FIELD_RECT.position.y + FIELD_RECT.size.y * 0.48
|
||||
_draw_dashed_line(viewport, Vector2(FIELD_RECT.position.x + 20, divider_y),
|
||||
Vector2(FIELD_RECT.position.x + FIELD_RECT.size.x - 20, divider_y))
|
||||
|
||||
# Forwards / Backups sub-labels
|
||||
_draw_label(viewport, "FORWARDS",
|
||||
Vector2(FIELD_RECT.position.x + FIELD_RECT.size.x / 2, FIELD_RECT.position.y + FIELD_RECT.size.y * 0.22), 32)
|
||||
_draw_label(viewport, "BACKUPS",
|
||||
Vector2(FIELD_RECT.position.x + FIELD_RECT.size.x / 2, FIELD_RECT.position.y + FIELD_RECT.size.y * 0.74), 32)
|
||||
|
||||
# Turn structure reference (decorative)
|
||||
_draw_turn_structure(viewport)
|
||||
|
||||
# Add outer border around entire mat
|
||||
_draw_border_rect(viewport, Rect2(5, 5, MAT_TEXTURE_WIDTH - 10, MAT_TEXTURE_HEIGHT - 10), ZONE_BORDER_COLOR, 2)
|
||||
|
||||
add_child(viewport)
|
||||
|
||||
# Wait for the viewport to render
|
||||
await RenderingServer.frame_post_draw
|
||||
|
||||
# Grab the rendered image
|
||||
var image = viewport.get_texture().get_image()
|
||||
var texture = ImageTexture.create_from_image(image)
|
||||
|
||||
# Clean up
|
||||
viewport.queue_free()
|
||||
|
||||
return texture
|
||||
|
||||
func _draw_zone(viewport: SubViewport, rect: Rect2, label_text: String) -> void:
|
||||
# Zone fill
|
||||
var fill = ColorRect.new()
|
||||
fill.color = ZONE_FILL_COLOR
|
||||
fill.position = rect.position
|
||||
fill.size = rect.size
|
||||
viewport.add_child(fill)
|
||||
|
||||
# Zone border (4 thin ColorRects forming a rectangle)
|
||||
_draw_border_rect(viewport, rect, ZONE_BORDER_COLOR, BORDER_WIDTH)
|
||||
|
||||
# Zone label centered at top of zone
|
||||
_draw_label(viewport, label_text,
|
||||
Vector2(rect.position.x + rect.size.x / 2, rect.position.y + 30), 28)
|
||||
|
||||
func _draw_border_rect(viewport: SubViewport, rect: Rect2, color: Color, width: int) -> void:
|
||||
# Top edge
|
||||
var top = ColorRect.new()
|
||||
top.color = color
|
||||
top.position = rect.position
|
||||
top.size = Vector2(rect.size.x, width)
|
||||
viewport.add_child(top)
|
||||
|
||||
# Bottom edge
|
||||
var bottom = ColorRect.new()
|
||||
bottom.color = color
|
||||
bottom.position = Vector2(rect.position.x, rect.position.y + rect.size.y - width)
|
||||
bottom.size = Vector2(rect.size.x, width)
|
||||
viewport.add_child(bottom)
|
||||
|
||||
# Left edge
|
||||
var left = ColorRect.new()
|
||||
left.color = color
|
||||
left.position = rect.position
|
||||
left.size = Vector2(width, rect.size.y)
|
||||
viewport.add_child(left)
|
||||
|
||||
# Right edge
|
||||
var right = ColorRect.new()
|
||||
right.color = color
|
||||
right.position = Vector2(rect.position.x + rect.size.x - width, rect.position.y)
|
||||
right.size = Vector2(width, rect.size.y)
|
||||
viewport.add_child(right)
|
||||
|
||||
func _draw_label(viewport: SubViewport, text: String, center_pos: Vector2, font_size: int) -> void:
|
||||
var label = Label.new()
|
||||
label.text = text
|
||||
label.add_theme_font_size_override("font_size", font_size)
|
||||
label.add_theme_color_override("font_color", LABEL_COLOR)
|
||||
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
# Size the label wide enough and position so center_pos is the center
|
||||
var label_width = text.length() * font_size * 0.7
|
||||
var label_height = font_size * 1.5
|
||||
label.position = Vector2(center_pos.x - label_width / 2, center_pos.y - label_height / 2)
|
||||
label.size = Vector2(label_width, label_height)
|
||||
viewport.add_child(label)
|
||||
|
||||
func _draw_dashed_line(viewport: SubViewport, from: Vector2, to: Vector2) -> void:
|
||||
var dash_length = 20.0
|
||||
var gap_length = 15.0
|
||||
var direction = (to - from).normalized()
|
||||
var total_length = from.distance_to(to)
|
||||
var current = 0.0
|
||||
|
||||
while current < total_length:
|
||||
var dash_end = min(current + dash_length, total_length)
|
||||
var start_pos = from + direction * current
|
||||
var end_pos = from + direction * dash_end
|
||||
|
||||
var dash = ColorRect.new()
|
||||
dash.color = FIELD_LINE_COLOR
|
||||
dash.position = start_pos
|
||||
dash.size = Vector2(dash_end - current, 2)
|
||||
viewport.add_child(dash)
|
||||
|
||||
current = dash_end + gap_length
|
||||
|
||||
func _draw_turn_structure(viewport: SubViewport) -> void:
|
||||
var phases = [
|
||||
"Turn Structure",
|
||||
"",
|
||||
"1. Active Phase",
|
||||
"2. Draw Phase",
|
||||
"3. Main Phase 1",
|
||||
"4. Attack Phase",
|
||||
"5. Main Phase 2",
|
||||
"6. End Phase",
|
||||
]
|
||||
|
||||
var start_y = TURN_REF_RECT.position.y + 20
|
||||
var x = TURN_REF_RECT.position.x + 15
|
||||
|
||||
for i in range(phases.size()):
|
||||
var text = phases[i]
|
||||
if text == "":
|
||||
continue
|
||||
|
||||
var label = Label.new()
|
||||
label.text = text
|
||||
var font_size = 20 if i == 0 else 16
|
||||
label.add_theme_font_size_override("font_size", font_size)
|
||||
label.add_theme_color_override("font_color", TURN_TEXT_COLOR)
|
||||
label.position = Vector2(x, start_y + i * 28)
|
||||
label.size = Vector2(TURN_REF_RECT.size.x - 30, 28)
|
||||
viewport.add_child(label)
|
||||
Reference in New Issue
Block a user