Files
fenix8v3-watchface/tools/gen_devices.py
ericwyuan 22340b09fa 机型覆盖 17 → 55 款,补 LICENSE 与 CHANGELOG
机型
  新增 38 款圆屏 + CIQ ≥ 4.2 的机型:fenix 7 Pro 全系、Venu 2/3S、
  Approach S50/S70、Descent G2/Mk3、D2 系列、Instinct 3 AMOLED、
  FR255S/265S/570/955 等。其中 34 款的屏宽已有现成图标资源。

  机型列表和 monkey.jungle 改由 tools/gen_devices.py 扫描本机 SDK 生成,
  筛选条件是「支持 watchFace + 圆屏 + CIQ ≥ 4.2」(Complications 要 4.2)。
  55 条资源路径不再手写。

  新增 218px 与 360px 两档图标。218px 上图标只有 14×14,设计稿里太阳与云
  之间那道 1.7 设计像素的暗缝连一个物理像素都占不到,光栅化出来是一坨没有
  结构的橙块 —— 该尺寸改用按目标像素直接摆的简化标记。

常亮模式:结论是不改
  为了压所谓的 10% 点亮率,一度把进度环也砍掉了。换成平均亮度(AMOLED 功耗
  的合理代理)重新量之后发现:普通模式 14.1%,常亮 2.9%,本来就只有 1/5;
  砍掉环只从 3.01% 降到 2.91%。0.1 个百分点换掉一个可见特征不划算,环留着。
  两种度量的差异和这个决定都写进了代码注释和 README。

其它
  - LICENSE(MIT)。只覆盖代码 —— design/ 下的设计稿版权归第三方,
    发布前需取得原作者授权或替换视觉,文件内已注明。
  - UserProfile.getProfile() 加异常保护(这个 API 家族已经坑过三次)
  - CHANGELOG.md,版本号 1.0.0 → 1.1.0

验证:55 款全部编译通过(分三批 18+18+19);.iq 上架包可正常导出。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 11:27:54 +08:00

119 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""扫描本机安装的 Connect IQ 设备,重写 manifest 的机型列表和 monkey.jungle。
筛选条件(三条都要满足):
1. 支持 watchFace 类型
2. Connect IQ >= 4.2 —— Toybox.Complications 是这个版本引入的,
本表盘的日历/训练状态/第三方 App 字段依赖它
3. 圆屏deviceFamily 以 round- 开头)
python3 tools/gen_devices.py
改写两处:
manifest.xml <iq:products> 整块
monkey.jungle 每台设备的 resourcePath图标按屏宽、启动图标按各自要求的尺寸
⚠️ 结果取决于本机 SDK 里**装了哪些设备**。如果某台机器上少装了几款,
跑一遍会把它们从 manifest 里删掉。所以脚本会打印找到的数量,
提交前确认一下数字对不对(当前应为 55 款)。
图标资源的尺寸集合由本脚本算出后交给 tools/gen_icons.py 使用,
两者的 WIDTHS / LAUNCHER 必须一致,所以改完这里要跟着跑一遍 gen_icons.py。
"""
import json
import os
import re
from collections import defaultdict
HERE = os.path.dirname(os.path.abspath(__file__))
ROOT = os.path.dirname(HERE)
DEV = os.path.expanduser(
"~/Library/Application Support/Garmin/ConnectIQ/Devices")
def eligible():
"""返回 [(设备id, 屏宽, 启动图标尺寸, 是否支持alpha), ...],按 id 排序。"""
out = []
if not os.path.isdir(DEV):
raise SystemExit("找不到设备目录:%s" % DEV)
for d in sorted(os.listdir(DEV)):
p = os.path.join(DEV, d, "compiler.json")
if not os.path.exists(p):
continue
try:
c = json.load(open(p))
except Exception:
continue
types = {t["type"] for t in c.get("appTypes", []) if isinstance(t, dict)}
if "watchFace" not in types:
continue
if not str(c.get("deviceFamily", "")).startswith("round"):
continue
vers = [str(pn.get("connectIQVersion", "0"))
for pn in c.get("partNumbers", [])]
if not any(_ciq_ok(v) for v in vers):
continue
li = c.get("launcherIcon", {})
out.append((d, c["resolution"]["width"], li.get("width"),
bool(c.get("alphaBlendingSupport"))))
return out
def _ciq_ok(v):
try:
a = [int(x) for x in v.split(".")[:2]]
return a[0] > 4 or (a[0] == 4 and a[1] >= 2)
except Exception:
return False
def write_manifest(devs):
p = os.path.join(ROOT, "manifest.xml")
s = open(p).read()
body = "\n".join(' <iq:product id="%s"/>' % d for d, _, _, _ in devs)
block = " <iq:products>\n%s\n </iq:products>" % body
s = re.sub(r" <iq:products>.*?</iq:products>", block, s, flags=re.S)
open(p, "w").write(s)
print("manifest.xml: 写入 %d 款机型" % len(devs))
def write_jungle(devs):
L = ["project.manifest = manifest.xml", "",
"base.sourcePath = source", "",
"# resources-chn 是简体中文文案;目录名的 -chn 后缀就是语言标记。",
"base.resourcePath = resources;resources-chn", "",
"# 下面每台设备再挂两棵资源树,都由 tools/gen_icons.py 生成:",
"# resources-icons-<屏宽> 按该屏幕像素网格光栅化的日出/日落/天气图标",
"# resources-launcher-<尺寸> 该机型要求尺寸的启动图标",
"# 这一整段由 tools/gen_devices.py 生成,不要手改。",
""]
for d, w, li, _ in devs:
L.append("%s.resourcePath = $(base.resourcePath)"
";resources-icons-%d;resources-launcher-%d" % (d, w, li))
L += ["", "base.excludeAnnotations = release"]
open(os.path.join(ROOT, "monkey.jungle"), "w").write("\n".join(L) + "\n")
print("monkey.jungle: 写入 %d 条资源路径" % len(devs))
def main():
devs = eligible()
if not devs:
raise SystemExit("一款符合条件的机型都没找到,请检查 SDK 设备是否已安装")
widths = defaultdict(set)
for _, w, _, alpha in devs:
widths[w].add(alpha)
print("符合条件的机型:%d" % len(devs))
print("需要的图标屏宽:%s" % sorted(widths))
print("需要的启动图标尺寸:%s" % sorted({li for _, _, li, _ in devs}))
for w in sorted(widths):
if len(widths[w]) > 1:
print(" ⚠️ %dpx 同时存在支持/不支持 alpha 的机型,"
"图标按硬边生成" % w)
write_manifest(devs)
write_jungle(devs)
print("\n接着跑python3 tools/gen_icons.py")
if __name__ == "__main__":
main()