C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

曲線の長さと同期させる6

こちらの続きです。
曲線の長さと同期させる5 - C#ATIA

業務が忙しくなり、まとまった時間が確保出来ずほぼ進展無いのですが、
前回の動画で使用していたコードの一部を公開しておきます。
・・・紛失してしまいそうな予感がするからです。

import adsk.core
import adsk.fusion
import json


GROUPNAME = 'kantoku' # コマンド名にすべき
ATTRKEY = 'curves$'
_debug = True

class SynchronousParameterFactry():
    def __init__(self) -> None:
        self.containers = []

        self.registerContainers()

    def __getEntityByToken__(
        self,
        token: str):

        des: adsk.fusion.Design = self.__getActDoc__().design
        ents = des.findEntityByToken(token)
        if len(ents) < 1:
            return None

        return ents[0]


    def __getEntityByParameterAttr__(self, prm: adsk.fusion.UserParameter) -> list:
        attr: adsk.core.Attribute = prm.attributes.itemByName(GROUPNAME, ATTRKEY)
        if not attr:
            return

        crvsTokenDict: dict = json.loads(attr.value)
        lst = []
        for token in crvsTokenDict.values():
            crv = self.__getEntityByToken__(token)
            if not crv:
                continue

            lst.append(crv)

        return lst


    def __getHasAttrUserParameter__(self) -> list:
        prms: adsk.fusion.UserParameters = self.__getActDoc__().design.userParameters

        lst = []
        prm: adsk.fusion.UserParameter
        for prm in prms:
            if prm.attributes.itemByName(GROUPNAME, ATTRKEY):
                lst.append(prm)

        return lst


    def __getActDoc__(
        self,) -> adsk.fusion.FusionDocument:

        app: adsk.core.Application = adsk.core.Application.get()
        return app.activeDocument


    def __getContainer__(
        self,
        prm: adsk.fusion.UserParameter) -> 'ParameterContainer':

        for container in self.containers:
            if container.param != prm:
                continue
            return container
        
        return None


    def __initContainer__(
        self,
        parameter: adsk.fusion.UserParameter,
        crvs: list) -> None:

        container: 'ParameterContainer' = ParameterContainer(
            parameter,
            crvs
        )
        self.containers.append(container)

        return container


    def __updateContainer__(
        self,
        container: 'ParameterContainer',
        crvs: list) -> None:

        container.updateCurves(crvs)


    def registerContainers(self) -> None:
        self.containers = [] # これが必要か判断出来ない・・・
        prms = self.__getHasAttrUserParameter__()
        if len(prms) < 1:
            return

        prm: adsk.fusion.UserParameter
        for prm in prms:
            self.set(
                prm,
                self.__getEntityByParameterAttr__(prm)
            )


    def set(
        self,
        parameter: adsk.fusion.UserParameter,
        crvs: list) -> None:

        container: 'ParameterContainer' = self.__getContainer__(
            parameter,
        )

        if container:
            self.__updateContainer__(
                container,
                crvs
            )
        else:
            container = self.__initContainer__(
                parameter,
                crvs
            )

        container.updateParameter()


    def update(
        self) -> None:

        container: 'ParameterContainer'
        for container in self.containers:
            container.updateParameter()


    def getCurves(
        self,
        Parameter: adsk.fusion.UserParameter) -> list:

        container: 'ParameterContainer' = self.__getContainer__(
            Parameter,
        )

        if not container:
            return []

        return container.getCurves()

    def getParameterNames(
        self) -> list:

        return [container.param.name for container in self.containers]
            



# ************************************
class ParameterContainer():
    def __init__(
        self,
        parameter: adsk.fusion.UserParameter,
        curves: list) -> None:

        self.param: adsk.fusion.UserParameter = parameter
        self.curves: list = curves


    def __del__(self) -> None:
        self.param = None
        self.curves = []


    def __addAttr__(self) -> None:
        # curves tokens
        tokens = {str(idx): c.entityToken for idx, c in enumerate(self.curves)}

        # add attr
        attrs: adsk.core.Attributes = self.param.attributes
        attrs.add(
            GROUPNAME,
            ATTRKEY,
            json.dumps(tokens)
        )


    def __updateAttr__(self) -> None:
        # curves tokens
        tokens = {str(idx): c.entityToken for idx, c in enumerate(self.curves)}

        # add attr
        attrs: adsk.core.Attributes = self.param.attributes
        attr: adsk.core.Attribute = attrs.itemByName(
            GROUPNAME,
            ATTRKEY
        )

        if attr:
            if set(json.loads(attr.value).values()) == set(tokens.values()):
                return
            else:
                attr.value = json.dumps(tokens)
        else:
            self.__addAttr__()


    def __updatePrm__(self) -> None:
        if not self.param:
            return

        value = self.getCurvesLength()
        if self.param.value != value:
            self.param.value = value


    def __isVisible__(self, ent) -> bool:
        try:
            if not hasattr(ent, 'isVisible'):
                return False

            if ent.isVisible:
                return True
            return False
        except:
            return False


    def getCurvesLength(self) -> float:
        value = 0
        crv: adsk.fusion.SketchEntity
        for crv in self.curves:
            value += crv.length

        return value


    def updateParameter(self) -> None:
        # curves
        self.curves = [c for c in self.curves if self.__isVisible__(c)]

        # parameter
        self.__updatePrm__()

        # attr
        self.__updateAttr__()


    def updateCurves(self, curves: list) -> None:
        # curves
        newCrvs = [e for e in curves if self.__isVisible__(e)]
        oldCrvs = [e for e in self.curves if self.__isVisible__(e)]

        newToken = set(e.entityToken for e in newCrvs)
        oldToken = set(e.entityToken for e in oldCrvs)
        if newToken != oldToken:
            self.curves = newCrvs
        elif len(oldCrvs) != len(self.curves):
            self.curves = oldCrvs

        # parameter
        self.__updatePrm__()

        # attr
        self.__updateAttr__()


    def getCurves(self) -> list:
        return self.curves

念の為ですが、パラメータと監視すべき曲線を紐付けしておくための
クラスの為、これ単体では動きません。
これで完成では無く修正が必要なのですが、UIを作成しないと何が
必要なのか分からない状態に陥り、悶えています。

UIについてもどんな機能が必要なものか迷っている上、望んでいるような
ものを作る為にはかなり勉強する必要性を感じ、悩んでいます。
完成するかな? 捨てるにはもったいない気がしているのですが。