From ec128f3b9c118737ce7f7fb26e9d5c66f6012dd5 Mon Sep 17 00:00:00 2001 From: yyc12345 Date: Thu, 23 Feb 2023 20:50:58 +0800 Subject: [PATCH] finish abstract BB/oper tree layout generation --- SuperScriptDecorator/DecoratorBB.py | 33 +++++++------- SuperScriptDecorator/DecoratorConst.py | 5 +++ SuperScriptDecorator/DecoratorCore.py | 59 ++++++++++++++++++-------- SuperScriptDecorator/DecoratorData.py | 5 ++- example.txt | 2 +- 5 files changed, 68 insertions(+), 36 deletions(-) diff --git a/SuperScriptDecorator/DecoratorBB.py b/SuperScriptDecorator/DecoratorBB.py index d3bb091..791a83b 100644 --- a/SuperScriptDecorator/DecoratorBB.py +++ b/SuperScriptDecorator/DecoratorBB.py @@ -34,7 +34,8 @@ class FindOperRootEnvironment(object): class BlocksFactory(object): def __init__(self, db: sqlite3.Connection, graph: DecoratorData.GraphResult): # assign members - self.m_Graph: DecoratorData.GraphResult = graph + self.m_Graph: DecoratorData.GraphResult = DecoratorData.GraphResult() + self.m_Graph.m_GraphCKID = graph self.m_Db: sqlite3.Connection = db self.__AllBB: set[int] = set() @@ -54,16 +55,16 @@ class BlocksFactory(object): def __FillDataFromDb(self): cursor: sqlite3.Cursor = self.m_Db.cursor() - cursor.execute('SELECT * FROM [script_behavior] WHERE parent == ?', (self.m_Graph.m_GraphCKID, )) + cursor.execute('SELECT * FROM [script_behavior] WHERE parent == ?;', (self.m_Graph.m_GraphCKID, )) for sqldata in cursor.fetchall(): payload: DecoratorData.BBDataPayload = DecoratorData.BBDataPayload(sqldata) - self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.BBTreeNode(payload) + self.m_Graph.m_BBDict[payload.m_CKID] = DecoratorData.BBTreeNodeWrapper(payload) self.__AllBB.add(payload.m_CKID) - cursor.execute('SELECT * FROM [script_pOper] WHERE parent == ?', (self.m_Graph.m_GraphCKID, )) + cursor.execute('SELECT * FROM [script_pOper] WHERE parent == ?;', (self.m_Graph.m_GraphCKID, )) for sqldata in cursor.fetchall(): payload: DecoratorData.OperDataPayload = DecoratorData.OperDataPayload(sqldata) - self.m_Graph.m_BlockDict[payload.m_CKID] = DecoratorData.OperTreeNode(payload) + self.m_Graph.m_OperDict[payload.m_CKID] = DecoratorData.BBTreeNodeWrapper(payload) self.__AllOper.add(payload.m_CKID) cursor.close() @@ -81,7 +82,7 @@ class BlocksFactory(object): # read datas for (output_obj, output_type, output_is_bb, ) in envir.m_Cursor.fetchall(): # check dup - if output_obj in envir.m_WalkedOper: + if output_obj in envir.m_WalkedOper or output_obj not in self.__AllOper: continue envir.m_WalkedOper.add(output_obj) @@ -120,7 +121,7 @@ class BlocksFactory(object): # if depth == 0, all item should start from a new layer for item in gottenOper: envir.m_Tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER) - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[item]) + envir.m_Tree.NewItem(self.m_Graph.m_OperDict[item]) self.__RecursiveBuildOper(BuildOperEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, item )) @@ -128,7 +129,7 @@ class BlocksFactory(object): # otherwise, only non-first node need new layer # proc first node first: int = gottenOper[0] - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[first]) + envir.m_Tree.NewItem(self.m_Graph.m_OperDict[first]) self.__RecursiveBuildOper(BuildOperEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, first )) @@ -140,7 +141,7 @@ class BlocksFactory(object): # proc other node for other in gottenOper[1:]: envir.m_Tree.NewLayer(cur_layer, cur_idx) - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[other]) + envir.m_Tree.NewItem(self.m_Graph.m_OperDict[other]) self.__RecursiveBuildOper(BuildOperEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, other )) @@ -166,7 +167,7 @@ class BlocksFactory(object): # we need process this BB related opers now # for every item for bbid in gottenBB: - bb: DecoratorData.BBTreeNodeWrapper = self.m_Graph.m_BlockDict[bbid] + bb: DecoratorData.BBTreeNodeWrapper = self.m_Graph.m_BBDict[bbid] # upper opers self.__RecursiveBuildOper(BuildOperEnvironment( envir.m_Cursor, bb.m_UpperOper, 0, bbid @@ -179,7 +180,7 @@ class BlocksFactory(object): # we need add it manually self.__AllOper.remove(operid) bb.m_LowerOper.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER) - bb.m_LowerOper.NewItem(self.m_Graph.m_BlockDict[operid]) + bb.m_LowerOper.NewItem(self.m_Graph.m_BBDict[operid]) # gotten "root" is oper's CKID, so use depth 1 to cheat this function self.__RecursiveBuildOper(BuildOperEnvironment( @@ -191,7 +192,7 @@ class BlocksFactory(object): # if depth == 0, all item should start from a new layer for item in gottenBB: envir.m_Tree.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER) - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[item]) + envir.m_Tree.NewItem(self.m_Graph.m_BBDict[item]) self.__RecursiveBuildBB(BuildBBEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, item )) @@ -199,7 +200,7 @@ class BlocksFactory(object): # otherwise, only non-first node need new layer # proc first node first: int = gottenBB[0] - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[first]) + envir.m_Tree.NewItem(self.m_Graph.m_BBDict[first]) self.__RecursiveBuildBB(BuildBBEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, first )) @@ -211,7 +212,7 @@ class BlocksFactory(object): # proc other node for other in gottenBB[1:]: envir.m_Tree.NewLayer(cur_layer, cur_idx) - envir.m_Tree.NewItem(self.m_Graph.m_BlockDict[other]) + envir.m_Tree.NewItem(self.m_Graph.m_BBDict[other]) self.__RecursiveBuildBB(BuildBBEnvironment( envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, other )) @@ -232,7 +233,7 @@ class BlocksFactory(object): self.__AllBB.remove(bbid) self.m_Graph.m_ActivePassiveBB.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER) - self.m_Graph.m_ActivePassiveBB.NewItem(self.m_Graph.m_BlockDict[bbid]) + self.m_Graph.m_ActivePassiveBB.NewItem(self.m_Graph.m_BBDict[bbid]) # use depth = 1 to cheat this function for avoiding error bIO type self.__RecursiveBuildBB(BuildBBEnvironment( @@ -257,7 +258,7 @@ class BlocksFactory(object): # we need add it manually self.__AllOper.remove(operid) self.m_Graph.m_PassiveOper.NewLayer(DecoratorData.TreeLayout.NO_REFERENCE_LAYER, DecoratorData.TreeLayout.NO_START_POS_OF_REF_LAYER) - self.m_Graph.m_PassiveOper.NewItem(self.m_Graph.m_BlockDict[operid]) + self.m_Graph.m_PassiveOper.NewItem(self.m_Graph.m_OperDict[operid]) # gotten "roots" is oper's CKID, so use depth 1 to cheat this function self.__RecursiveBuildOper(BuildOperEnvironment( diff --git a/SuperScriptDecorator/DecoratorConst.py b/SuperScriptDecorator/DecoratorConst.py index 8f1ce35..77699ca 100644 --- a/SuperScriptDecorator/DecoratorConst.py +++ b/SuperScriptDecorator/DecoratorConst.py @@ -3,6 +3,11 @@ class Export_Boolean(object): TRUE = 1 FALSE = 0 +class Export_Behavior_Type(object): + FUNCTION = 0 + GRAPH = 1 + SCRIPT = 4 + class Export_bLink_InputOutputType(object): INPUT = 0 OUTPUT = 1 diff --git a/SuperScriptDecorator/DecoratorCore.py b/SuperScriptDecorator/DecoratorCore.py index afc451a..367b3bc 100644 --- a/SuperScriptDecorator/DecoratorCore.py +++ b/SuperScriptDecorator/DecoratorCore.py @@ -1,5 +1,6 @@ import sqlite3, json, collections import CustomConfig, Progressbar +import DecoratorBB, DecoratorConst class CompositionIngredients(object): def __init__(self, name: str, export_id: int, env_id: int): @@ -7,21 +8,22 @@ class CompositionIngredients(object): self.m_ExportIndex = export_id self.m_EnvIndex = env_id -def _InitDecoratedDb(db: sqlite3.Connection): +def __InitDecoratedDb(db: sqlite3.Connection): cur = db.cursor() cur.execute("CREATE TABLE [compositions] ([id] INTEGER, [name] TEXT, [export_id] INTEGER, [env_id] INTEGER);") - cur.execute("CREATE TABLE graph([graph_ckid] INTEGER, [graph_name] TEXT, [hierarchy_ckid] TEXT, [export_id] INTEGER);") + cur.execute("CREATE TABLE [graph_graph] ([parent_export] INTEGER, [thisobj] INTEGER, [name] TEXT, [hierarchy] TEXT, [height] REAL, [width] REAL, [bind_behavior] TEXT, [bind_beh_ord] INTEGER);") #cur.execute("CREATE TABLE info([target] INTEGER, [attach_bb] INTEGER, [is_setting] INTEGER, [name] TEXT, [field] TEXT, [data] TEXT);") - #cur.execute("CREATE TABLE block([belong_to_graph] INETGER, [thisobj] INTEGER, [name] TEXT, [assist_text] TEXT, [pin-ptarget] TEXT, [pin-pin] TEXT, [pin-pout] TEXT, [pin-bin] TEXT, [pin-bout] TEXT, [x] REAL, [y] REAL, [width] REAL, [height] REAL, [expandable] INTEGER);") - #cur.execute("CREATE TABLE cell([belong_to_graph] INETGER, [thisobj] INTEGER, [name] TEXT, [assist_text] TEXT, [x] REAL, [y] REAL, [type] INTEGER);") - #cur.execute("CREATE TABLE link([belong_to_graph] INETGER, [delay] INTEGER, [start_interface] INTEGER, [end_interface] INTEGER, [startobj] INTEGER, [endobj] INTEGER, [start_type] INTEGER, [end_type] INTEGER, [start_index] INTEGER, [end_index] INTEGER, [x1] REAL, [y1] REAL, [x2] REAL, [y2] REAL);") + cur.execute("CREATE TABLE [graph_block] ([parent_graph] INETGER, [parent_export] INTEGER, [thisobj] INTEGER, [name] TEXT, [assist_text] TEXT, [x] REAL, [y] REAL, [width] REAL, [height] REAL, [expand_id] INTEGER);") + cur.execute("CREATE TABLE [graph_cell] ([parent_graph] INETGER, [parent_export] INTEGER, [thisobj] INTEGER, [name] TEXT, [assist_text] TEXT, [x] REAL, [y] REAL, [type] INTEGER);") + cur.execute("CREATE TABLE [graph_particle] ([parent_graph] INETGER, [parent_export] INTEGER, [thisobj] INTEGER, [name] TEXT, [x] REAL, [y] REAL, [type] INTEGER, [relation_block] INTEGER);") + cur.execute("CREATE TABLE [graph_link] ([parent_graph] INETGER, [parent_export] INTEGER, [delay] INTEGER, [start_particle] INTEGER, [end_particle] INTEGER, [start_block] INTEGER, [end_block] INTEGER, [line_type] INTEGER, [x1] REAL, [y1] REAL, [x2] REAL, [y2] REAL);") db.commit() cur.close() -def _GenerateCompositions(cfg: CustomConfig.CustomConfig) -> tuple[tuple[CompositionIngredients], tuple[str], tuple[str]]: +def __GenerateCompositions(cfg: CustomConfig.CustomConfig) -> tuple[tuple[CompositionIngredients], tuple[str], tuple[str]]: compositions: list[CompositionIngredients] = [] exportdb: collections.OrderedDict = collections.OrderedDict() envdb: collections.OrderedDict = collections.OrderedDict() @@ -43,20 +45,43 @@ def _GenerateCompositions(cfg: CustomConfig.CustomConfig) -> tuple[tuple[Composi return ( tuple(compositions), - tuple(exportdb.values()), - tuple(envdb.values()) + tuple(exportdb.keys()), + tuple(envdb.keys()) ) -def _UploadComposition(db: sqlite3.Connection, compositions: list[CompositionIngredients]): +def __UploadComposition(db: sqlite3.Connection, compositions: list[CompositionIngredients]): cur = db.cursor() - for idx, ingredient in enumerate(compositions): - cur.execute("INSERT INTO [compositions] VALUES(?, ?, ?, ?)", - (idx, ingredient.m_CompositionName, ingredient.m_ExportIndex, ingredient.m_EnvIndex) - ) + cur.executemany('INSERT INTO [compositions] VALUES(?, ?, ?, ?);', + ((idx, ingredient.m_CompositionName, ingredient.m_ExportIndex, ingredient.m_EnvIndex) for idx, ingredient in enumerate(compositions)) + ) db.commit() cur.close() +def __ProcessGraph(cfg: CustomConfig.CustomConfig, export_id: int, export_filename: str): + # create database and apply encoding + db: sqlite3.Connection = sqlite3.connect(export_filename) + db.text_factory = lambda x: x.decode(cfg.m_DatabaseEncoding, errors="ignore") + + # create a cursor to get graph + cur: sqlite3.Cursor = db.cursor() + cur.execute('SELECT [thisobj] FROM [script_behavior] WHERE [type] != ?;', + (DecoratorConst.Export_Behavior_Type.FUNCTION, ) + ) + + # proc each graph + for (thisobj, ) in cur.fetchall(): + # todo: add more proc step + blocks: DecoratorBB.BlocksFactory = DecoratorBB.BlocksFactory(db, thisobj) + del blocks + + # todo: recursively build [graph_graph] + + # close db + cur.close() + db.close() + + def Run(cfg: CustomConfig.CustomConfig): # establish target database print('Opening decorated database...') @@ -64,20 +89,20 @@ def Run(cfg: CustomConfig.CustomConfig): # init table print('Initializing decorated database...') - _InitDecoratedDb(decorateDb) + __InitDecoratedDb(decorateDb) decorateDb.commit() # we need know which database we need analyse first print('Generating compositions...') - (compositions, exportdb, envdb) = _GenerateCompositions(cfg) - _UploadComposition(decorateDb, compositions) + (compositions, exportdb, envdb) = __GenerateCompositions(cfg) + __UploadComposition(decorateDb, compositions) print(f'Analysation done. {len(exportdb)} Export DB and {len(envdb)} Env DB.') # process export print('Generating graphs...') progressbar: Progressbar.Prograssbar = Progressbar.Prograssbar(len(exportdb)) for expid, exp in enumerate(exportdb): - pass + __ProcessGraph(cfg, expid, exp) progressbar.Finish() # process env diff --git a/SuperScriptDecorator/DecoratorData.py b/SuperScriptDecorator/DecoratorData.py index 794c1a5..ce06b2a 100644 --- a/SuperScriptDecorator/DecoratorData.py +++ b/SuperScriptDecorator/DecoratorData.py @@ -111,7 +111,7 @@ class TreeLayout(typing.Generic[TNode]): def GetCurrentItemIndex(self) -> int: if self.__CurrentLayer is None: raise Exception("No layer!") - result = len(self.__CurrentLayer) + result = len(self.__CurrentLayer.m_Container) if result == 0: raise Exception("No item!") return result - 1 @@ -175,7 +175,8 @@ class GraphResult(ICanManipulate): def __init__(self): self.m_GraphCKID: int = 0 - self.m_BlockDict: dict[int, ICanManipulate] = {} + self.m_BBDict: dict[int, BBTreeNodeWrapper] = {} + self.m_OperDict: dict[int, OperTreeNodeWrapper] = {} self.m_CellDict: dict[int, ICanManipulate] = {} self.m_ParticleDict: dict[int, ICanManipulate] = {} diff --git a/example.txt b/example.txt index 4dcd3cc..d50b73f 100644 --- a/example.txt +++ b/example.txt @@ -1,2 +1,2 @@ Ballance/vt2obj "example.nmo" "export.db" "env.db" -"Ballance/vt2obj mirror" Gameplay.nmo export2.db env.db \ No newline at end of file +"Ballance/vt2obj mirror" Gameplay.nmo export.db env.db \ No newline at end of file