SuperScriptMaterializer/SuperScriptDecorator/DecoratorData.py

193 lines
6.9 KiB
Python
Raw Permalink Normal View History

2023-02-22 21:49:31 +08:00
'''
NOTE:
There are 3 different styles shape in generated graph.
"Block" is stands for the large block, including BB and pOper.
"Cell" is stands for the medium block, including pLocal, pAttr, Shortcut.
"Particle" is stands for the small block, including bIO, pIO, pTarget.
Besides these shapes, the generated graph also include various links.
There are 2 types link. bLink and pLink.
'''
import typing, collections, sqlite3
class Vector(object):
2023-02-21 22:27:38 +08:00
def __init__(self):
self.X: float = 0.0
self.Y: float = 0.0
def __init__(self, x: float, y: float):
self.X: float = x
self.Y: float = y
2023-02-21 22:27:38 +08:00
@property
def LenLeavesDir(self):
return self.X
@LenLeavesDir.setter
def LenLeavesDir(self, v):
self.X = v
@property
def LenRootsDir(self):
return self.Y
@LenRootsDir.setter
def LenRootsDir(self, v):
self.Y = v
def __add__(self, other):
if not isinstance(other, Vector): return NotImplemented
return Vector(self.X + other.X, self.Y + other.Y)
def __sub__(self, other):
if not isinstance(other, Vector): return NotImplemented
return Vector(self.X - other.X, self.Y - other.Y)
def __radd__(self, other):
if not isinstance(other, Vector): return NotImplemented
return Vector(self.X + other.X, self.Y + other.Y)
def __rsub__(self, other):
if not isinstance(other, Vector): return NotImplemented
return Vector(self.X - other.X, self.Y - other.Y)
def __iadd__(self, other):
if not isinstance(other, Vector): return NotImplemented
self.X += other.X
self.Y += other.Y
return self
def __isub__(self, other):
if not isinstance(other, Vector): return NotImplemented
self.X -= other.X
self.Y -= other.Y
return self
def __eq__(self, other) -> bool:
if not isinstance(other, Vector): return NotImplemented
return (self.X == other.X and self.Y == other.Y)
def __ne__(self, other) -> bool:
if not isinstance(other, Vector): return NotImplemented
return (self.X != other.X or self.Y != other.Y)
2023-02-21 22:27:38 +08:00
class Margin(object):
def __init__(self):
self.m_TopSize: Vector = Vector()
self.m_BodySize: Vector = Vector()
self.m_BottomSize: Vector = Vector()
2023-02-22 21:49:31 +08:00
class ICanManipulate(object):
'''
This class is served for TreeLayout class.
All classes inherit this class will have ability to calculate the size of self,
and report to TreeLayout. TreeLayout will use these data to distribute position.
The functions declared in this class have unique name meaning.
The reason is that the vertical and horizonal direction between BB and Oper is opposited.
So we use Leaves and Root to give theme an uniformed concept.
'''
2023-02-22 21:49:31 +08:00
def SetOrigin():
pass
2023-02-21 22:27:38 +08:00
def ComputeSize() -> Vector:
'''
2023-02-21 22:27:38 +08:00
Get current node's start position
'''
raise NotImplementedError()
2023-02-22 21:49:31 +08:00
TNode = typing.TypeVar('TNode', bound=ICanManipulate)
2023-02-21 22:27:38 +08:00
class TreeLayoutLayer(typing.Generic[TNode]):
def __init__(self, ref_layer: int, start_pos_of_ref_layer: int):
self.m_Container: collections.deque[TNode] = collections.deque()
self.m_RefLayer: int = ref_layer
self.m_RefLayerIndex: int = start_pos_of_ref_layer
class TreeLayout(typing.Generic[TNode]):
2023-02-21 22:27:38 +08:00
NO_REFERENCE_LAYER: int = -1
2023-02-22 10:23:05 +08:00
NO_START_POS_OF_REF_LAYER: int = -1
2023-02-21 22:27:38 +08:00
def __init__(self):
self.m_Layers: collections.deque[TreeLayoutLayer[TNode]] = collections.deque()
self.__CurrentLayer: TreeLayoutLayer[TNode] = None
2023-02-22 10:23:05 +08:00
def GetCurrentLayerIndex(self) -> int:
if self.__CurrentLayer is None: raise Exception("No layer!")
return len(self.m_Layers) - 1
def GetCurrentItemIndex(self) -> int:
if self.__CurrentLayer is None: raise Exception("No layer!")
result = len(self.__CurrentLayer.m_Container)
2023-02-22 10:23:05 +08:00
if result == 0: raise Exception("No item!")
return result - 1
2023-02-21 22:27:38 +08:00
def NewLayer(self, ref_layer: int, start_pos_of_ref_layer: int):
self.__CurrentLayer = TreeLayoutLayer(ref_layer, start_pos_of_ref_layer)
self.m_Layers.append(self.__CurrentLayer)
def NewItem(self, node: TNode):
if self.__CurrentLayer is None: raise Exception("No layer to append data!")
self.__CurrentLayer.m_Container.append(node)
class BBDataPayload(object):
2023-02-21 22:27:38 +08:00
SqlTableProto = collections.namedtuple('Behavior', 'thisobj, name, type, proto_name, proto_guid, flags, priority, version, pin_count, parent')
def __init__(self, sql_data: tuple):
2023-02-21 22:27:38 +08:00
v = BBDataPayload.SqlTableProto._make(sql_data)
self.m_CKID: int = v.thisobj
self.m_Name: str = v.name
self.m_Type: int = v.type
self.m_ProtoName: str = v.proto_name
self.m_ProtoGUID: str = v.proto_guid
self.m_Flags: int = v.flags
self.m_Priority: int = v.priority
self.m_Version: int = v.version
self.m_Parent: int = v.parent
div_pin_count = v.pin_count.split(',')
self.m_pTargetExisting: bool = int(div_pin_count[0] == 1)
self.m_pInCount: int = int(div_pin_count[1])
self.m_pOutCount: int = int(div_pin_count[2])
self.m_bInCount: int = int(div_pin_count[3])
self.m_bOutCount: int = int(div_pin_count[4])
2023-02-21 22:27:38 +08:00
class OperDataPayload(object):
SqlTableProto = collections.namedtuple('Oper', 'thisobj, name, op_guid, parent')
def __init__(self, sql_data: tuple):
v = OperDataPayload.SqlTableProto._make(sql_data)
self.m_CKID: int = v.thisobj
self.m_Name: str = v.name
self.m_OpGuid: str = v.op_guid
self.m_Parent: int = v.parent
class OperTreeNodeWrapper(ICanManipulate):
2023-02-21 22:27:38 +08:00
def __init__(self, payload: OperDataPayload):
self.m_Payload: OperDataPayload = payload
class BBTreeNodeWrapper(ICanManipulate):
2023-02-21 22:27:38 +08:00
def __init__(self, payload: BBDataPayload):
self.m_UpperOper: TreeLayout[OperTreeNodeWrapper] = TreeLayout()
self.m_LowerOper: TreeLayout[OperTreeNodeWrapper] = TreeLayout()
self.m_Upperval: collections.deque = collections.deque()
self.m_LowerVal: collections.deque = collections.deque()
2023-02-21 22:27:38 +08:00
self.m_Payload: BBDataPayload = payload
2023-02-22 21:49:31 +08:00
class GraphResult(ICanManipulate):
def __init__(self):
2023-02-22 21:49:31 +08:00
self.m_GraphCKID: int = 0
self.m_BBDict: dict[int, BBTreeNodeWrapper] = {}
self.m_OperDict: dict[int, OperTreeNodeWrapper] = {}
2023-02-22 21:49:31 +08:00
self.m_CellDict: dict[int, ICanManipulate] = {}
self.m_ParticleDict: dict[int, ICanManipulate] = {}
self.m_bIn: collections.deque = collections.deque()
self.m_bOut: collections.deque = collections.deque()
self.m_pIn: collections.deque = collections.deque()
self.m_pOut: collections.deque = collections.deque()
self.m_PassiveVal: collections.deque = collections.deque()
self.m_PassiveOper: TreeLayout[OperTreeNodeWrapper] = TreeLayout()
self.m_ActivePassiveBB: TreeLayout[BBTreeNodeWrapper] = TreeLayout()