Merge agy/ui round 2
This commit is contained in:
commit
8645298b41
7 files changed
+123
-35
No files matched your search
@@ -739,11 +739,20 @@ def hw_selected():
|
||||
return c
|
||||
|
||||
|
||||
def hw_groove():
|
||||
"""PLEDGER 墨水屏输入框凹槽(12×12,九宫格边 2):浅色底、1 像素深墨边。"""
|
||||
c = Canvas(12, 12)
|
||||
c.rect(0, 0, 11, 11, 'n')
|
||||
c.rect(1, 1, 10, 10, 'P')
|
||||
return c
|
||||
|
||||
|
||||
UI_ICONS = {'ui_bank': ui_bank, 'ui_poinbase': ui_poinbase, 'ui_web3': ui_web3}
|
||||
UI_ICONS['ui_hw_shell'] = lambda: rounded(32, 7, 'K', 'E', 'z')
|
||||
UI_ICONS['ui_hw_bezel'] = lambda: rounded(16, 4, 'n')
|
||||
UI_ICONS['ui_hw_paper'] = lambda: rounded(12, 2, 'P')
|
||||
UI_ICONS['ui_hw_sel'] = hw_selected
|
||||
UI_ICONS['ui_hw_groove'] = hw_groove
|
||||
UI_ICONS['ui_hw_ok'] = lambda: hw_button('ok')
|
||||
UI_ICONS['ui_hw_no'] = lambda: hw_button('no')
|
||||
|
||||
|
||||
@@ -170,9 +170,7 @@ stable.ok,"Pegged"
|
||||
stable.depeg,"Depegged"
|
||||
stable.warn,"Warning: staking subsidy pool low"
|
||||
stable.spiral,"Collapsing"
|
||||
aml.window,"Withdrawn in the last {0} days: {1} credits (cumulative line {2})"
|
||||
aml.taint,"Account taint share: {0}%"
|
||||
aml.chance,"At this amount, estimated review chance: {0}%"
|
||||
mixer.h,Mixer
|
||||
mixer.ok,Status: operating normally
|
||||
mixer.sanctioned,Status: sanctioned ({0} more day(s)). Coins withdrawn meanwhile are flagged.
|
||||
|
||||
|
@@ -169,9 +169,7 @@ stable.ok,"锚定正常"
|
||||
stable.depeg,"脱锚"
|
||||
stable.warn,"预兆:质押补贴池告急"
|
||||
stable.spiral,"崩盘中"
|
||||
aml.window,"近 {0} 天已提取 {1} 信用点(累计线 {2})"
|
||||
aml.taint,"账户污点比例:{0}%"
|
||||
aml.chance,"按这个数量,预计审查概率:{0}%"
|
||||
mixer.h,混币器
|
||||
mixer.ok,状态:运行正常
|
||||
mixer.sanctioned,状态:已被制裁(还有 {0} 天),此期间提出的币视为被标记。
|
||||
|
||||
|
Binary file not shown.
|
After Width: | Height: | Size: 86 B |
@@ -27,8 +27,16 @@ namespace Decentralized
|
||||
public static readonly Color Paper = new Color(0.847f, 0.855f, 0.816f); // #D8DAD0
|
||||
public static readonly Color RowNormal = new Color(0f, 0f, 0f, 0.04f);
|
||||
public static readonly Color Transparent = new Color(0f, 0f, 0f, 0f);
|
||||
public static readonly Color MaskClear = new Color(0f, 0f, 0f, 0.004f);
|
||||
public static readonly Color Separator = new Color(0.12f, 0.12f, 0.14f, 0.18f);
|
||||
|
||||
/// <summary>透明化底图:若附带 Mask 组件则保留极微小 alpha(0.004),避免 Mask 模板 alpha 为 0 导致子内容被整裁。</summary>
|
||||
public static void SetClear(Image img)
|
||||
{
|
||||
if (img == null) return;
|
||||
img.color = (img.GetComponent<Mask>() != null) ? MaskClear : Transparent;
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, Sprite> Sliced = new Dictionary<string, Sprite>();
|
||||
|
||||
/// <summary>把本 mod 的像素图做成九宫格贴到 Image 上:边角 border 像素不拉伸,一个像素放大成 3 个界面单位。</summary>
|
||||
@@ -48,6 +56,35 @@ namespace Decentralized
|
||||
img.color = Color.white;
|
||||
}
|
||||
|
||||
/// <summary>把输入框切片为墨水屏凹槽:浅色底、1 像素深墨边框(1:1 像素映射)。</summary>
|
||||
public static void SliceGroove(Image img)
|
||||
{
|
||||
if (img == null) return;
|
||||
if (!Sliced.TryGetValue("ui_hw_groove", out var sp))
|
||||
{
|
||||
var src = Items.ModSprite("ui_hw_groove");
|
||||
if (src != null)
|
||||
{
|
||||
src.texture.filterMode = FilterMode.Point;
|
||||
sp = Sprite.Create(src.texture, src.rect, new Vector2(0.5f, 0.5f), src.pixelsPerUnit, 0, SpriteMeshType.FullRect, new Vector4(2, 2, 2, 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
var tex = new Texture2D(12, 12, TextureFormat.RGBA32, false) { filterMode = FilterMode.Point };
|
||||
for (int y = 0; y < 12; y++)
|
||||
for (int x = 0; x < 12; x++)
|
||||
tex.SetPixel(x, y, (x == 0 || x == 11 || y == 0 || y == 11) ? Ink : Paper);
|
||||
tex.Apply();
|
||||
sp = Sprite.Create(tex, new Rect(0, 0, 12, 12), new Vector2(0.5f, 0.5f), 100f, 0, SpriteMeshType.FullRect, new Vector4(2, 2, 2, 2));
|
||||
}
|
||||
Sliced["ui_hw_groove"] = sp;
|
||||
}
|
||||
img.sprite = sp;
|
||||
img.type = Image.Type.Sliced;
|
||||
img.pixelsPerUnitMultiplier = 100f / sp.pixelsPerUnit;
|
||||
img.color = Color.white;
|
||||
}
|
||||
|
||||
/// <summary>屏上的选择按钮(币种、档位、子页):选中的一个画成白底黑框黑字、四角带准星角标。</summary>
|
||||
public static void Pick(CustomUIBuilder b, string text, bool selected, Action onClick, ICollection<GameObject> picked)
|
||||
{
|
||||
@@ -116,7 +153,7 @@ namespace Decentralized
|
||||
foreach (var name in new[] { "header", "rule" })
|
||||
{
|
||||
var img = win.root.transform.Find(name)?.GetComponent<Image>();
|
||||
if (img != null) img.color = Transparent;
|
||||
if (img != null) SetClear(img);
|
||||
}
|
||||
if (win.frame?.titleText != null)
|
||||
{
|
||||
@@ -147,9 +184,11 @@ namespace Decentralized
|
||||
t.color = t.gameObject.name.Contains("_note") ? Alert : t.gameObject.name.Contains("_dim") ? Dim : Ink;
|
||||
}
|
||||
|
||||
// 屏上输入框
|
||||
// 屏上输入框:墨水屏凹槽样式(浅色底、深墨 1px 边、深墨文字、灰色占位符)
|
||||
foreach (var inp in screen.GetComponentsInChildren<TMP_InputField>(true))
|
||||
{
|
||||
var bg = inp.GetComponent<Image>() ?? inp.targetGraphic as Image;
|
||||
if (bg != null) SliceGroove(bg);
|
||||
if (inp.textComponent != null) inp.textComponent.color = Ink;
|
||||
if (inp.placeholder is TextMeshProUGUI ph) ph.color = Dim;
|
||||
}
|
||||
@@ -193,35 +232,70 @@ namespace Decentralized
|
||||
foreach (var scroll in screen.GetComponentsInChildren<ScrollRect>(true))
|
||||
{
|
||||
var bg = scroll.GetComponent<Image>();
|
||||
if (bg != null) bg.color = Transparent;
|
||||
if (bg != null) SetClear(bg);
|
||||
if (scroll.viewport != null)
|
||||
{
|
||||
var vpImg = scroll.viewport.GetComponent<Image>();
|
||||
// 视口的图是 Mask 的模板:alpha 为 0 会把整个内容裁掉,只能压到几乎看不见
|
||||
if (vpImg != null) vpImg.color = new Color(0f, 0f, 0f, 0.004f);
|
||||
if (vpImg != null) SetClear(vpImg);
|
||||
}
|
||||
if (scroll.verticalScrollbar != null)
|
||||
{
|
||||
var sb = scroll.verticalScrollbar;
|
||||
var track = sb.GetComponent<Image>();
|
||||
if (track != null) track.color = Transparent;
|
||||
var sbrt = sb.transform as RectTransform;
|
||||
if (sbrt != null) sbrt.sizeDelta = new Vector2(6f, sbrt.sizeDelta.y);
|
||||
foreach (var img in sb.GetComponentsInChildren<Image>(true))
|
||||
{
|
||||
if (sb.handleRect != null && (img.gameObject == sb.handleRect.gameObject || img.transform.IsChildOf(sb.handleRect)))
|
||||
continue;
|
||||
SetClear(img);
|
||||
}
|
||||
if (sb.handleRect != null)
|
||||
{
|
||||
sb.handleRect.sizeDelta = new Vector2(0f, sb.handleRect.sizeDelta.y);
|
||||
var handleImg = sb.handleRect.GetComponent<Image>();
|
||||
if (handleImg != null)
|
||||
{
|
||||
handleImg.sprite = MachineryStyle.White;
|
||||
handleImg.type = Image.Type.Simple;
|
||||
handleImg.color = Ink;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (scroll.horizontalScrollbar != null)
|
||||
{
|
||||
var sb = scroll.horizontalScrollbar;
|
||||
var sbrt = sb.transform as RectTransform;
|
||||
if (sbrt != null) sbrt.sizeDelta = new Vector2(sbrt.sizeDelta.x, 6f);
|
||||
foreach (var img in sb.GetComponentsInChildren<Image>(true))
|
||||
{
|
||||
if (sb.handleRect != null && (img.gameObject == sb.handleRect.gameObject || img.transform.IsChildOf(sb.handleRect)))
|
||||
continue;
|
||||
SetClear(img);
|
||||
}
|
||||
if (sb.handleRect != null)
|
||||
{
|
||||
sb.handleRect.sizeDelta = new Vector2(sb.handleRect.sizeDelta.x, 0f);
|
||||
var handleImg = sb.handleRect.GetComponent<Image>();
|
||||
if (handleImg != null)
|
||||
{
|
||||
handleImg.sprite = MachineryStyle.White;
|
||||
handleImg.type = Image.Type.Simple;
|
||||
handleImg.color = Ink;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清理辅助 Panel 底图
|
||||
// 清理辅助 Panel 底图与任何残留原生灰色边框的容器
|
||||
if (clear != null)
|
||||
{
|
||||
foreach (var img in clear)
|
||||
if (img != null) img.color = Transparent;
|
||||
if (img != null) SetClear(img);
|
||||
}
|
||||
foreach (var img in screen.GetComponentsInChildren<Image>(true))
|
||||
{
|
||||
if (img.sprite == MachineryStyle.BevelFrame) SetClear(img);
|
||||
}
|
||||
|
||||
// 数据表行:反色高亮与整行点击
|
||||
@@ -241,6 +315,26 @@ namespace Decentralized
|
||||
if (pBtn != null && pBtn.gameObject != r.Root) continue;
|
||||
t.color = r.Selected ? KeyText : Ink;
|
||||
}
|
||||
if (r.Selected)
|
||||
{
|
||||
// 选中行整行反色(深墨底):行内的操作按钮反转为浅色底、深墨字
|
||||
foreach (var cBtn in r.Root.GetComponentsInChildren<Button>(true))
|
||||
{
|
||||
if (cBtn.gameObject == r.Root) continue;
|
||||
cBtn.transition = Selectable.Transition.None;
|
||||
var img = cBtn.GetComponent<Image>();
|
||||
if (img != null)
|
||||
{
|
||||
img.sprite = MachineryStyle.White;
|
||||
img.type = Image.Type.Simple;
|
||||
img.color = KeyText;
|
||||
}
|
||||
foreach (var t in cBtn.GetComponentsInChildren<TextMeshProUGUI>(true))
|
||||
{
|
||||
t.color = Ink;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (r.OnClick != null)
|
||||
{
|
||||
var btn = r.Root.GetComponent<Button>() ?? r.Root.AddComponent<Button>();
|
||||
|
||||
@@ -194,34 +194,23 @@ namespace Decentralized
|
||||
r.AddHeader(L.T("bank.ops"));
|
||||
AmountRow(r);
|
||||
AmlPreview(r);
|
||||
r.AddSpace(4f);
|
||||
r.BeginRow(6f);
|
||||
r.AddSpace(6f);
|
||||
r.AddButton(L.T("trade.deposit"), Deposit);
|
||||
r.Last?.SetPreferredSize(RightW - 30f, 28f);
|
||||
r.AddSpace(4f);
|
||||
r.AddButton(L.T("trade.withdraw"), Withdraw);
|
||||
r.End();
|
||||
r.Last?.SetPreferredSize(RightW - 30f, 28f);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>提取前的合规审查提示:本周已提取的累计、污点比例,以及按当前数量估算的审查概率。</summary>
|
||||
/// <summary>提取前的合规审查提示:仅保留账户污点比例(额度与命中概率按设计不公开)。</summary>
|
||||
private static void AmlPreview(CustomUIBuilder b)
|
||||
{
|
||||
var d = Session.Data;
|
||||
int day = StoreStation.GetDayCounter();
|
||||
double rent = Session.Rent();
|
||||
double recent = d.Exchange.History.Where(h => h.Key > day - Tuning.AmlWindowDays).Sum(h => h.Value);
|
||||
b.AddSeparator();
|
||||
b.AddLabel(L.T("aml.window", Tuning.AmlWindowDays, Fmt.Credits(recent), Fmt.Credits(Tuning.AmlCumRents * rent)), "aml_dim");
|
||||
var pb = d.Poinbase;
|
||||
var pb = Session.Data.Poinbase;
|
||||
double total = pb.Value(Session.Price);
|
||||
double taintRatio = total > 0 ? pb.Taint / total : 0;
|
||||
b.AddSeparator();
|
||||
b.AddLabel(L.T("aml.taint", (int)Math.Round(taintRatio * 100)), taintRatio > 0.05 ? "aml_note" : "aml_dim");
|
||||
if (double.TryParse((_amount ?? "").Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out double v) && v > 0)
|
||||
{
|
||||
double value = Math.Min(v, pb.Get(Assets.CRC)) * Session.Price(Assets.CRC);
|
||||
double taint = total > 0 ? pb.Taint * Math.Min(1, value / total) : 0;
|
||||
double chance = Exchange.HitChance(value, taint, recent, rent, pb.Flagged);
|
||||
b.AddLabel(L.T("aml.chance", (int)Math.Round(chance * 100)), chance > 0.1 ? "aml_chance_note" : "aml_chance_dim");
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly float[] StableW = { 80f, 100f, 220f };
|
||||
@@ -331,7 +320,7 @@ namespace Decentralized
|
||||
private static string _perpProduct = "PSC";
|
||||
private static bool _perpLong = true;
|
||||
private static int _perpLev = 3;
|
||||
private static readonly float[] PerpW = { 118f, 60f, 104f, 60f, 58f };
|
||||
private static readonly float[] PerpW = { 90f, 85f, 80f, 90f, 55f };
|
||||
private static readonly TextAnchor[] PerpAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||
|
||||
private static double PerpSpot(string p) => p == "SPARK" ? Session.Data.Stable.Spark : Session.Data.Market.Price;
|
||||
@@ -417,7 +406,7 @@ namespace Decentralized
|
||||
});
|
||||
}
|
||||
|
||||
private static readonly float[] PoolW = { 128f, 50f, 64f, 64f, 50f, 60f };
|
||||
private static readonly float[] PoolW = { 110f, 50f, 64f, 64f, 50f, 78f };
|
||||
private static readonly TextAnchor[] PoolAligns = { TextAnchor.MiddleLeft, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight, TextAnchor.MiddleRight };
|
||||
|
||||
/// <summary>第三方收益池:日息、储备、时间锁、审计、我的存款,存入 / 取出(合约调用,签名)。是不是骗局看不见。</summary>
|
||||
@@ -808,13 +797,13 @@ namespace Decentralized
|
||||
r.AddLabel(PredictGame.Question(m));
|
||||
var tip = d.Predict.TipFor(m.Id);
|
||||
if (tip != null) { r.AddLabel(L.T("predict.clue.tip", L.T("predict.tier." + tip.Tier), L.T(tip.Claim ? "predict.yes" : "predict.no")), "intel_tip_dim"); continue; }
|
||||
r.BeginRow(4f);
|
||||
for (int t = 0; t < 3; t++)
|
||||
{
|
||||
int tier = t;
|
||||
r.AddButton(L.T("intel.tip.buy", (int)Math.Round(Tuning.IntelTipAcc[t] * 100), Fmt.Num(Tuning.IntelTipPrice[t] * m.MaxLoss)), () => IntelBuyTip(mk, tier));
|
||||
r.Last?.SetPreferredSize(RightW - 30f, 28f);
|
||||
if (t < 2) r.AddSpace(2f);
|
||||
}
|
||||
r.End();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ namespace Decentralized
|
||||
OnClick = () => { dev.Asset = x.asset; dev.Note = null; Open(dev); }
|
||||
});
|
||||
PledgerSkin.Apply(win, screen, bezel, paper, _picked, _clear, rows);
|
||||
if (plate != null) plate.color = PledgerSkin.Transparent;
|
||||
if (plate != null) PledgerSkin.SetClear(plate);
|
||||
// 签名要按住 ✓:在按键上挂一个按住计时
|
||||
if (ok != null && dev.Screen == Screen.Review && ok.GetComponent<HoldToSign>() == null) ok.AddComponent<HoldToSign>().Device = dev.Address;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user