feat: add some action icons

This commit is contained in:
2026-08-27 14:57:09 +08:00
parent 80738d1254
commit 9d20e60adb
5 changed files with 74 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
Blue Background Node 1,#001fbe
Blue Background Node 2,#1439ff
Paper Background Node 1,#ffffff
Paper Backgroundr Node 2,#e3e3e3
1 Blue Background Node 1 #001fbe
2 Blue Background Node 2 #1439ff
3 Paper Background Node 1 #ffffff
4 Paper Backgroundr Node 2 #e3e3e3
@@ -9,7 +9,7 @@ def load_input_artifact(p: Path) -> ArtifactFile:
""" """
Load input artifact used for building temporary and output artifact. Load input artifact used for building temporary and output artifact.
""" """
logging.info("Loading asset: %s", p) logging.debug("Loading input artifact: %s", p)
return PIL.Image.open(p, "r", ["PNG", "JPEG", "BMP"]) return PIL.Image.open(p, "r", ["PNG", "JPEG", "BMP"])
@@ -17,14 +17,15 @@ def load_artifact(p: Path) -> ArtifactFile:
""" """
Load artifact saved previously as the intermediary. Load artifact saved previously as the intermediary.
""" """
logging.info("Loading artifact: %s", p) logging.debug("Loading temporary or output artifact: %s", p)
return PIL.Image.open(p, "r", ["PNG"]) return PIL.Image.open(p, "r", ["PNG"])
def save_artifact(art: Artifact, p: Path) -> None: def save_artifact(art: Artifact, p: Path) -> None:
logging.info("Saving artifact: %s", p) logging.debug("Saving artifact: %s", p)
art.save(p, format="PNG") art.save(p, format="PNG")
def dup_artifact(src: Path, dst: Path) -> None: def dup_artifact(src: Path, dst: Path) -> None:
logging.debug("Duplicating artifact: %s -> %s", src, dst)
shutil.copyfile(src, dst) shutil.copyfile(src, dst)
@@ -39,7 +39,7 @@ def render_svg(src: Path, dst: Path, kind: SvgRenderKind, cfg: SvgConfig) -> Non
:param kind: The selected SVG render kind. :param kind: The selected SVG render kind.
:param cfg: The configuration when rendering. :param cfg: The configuration when rendering.
""" """
logging.info("Rendering SVG artifact with render {kind.name}: %s -> %s", src, dst) logging.debug("Rendering SVG artifact with render %s: %s -> %s", kind.name, src, dst)
match kind: match kind:
case SvgRenderKind.Inkscape: case SvgRenderKind.Inkscape:
@@ -133,7 +133,7 @@ def render_blender(src: Path, dst: Path, temp_script: Path, cfg: BlenderConfig)
The caller must make sure that this file is immutable during calling this function. The caller must make sure that this file is immutable during calling this function.
:param cfg: The configuration when rendering. :param cfg: The configuration when rendering.
""" """
logging.info("Rendering Blender artifact: %s -> %s", src, dst) logging.debug("Rendering Blender artifact: %s -> %s", src, dst)
script = _BLENDER_RENDER_SCRIPT.format( script = _BLENDER_RENDER_SCRIPT.format(
width=cfg.width, height=cfg.height, dst=repr(str(dst)) width=cfg.width, height=cfg.height, dst=repr(str(dst))
@@ -167,7 +167,7 @@ def render_thumbnail(art: Artifact, hws: Iterable[int]) -> Iterator[Artifact]:
""" """
check_vanilla_artifact(art) check_vanilla_artifact(art)
for hw in hws: for hw in hws:
logging.info("Rendering thumbnail %dx%d.", hw, hw) logging.debug("Rendering thumbnail %dx%d.", hw, hw)
thumbnail = art.copy() thumbnail = art.copy()
thumbnail.thumbnail((hw, hw), PIL.Image.Resampling.LANCZOS) thumbnail.thumbnail((hw, hw), PIL.Image.Resampling.LANCZOS)
yield thumbnail yield thumbnail
@@ -180,7 +180,7 @@ def render_ico(art: Artifact, dst: Path) -> None:
:param art: The artifact to be rendered. :param art: The artifact to be rendered.
:param dst: The path to rendered result. :param dst: The path to rendered result.
""" """
logging.info("Rendering .ICO artifact: -> %s", dst) logging.debug("Rendering .ICO artifact: %s", dst)
check_vanilla_artifact(art) check_vanilla_artifact(art)
sizes = [16, 32, 48, 64, 128, 256] sizes = [16, 32, 48, 64, 128, 256]
@@ -202,7 +202,7 @@ def render_icns(art: Artifact, dst: Path) -> None:
:param art: The artifact to be rendered. :param art: The artifact to be rendered.
:param dst: The path to rendered result. :param dst: The path to rendered result.
""" """
logging.info("Rendering .ICNS artifact: -> %s", dst) logging.debug("Rendering .ICNS artifact: %s", dst)
check_vanilla_artifact(art) check_vanilla_artifact(art)
# provide every smaller frame explicitly; the 1024x1024 entry is # provide every smaller frame explicitly; the 1024x1024 entry is
@@ -160,7 +160,9 @@ class AdvancedContext:
""" """
Load given input bitmap asset. Load given input bitmap asset.
""" """
return artio.load_input_artifact(self.input_artifact(*args)) p = self.input_artifact(*args)
logging.info("Loading input artifact: %s", p)
return artio.load_input_artifact(p)
# endregion # endregion
@@ -181,7 +183,9 @@ class AdvancedContext:
return self.__user_temporary_artifact(*args) return self.__user_temporary_artifact(*args)
def load_temporary_artifact(self, *args: str) -> ArtifactFile: def load_temporary_artifact(self, *args: str) -> ArtifactFile:
return artio.load_artifact(self.temporary_artifact(*args)) p = self.temporary_artifact(*args)
logging.info("Loading temporary artifact: %s", p)
return artio.load_artifact(p)
def save_temporary_artifact(self, art: Artifact, *args: str) -> None: def save_temporary_artifact(self, art: Artifact, *args: str) -> None:
""" """
@@ -189,7 +193,9 @@ class AdvancedContext:
All existence of sub-directory should be ensured on your own. All existence of sub-directory should be ensured on your own.
""" """
artio.save_artifact(art, self.temporary_artifact(*args)) p = self.temporary_artifact(*args)
logging.info("Saving temporary artifact: %s", p)
artio.save_artifact(art, p)
def __allocate_lib_temporary_artifact(self, suffix: Optional[str] = None) -> Path: def __allocate_lib_temporary_artifact(self, suffix: Optional[str] = None) -> Path:
p = self.__lib_temporary_artifact(_TEMP_LIB_ALLOC_DIR) p = self.__lib_temporary_artifact(_TEMP_LIB_ALLOC_DIR)
@@ -213,7 +219,10 @@ class AdvancedContext:
:return: The path to destination storing render result. :return: The path to destination storing render result.
""" """
if dst is None: if dst is None:
logging.info("Rendering temporary SVG: %s", src)
dst = self.__allocate_lib_temporary_artifact(".png") dst = self.__allocate_lib_temporary_artifact(".png")
else:
logging.info("Rendering SVG: %s -> %s", src, dst)
artrender.render_svg(src, dst, self.__context.prerequisite.svg_render, cfg) artrender.render_svg(src, dst, self.__context.prerequisite.svg_render, cfg)
return dst return dst
@@ -257,7 +266,10 @@ class AdvancedContext:
""" """
temp_script = self.__fetch_const_lib_temporary_artifact("blender.py") temp_script = self.__fetch_const_lib_temporary_artifact("blender.py")
if dst is None: if dst is None:
logging.info("Rendering temporary Blender composition: %s", src)
dst = self.__allocate_lib_temporary_artifact(".png") dst = self.__allocate_lib_temporary_artifact(".png")
else:
logging.info("Rendering Blender composition: %s -> %s", src, dst)
artrender.render_blender(src, dst, temp_script, cfg) artrender.render_blender(src, dst, temp_script, cfg)
return dst return dst
@@ -305,7 +317,7 @@ class AdvancedContext:
:param name: The name of saved artifact. The file extension ".png" is not required. :param name: The name of saved artifact. The file extension ".png" is not required.
""" """
logging.info( logging.info(
"Saving FreeDesktop artifact with kind %s and name %s.", kind, name 'Saving FreeDesktop artifact with kind "%s" and name "%s".', kind, name
) )
for hw, thumbnail in zip( for hw, thumbnail in zip(
@@ -317,6 +329,13 @@ class AdvancedContext:
def dup_fd_artifact( def dup_fd_artifact(
self, src_kind: FdContext, src_name: str, dst_kind: FdContext, dst_name: str self, src_kind: FdContext, src_name: str, dst_kind: FdContext, dst_name: str
) -> None: ) -> None:
logging.info(
'Duplicating FreeDesktop artifact from kind "%s" name "%s" to kind "%s" name "%s".',
src_kind,
src_name,
dst_kind,
dst_name,
)
for hw in _FD_THUMBNAIL_HWS: for hw in _FD_THUMBNAIL_HWS:
artio.dup_artifact( artio.dup_artifact(
self.__fd_artifact(hw, src_kind, src_name), self.__fd_artifact(hw, src_kind, src_name),
@@ -333,13 +352,20 @@ class AdvancedContext:
:param name: The name of saved artifact. The file extension ".ico" is not required. :param name: The name of saved artifact. The file extension ".ico" is not required.
""" """
logging.info( logging.info(
"Saving Windows-only artifact with kind %s and name %s.", kind, name 'Saving Windows-only artifact with kind "%s" and name "%s".', kind, name
) )
artrender.render_ico(art, self.__win_artifact(kind, name)) artrender.render_ico(art, self.__win_artifact(kind, name))
def dup_win_artifact( def dup_win_artifact(
self, src_kind: WinCategory, src_name: str, dst_kind: WinCategory, dst_name: str self, src_kind: WinCategory, src_name: str, dst_kind: WinCategory, dst_name: str
) -> None: ) -> None:
logging.info(
'Duplicating Windows-only artifact from kind "%s" name "%s" to kind "%s" name "%s".',
src_kind,
src_name,
dst_kind,
dst_name,
)
artio.dup_artifact( artio.dup_artifact(
self.__win_artifact(src_kind, src_name), self.__win_artifact(src_kind, src_name),
self.__win_artifact(dst_kind, dst_name), self.__win_artifact(dst_kind, dst_name),
@@ -354,12 +380,21 @@ class AdvancedContext:
:param name: The name of saved artifact. The file extension ".icns" is not required. :param name: The name of saved artifact. The file extension ".icns" is not required.
""" """
logging.info("Saving macOS-only artifact with kind %s and name %s.", kind, name) logging.info(
'Saving macOS-only artifact with kind "%s" and name "%s".', kind, name
)
artrender.render_icns(art, self.__mac_artifact(kind, name)) artrender.render_icns(art, self.__mac_artifact(kind, name))
def dup_mac_artifact( def dup_mac_artifact(
self, src_kind: MacCategory, src_name: str, dst_kind: MacCategory, dst_name: str self, src_kind: MacCategory, src_name: str, dst_kind: MacCategory, dst_name: str
) -> None: ) -> None:
logging.info(
'Duplicating macOS-only artifact from kind "%s" name "%s" to kind "%s" name "%s".',
src_kind,
src_name,
dst_kind,
dst_name,
)
artio.dup_artifact( artio.dup_artifact(
self.__mac_artifact(src_kind, src_name), self.__mac_artifact(src_kind, src_name),
self.__mac_artifact(dst_kind, dst_name), self.__mac_artifact(dst_kind, dst_name),
@@ -4,13 +4,13 @@ from ..assemblicon.context import AdvancedContext, FdContext
def build_action_icons(ctx: AdvancedContext) -> None: def build_action_icons(ctx: AdvancedContext) -> None:
_build_go_icons(ctx) _build_go_icons(ctx)
_build_object_flip_icons(ctx)
_build_object_rotate_icons(ctx)
def _build_go_icons(ctx: AdvancedContext) -> None: def _build_go_icons(ctx: AdvancedContext) -> None:
# build go-* base # build go-* base
go_base = ctx.render_svg_then_load( go_base = ctx.render_svg_then_load(ctx.input_artifact("component", "go-base.svg"))
ctx.input_artifact("component", "go-base.svg")
)
# build go-* shining # build go-* shining
go_inner_shining = ctx.render_svg_then_load( go_inner_shining = ctx.render_svg_then_load(
ctx.input_artifact("component", "go-inner-shining.svg"), ctx.input_artifact("component", "go-inner-shining.svg"),
@@ -26,9 +26,23 @@ def _build_go_icons(ctx: AdvancedContext) -> None:
go = go_base.copy() go = go_base.copy()
# render shining with inner mask # render shining with inner mask
go.paste(go_inner_shining, (0, 0), go_mask) go.paste(go_inner_shining, (0, 0), go_mask)
# save as FD action # save as FD action
ctx.save_fd_artifact(go, FdContext.Actions, f'go-{part}') ctx.save_fd_artifact(go, FdContext.Actions, f"go-{part}")
# rotate it for next calling # rotate it for next calling
go_mask = go_mask.transpose(PIL.Image.Transpose.ROTATE_90) go_mask = go_mask.transpose(PIL.Image.Transpose.ROTATE_90)
def _build_object_flip_icons(ctx: AdvancedContext) -> None:
art = ctx.render_svg_then_load(ctx.input_artifact("object-flip-horizontal.svg"))
ctx.save_fd_artifact(art, FdContext.Actions, "object-flip-horizontal")
art = ctx.render_svg_then_load(ctx.input_artifact("object-flip-vertical.svg"))
ctx.save_fd_artifact(art, FdContext.Actions, "object-flip-vertical")
def _build_object_rotate_icons(ctx: AdvancedContext) -> None:
art = ctx.render_svg_then_load(ctx.input_artifact("object-rotate-left.svg"))
ctx.save_fd_artifact(art, FdContext.Actions, "object-rotate-left")
art = ctx.render_svg_then_load(ctx.input_artifact("object-rotate-right.svg"))
ctx.save_fd_artifact(art, FdContext.Actions, "object-rotate-right")