feat: integrate authored market ui components
This commit is contained in:
@@ -169,6 +169,15 @@ interim dashboard composition. The reusable page grammar is now explicit:
|
||||
760x360, 844x390 and 1280x720 in Chinese and English. The detailed reusable
|
||||
rules live in `docs/runtime/M52_SHARED_UI_RULES.md`.
|
||||
|
||||
Market component asset pass (`working tree`, 2026-09-09): a transparent 2x2
|
||||
component sheet was generated through API Mart task
|
||||
`task_01M22JS3QVF9TE1J2V9R9FSJ74` and sliced into title, recruit-card, ledger
|
||||
and wood-button assets under `runtime/assets/ui_m52_market/v2/`. The first
|
||||
NinePatch experiment was rejected because the source silhouettes contained
|
||||
non-uniform transparent margins; the current preview uses whole-silhouette
|
||||
TextureRect scaling while dedicated edge/center slices remain a follow-up.
|
||||
The raw sheet, prompts and provider report are retained for provenance.
|
||||
|
||||
### M52-C — Complete one playable loop and owner tryout
|
||||
|
||||
- Extend the same visual language through Recruit Review, Party, Battle and
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Use case: ui-mockup
|
||||
Asset type: reusable game UI component sheet for a Godot Japanese 2D hand-drawn fantasy RPG
|
||||
Primary request: Create ONE REGULAR 2x2 GRID with FOUR EQUAL CELLS and clear fixed boundaries. Produce four blank, text-free, transparent-ready UI components that match one another as a single authored family. Warm Q-style Japanese chibi fantasy, hand-inked contours, cel-painted paper and wood, brass corner fittings, soft painted shadows, crisp at play size. No characters, no logos, no letters, no numbers, no fake glyphs, no watermark. Use a solid bright green #00FF00 background across the entire sheet. Subjects must stay inside their cells with generous padding and must not cross cell boundaries.
|
||||
TOP-LEFT: ornate horizontal market title plaque, cream parchment center, carved warm wood frame, teal cloth ribbon, brass corner studs, soft shadow, wide horizontal shape.
|
||||
TOP-RIGHT: vertical recruit parchment card, hanging rope loops at the top, cream paper with warm wood trim, one empty colored profession ribbon slot and one empty circular seal slot, blank interior for runtime portrait and text.
|
||||
BOTTOM-LEFT: tall adventurer ledger panel, warm parchment book-board with wood trim, empty portrait window, empty text bands, large empty action-button area at the bottom, no text.
|
||||
BOTTOM-RIGHT: horizontal wood command button, chunky carved wood frame, brass studs, teal inset accent, soft shadow, empty center for runtime label and icon.
|
||||
Composition: each cell is an isolated production asset with clean edges, front-facing orthographic UI view, consistent light from upper-left, readable material separation, no perspective distortion.
|
||||
Avoid: UI dashboard look, dark navy rectangles, generic web cards, pixel art, hard pixel edges, thin hairline borders, gradients without material, baked text, symbols, people, scenery, overlapping cells.
|
||||
@@ -0,0 +1,9 @@
|
||||
Use case: ui-mockup
|
||||
Asset type: reusable game UI component sheet for a Godot Japanese 2D hand-drawn fantasy RPG
|
||||
Primary request: Create ONE REGULAR 2x2 GRID with FOUR EQUAL CELLS and clear fixed boundaries. Produce four blank, text-free, production-ready UI components in one coherent Q-style Japanese chibi fantasy game UI family. Output a true transparent PNG with real alpha in every empty area; absolutely no green screen, no black background, no colored matte. No characters, no logos, no letters, no numbers, no fake glyphs, no watermark. Subjects must stay inside their cells with generous padding and must not cross cell boundaries.
|
||||
TOP-LEFT: ornate horizontal market title plaque, cream parchment center, carved warm wood frame, teal cloth ribbon, brass corner studs, soft shadow, wide horizontal shape.
|
||||
TOP-RIGHT: vertical recruit parchment card, hanging rope loops at the top, cream paper with warm wood trim, one empty colored profession ribbon slot and one empty circular seal slot, blank interior for runtime portrait and text.
|
||||
BOTTOM-LEFT: tall adventurer ledger panel, warm parchment book-board with wood trim, empty portrait window, empty text bands, large empty teal action-button area at the bottom, no text.
|
||||
BOTTOM-RIGHT: horizontal wood command button, chunky carved wood frame, brass studs, teal inset accent, soft shadow, empty center for runtime label and icon.
|
||||
Composition: each cell is an isolated production asset with clean anti-aliased alpha edges, front-facing orthographic UI view, consistent light from upper-left, readable material separation, no perspective distortion.
|
||||
Avoid: UI dashboard look, dark navy rectangles, generic web cards, pixel art, hard pixel edges, thin hairline borders, gradients without material, baked text, symbols, people, scenery, overlapping cells, any background color.
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"mode": "execute",
|
||||
"model": "gpt-image-2",
|
||||
"size": "1:1",
|
||||
"resolution": "2k",
|
||||
"output": "/tmp/m52_market_ui_components_transparent_raw.png",
|
||||
"local_references": [],
|
||||
"remote_reference_count": 0,
|
||||
"prompt_chars": 1829,
|
||||
"task_id": "task_01M22JS3QVF9TE1J2V9R9FSJ74",
|
||||
"status": "completed",
|
||||
"bytes": 3876599,
|
||||
"cost": 0.014,
|
||||
"credits_cost": 0.14
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 791 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 614 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 533 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 3.7 MiB |
@@ -829,7 +829,7 @@ func _render_m52_market_restore(data: Dictionary) -> void:
|
||||
var title_plate := Control.new()
|
||||
title_plate.name = "MarketTitlePlaque"
|
||||
_market_place(title_plate, Rect2(0.045, 0.035, 0.34, 0.18))
|
||||
var title_chrome := MarketChrome.new().configure("title")
|
||||
var title_chrome := _m52_texture_surface(preload("res://assets/ui_m52_market/v2/title_plaque.png"), "TitleChrome", Vector4(56, 46, 56, 46))
|
||||
title_chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
title_plate.add_child(title_chrome)
|
||||
var title := UIFactory.label(_tr("市场", "MARKET", data), "title", 1.0, MarketChrome.INK)
|
||||
@@ -931,7 +931,7 @@ func _render_m52_market_restore(data: Dictionary) -> void:
|
||||
ledger.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
ledger.z_index = 12
|
||||
ledger.add_theme_stylebox_override("panel", StyleBoxEmpty.new())
|
||||
var ledger_chrome := MarketChrome.new().configure("ledger")
|
||||
var ledger_chrome := _m52_texture_surface(preload("res://assets/ui_m52_market/v2/ledger_panel.png"), "LedgerChrome", Vector4(44, 44, 44, 44))
|
||||
ledger_chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
ledger.add_child(ledger_chrome)
|
||||
page.add_child(ledger)
|
||||
@@ -959,19 +959,19 @@ func _render_m52_market_restore(data: Dictionary) -> void:
|
||||
portrait.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
portrait.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
|
||||
portrait.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
||||
_market_place(portrait, Rect2(0.19, 0.18, 0.62, 0.28))
|
||||
_market_place(portrait, Rect2(0.10, 0.24, 0.38, 0.32))
|
||||
portrait.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
ledger.add_child(portrait)
|
||||
var detail_title := UIFactory.label(selected_title if not selected_title.is_empty() else _tr("候选人名册", "ADVENTURER LEDGER", data), "label", 1.0, MarketChrome.INK)
|
||||
detail_title.name = "MarketCandidateName"
|
||||
_market_place(detail_title, Rect2(0.10, 0.47, 0.80, 0.08))
|
||||
_market_place(detail_title, Rect2(0.50, 0.26, 0.40, 0.10))
|
||||
detail_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
detail_title.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
detail_title.text_overrun_behavior = TextServer.OVERRUN_TRIM_ELLIPSIS
|
||||
ledger.add_child(detail_title)
|
||||
var detail := UIFactory.label(selected_detail, "micro", 1.0, MarketChrome.INK_SOFT)
|
||||
detail.name = "MarketNoSelection" if selected_offer_id.is_empty() else "M50CommissionDetail"
|
||||
_market_place(detail, Rect2(0.12, 0.56, 0.76, 0.12))
|
||||
_market_place(detail, Rect2(0.50, 0.38, 0.40, 0.22))
|
||||
detail.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
detail.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
detail.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
@@ -979,11 +979,11 @@ func _render_m52_market_restore(data: Dictionary) -> void:
|
||||
if not selected_price.is_empty():
|
||||
var price := UIFactory.label(selected_price, "label", 1.0, MarketChrome.INK)
|
||||
price.name = "MarketCandidatePrice"
|
||||
_market_place(price, Rect2(0.12, 0.69, 0.76, 0.06))
|
||||
_market_place(price, Rect2(0.50, 0.63, 0.40, 0.07))
|
||||
price.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||
price.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
|
||||
ledger.add_child(price)
|
||||
var review := _m52_action_button("MarketReviewRecruit", _tr("查看详情", "VIEW DETAILS", data), Rect2(0.12, 0.80, 0.76, 0.14), "recruit_review", selected_offer_id.is_empty() or selected_kind != "recruit", data)
|
||||
var review := _m52_action_button("MarketReviewRecruit", _tr("查看详情", "VIEW DETAILS", data), Rect2(0.10, 0.80, 0.80, 0.14), "recruit_review", selected_offer_id.is_empty() or selected_kind != "recruit", data)
|
||||
review.z_index = 20
|
||||
ledger.add_child(review)
|
||||
|
||||
@@ -1013,6 +1013,20 @@ func _render_m52_market_restore(data: Dictionary) -> void:
|
||||
page.add_child(category_button)
|
||||
|
||||
|
||||
func _m52_texture_surface(texture: Texture2D, node_name: String, margins: Vector4) -> TextureRect:
|
||||
var surface := TextureRect.new()
|
||||
surface.name = node_name
|
||||
surface.texture = texture
|
||||
# The generated source is a transparent component atlas crop. Keep the
|
||||
# whole authored silhouette together while the next pass produces dedicated
|
||||
# nine-patch center/edge slices.
|
||||
surface.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||
surface.stretch_mode = TextureRect.STRETCH_SCALE
|
||||
surface.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR_WITH_MIPMAPS
|
||||
surface.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
return surface
|
||||
|
||||
|
||||
func _m52_resource_badge(node_name: String, icon_kind: String, caption: String, value: String, area: Rect2) -> Control:
|
||||
var badge := Control.new()
|
||||
badge.name = node_name
|
||||
@@ -1045,7 +1059,7 @@ func _m52_recruit_card(index: int, offer: Dictionary, area: Rect2, selected_kind
|
||||
for state in ["normal", "hover", "pressed", "disabled", "focus", "hover_pressed"]:
|
||||
card.add_theme_stylebox_override(state, StyleBoxEmpty.new())
|
||||
var accent := "blue" if index == 0 else "red" if index == 1 else "gold"
|
||||
var chrome := MarketChrome.new().configure("card", accent)
|
||||
var chrome := _m52_texture_surface(preload("res://assets/ui_m52_market/v2/recruit_card.png"), "CardChrome", Vector4(38, 38, 38, 38))
|
||||
chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
card.add_child(chrome)
|
||||
var ribbon := UIFactory.label(String(p.get("profession_name", "")), "micro", 1.0, MarketChrome.PAPER_LIGHT)
|
||||
@@ -1111,7 +1125,7 @@ func _m52_wood_button(node_name: String, text_value: String, area: Rect2, icon_k
|
||||
_market_place(button, area)
|
||||
for state in ["normal", "hover", "pressed", "disabled", "focus", "hover_pressed"]:
|
||||
button.add_theme_stylebox_override(state, StyleBoxEmpty.new())
|
||||
var chrome := MarketChrome.new().configure("wood_button")
|
||||
var chrome := _m52_texture_surface(preload("res://assets/ui_m52_market/v2/wood_button.png"), "WoodChrome", Vector4(46, 34, 46, 34))
|
||||
chrome.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
button.add_child(chrome)
|
||||
var icon := UIFactory.attach_icon(button, icon_kind, "CommandIcon", "light", Rect2(0.05, 0.20, 0.18, 0.60))
|
||||
|
||||
Reference in New Issue
Block a user