refactor: cleanup project. ready for refactor.

- remove all old code
- build directory hierarchy, add basic cmake scripts.
This commit is contained in:
2024-07-23 21:37:56 +08:00
parent 4503b5cefc
commit ecebc42603
84 changed files with 298 additions and 6961 deletions

76
.gitignore vendored
View File

@@ -1,18 +1,30 @@
# ============== My Options ============== # -------------------- Personal Disabled --------------------
# Ignore test used SQLite database
# ignore generated Virtools.props
Virtools.props
SuperScriptMaterializer/Virtools.props
GPVirtoolsStatic/Virtools.props
# ignore generated database
*.db *.db
*.db-journal *.db-journal
# -------------------- Output --------------------
out/
CMakeSettings.json
# -------------------- CMake --------------------
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
# -------------------- Visual Studio --------------------
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
## ##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
# User-specific files # User-specific files
*.rsuser *.rsuser
@@ -42,7 +54,6 @@ bld/
[Oo]bj/ [Oo]bj/
[Ll]og/ [Ll]og/
[Ll]ogs/ [Ll]ogs/
Temp/
# Visual Studio 2015/2017 cache/options directory # Visual Studio 2015/2017 cache/options directory
.vs/ .vs/
@@ -102,6 +113,7 @@ StyleCopReport.xml
*.tmp_proj *.tmp_proj
*_wpftmp.csproj *_wpftmp.csproj
*.log *.log
*.tlog
*.vspscc *.vspscc
*.vssscc *.vssscc
.builds .builds
@@ -154,7 +166,9 @@ _TeamCity*
!.axoCover/settings.json !.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool # Coverlet is a free, cross platform Code Coverage Tool
coverage*[.json, .xml, .info] coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results # Visual Studio code coverage results
*.coverage *.coverage
@@ -303,6 +317,17 @@ node_modules/
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw *.vbw
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
*.vbp
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
*.dsw
*.dsp
# Visual Studio 6 technical files
*.ncb
*.aps
# Visual Studio LightSwitch build output # Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts **/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts
@@ -359,6 +384,9 @@ ASALocalRun/
# Local History for Visual Studio # Local History for Visual Studio
.localhistory/ .localhistory/
# Visual Studio History (VSHistory) files
.vshistory/
# BeatPulse healthcheck temp database # BeatPulse healthcheck temp database
healthchecksdb healthchecksdb
@@ -368,6 +396,26 @@ MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder # Ionide (cross platform F# VS Code tools) working folder
.ionide/ .ionide/
# ============== My Options ============== # Fody - auto-generated XML schema
# force adding debug profile for SuperScriptMaterializer FodyWeavers.xsd
!SuperScriptMaterializer/SuperScriptMaterializer.vcxproj.user
# VS Code files for those working on multiple tools
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# Local History for Visual Studio Code
.history/
# Windows Installer files from build outputs
*.cab
*.msi
*.msix
*.msm
*.msp
# JetBrains Rider
*.sln.iml

30
CMakeLists.txt Normal file
View File

@@ -0,0 +1,30 @@
cmake_minimum_required(VERSION 3.23)
project(VirtoolsSchematicWeaver
VERSION 2.0.0
LANGUAGES CXX
)
# Provide options
option(VSW_BUILD_MATERIALIZER "Build Materializer part of Virtools Schematic Weaver." ON)
option(VSW_BUILD_DECORATOR "Build Decorator part of Virtools Schematic Weaver" ON)
# Setup install path
include(GNUInstallDirs)
set(VSW_INSTALL_BIN_PATH ${CMAKE_INSTALL_BINDIR} CACHE PATH
"Binary install path relative to CMAKE_INSTALL_PREFIX unless set to an absolute path.")
# Import shared library and essential library
if (VSW_BUILD_MATERIALIZER OR VSW_BUILD_DECORATOR)
# Import YYCC and sqlite because all project use them
include(${CMAKE_CURRENT_LIST_DIR}/cmake/custom_import_yycc.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/cmake/custom_import_sqlite.cmake)
# Import shared library
add_subdirectory(shared)
endif ()
# Import build targets
if (VSW_BUILD_MATERIALIZER)
add_subdirectory(materializer)
endif ()
if (VSW_BUILD_DECORATOR)
add_subdirectory(decorator)
endif ()

View File

@@ -1,98 +1,5 @@
# Super Script Materializer # Virtools Schematic Weaver
[中文文档](./README_ZH.md) Virtools Schematic Weaver (former name Super Script Materializer)
--- Work in Progress. Do not use this branch now!
![preview_image](./preview.png)
---
The project consist of two parts:
1. SuperScriptMaterializer - Custom Virtools Interface Plugin that allows you to export all scripts/schematics into a SQLite database file
2. SuperScriptViewer - a python parser that creates a web page based on the exported databases to view the schematic in Behavior Graph mode similar to how Virtools Dev displays.
The purpose of the project is to allow users to have a backup graph of their scripts from Virtools while providing support for analyzing `--Script Hidden--` scripts by generating relation among each script component.
The inspiration came from:
- [BearKidsTeam/Script-Materializer](https://github.com/BearKidsTeam/Script-Materializer) - Allows exporting specific scripts into a JSON file
- [BearKidsTeam/VirtoolsScriptDeobfuscation](https://github.com/BearKidsTeam/VirtoolsScriptDeobfuscation) - A custom interface plugin that loads Virtools files with hidden scripts and makes them visible and editable.
**NOTE:**
* This project does not give ability to edit hidden scripts within the file. It simply exports and views.
* The latest commit may not be stable to use, please visit the Release page to get a stable version.
* If you change the version (including the version before the first stable version), then you need to rebuild all the data, because the data between the various versions may not be compatible with each other.
## Requirements
### Use
- Virtools Dev 5.0
- Python 3.0 with Flask module
- Common browsers (except Safari)
### Compile
For compile or debug this project, follwing tools also are necessary.
- Virtools Dev 5.0 SDK (May work for others, Virtools 4 has been tested and can be compiled and run without any modification)
- Visual Studio 2015 with at least v140 toolset
## Usage
### Exporting Scripts from Virtools
1. Make Sure Virtools Dev is closed.
2. Copy compiled SuperScriptMaterializer.dll into Virtools's InterfacePlugins folder. Copy `sqlite3.dll` you downloaded into Virtool's base folder (where `devr.exe` exist). If you use the packaged file on the Release page, just decompress it directly in the root directory of Virtools and allow folder merging and file overwriting.
3. Open Virtools and load a Virtools document of your choice.
4. Go to the menu bar and click `Super Script Materializer` and `Export all script`. Name it `export.db` and save it into `SuperScriptViewer` folder
5. Go to the menu bar and click `Super Script Materializer` and `Export environment`. Name it `env.db` and save it into `SuperScriptViewer` folder
### Viewing Exported Databases
1. Run the viewer by `python3 SuperScriptViewer.py`
2. It will generate a unique decorated database (`decorated.db`) used for viewing based on `export.db` and `env.db`
3. Once generated, a webpage will be hosted (default 127.0.0.1:5000) to view all graphs.
There is advanced command line switches if needed for the SuperScriptViewer
- `-i filename.db` specify an input file to be used as `export.db`
- `-e filename.db` specify an input file to be used as `env.db`
- `-o filename.db` specify an output file to generate `decorated.db`. If it already exists, it will used that instead of generating a new one.
- `-c encoding_name` specify database encoding. The list of supported encodings can be viewed [here](https://docs.python.org/3/library/codecs.html#standard-encodings)
- `-f` forces the output database to be regenerated (useful if you are unsure if decorated.db matches what export.db and env.db used)
- `-d` enable debugging mode. Directly raise exceptions instead of outputting to the console after capture, which is convenient for debugging
A document instructing you how to use the SuperScriptViewer is built into the SuperScriptViewer and can be viewed from the Help page.
## Troubleshooting
- If `SuperScriptViewer.py` displays `TEXT` type decoding error, you will need to use switch `-c` to whatever encoding system your OS uses since Virtools uses multi-byte encoding and depends on your system's locale. It should be noted that the specified encoding is not the current code page of your computer, but the code page of the author who made this Virtools document.
- If Virtools or SuperScriptViewer show an error window or message, please create an issues page noting what Virtools version you have, a link to your file you used to export and the error message.
## Build
1. Download repository.
2. Get SQLite SDK (amalgamation) and binaries (sqlite-dll-win32-x86) from [sqlite.org](http://www.sqlite.org/)
3. Extract both SQLite SDK and binaries to the same folder.
4. Open Developer Command Prompt for VS 2015 by typing Developer Command in Windows Search
5. Go to directory where you've extracted SDK and binaries and type `lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x86` which will build a lib file for SQLite.
6. Open SuperScriptMaterializer solution.
7. Edit SuperScriptMaterializer Properties page as necessary:
- General -> Target Platform Version
- General -> Output Directory
- General -> Platform Toolset
- C/C++ -> General -> Additional Include Directories (Add your SQLite path and Virtools Includes Path)
- Linker -> General -> Output File
- Linker -> General -> Additional Library Dependencies (Add your SQLite path and Virtools Lib/Win32/Release Path)
- Linker -> Debugging -> Generate Program Database File
8. Clean and Build as Release
## Development plan
In subsequent versions, the following features will be gradually added:
* Current page search and global search
* Shortcut tracking
* Move Block and BB in Viewer

View File

@@ -1,155 +0,0 @@
# Super Script Materializer
[English document](./README.md)
---
![preview_image](./preview.png)
---
## 简介
超级Virtools脚本物化器机翻确信
本项目分为3个部分
* `SuperScriptMaterializer`一个C++工程将生成一个Virtools界面插件或独立播放器用于导出初步数据。
* `SuperScriptDecorator`一个Python工程将解析导出的数据并将其组合成易于浏览的格式。
* `SuperScriptViewer`一个Python工程使用Flask提供一个本地Web界面进行脚本以供快速查看。
整个工程所作的事情就是将Virtools文档中的所有脚本导出成一个SQLite数据库文件`Materializer`所做的任务然后经过Python进行排布处理`Decorator`所做的任务最后提供一个本地Web前端查看脚本`Viewer`所做的任务)。整个的查看流程比较复杂,涉及到多个软件的操作。希望您能继续阅读下面比较概要操作说明,以获得良好的使用体验。
物化器同样适用于`Script Hidden`的Virtools脚本也适用于其中含有不可展开的`Behavior Graph`的脚本。物化器不能完全恢复脚本的原有排布无论原有排布是否存在物化器都将重新自动生成脚本中的各个元素的位置。某些结构的关系可能会改变例如Export parameter亦或者是与Virtools中的呈现不同但是逻辑思路将不会改变。同时物化器不能将已经生成的结构回写成Virtools可接受的格式因此物化器只能提供无视脚本隐藏的分析功能。
**注意事项**
* 当前最新的commit并不一定可以稳定使用请访问Release界面获取可以稳定使用的版本。
* 如果您更换了使用的版本(包括第一个稳定版本之前的版本),则需要重新构建所有数据,因为各个版本之间的数据可能彼此不兼容。
## SuperScriptMaterializer
SuperScriptMaterializer分为两种类型一种是*插件*模式在Virtools内部作为界面插件由人手动点击菜单进行导出一般用于本地快速查看。另一种是*独立*模式使用独立的Virtools编译器加载文件并导出通过命令行参数的方式获得需要解析的文件和解析后数据库的路径一般用于编写Shell脚本批量进行脚本导出。目前我们支持的Virtools版本和模式如下
|已知的Virtools版本|插件模式|独立模式|
|:---|:---|:---|
|Virtools 2.1|× (0)|√ (1)|
|Virtools 2.5|× (2)|√ (4)|
|Virtools 3.0|× (3)|× (3)|
|Virtools 3.5|√|√|
|Virtools 4.0|√|√ (4)|
|Virtools 5.0|√|√|
0. 没有可用的Virtools Dev 2.1,因此没有插件模式
0. 使用Ballance Mod Loader提供的逆向Virtools SDK进行编译
0. Virtools SDK不支持在界面上添加菜单
0. 缺少Virtools SDK无法编译
0. 有不影响输出的错误
### 运行环境
* 至少一个可以使用的Virtools环境
### 使用
无论您现在要使用何种版本,您都必须先下载一份可用的,匹配的`sqlite.dll`。通常来说,我们在每一次版本发布的时候都会附带对应的`sqlite.dll`,您只需要下载即可。
如果您将Virtools 2.1作为目标则由于其只有独立模式您需要准备一份Virtools 2.1的运行环境(通常而言是`CK2.dll``VxMath.dll`等一系列文件。由于Virtools 2.1并没有创作环境因此您只能从其他分发版本中获取到这个运行环境通常来说是一种游戏在您的游戏文件夹内搜索相关dll即可找到将下载好的独立模式的exe和`sqlite.dll`一起放在那里即可。
如果您选择其他Virtools版本那么很幸运它们的创作环境还能被下载到。因此如果你选择独立模式可以将下载到的exe和`sqlite.dll`一起放在Virtools创作环境的根目录下通常有一个名为`Dev.exe`的可执行程序在那里。当然如果你是要解析某个游戏的内容则可以和游戏所使用的Virtools环境放在一起。如果你选择插件模式那么请仍然将`sqlite.dll`放在Virtools创作环境的根目录下但是将下载到的dll插件文件放在名为`InterfacePlugins`的目录下。
#### 插件版本
启动Virtools打开需要解析的文档点击菜单栏的`Super Script Materializer`-`Export all script`,保存为`export.db`然后等待Virtools提示你已经导出完成。这一步将导出所有脚本。然后同样的操作执行`Super Script Materializer`-`Export environment`,并将其保存为`env.db`。这一步将保存所有环境变量。环境变量很重要,尤其是分析脚本中的一些数据的时候。
#### 独立版本
在独立版本所在文件夹内启动命令行,按以下格式输入命令:`SuperScriptMaterializer.exe [virtools composition] [script db path] [env db path]`
* `virtools composition`要导出的Virtools文档的地址
* `script db path`:导出所有脚本所用数据库的地址
* `env db path`:保存所有环境变量所用数据库的地址
## SuperScriptDecorator
上一步导出的数据库文件并不能直接被使用,需要通过`SuperScriptDecorator`辅助生成各个Building Graph的位置以及各种连线之后才能进入下一步查看。同时为了支持一次性在一个工程内浏览所有的脚本内容`Decorator`还负责将多个上游导出的数据库合并成一个数据库,以供`Viewer`进行查看。
### 运行环境
* Python 3.x
### 使用
将上一步得到的`export.db``env.db``SuperScriptDecorator.py`放在一起。然后新建一个文件名为`import.txt`使用UTF-8编码在里面输入如下内容三个部分之间的空白是`Tab`而不是空格):
```
example.cmo export.db env.db
```
然后在此目录中运行`python3 ./SuperScriptDecorator.py`等待Python交互界面提示完成操作即可。
`SuperScriptDecorator.py`具有一些命令行开关:
- `-i`:指定输入的`import.txt`
- `-o`:指定输出的`decorated.db`,如果已经存在将覆盖
- `-c`:指定数据库编码,可用的编码表可以在[这里](https://docs.python.org/3/library/codecs.html#standard-encodings)查看
- `-d`:无参数,启用调试模式,直接抛出异常,而不是捕获后在控制台输出,方便调试
### import.txt
`import.txt`是一个提供输入文件的集和的文本文件。由于`Decorator`还负责将多个上游导出的数据库合并成一个数据库,这些多个由上游导出的数据库需要由`import.txt`来指示。`import.txt`的基本格式就是:
* 每一行代表一组输入
* 每一行共有3个输入从左至右分别为文档的名字会被显示在脚本层次图中`export.db`,和`env.db`
* 每一行3个部分中间由`Tab`分割
* 空行会被忽略
### 提示
以上某些选项在基本使用中应该不会用到,因此按最开始所述的方式直接放置好文件直接运行即可。
如果Python交互界面提示数据库`TEXT`类型解码失败,或者解析的字符出现乱码,那么可能您需要手动使用`-c`开关指定数据库文本解码方式。因为Virtools使用多字节编码依赖于当前操作系统的代码页`SuperScriptDecorator`做了特殊获取以保证大多数计算机可以直接运行但仍然不能排除一些特殊情况。需要注意的是指定的编码不是你计算机当前的代码页而是制作这个Virtools文档的作者的计算机的代码页。
## SuperScriptViewer
`SuperScriptViewer`旨在提供一个网页前端查看已经生成好的数据文件。至于`Viewer`的使用,一份指导你如何使用`Viewer`的文档已内置在`Viewer`可以从Help页面进行查看。
### 运行环境
* 装有Flask的Python 3.x
* 常见浏览器Safari除外
### 使用
如果您只是为了简单查看一下导出的文件,我们建议以调试模式运行`Viewer`,即将上一步得到的`decorated.db``SuperScriptViewer.py`放在一起,然后运行`python3 ./SuperScriptDecorator.py`,即可以运行调试模式的`Viewer`。如果您是要将生成的结果部署到服务器,我们更建议您使用生产模式进行部署,详情请参见[部署](./Documents/DEPLOY_ZH.md)。
## 问题反馈
以下情况可能是程序陷入了错误请附带您引起bug的文件如果可以以及错误窗口的内容提交bug
* `SuperScriptMaterializer`插件模式在选择完文件后弹出错误或长时间没有反应
* `SuperScriptMaterializer`独立模式输出了`[ERROR]`等类似内容
* Python交互界面弹出错误
## 部署
参见[部署](./Documents/DEPLOY_ZH.md)
## 编译
参见[编译](./Documents/COMPILE_ZH.md)
## 开发计划
在之后的版本中,以下功能将逐步加入:
* 当前页面搜索和全局搜索
* Shortcut追踪
## 特别感谢
* Dassault System提供了Virtools 2.5及其可用的SDK
* [BearKidsTeam/Script-Materializer](https://github.com/BearKidsTeam/Script-Materializer)该工程用于将指定脚本导出为JSON文档
* [BearKidsTeam/VirtoolsScriptDeobfuscation](https://github.com/BearKidsTeam/VirtoolsScriptDeobfuscation)该工程能够在Virtools 3.5中提供内置的隐藏脚本解析功能将解析结果解析为可以被Virtools识别的格式
* [Gamepiaynmo/BallanceModLoader](https://github.com/Gamepiaynmo/BallanceModLoader)该工程提供了可以用于Virtools 2.1目标编译的由逆向得到的Virtools SDK
* [phaicm](https://github.com/phaicm): 提供了许多测试文件用于修复程序Bug。以及说明文档翻译上的帮助。

View File

@@ -1,14 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "SSDecorator",
"type": "python",
"request": "launch",
"program": "SuperScriptDecorator.py",
"console": "integratedTerminal",
"args": ["-d", "-i", "../example.txt", "-o", "decorate.db"],
"justMyCode": false
}
]
}

View File

@@ -1,58 +0,0 @@
import locale, sys, os, shlex
class InputEntry(object):
def __init__(self, data: tuple[str]):
if len(data) != 4:
raise Exception(f"Input syntax error. Require 4 items but got {len(data)}")
self.m_Name: str = data[0]
self.m_VtFile: str = data[1]
self.m_ExportDb: str = data[2]
self.m_EnvDb: str = data[3]
class CustomConfig(object):
def __init__(self):
# encoding list
# https://docs.python.org/3/library/codecs.html#standard-encodings
self.m_DatabaseEncoding: str = locale.getpreferredencoding()
self.m_DebugMode = False
self.m_ImportTxt: str = None
self.m_DecoratedDb: str = None
self.m_InputEntries: list[InputEntry] = []
def Regulate(self) -> bool:
# check input and output
if self.m_ImportTxt is None:
print("No input. Decorator exit.")
return False
if not os.path.isfile(self.m_ImportTxt):
print(f'No such input: "{self.m_ImportTxt}"')
return False
if self.m_DecoratedDb is None:
print("No output. Decorator exit.")
return False
if os.path.isdir(self.m_DecoratedDb):
print("Output must be a file.")
return False
# remove result database in debug mode
if self.m_DebugMode and os.path.isfile(self.m_DecoratedDb):
os.remove(self.m_DecoratedDb)
# process input file
try:
with open(self.m_ImportTxt, 'r', encoding='utf-8') as f:
while True:
ln = f.readline()
if ln == '': break
ln.strip()
if ln == '': continue
self.m_InputEntries.append(InputEntry(shlex.split(ln)))
except Exception as ex:
print("Errro when processing input file.")
print(ex)
return True

View File

@@ -1,270 +0,0 @@
import sqlite3, collections
import DecoratorData, DecoratorConst
class BuildBBEnvironment(object):
def __init__(self,
cursor: sqlite3.Cursor, tree: DecoratorData.TreeLayout[DecoratorData.BBTreeNodeWrapper],
depth: int, query_bb: int):
self.m_Cursor: sqlite3.Cursor = cursor
self.m_Tree: DecoratorData.TreeLayout[DecoratorData.BBTreeNodeWrapper] = tree
self.m_Depth: int = depth
self.m_QueryBB: int = query_bb
class BuildOperEnvironment(object):
def __init__(self,
cursor: sqlite3.Cursor, tree: DecoratorData.TreeLayout[DecoratorData.OperTreeNodeWrapper],
depth: int, query_oper: int):
self.m_Cursor: sqlite3.Cursor = cursor
self.m_Tree: DecoratorData.TreeLayout[DecoratorData.OperTreeNodeWrapper] = tree
self.m_Depth: int = depth
self.m_QueryOper: int = query_oper
class FindOperRootEnvironment(object):
def __init__(self,
cursor: sqlite3.Cursor, walked_oper: set[int],
depth: int, query_oper: int):
self.m_Cursor: sqlite3.Cursor = cursor
self.m_WalkedOper: set[int] = walked_oper
self.m_Depth: int = depth
self.m_QueryOper: int = query_oper
class BlocksFactory(object):
def __init__(self, db: sqlite3.Connection, graph: DecoratorData.GraphResult):
# assign members
self.m_Graph: DecoratorData.GraphResult = DecoratorData.GraphResult()
self.m_Graph.m_GraphCKID = graph
self.m_Db: sqlite3.Connection = db
self.__AllBB: set[int] = set()
self.__AllOper: set[int] = set()
# fill data first
self.__FillDataFromDb()
# proc each data
self.__ProcActiveBB()
self.__ProcPassiveBB()
self.__ProcPassiveOper()
def __GetOneFromSet(self, vals: set[int]) -> int:
return next(iter(vals))
def __FillDataFromDb(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
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_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, ))
for sqldata in cursor.fetchall():
payload: DecoratorData.OperDataPayload = DecoratorData.OperDataPayload(sqldata)
self.m_Graph.m_OperDict[payload.m_CKID] = DecoratorData.BBTreeNodeWrapper(payload)
self.__AllOper.add(payload.m_CKID)
cursor.close()
def __RecursiveFindOperRoot(self, envir: FindOperRootEnvironment) -> tuple[int]:
envir.m_Cursor.execute('SELECT [output_obj], [output_type], [output_is_bb] FROM [script_pLink] WHERE ([input_obj] == ? AND [input_is_bb] == ? AND NOT (([output_type] == ? OR [output_type] == ?) AND [output_is_bb] == ?) AND [parent] == ?);',
(envir.m_QueryOper, (DecoratorConst.Export_Boolean.TRUE if envir.m_Depth == 0 else DecoratorConst.Export_Boolean.FALSE),
DecoratorConst.Export_pLink_InputOutputType.PIN, DecoratorConst.Export_pLink_InputOutputType.PTARGET, DecoratorConst.Export_Boolean.TRUE, # filter all BB's pIn
self.m_Graph.m_GraphCKID)
)
opers: set[int] = set()
results: set[int] = set()
# read datas
for (output_obj, output_type, output_is_bb, ) in envir.m_Cursor.fetchall():
# check dup
if output_obj in envir.m_WalkedOper or output_obj not in self.__AllOper:
continue
envir.m_WalkedOper.add(output_obj)
if output_type == DecoratorConst.Export_pLink_InputOutputType.PIN:
# this is a oper. find its pOut and add into stack
opers.add(output_obj)
else:
# this oper point to non-pIn, should be add into result
if envir.m_Depth != 0: # omit BB
results.add(envir.m_QueryOper)
# recursive calling opers to get root
for oper in opers:
results.update(self.__RecursiveFindOperRoot(FindOperRootEnvironment(
envir.m_Cursor, envir.m_WalkedOper, envir.m_Depth + 1, oper
)))
return tuple(i for i in results)
def __RecursiveBuildOper(self, envir: BuildOperEnvironment):
envir.m_Cursor.execute("SELECT [input_obj] FROM [script_pLink] WHERE ([output_obj] == ? AND [output_type] == ? AND [input_type] == ? AND [input_is_bb] == ? AND [parent] = ?);",
(envir.m_QueryOper, DecoratorConst.Export_pLink_InputOutputType.PIN, # order pOper's pIn
DecoratorConst.Export_pLink_InputOutputType.POUT, DecoratorConst.Export_Boolean.FALSE, # order pOper's pOut
self.m_Graph.m_GraphCKID, )
)
gottenOper: list[int] = []
for (input_obj, ) in envir.m_Cursor.fetchall():
if input_obj in self.__AllOper:
self.__AllOper.remove(input_obj)
gottenOper.append(input_obj)
if len(gottenOper) == 0:
return
if envir.m_Depth == 0:
# 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_OperDict[item])
self.__RecursiveBuildOper(BuildOperEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, item
))
else:
# otherwise, only non-first node need new layer
# proc first node
first: int = gottenOper[0]
envir.m_Tree.NewItem(self.m_Graph.m_OperDict[first])
self.__RecursiveBuildOper(BuildOperEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, first
))
# get layer and pos
cur_layer = envir.m_Tree.GetCurrentLayerIndex()
cur_idx = envir.m_Tree.GetCurrentItemIndex()
# proc other node
for other in gottenOper[1:]:
envir.m_Tree.NewLayer(cur_layer, cur_idx)
envir.m_Tree.NewItem(self.m_Graph.m_OperDict[other])
self.__RecursiveBuildOper(BuildOperEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, other
))
def __RecursiveBuildBB(self, envir: BuildBBEnvironment):
# query all link for next bb
envir.m_Cursor.execute('SELECT [output_obj] FROM [script_bLink] WHERE ([input_obj] == ? AND [input_type] == ? AND [parent] = ?) ORDER BY [input_index] ASC;',
(envir.m_QueryBB,
(DecoratorConst.Export_bLink_InputOutputType.INPUT if envir.m_Depth == 0 else DecoratorConst.Export_bLink_InputOutputType.OUTPUT),
self.m_Graph.m_GraphCKID)
)
# filter useless bb
gottenBB: list[int] = []
for (output_obj, ) in envir.m_Cursor.fetchall():
if output_obj in self.__AllBB:
self.__AllBB.remove(output_obj)
gottenBB.append(output_obj)
if len(gottenBB) == 0:
return
# we need process this BB related opers now
# for every item
for bbid in gottenBB:
bb: DecoratorData.BBTreeNodeWrapper = self.m_Graph.m_BBDict[bbid]
# upper opers
self.__RecursiveBuildOper(BuildOperEnvironment(
envir.m_Cursor, bb.m_UpperOper, 0, bbid
))
# lower opers
lower_root: tuple[int] = self.__RecursiveFindOperRoot(FindOperRootEnvironment(
envir.m_Cursor, set(), 0, bbid
))
for operid in lower_root:
# 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_OperDict[operid])
# gotten "root" is oper's CKID, so use depth 1 to cheat this function
self.__RecursiveBuildOper(BuildOperEnvironment(
envir.m_Cursor, bb.m_LowerOper, 1, operid
))
# now we place BB in tree layout
if envir.m_Depth == 0:
# 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_BBDict[item])
self.__RecursiveBuildBB(BuildBBEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, item
))
else:
# otherwise, only non-first node need new layer
# proc first node
first: int = gottenBB[0]
envir.m_Tree.NewItem(self.m_Graph.m_BBDict[first])
self.__RecursiveBuildBB(BuildBBEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, first
))
# get layer and pos
cur_layer = envir.m_Tree.GetCurrentLayerIndex()
cur_idx = envir.m_Tree.GetCurrentItemIndex()
# proc other node
for other in gottenBB[1:]:
envir.m_Tree.NewLayer(cur_layer, cur_idx)
envir.m_Tree.NewItem(self.m_Graph.m_BBDict[other])
self.__RecursiveBuildBB(BuildBBEnvironment(
envir.m_Cursor, envir.m_Tree, envir.m_Depth + 1, other
))
def __ProcActiveBB(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
self.__RecursiveBuildBB(BuildBBEnvironment(
cursor, self.m_Graph.m_ActivePassiveBB, 0, self.m_Graph.m_GraphCKID
))
cursor.close()
def __ProcPassiveBB(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
while len(self.__AllBB) != 0:
# we manually add first
bbid = self.__GetOneFromSet(self.__AllBB)
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_BBDict[bbid])
# use depth = 1 to cheat this function for avoiding error bIO type
self.__RecursiveBuildBB(BuildBBEnvironment(
cursor, self.m_Graph.m_ActivePassiveBB, 1, bbid
))
cursor.close()
def __ProcPassiveOper(self):
cursor: sqlite3.Cursor = self.m_Db.cursor()
while len(self.__AllOper) != 0:
# peek one randomly and try finding root
peek: int = self.__GetOneFromSet(self.__AllOper)
roots: tuple[int] = self.__RecursiveFindOperRoot(FindOperRootEnvironment(
cursor, set(), 1, peek # use 1 to cheat this function
))
# if no root found, add self
roots = (peek, )
# generate tree
for operid in roots:
# 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_OperDict[operid])
# gotten "roots" is oper's CKID, so use depth 1 to cheat this function
self.__RecursiveBuildOper(BuildOperEnvironment(
cursor, self.m_Graph.m_PassiveOper, 1, operid
))
cursor.close()

View File

@@ -1,20 +0,0 @@
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
class Export_pLink_InputOutputType(object):
PIN = 0
POUT = 1
PLOCAL = 2
PTARGET = 3
PATTR = 4

View File

@@ -1,129 +0,0 @@
import json
FONT_SIZE = 12
GRAPH_POFFSET = 40 # 主体bb的p距离左边框距离
GRAPH_BOFFSET = 40 # 主体bb的b距离上边框距离
GRAPH_PSPAN = 20 # 主体bb的每个p之间的水平间距
GRAPH_BSPAN = 20 # 主体bb的每个b之间的垂直间距
GRAPH_LAYER_SPAN = 50 # 绘图中各个bb层之间的间距
GRAPH_BB_SPAN = 25 # 绘图中每个bb之间的距离扩展到Oper和不可插入的local之间的距离
GRAPH_SPAN_BB_POPER = 60 # 每个bb上面挂载的oper和被挂载bb之间的垂直距离 和 每个bb上面挂载的oper的各层之间的垂直距离
GRAPH_SPAN_BB_PLOCAL = 10 # 每个bb上面挂载的plocal和被挂载bb之间的垂直距离
GRAPH_CONTENTOFFSET_X = 40 # 绘图内容原点到左边框的距离
GRAPH_CONTENTOFFSET_Y = 40 # 绘图内容原点到顶边框的距离
BB_POFFSET = 20 # bb框中的p距离左边框距离
BB_BOFFSET = 10 # bb框中的b距离上边框距离
BB_PSPAN = 20 # bb框每个p之间的水平间距
BB_BSPAN = 20 # bb框每个b之间的垂直间距
BB_PBSIZE = 6 # bb框中o和b的正方形符号的边长扩展到graph中的p/b大小
CELL_WIDTH = 15
CELL_HEIGHT = 5
class dbPLinkInputOutputType(object):
PIN = 0
POUT = 1
PLOCAL = 2
PTARGET = 3
PATTR = 4
class dbBLinkInputOutputType(object):
INPUT = 0
OUTPUT = 1
class CellType(object):
PLOCAL = 0
SHORTCUT = 1
PIO = 2
BIO = 3
PTARGET = 4
class LocalUsageType(object):
PIN = 0
POUT = 1
PLOCAL = 2
PATTR = 3
class JsonCustomEncoder(json.JSONEncoder):
def default(self, field):
if isinstance(field, PinInformation):
return {'id': field.id, 'name': field.name, 'type': field.type}
else:
return json.JSONEncoder.default(self, field)
class BlockCellItem(object):
def __init__(self, x, y, w, h):
self.x = x
self.y = y
self.w = w
self.h = h
class BBTreeNode(object):
def __init__(self, ckid, layer):
self.bb = ckid
self.layer = layer
self.nodes = []
class BBResult(object):
def __init__(self, name, assistName, pin, pout, bin, bout, expandable):
self.name = name
self.assistName = assistName
self.ptargetData = None
self.pin = int(pin)
self.pinData = None
self.pout = int(pout)
self.poutData = None
self.bin = int(bin)
self.binData = None
self.bout = int(bout)
self.boutData = None
self.x = 0.0
self.y = 0.0
self.width = 0.0
self.height = 0.0
self.expandable = expandable
def computSize(self):
wText = max(len(self.name), len(self.assistName)) * FONT_SIZE / 3 * 2
hText = FONT_SIZE * 3
wp = max(self.pin, self.pout) * (BB_PBSIZE + BB_PSPAN)
hb = max(self.bin, self.bout) * (BB_PBSIZE + BB_BSPAN)
self.width = 2 * BB_POFFSET + max(wp, wText)
self.height = 2 * BB_BOFFSET + max(hb, hText)
class OperResult(object):
def __init__(self, name):
self.name = name
self.x = 0.0
self.y = 0.0
self.pinData = None
self.poutData = None
self.height = 0.0
self.width = 0.0
def computSize(self):
wText = len(self.name) * FONT_SIZE / 3 * 2
hText = FONT_SIZE * 3
wp = 2 * BB_POFFSET + 2 * (BB_PBSIZE + BB_PSPAN)
hb = 2 * BB_BOFFSET + 0 * (BB_PBSIZE + BB_BSPAN)
self.width = max(wp, wText)
self.height = max(hb, hText)
class PinInformation(object):
def __init__(self, id, name, type):
self.id = id
self.name = name
self.type = type
class LocalUsageItem(object):
def __init__(self, count, isshortcut, internal_type):
self.count = count
self.lastUse = -1
self.lastDirection = 0 # 0 for pIn, 1 for pOut
self.lastIndex = -1 # -1 for pTarget, otherwise the real index
self.isshortcut = isshortcut
self.internal_type = internal_type # 0 pIn, 1 pOut, 2 pLocal. for convenient query match data

View File

@@ -1,710 +0,0 @@
import sqlite3
import DecoratorConstValue as dcv
import json
import CustomConfig
import Progressbar
def run():
exportDb = sqlite3.connect(CustomConfig.export_db)
exportDb.text_factory = lambda x: x.decode(CustomConfig.database_encoding, errors="ignore")
decorateDb = sqlite3.connect(CustomConfig.decorated_db)
# init table
print('Init decorate database...')
initDecorateDb(decorateDb)
decorateDb.commit()
# decorate graph
print('Generating gragh list...')
graphList = []
decorateGraph(exportDb, decorateDb, graphList)
# decorate each graph
print('Generating graph...')
currentGraphBlockCell = {}
Progressbar.initProgressbar(len(graphList))
for i in graphList:
currentGraphBlockCell.clear()
buildBlock(exportDb, decorateDb, i, currentGraphBlockCell)
graphPIO = buildCell(exportDb, decorateDb, i, currentGraphBlockCell)
buildLink(exportDb, decorateDb, i, currentGraphBlockCell, graphPIO)
Progressbar.stepProgressbar()
Progressbar.finProgressbar()
# export information
print('Generating info...')
buildInfo(exportDb, decorateDb)
# give up all change of eexport.db (because no change)
exportDb.close()
decorateDb.commit()
decorateDb.close()
def initDecorateDb(db):
cur = db.cursor()
cur.execute("CREATE TABLE graph([graph] INTEGER, [graph_name] TEXT, [width] INTEGER, [height] INTEGER, [index] INTEGER, [belong_to] TEXT);")
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);")
def decorateGraph(exDb, deDb, graph):
exCur = exDb.cursor()
deCur = deDb.cursor()
scriptMap = {}
exCur.execute("SELECT [behavior], [index], [name] FROM script;")
while True:
lines = exCur.fetchone()
if lines == None:
break
scriptMap[lines[0]] = (lines[1], lines[2])
exCur.execute("SELECT [thisobj], [type], [name] FROM behavior WHERE [type] != 0;")
while True:
lines = exCur.fetchone()
if lines == None:
break
# add into global graph list
graph.append(lines[0])
# width and height will be computed by following method and use update
# statement to change it
if lines[1] == 1:
# script
deCur.execute("INSERT INTO graph VALUES(?, ?, 0, 0, ?, ?)", (lines[0], lines[2], scriptMap[lines[0]][0], scriptMap[lines[0]][1]))
else:
# sub bb
deCur.execute("INSERT INTO graph VALUES(?, ?, 0, 0, -1, '')", (lines[0], lines[2]))
def buildBlock(exDb, deDb, target, currentGraphBlockCell):
exCur = exDb.cursor()
deCur = deDb.cursor()
# sort inner bb
# use current graph input as the start point
treeRoot = dcv.BBTreeNode(target, -1)
processedBB = set()
# layer start from 2, 0 is occupied for pLocal, 1 is occupied for pOper
arrangedLayer = recursiveBuildBBTree(treeRoot, exCur, processedBB, 2, 0, target)
# get no linked bb and place them. linked bb position will be computed
# following
# calc each bb's x postion, as for y, calc later
# flat bb tree
arrangedLayer+=1
singleBB = set()
bbResult = {}
bb_layer_map = {}
baseX = dcv.GRAPH_CONTENTOFFSET_X
exCur.execute('SELECT [thisobj], [name], [type], [proto_name], [pin_count] FROM behavior WHERE parent == ?', (target,))
for i in exCur.fetchall():
pinSplit = i[4].split(',')
bbCache = dcv.BBResult(i[1], i[3], pinSplit[1], pinSplit[2], pinSplit[3], pinSplit[4], (i[0] if i[2] != 0 else -1))
bbCache.computSize()
if i[0] not in processedBB:
# single bb, process it
singleBB.add(i[0])
bbCache.x = baseX
baseX += bbCache.width + dcv.GRAPH_BB_SPAN
bb_layer_map[i[0]] = arrangedLayer
bbResult[i[0]] = bbCache
recursiveCalcBBX(treeRoot, dcv.GRAPH_CONTENTOFFSET_X, bbResult, bb_layer_map)
# calc poper
allBB = processedBB | singleBB
processedOper = set()
pluggedOper = {}
occupiedLayerCountForSpecificBB = {}
exCur.execute('SELECT [thisobj] FROM pOper WHERE [belong_to] == ?', (target,))
newCur = exDb.cursor()
newCur2 = exDb.cursor()
for i in exCur.fetchall():
if i[0] in processedOper:
continue
# check current bout, plugin into the first bb
newCur.execute("SELECT [output_obj] FROM pLink WHERE ([input_obj] == ? AND [output_type] == ? AND [output_is_bb] == 1)", (i[0], dcv.dbPLinkInputOutputType.PIN))
for j in newCur.fetchall():
if j[0] in allBB:
# can be plugin
# try get tree
if j[0] not in pluggedOper.keys():
pluggedOper[j[0]] = {}
recursiveBuildOperTree(i[0], bb_layer_map, processedOper, occupiedLayerCountForSpecificBB, newCur2, 1, j[0], target, pluggedOper[j[0]])
# exit for due to have found a proper host bb
break
# calc layer position
layer_height = {}
layer_y = {}
layer_height[0] = 25
layer_height[1] = 50
for i in bb_layer_map.keys():
curLayer = bb_layer_map[i]
if curLayer not in layer_height.keys():
layer_height[curLayer] = bbResult[i].height
else:
layer_height[curLayer] = max(layer_height.get(curLayer, 0), bbResult[i].height)
layer_height[arrangedLayer] = layer_height.get(arrangedLayer, 0) # make sure misc bb height exist
layer_height[2] = layer_height.get(2, 0) # make sure at least have a bb layer (when there are no bb in a map)
# calc bb Y
baseY = dcv.GRAPH_CONTENTOFFSET_Y
for i in range(arrangedLayer + 1):
baseY += layer_height[i] + dcv.GRAPH_LAYER_SPAN
baseY += occupiedLayerCountForSpecificBB.get(i, 0) * dcv.GRAPH_SPAN_BB_POPER # add oper occipation
layer_y[i] = baseY
for i in bbResult.keys():
cache = bbResult[i]
layer = bb_layer_map[i]
cache.y = layer_y[layer] - layer_height[layer]
# calc oper position
# flat oper tree
operResult = {}
exCur.execute('SELECT [thisobj], [op] FROM pOper WHERE [belong_to] == ?', (target,))
homelessOperCurrentX = dcv.GRAPH_CONTENTOFFSET_X
for i in exCur.fetchall():
if i[0] not in processedOper:
# homeless oper
cache2 = dcv.OperResult(i[1])
cache2.computSize()
cache2.x = homelessOperCurrentX
cache2.y = layer_y[1] - cache2.height
homelessOperCurrentX += cache2.width + dcv.GRAPH_BB_SPAN
operResult[i[0]] = cache2
for i in pluggedOper.keys(): # plugged oper
cache = bbResult[i]
for j in pluggedOper[i]:
jCache = pluggedOper[i][j]
baseX = cache.x
for q in jCache:
exCur.execute("SELECT [op] FROM pOper WHERE [thisobj] == ?", (q,))
cache2 = dcv.OperResult(exCur.fetchone()[0])
cache2.computSize()
cache2.x = baseX
baseX += cache2.width + dcv.GRAPH_BB_SPAN
cache2.y = cache.y - j * dcv.GRAPH_SPAN_BB_POPER
operResult[q] = cache2
# query bb pin's data
listCache = []
listItemCache = None
for i in allBB:
cache = bbResult[i]
exCur.execute("SELECT [thisobj], [name], [type] FROM pTarget WHERE [belong_to] == ?;", (i,))
temp = exCur.fetchone()
if temp == None:
cache.ptargetData = '{}'
else:
cache.ptargetData = json.dumps(dcv.PinInformation(temp[0], temp[1], temp[2]), cls = dcv.JsonCustomEncoder)
listCache.clear()
exCur.execute("SELECT [thisobj], [name] FROM bIn WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], '')
listCache.append(listItemCache)
cache.binData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
listCache.clear()
exCur.execute("SELECT [thisobj], [name] FROM bOut WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], '')
listCache.append(listItemCache)
cache.boutData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
listCache.clear()
exCur.execute("SELECT [thisobj], [name], [type] FROM pIn WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], j[2])
listCache.append(listItemCache)
cache.pinData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
listCache.clear()
exCur.execute("SELECT [thisobj], [name], [type] FROM pOut WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], j[2])
listCache.append(listItemCache)
cache.poutData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
# query oper pin's data
for i in operResult.keys():
cache = operResult[i]
listCache.clear()
exCur.execute("SELECT [thisobj], [name], [type] FROM pIn WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], j[2])
listCache.append(listItemCache)
cache.pinData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
listCache.clear()
exCur.execute("SELECT [thisobj], [name], [type] FROM pOut WHERE [belong_to] == ? ORDER BY [index];", (i,))
for j in exCur.fetchall():
listItemCache = dcv.PinInformation(j[0], j[1], j[2])
listCache.append(listItemCache)
cache.poutData = json.dumps(listCache, cls = dcv.JsonCustomEncoder)
# write to database and return
for i in bbResult.keys():
cache = bbResult[i]
currentGraphBlockCell[i] = dcv.BlockCellItem(cache.x, cache.y, cache.width, cache.height)
deCur.execute('INSERT INTO block VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
(target, i, cache.name, cache.assistName, cache.ptargetData, cache.pinData, cache.poutData, cache.binData, cache.boutData, cache.x, cache.y, cache.width, cache.height, cache.expandable))
for i in operResult.keys():
cache = operResult[i]
currentGraphBlockCell[i] = dcv.BlockCellItem(cache.x, cache.y, cache.width, cache.height)
deCur.execute("INSERT INTO block VALUES (?, ?, ?, '', '{}', ?, ?, '[]', '[]', ?, ?, ?, ?, -1)",
(target, i, cache.name, cache.pinData, cache.poutData, cache.x, cache.y, cache.width, cache.height))
def recursiveBuildBBTree(node, exCur, processedBB, layer, depth, graphId):
realLinkedBB = set()
# find links
exCur.execute("SELECT [output_obj] FROM bLink WHERE ([input_obj] == ? AND [input_type] == ? AND [belong_to] = ?) ORDER BY [input_index] ASC;",
(node.bb, (dcv.dbBLinkInputOutputType.INPUT if depth == 0 else dcv.dbBLinkInputOutputType.OUTPUT), graphId))
for i in exCur.fetchall():
if i[0] != graphId: # omit self
realLinkedBB.add(i[0])
if (len(realLinkedBB) == 0):
return layer
# ignore duplicated bb
# calc need processed bb first
# and register all gotten bb. for preventing infinity resursive func and
# keep bb tree structure
realLinkedBB = realLinkedBB - processedBB
processedBB.update(realLinkedBB)
# iterate each bb
for i in realLinkedBB:
# recursive execute this method
newNode = dcv.BBTreeNode(i, layer)
layer = recursiveBuildBBTree(newNode, exCur, processedBB, layer, depth + 1, graphId)
# add new node into list and ++layer
layer+=1
node.nodes.append(newNode)
# minus extra ++ due to for
if (len(realLinkedBB) != 0):
layer-=1
return layer
def recursiveCalcBBX(node, baseX, resultList, layerMap):
maxExpand = 0
for i in node.nodes:
layerMap[i.bb] = i.layer
resultList[i.bb].x = baseX
maxExpand = max(maxExpand, resultList[i.bb].width)
for i in node.nodes:
recursiveCalcBBX(i, baseX + maxExpand + dcv.GRAPH_BB_SPAN, resultList, layerMap)
def recursiveBuildOperTree(oper, bb_layer_map, processedOper, occupiedLayerMap, exCur, sublayer, bb, graphId, subLayerColumnMap):
if oper in processedOper:
return
# for avoid fucking export parameter feature. check whether self is
# current graph's memeber
exCur.execute("SELECT [belong_to] FROM pOper WHERE [thisobj] == ?;", (oper,))
if (exCur.fetchone()[0] != graphId):
# fuck export param, exit
return
# make sure sub layer column map is ok
if sublayer not in subLayerColumnMap.keys():
subLayerColumnMap[sublayer] = []
# register self
# mark processed
processedOper.add(oper)
subLayerColumnMap[sublayer].append(oper)
# record layer occupation
layer = bb_layer_map[bb]
occupiedLayerMap[layer] = max(occupiedLayerMap.get(layer, -1), sublayer)
# iterate sub item
exCur.execute("SELECT [input_obj] FROM pLink WHERE ([output_obj] == ? AND [input_type] == ? AND [input_is_bb] == 0) ORDER BY [output_index];", (oper, dcv.dbPLinkInputOutputType.POUT))
res = []
for i in exCur.fetchall():
res.append(i[0])
for i in res:
recursiveBuildOperTree(i, bb_layer_map, processedOper, occupiedLayerMap, exCur, sublayer + 1, bb, graphId, subLayerColumnMap)
def buildCell(exDb, deDb, target, currentGraphBlockCell):
exCur = exDb.cursor()
deCur = deDb.cursor()
# prepare block set
blockSet = set()
for i in currentGraphBlockCell.keys():
blockSet.add(i)
# find current graph's pio bio
boutx = set()
pouty = set()
graphPIO = set()
# bOut.x and pOut.y data is not confirmed, when graph size was confirmed,
# update it
exCur.execute("SELECT [thisobj], [name], [index] FROM bIn WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
x = 0
y = dcv.GRAPH_BOFFSET + i[2] * (dcv. BB_PBSIZE + dcv.GRAPH_BSPAN)
currentGraphBlockCell[i[0]] = dcv.BlockCellItem(x, y, dcv.BB_PBSIZE, dcv.BB_PBSIZE)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, '', ?, ?, ?)", (target, i[0], i[1], x, y, dcv.CellType.BIO))
exCur.execute("SELECT [thisobj], [name], [index] FROM bOut WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
x = 0
y = dcv.GRAPH_BOFFSET + i[2] * (dcv. BB_PBSIZE + dcv.GRAPH_BSPAN)
currentGraphBlockCell[i[0]] = dcv.BlockCellItem(x, y, dcv.BB_PBSIZE, dcv.BB_PBSIZE)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, '', ?, ?, ?)", (target, i[0], i[1], x, y, dcv.CellType.BIO))
boutx.add(i[0])
exCur.execute("SELECT [thisobj], [name], [index], [type] FROM pIn WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
x = dcv.GRAPH_POFFSET + i[2] * (dcv. BB_PBSIZE + dcv.GRAPH_PSPAN)
y = 0
currentGraphBlockCell[i[0]] = dcv.BlockCellItem(x, y, dcv.BB_PBSIZE, dcv.BB_PBSIZE)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, ?, ?, ?, ?)", (target, i[0], i[1], i[3], x, y, dcv.CellType.PIO))
graphPIO.add(i[0])
exCur.execute("SELECT [thisobj], [name], [index], [type] FROM pOut WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
x = dcv.GRAPH_POFFSET + i[2] * (dcv. BB_PBSIZE + dcv.GRAPH_PSPAN)
y = 0
currentGraphBlockCell[i[0]] = dcv.BlockCellItem(x, y, dcv.BB_PBSIZE, dcv.BB_PBSIZE)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, ?, ?, ?, ?)", (target, i[0], i[1], i[3], x, y, dcv.CellType.PIO))
graphPIO.add(i[0])
pouty.add(i[0])
exCur.execute("SELECT [thisobj], [name], [type] FROM pTarget WHERE [belong_to] == ?", (target,))
cache = exCur.fetchone()
if cache != None:
currentGraphBlockCell[cache[0]] = dcv.BlockCellItem(0, 0, dcv.BB_PBSIZE, dcv.BB_PBSIZE)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, ?, 0, 0, ?)", (target, i[0], i[1], i[2], dcv.CellType.PTARGET))
graphPIO.add(cache[0])
# query all plocal
allLocal = set()
localUsageCounter = {}
exCur.execute("SELECT [thisobj], [name], [type] FROM pLocal WHERE [belong_to] == ?;", (target,))
for i in exCur.fetchall():
allLocal.add(i[0])
localUsageCounter[i[0]] = dcv.LocalUsageItem(0, False, dcv.LocalUsageType.PLOCAL)
# query all links(don't need to consider export pIO, due to it will not add
# any shortcut)
# !! the same if framework in pLink generator function !! SHARED
createdShortcut = set()
exCur.execute("SELECT * FROM pLink WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
# analyse 5 chancee one by one
if (i[7] == dcv.dbPLinkInputOutputType.PTARGET or i[7] == dcv.dbPLinkInputOutputType.PIN):
if (i[3] == dcv.dbPLinkInputOutputType.PLOCAL):
if i[2] in allLocal or i[2] in createdShortcut:
cache = localUsageCounter[i[2]]
else:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.PLOCAL)
localUsageCounter[i[2]] = cache
createdShortcut.add(i[2])
cache.count += 1
cache.lastUse = i[6]
cache.lastDirection = 0
cache.lastIndex = i[9]
elif (i[3] == dcv.dbPLinkInputOutputType.PIN):
if i[2] == target:
continue # ignore self pIn/pOut. it doesn't need any shortcut
if i[2] not in blockSet:
if i[0] not in createdShortcut:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.PIN)
localUsageCounter[i[0]] = cache
createdShortcut.add(i[0])
else:
cache = localUsageCounter[i[0]]
cache.count+=1
cache.lastUse = i[6]
cache.lastDirection = 0
cache.lastIndex = i[9]
elif (i[3] == dcv.dbPLinkInputOutputType.PATTR): # for attribute using
if i[2] not in createdShortcut:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.PATTR)
localUsageCounter[i[2]] = cache
createdShortcut.add(i[2])
else:
cache = localUsageCounter[i[2]]
cache.count+=1
cache.lastUse = i[6]
cache.lastDirection = 0
cache.lastIndex = i[9]
else:
if i[2] not in blockSet:
if i[0] not in createdShortcut:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.POUT)
localUsageCounter[i[0]] = cache
createdShortcut.add(i[0])
else:
cache = localUsageCounter[i[0]]
cache.count+=1
cache.lastUse = i[6]
cache.lastDirection = 1
cache.lastIndex = i[9]
else:
if (i[7] == dcv.dbPLinkInputOutputType.PLOCAL):
if i[6] in allLocal or i[6] in createdShortcut:
cache = localUsageCounter[i[6]]
else:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.PLOCAL)
localUsageCounter[i[6]] = cache
createdShortcut.add(i[6])
cache.count += 1
cache.lastUse = i[2]
cache.lastDirection = 1
cache.lastIndex = i[5]
else:
if i[6] == target:
continue # ignore self pIn/pOut. it doesn't need any shortcut
if i[6] not in blockSet:
if i[1] not in createdShortcut:
cache = dcv.LocalUsageItem(0, True, dcv.LocalUsageType.POUT)
localUsageCounter[i[1]] = cache
createdShortcut.add(i[1])
else:
cache = localUsageCounter[i[1]]
cache.count += 1
cache.lastUse = i[2]
cache.lastDirection = 1
cache.lastIndex = i[5]
# apply all cells
defaultCellIndex = 0
for i in localUsageCounter.keys():
cache = localUsageCounter[i]
# comput x,y
if (cache.count == 1):
# attachable
attachTarget = currentGraphBlockCell[cache.lastUse]
(x, y) = computCellPosition(attachTarget.x, attachTarget.y, attachTarget.h, cache.lastDirection, cache.lastIndex)
else:
# place it in default area
y = dcv.GRAPH_CONTENTOFFSET_Y
x = dcv.GRAPH_CONTENTOFFSET_X + defaultCellIndex * (dcv.CELL_WIDTH + dcv.GRAPH_BB_SPAN)
defaultCellIndex += 1
# get information
if (cache.internal_type == dcv.LocalUsageType.PIN):
tableName = 'pIn'
elif (cache.internal_type == dcv.LocalUsageType.POUT):
tableName = 'pOut'
elif (cache.internal_type == dcv.LocalUsageType.PATTR):
tableName = 'pAttr'
else:
tableName = 'pLocal'
exCur.execute("SELECT [name], [type] FROM {} WHERE [thisobj] == ?".format(tableName), (i,))
temp = exCur.fetchone()
# submit to database and map
currentGraphBlockCell[i] = dcv.BlockCellItem(x, y, dcv.CELL_WIDTH, dcv.CELL_HEIGHT)
deCur.execute("INSERT INTO cell VALUES (?, ?, ?, ?, ?, ?, ?)",
(target, i, temp[0], temp[1], x, y, (dcv.CellType.SHORTCUT if cache.isshortcut else dcv.CellType.PLOCAL)))
# comput size and update database and currentGraphBlockCell
graphX = 0
graphY = 0
for key, values in currentGraphBlockCell.items():
graphX = max(graphX, values.x + values.w)
graphY = max(graphY, values.y + values.h)
graphX += dcv.GRAPH_POFFSET
graphY += dcv.GRAPH_BOFFSET
deCur.execute("UPDATE graph SET [width] = ?, [height] = ? WHERE [graph] == ?", (graphX, graphY, target))
# update bOut.x and pOut.y data
for i in boutx:
deCur.execute("UPDATE cell SET [x] = ? WHERE ([thisobj] == ? AND [belong_to_graph] == ?)", (graphX - dcv.BB_PBSIZE, i, target))
currentGraphBlockCell[i].x = graphX - dcv.BB_PBSIZE
for i in pouty:
deCur.execute("UPDATE cell SET [y] = ? WHERE ([thisobj] == ? AND [belong_to_graph] == ?)", (graphY - dcv.BB_PBSIZE, i, target))
currentGraphBlockCell[i].y = graphY - dcv.BB_PBSIZE
return graphPIO
def computCellPosition(baseX, baseY, height, direction, index):
if (index == -1):
return (baseX, baseY - dcv.GRAPH_SPAN_BB_PLOCAL)
if (direction == 0):
return (baseX + dcv.BB_POFFSET + index * (dcv.BB_PBSIZE + dcv.BB_PSPAN), baseY - dcv.GRAPH_SPAN_BB_PLOCAL)
else:
return (baseX + dcv.BB_POFFSET + index * (dcv.BB_PBSIZE + dcv.BB_PSPAN), baseY + height + dcv.GRAPH_SPAN_BB_PLOCAL)
def buildLink(exDb, deDb, target, currentGraphBlockCell, graphPIO):
exCur = exDb.cursor()
deCur = deDb.cursor()
# prepare block set
blockSet = set()
for i in currentGraphBlockCell.keys():
blockSet.add(i)
# bLink
exCur.execute("SELECT * FROM bLink WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
if i[3] == target:
(x1, y1) = computLinkBTerminal(i[0], 0, -1 ,currentGraphBlockCell)
bStartObj = i[0]
bStartType = 0
bStartIndex = -1
else:
(x1, y1) = computLinkBTerminal(i[3], i[4], i[5], currentGraphBlockCell)
bStartObj = i[3]
bStartType = i[4]
bStartIndex = i[5]
if i[6] == target:
(x2, y2) = computLinkBTerminal(i[1], 0, -1,currentGraphBlockCell)
bEndObj = i[1]
bEndType = 0
bEndIndex = -1
else:
(x2, y2) = computLinkBTerminal(i[6], i[7], i[8],currentGraphBlockCell)
bEndObj = i[6]
bEndType = i[7]
bEndIndex = i[8]
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, i[2], i[0], i[1], bStartObj, bEndObj, bStartType, bEndType, bStartIndex, bEndIndex, x1, y1, x2, y2))
# pLink
# !! the same if framework in cell generator function !! SHARED
exCur.execute("SELECT * FROM pLink WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
# analyse 5 chancee one by one
if (i[7] == dcv.dbPLinkInputOutputType.PTARGET or i[7] == dcv.dbPLinkInputOutputType.PIN):
if (i[3] == dcv.dbPLinkInputOutputType.PLOCAL):
(x1, y1) = computLinkPTerminal(i[0], 0, -1, currentGraphBlockCell)
(x2, y2) = computLinkPTerminal(i[6], 0, i[9], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 0, 0, -1, i[9], x1, y1, x2, y2))
elif (i[3] == dcv.dbPLinkInputOutputType.PIN):
(x2, y2) = computLinkPTerminal(i[6], 0, i[9], currentGraphBlockCell)
if i[2] == target:
(x1, y1) = computLinkPTerminal(i[0], 0, -1, currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[0], i[6], 0, 0, -1, i[9], x1, y1, x2, y2))
else:
(x1, y1) = computLinkPTerminal(i[2], 0, i[5], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 0, 0, i[5], i[9], x1, y1, x2, y2))
elif (i[3] == dcv.dbPLinkInputOutputType.PATTR):
(x1, y1) = computLinkPTerminal(i[0], 0, -1, currentGraphBlockCell)
(x2, y2) = computLinkPTerminal(i[6], 0, i[9], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 0, 0, -1, i[9], x1, y1, x2, y2))
else:
if i[2] in blockSet: # process protencial pOut(shortcut) (because plocal input/input_obj
# output/output_obj is same, so don't need add for them)
(x1, y1) = computLinkPTerminal(i[2], 1, i[5], currentGraphBlockCell)
else:
(x1, y1) = computLinkPTerminal(i[0], 1, i[5], currentGraphBlockCell)
(x2, y2) = computLinkPTerminal(i[6], 0, i[9], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 1, 0, i[5], i[9], x1, y1, x2, y2))
else:
if (i[7] == dcv.dbPLinkInputOutputType.PLOCAL):
(x1, y1) = computLinkPTerminal(i[2], 1, i[5], currentGraphBlockCell)
(x2, y2) = computLinkPTerminal(i[1], 0, -1, currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 1, 0, i[5], -1, x1, y1, x2, y2))
else:
(x1, y1) = computLinkPTerminal(i[2], 1, i[5], currentGraphBlockCell)
if i[6] == target:
(x2, y2) = computLinkPTerminal(i[1], 0, -1, currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[1], 1, 0, i[5], -1, x1, y1, x2, y2))
else:
(x2, y2) = computLinkPTerminal(i[6], 1, i[9], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -1, i[0], i[1], i[2], i[6], 1, 1, i[5], i[9], x1, y1, x2, y2))
# eLink
exCur.execute("SELECT * FROM eLink WHERE [belong_to] == ?", (target,))
for i in exCur.fetchall():
(x1, y1) = computLinkPTerminal(i[0], 0, -1, currentGraphBlockCell)
(x2, y2) = computLinkPTerminal(i[1], 0 if i[2] == 1 else 1, i[3], currentGraphBlockCell)
deCur.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);",
(target, -2, i[0], i[0], target, i[1], 0, 0 if i[2] == 1 else 1, -1, i[3], x1, y1, x2, y2))
def computLinkBTerminal(obj, xtype, index, currentGraphBlockCell):
# index = -1 mean no offset, it will connect to graph io
cache = currentGraphBlockCell[obj]
return (cache.x if xtype == 0 else cache.x + cache.w - dcv.BB_PBSIZE,
cache.y if index == -1 else (cache.y + dcv.BB_BOFFSET + index * (dcv.BB_PBSIZE + dcv.BB_BSPAN)))
def computLinkPTerminal(obj, ytype, index, currentGraphBlockCell):
# ytype is not database type. it have the same meaning of LinkBTerminal,
# indicating the position. 0 is keep origin position(for pIn and pTarget),
# 1 is consider height(for pOut)
cache = currentGraphBlockCell[obj]
return (cache.x if index == -1 else (cache.x + dcv.BB_POFFSET + index * (dcv.BB_PBSIZE + dcv.BB_PSPAN)),
cache.y if ytype == 0 else (cache.y + cache.h - dcv.BB_PBSIZE))
def buildInfo(exDb, deDb):
exInfoCur = exDb.cursor()
exQueryCur = exDb.cursor()
deCur = deDb.cursor()
# declare tiny storage for convenient query
tinyStorageKey = 0
tinyStorageBB = -1
tinyStorageSetting = 0
tinyStorageName = ""
# export local data (including proto bb internal data)
exInfoCur.execute("SELECT * FROM pData;")
for i in exInfoCur.fetchall():
attachBB = -1
isSetting = 0
infoName = ""
if i[2] == tinyStorageKey:
attachBB = tinyStorageBB
isSetting = tinyStorageSetting
infotName = tinyStorageName
else:
# clear storage first
tinyStorageBB = -1
tinyStorageSetting = 0
tinyStorageName = ""
# query correspond pLocal
exQueryCur.execute("SELECT [belong_to], [is_setting], [name] FROM pLocal WHERE [thisobj] = ?", (i[2], ))
plocalCache = exQueryCur.fetchone()
if plocalCache is not None:
# add setting config
tinyStorageSetting = isSetting = plocalCache[1]
tinyStorageName = infoName = plocalCache[2]
# query bb again
exQueryCur.execute("SELECT [thisobj] FROM behavior WHERE ([thisobj] = ? AND [type] = 0)", (plocalCache[0], ))
behaviorCache = exQueryCur.fetchone()
if behaviorCache is not None:
tinyStorageBB = attachBB = behaviorCache[0]
deCur.execute("INSERT INTO info VALUES (?, ?, ?, ?, ?, ?)", (i[2], attachBB, isSetting, infoName, i[0], i[1]))

View File

@@ -1,118 +0,0 @@
import sqlite3, json, collections
import CustomConfig, Progressbar
import DecoratorBB, DecoratorConst
class CompositionIngredients(object):
def __init__(self, name: str, export_id: int, env_id: int):
self.m_CompositionName: str = name
self.m_ExportIndex = export_id
self.m_EnvIndex = env_id
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] ([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 [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]]:
compositions: list[CompositionIngredients] = []
exportdb: collections.OrderedDict = collections.OrderedDict()
envdb: collections.OrderedDict = collections.OrderedDict()
for entry in cfg.m_InputEntries:
# check 2 database
export_id = exportdb.get(entry.m_ExportDb, None)
if export_id is None:
export_id = len(exportdb)
exportdb[entry.m_ExportDb] = export_id
env_id = envdb.get(entry.m_EnvDb, None)
if env_id is None:
env_id = len(envdb)
envdb[entry.m_EnvDb] = env_id
# create record
compositions.append(CompositionIngredients(entry.m_Name, export_id, env_id))
return (
tuple(compositions),
tuple(exportdb.keys()),
tuple(envdb.keys())
)
def __UploadComposition(db: sqlite3.Connection, compositions: list[CompositionIngredients]):
cur = db.cursor()
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...')
decorateDb: sqlite3.Connection = sqlite3.connect(cfg.m_DecoratedDb)
# init table
print('Initializing decorated database...')
__InitDecoratedDb(decorateDb)
decorateDb.commit()
# we need know which database we need analyse first
print('Generating 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):
__ProcessGraph(cfg, expid, exp)
progressbar.Finish()
# process env
print('Generating infos...')
progressbar = Progressbar.Prograssbar(len(envdb))
for envid, env in enumerate(envdb):
pass
progressbar.Finish()
# close database
print('Closing decorated database...')
decorateDb.commit()
decorateDb.close()

View File

@@ -1,192 +0,0 @@
'''
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):
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
@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)
class Margin(object):
def __init__(self):
self.m_TopSize: Vector = Vector()
self.m_BodySize: Vector = Vector()
self.m_BottomSize: Vector = Vector()
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.
'''
def SetOrigin():
pass
def ComputeSize() -> Vector:
'''
Get current node's start position
'''
raise NotImplementedError()
TNode = typing.TypeVar('TNode', bound=ICanManipulate)
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]):
NO_REFERENCE_LAYER: int = -1
NO_START_POS_OF_REF_LAYER: int = -1
def __init__(self):
self.m_Layers: collections.deque[TreeLayoutLayer[TNode]] = collections.deque()
self.__CurrentLayer: TreeLayoutLayer[TNode] = None
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)
if result == 0: raise Exception("No item!")
return result - 1
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):
SqlTableProto = collections.namedtuple('Behavior', 'thisobj, name, type, proto_name, proto_guid, flags, priority, version, pin_count, parent')
def __init__(self, sql_data: tuple):
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])
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):
def __init__(self, payload: OperDataPayload):
self.m_Payload: OperDataPayload = payload
class BBTreeNodeWrapper(ICanManipulate):
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()
self.m_Payload: BBDataPayload = payload
class GraphResult(ICanManipulate):
def __init__(self):
self.m_GraphCKID: int = 0
self.m_BBDict: dict[int, BBTreeNodeWrapper] = {}
self.m_OperDict: dict[int, OperTreeNodeWrapper] = {}
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()

View File

@@ -1,51 +0,0 @@
import sys
class Prograssbar(object):
def __init__(self, filecount: int):
if (filecount < 0): raise Exception("Progressbar can not hold minus length!")
self.__FileCount: int = filecount
self.__FileNow: int = 0
self.__ContentCount: int = 0
self.__ContentNow: int = 0
self.__PbarFullChar: int = 50
self.__PercentPerFile: float = 1 / self.__FileCount
self.__CurFileName: str = None
self.__Render()
def StepFile(self, newfile: str, content_len: int):
if self.__CurFileName is not None:
# not first call, INC FileNow
# if first call, do not INC it
self.__FileNow += 1
# apply others
self.__CurFileName = newfile
self.__ContentNow = 0
self.__ContentCount = content_len
self.__Render()
def StepContent(self):
self.__ContentNow += 1
self.__Render()
def Finish(self):
sys.stdout.write('\n')
sys.stdout.flush()
def __Render(self):
percentage_content: float = 0 if self.__ContentCount == 0 else (self.__ContentNow / self.__ContentCount)
percentage_full: float = (percentage_content + self.__FileNow) * self.__PercentPerFile
percentage_bar = int(percentage_full * self.__PbarFullChar)
sys.stdout.write('\r[{}{}] {:.2f}% - {}'.format(
percentage_bar * '#',
(self.__PbarFullChar - percentage_bar) * '=',
percentage_full * 100,
self.__CurFileName if self.__CurFileName else ''
))
sys.stdout.flush()

View File

@@ -1,51 +0,0 @@
import CustomConfig, DecoratorCore, Progressbar
import os, sys, getopt, logging, time
# print banner
print('Super Script Decorator')
print('Homepage: https://github.com/yyc12345/SuperScriptMaterializer')
print('Report bug: https://github.com/yyc12345/SuperScriptMaterializer/issues')
print('')
# try get args
try:
opts, args = getopt.getopt(sys.argv[1:], "hi:o:e:c:fd")
except getopt.GetoptError:
print('Wrong arguments!')
print('python SuperScriptViewer.py -i <import.txt> -o <decorated.db> -c <codec_name> -d')
sys.exit(1)
# analyze args
cfg: CustomConfig.CustomConfig = CustomConfig.CustomConfig()
for opt, arg in opts:
if opt == '-h':
print('python SuperScriptViewer.py -i <import.txt> -o <decorated.db> -c <codec_name> -d')
sys.exit(0)
elif opt == '-i':
cfg.m_ImportTxt = arg
elif opt == '-o':
cfg.m_DecoratedDb = arg
elif opt == '-c':
cfg.m_DatabaseEncoding = arg
elif opt == '-d':
cfg.m_DebugMode = True
# regulate data
if not cfg.Regulate():
# failed. exit program
sys.exit(1)
# if in debug mode, run directly
# otherwise, run with a try wrapper.
if cfg.m_DebugMode:
DecoratorCore.Run(cfg)
else:
try:
DecoratorCore.Run(cfg)
except Exception as ex:
print("!!! An error occurs. Please report follwoing error output and reproduce file to developer. !!!")
logging.exception(ex)
sys.exit(1)
print('Decorated database generation done.')

View File

@@ -1,25 +0,0 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29418.71
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SuperScriptMaterializer", "SuperScriptMaterializer\SuperScriptMaterializer.vcxproj", "{4D941003-020F-47FD-9FA2-FFC989E306B8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4D941003-020F-47FD-9FA2-FFC989E306B8}.Debug|x86.ActiveCfg = Debug|Win32
{4D941003-020F-47FD-9FA2-FFC989E306B8}.Debug|x86.Build.0 = Debug|Win32
{4D941003-020F-47FD-9FA2-FFC989E306B8}.Release|x86.ActiveCfg = Release|Win32
{4D941003-020F-47FD-9FA2-FFC989E306B8}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {291FA855-812F-4C42-819E-6E463AEB219E}
EndGlobalSection
EndGlobal

View File

@@ -1,135 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<ProjectGuid>{4D941003-020F-47FD-9FA2-FFC989E306B8}</ProjectGuid>
<RootNamespace>SuperScriptMaterializer</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props"/>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<PlatformToolset>v142</PlatformToolset>
<UseOfMfc>Dynamic</UseOfMfc>
<CharacterSet>MultiByte</CharacterSet>
<ConfigurationType>DynamicLibrary</ConfigurationType></PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>Dynamic</UseOfMfc>
<ConfigurationType>DynamicLibrary</ConfigurationType></PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props"/>
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="Virtools.props"/>
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="Virtools.props"/>
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<PropertyGroup Label="UserMacros"/>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(VIRTOOLS_OUTPUT_PATH)</OutDir>
<LinkIncremental>true</LinkIncremental>
<IntDir>Temp\$(Configuration)\</IntDir>
<TargetExt>.$(VIRTOOLS_BUILD_SUFFIX)</TargetExt>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(VIRTOOLS_OUTPUT_PATH)</OutDir>
<IntDir>Temp\$(Configuration)\</IntDir>
<TargetExt>.$(VIRTOOLS_BUILD_SUFFIX)</TargetExt>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<AdditionalIncludeDirectories>$(VIRTOOLS_HEADER_PATH);$(SQLITE_HEADER_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;$(VIRTOOLS_VER);$(VIRTOOLS_STD_MACRO);$(VIRTOOLS_EXTRA_MACRO);VX_MEM_RELEASE;$(VIRTOOLS_BUILD_TYPE);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<FunctionLevelLinking>true</FunctionLevelLinking>
<DisableSpecificWarnings>4819;4996</DisableSpecificWarnings>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<OutputFile>$(VIRTOOLS_OUTPUT_PATH)SuperScriptMaterializer.$(VIRTOOLS_BUILD_SUFFIX)</OutputFile>
</Link>
<Link>
<AdditionalLibraryDirectories>$(SQLITE_LIB_PATH);$(VIRTOOLS_LIB_PATH);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(SQLITE_LIB_FILENAME);$(VIRTOOLS_LIB_FILENAME);%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<ProgramDatabaseFile>$(VIRTOOLS_OUTPUT_PATH)SuperScriptMaterializer.pdb</ProgramDatabaseFile>
<ModuleDefinitionFile>$(VIRTOOLS_MODULE_DEFINE)</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<FunctionLevelLinking>
</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<ConformanceMode>false</ConformanceMode>
<AdditionalIncludeDirectories>$(VIRTOOLS_HEADER_PATH);$(SQLITE_HEADER_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;$(VIRTOOLS_VER);$(VIRTOOLS_STD_MACRO);$(VIRTOOLS_EXTRA_MACRO);VX_MEM_RELEASE;_RELEASE;$(VIRTOOLS_BUILD_TYPE);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<DisableSpecificWarnings>4819;4996</DisableSpecificWarnings>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<ModuleDefinitionFile>$(VIRTOOLS_MODULE_DEFINE)</ModuleDefinitionFile>
<OutputFile>$(VIRTOOLS_OUTPUT_PATH)SuperScriptMaterializer.$(VIRTOOLS_BUILD_SUFFIX)</OutputFile>
<AdditionalLibraryDirectories>$(VIRTOOLS_LIB_PATH);$(SQLITE_LIB_PATH);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>$(SQLITE_LIB_FILENAME);$(VIRTOOLS_LIB_FILENAME);%(AdditionalDependencies)</AdditionalDependencies>
<ProgramDatabaseFile>$(VIRTOOLS_OUTPUT_PATH)SuperScriptMaterializer.pdb</ProgramDatabaseFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="database.hpp"/>
<ClInclude Include="env_export.hpp"/>
<ClInclude Include="resource.h"/>
<ClInclude Include="doc_export.hpp"/>
<ClInclude Include="string_helper.hpp"/>
<ClInclude Include="virtools_compatible.hpp"/>
<ClInclude Include="vt_menu.hpp"/>
<ClInclude Include="stdafx.h"/>
<ClInclude Include="vt_player.hpp"/>
</ItemGroup>
<ItemGroup>
<ClCompile Include="database.cpp"/>
<ClCompile Include="env_export.cpp"/>
<ClCompile Include="main.cpp"/>
<ClCompile Include="doc_export.cpp"/>
<ClCompile Include="string_helper.cpp"/>
<ClCompile Include="virtools_compatible.cpp"/>
<ClCompile Include="vt_menu.cpp"/>
<ClCompile Include="vt_player.cpp"/>
</ItemGroup>
<ItemGroup>
<None Include="SuperScriptMaterializer.def"/>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets"/>
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Sources">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Headers">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resources">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="database.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="env_export.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="resource.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="doc_export.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="vt_menu.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="virtools_compatible.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="string_helper.hpp">
<Filter>Headers</Filter>
</ClInclude>
<ClInclude Include="vt_player.hpp">
<Filter>Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="database.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="env_export.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="doc_export.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="vt_menu.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="vt_player.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="virtools_compatible.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="string_helper.cpp">
<Filter>Sources</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="SuperScriptMaterializer.def">
<Filter>Sources</Filter>
</None>
</ItemGroup>
</Project>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LocalDebuggerCommand>$(VIRTOOLS_DEBUG_TARGET)</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>$(VIRTOOLS_DEBUG_COMMANDLINE)</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(VIRTOOLS_DEBUG_ROOT)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LocalDebuggerCommand>$(VIRTOOLS_DEBUG_TARGET)</LocalDebuggerCommand>
<LocalDebuggerCommandArguments>$(VIRTOOLS_DEBUG_COMMANDLINE)</LocalDebuggerCommandArguments>
<LocalDebuggerWorkingDirectory>$(VIRTOOLS_DEBUG_ROOT)</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
</PropertyGroup>
</Project>

View File

@@ -1,612 +0,0 @@
#include "database.hpp"
namespace SSMaterializer {
namespace DataStruct {
namespace Helper {
DocumentHelper::DocumentHelper(CKParameterManager* paramManager) :
script(), script_behavior(), script_pOper(),
script_bIn(), script_bOut(), script_bLink(),
script_pIn(), script_pOut(), script_pLink(), script_eLink(),
script_pLocal(), script_pTarget(), script_pAttr(),
msg(), obj(),
data() {
param_manager = paramManager;
}
DocumentHelper::~DocumentHelper() {
;
}
EnvironmentHelper::EnvironmentHelper() :
op(), param(), attr(), plugin(), variable() {
;
}
EnvironmentHelper::~EnvironmentHelper() {
;
}
}
}
namespace Database {
#pragma region universal sqlite database init and free
SSMaterializerDatabase::SSMaterializerDatabase() :
mStmtCache(), mDb(NULL) {
;
}
SSMaterializerDatabase::~SSMaterializerDatabase() {
;
}
sqlite3_stmt* SSMaterializerDatabase::GetStmt(const char* str_stmt) {
// try find first
auto probe = mStmtCache.find(reinterpret_cast<const uintptr_t>(str_stmt));
if (probe != mStmtCache.end()) {
return probe->second;
}
// no found. create one
int result;
sqlite3_stmt* stmt = NULL;
result = sqlite3_prepare_v2(mDb, str_stmt, -1, &stmt, NULL);
if (result != SQLITE_OK) return NULL;
// append new one
mStmtCache.emplace(reinterpret_cast<const uintptr_t>(str_stmt), stmt);
return stmt;
}
void SSMaterializerDatabase::FakeConstructor(const char* file) {
// open mDb
int result;
result = sqlite3_open(file, &mDb);
if (result != SQLITE_OK) goto open_fail;
// disable synchronous
result = sqlite3_exec(mDb, "PRAGMA synchronous = OFF;", NULL, NULL, NULL);
if (result != SQLITE_OK) goto fail;
// run init
if (!Init()) goto fail;
//start job
result = sqlite3_exec(mDb, "begin;", NULL, NULL, NULL);
if (result != SQLITE_OK) goto fail;
return;
fail:
sqlite3_close(mDb);
open_fail:
mDb = NULL;
}
void SSMaterializerDatabase::FakeDeconstructor() {
if (mDb == NULL) return;
int result;
//commit job
result = sqlite3_exec(mDb, "commit;", NULL, NULL, NULL);
if (result != SQLITE_OK) goto fail;
// run extra stuff
if (!Finalize()) goto fail;
//free all cached stmts and commit job
for (auto it = mStmtCache.begin(); it != mStmtCache.end(); it++) {
if (it->second != NULL) {
result = sqlite3_finalize(it->second);
if (result != SQLITE_OK) goto fail;
}
}
fail:
//release res
sqlite3_close(mDb);
mDb = NULL;
}
BOOL SSMaterializerDatabase::Init() {
return TRUE;
}
BOOL SSMaterializerDatabase::Finalize() {
return TRUE;
}
#pragma endregion
#pragma region sub-database constructor, deconstructor and help functions
DocumentDatabase::DocumentDatabase(const char* file, CKParameterManager* paramManager) :
SSMaterializerDatabase(), mUniqueAttr(), /*mUniqueObj(), */mDbHelper(paramManager) {
FakeConstructor(file);
}
DocumentDatabase::~DocumentDatabase() {
FakeDeconstructor();
}
EnvironmentDatabase::EnvironmentDatabase(const char* file) :
SSMaterializerDatabase(), mDbHelper() {
FakeConstructor(file);
}
EnvironmentDatabase::~EnvironmentDatabase() {
FakeDeconstructor();
}
BOOL DocumentDatabase::is_attr_duplicated(DataStruct::EXPAND_CK_ID parents) {
// check duplication
if (mUniqueAttr.find(parents) != mUniqueAttr.end()) {
//existing item. skip it to make sure unique
return TRUE;
} else {
//add this item
mUniqueAttr.insert(parents);
return FALSE;
}
}
//BOOL DocumentDatabase::is_obj_duplicated(DataStruct::EXPAND_CK_ID parents) {
// // check duplication
// if (mUniqueObj.find(parents) != mUniqueObj.end()) {
// //existing item. skip it to make sure unique
// return TRUE;
// } else {
// //add this item
// mUniqueObj.insert(parents);
// return FALSE;
// }
//}
#pragma endregion
#pragma region table, index creation functions
#define SafeSqlExec(sql) result = sqlite3_exec(mDb, sql, NULL, NULL, NULL); \
if (result != SQLITE_OK) { return FALSE; }
BOOL DocumentDatabase::Init() {
// execute parent first
if (!SSMaterializerDatabase::Init()) return FALSE;
int result;
//Init table
SafeSqlExec("begin;");
SafeSqlExec("CREATE TABLE [script] ([thisobj] INTEGER, [name] TEXT, [index] INTEGER, [behavior] INTEGER);");
SafeSqlExec("CREATE TABLE [script_behavior] ([thisobj] INTEGER, [name] TEXT, [type] INTEGER, [proto_name] TEXT, [proto_guid] TEXT, [flags] INTEGER, [priority] INTEGER, [version] INTEGER, [pin_count] TEXT, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pTarget] ([thisobj] INTEGER, [name] TEXT, [type] TEXT, [type_guid] TEXT, [parent] INTEGER, [direct_source] INTEGER, [shard_source] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pIn] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [type] TEXT, [type_guid] TEXT, [parent] INTEGER, [direct_source] INTEGER, [shared_source] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pOut] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [type] TEXT, [type_guid] TEXT, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_bIn] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_bOut] ([thisobj] INTEGER, [index] INTEGER, [name] TEXT, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_bLink] ([input] INTEGER, [output] INTEGER, [delay] INTEGER, [input_obj] INTEGER, [input_type] INTEGER, [input_index] INETEGR, [output_obj] INTEGER, [output_type] INTEGER, [output_index] INETEGR, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pLocal] ([thisobj] INTEGER, [name] TEXT, [type] TEXT, [type_guid] TEXT, [is_setting] INTEGER, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pLink] ([input] INTEGER, [output] INTEGER, [input_obj] INTEGER, [input_type] INTEGER, [input_is_bb] INTEGER, [input_index] INETEGR, [output_obj] INTEGER, [output_type] INTEGER, [output_is_bb] INTEGER, [output_index] INETEGR, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pOper] ([thisobj] INTEGER, [op] TEXT, [op_guid] TEXT, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_eLink] ([export_obj] INTEGER, [internal_obj] INTEGER, [is_in] INTEGER, [index] INTEGER, [parent] INTEGER);");
SafeSqlExec("CREATE TABLE [script_pAttr] ([thisobj] INTEGER, [name] TEXT, [type] TEXT, [type_guid] TEXT);");
SafeSqlExec("CREATE TABLE [msg] ([index] INTEGER, [name] TEXT);");
SafeSqlExec("CREATE TABLE [obj] ([id] INTEGER, [name] TEXT, [classid] INTEGER, [classtype] TEXT);");
SafeSqlExec("CREATE TABLE [data] ([field] TEXT, [data] TEXT, [parent] INTEGER);");
SafeSqlExec("commit;");
return TRUE;
}
BOOL DocumentDatabase::Finalize() {
// execute parent first
if (!SSMaterializerDatabase::Finalize()) return FALSE;
//create index for quick select in SuperScriptDecorator
int result;
SafeSqlExec("begin;");
SafeSqlExec("CREATE INDEX [quick_where1] ON [script_behavior] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where2] ON [script_pOper] ([parent], [thisobj])");
SafeSqlExec("CREATE INDEX [quick_where3] ON [script_pTarget] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where4] ON [script_bIn] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where5] ON [script_bOut] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where6] ON [script_pIn] ([parent], [thisobj])");
SafeSqlExec("CREATE INDEX [quick_where7] ON [script_pOut] ([parent], [thisobj])");
SafeSqlExec("CREATE INDEX [quick_where8] ON [script_pLocal] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where9] ON [script_pLink] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where10] ON [script_bLink] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where11] ON [script_elink] ([parent])");
SafeSqlExec("CREATE INDEX [quick_where12] ON [script_pAttr] ([thisobj])");
SafeSqlExec("CREATE INDEX [quick_where13] ON [data] ([parent])");
SafeSqlExec("commit;");
return TRUE;
}
BOOL EnvironmentDatabase::Init() {
// execute parent first
if (!SSMaterializerDatabase::Init()) return FALSE;
int result;
//init table
SafeSqlExec("begin;");
SafeSqlExec("CREATE TABLE [op] ([funcptr] INTEGER, [in1_guid] TEXT, [in2_guid] TEXT, [out_guid] TEXT, [op_guid] TEXT, [op_name] TEXT, [op_code] INTEGER);");
SafeSqlExec("CREATE TABLE [param] ([index] INTEGER, [guid] TEXT, [derived_from] TEXT, [type_name] TEXT, [default_size] INTEGER, [func_CreateDefault] INTEGER, [func_Delete] INTEGER, [func_SaveLoad] INTEGER, [func_Check] INTEGER, [func_Copy] INTEGER, [func_String] INTEGER, [func_UICreator] INTEGER, [creator_dll_index] INTEGER, [creator_plugin_index] INTEGER, [dw_param] INTEGER, [dw_flags] INTEGER, [cid] INTEGER, [saver_manager] TEXT);");
SafeSqlExec("CREATE TABLE [attr] ([index] INTEGER, [name] TEXT, [category_index] INTEGER, [category_name] TEXT, [flags] INTEGER, [param_index] INTEGER, [compatible_classid] INTEGER, [default_value] TEXT);");
SafeSqlExec("CREATE TABLE [plugin] ([dll_index] INTEGER, [dll_name] TEXT, [plugin_index] INTEGER, [category] TEXT, [active] INTEGER, [guid] TEXT, [desc] TEXT, [author] TEXT, [summary] TEXT, [version] INTEGER, [func_init] INTEGER, [func_exit] INTEGER);");
SafeSqlExec("CREATE TABLE [variable] ([name] TEXT, [description] TEXT, [flags] INTEGER, [type] INTEGER, [representation] TEXT, [data] TEXT);");
SafeSqlExec("commit;");
return TRUE;
}
BOOL EnvironmentDatabase::Finalize() {
// execute parent first
if (!SSMaterializerDatabase::Finalize()) return FALSE;
return TRUE;
}
#undef SafeSqlExec
#pragma endregion
#pragma region document database
void DocumentDatabase::write_script(DataStruct::dbdoc_script& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.host_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.index);
sqlite3_bind_int(stmt, 4, data.behavior);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_behavior(DataStruct::dbdoc_script_behavior& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_behavior] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.type);
sqlite3_bind_text(stmt, 4, data.proto_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, data.proto_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 6, data.flags);
sqlite3_bind_int(stmt, 7, data.priority);
sqlite3_bind_int(stmt, 8, data.version);
sqlite3_bind_text(stmt, 9, data.pin_count.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 10, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pTarget(DataStruct::dbdoc_script_pTarget& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pTarget] VALUES (?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, data.parent);
sqlite3_bind_int(stmt, 6, data.direct_source);
sqlite3_bind_int(stmt, 7, data.shared_source);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pIn(DataStruct::dbdoc_script_pIn& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pIn] VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_int(stmt, 2, data.index);
sqlite3_bind_text(stmt, 3, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, data.type_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 6, data.parent);
sqlite3_bind_int(stmt, 7, data.direct_source);
sqlite3_bind_int(stmt, 8, data.shared_source);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pOut(DataStruct::dbdoc_script_pOut& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pOut] VALUES (?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_int(stmt, 2, data.index);
sqlite3_bind_text(stmt, 3, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, data.type_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 6, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_bIn(DataStruct::dbdoc_script_bIn& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_bIn] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_int(stmt, 2, data.index);
sqlite3_bind_text(stmt, 3, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 4, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_bOut(DataStruct::dbdoc_script_bOut& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_bOut] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_int(stmt, 2, data.index);
sqlite3_bind_text(stmt, 3, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 4, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_bLink(DataStruct::dbdoc_script_bLink& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_bLink] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.input);
sqlite3_bind_int(stmt, 2, data.output);
sqlite3_bind_int(stmt, 3, data.delay);
sqlite3_bind_int(stmt, 4, data.input_obj);
sqlite3_bind_int(stmt, 5, data.input_type);
sqlite3_bind_int(stmt, 6, data.input_index);
sqlite3_bind_int(stmt, 7, data.output_obj);
sqlite3_bind_int(stmt, 8, data.output_type);
sqlite3_bind_int(stmt, 9, data.output_index);
sqlite3_bind_int(stmt, 10, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pLocal(DataStruct::dbdoc_script_pLocal& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pLocal] VALUES (?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, data.is_setting);
sqlite3_bind_int(stmt, 6, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pLink(DataStruct::dbdoc_script_pLink& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pLink] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.input);
sqlite3_bind_int(stmt, 2, data.output);
sqlite3_bind_int(stmt, 3, data.input_obj);
sqlite3_bind_int(stmt, 4, data.input_type);
sqlite3_bind_int(stmt, 5, data.input_is_bb);
sqlite3_bind_int(stmt, 6, data.input_index);
sqlite3_bind_int(stmt, 7, data.output_obj);
sqlite3_bind_int(stmt, 8, data.output_type);
sqlite3_bind_int(stmt, 9, data.output_is_bb);
sqlite3_bind_int(stmt, 10, data.output_index);
sqlite3_bind_int(stmt, 11, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pOper(DataStruct::dbdoc_script_pOper& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pOper] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.op.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.op_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 4, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_eLink(DataStruct::dbdoc_script_eLink& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_eLink] VALUES (?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.export_obj);
sqlite3_bind_int(stmt, 2, data.internal_obj);
sqlite3_bind_int(stmt, 3, data.is_in);
sqlite3_bind_int(stmt, 4, data.index);
sqlite3_bind_int(stmt, 5, data.parent);
sqlite3_step(stmt);
}
void DocumentDatabase::write_script_pAttr(DataStruct::dbdoc_script_pAttr& data) {
// then check database validation
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [script_pAttr] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.thisobj);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.type.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
return;
}
void DocumentDatabase::write_msg(DataStruct::dbdoc_msg& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [msg] VALUES (?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.index);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
}
void DocumentDatabase::write_obj(DataStruct::dbdoc_obj& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [obj] VALUES (?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.id);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.classid);
sqlite3_bind_text(stmt, 4, data.classtype.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
}
void DocumentDatabase::write_data(DataStruct::dbdoc_data& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [data] VALUES (?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_text(stmt, 1, data.field.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, data.data.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.parent);
sqlite3_step(stmt);
}
#pragma endregion
#pragma region environment database
void EnvironmentDatabase::write_op(DataStruct::dbenv_op& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [op] VALUES (?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, (int)data.funcPtr);
sqlite3_bind_text(stmt, 2, data.in1_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.in2_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.out_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 5, data.op_guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, data.op_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 7, data.op_code);
sqlite3_step(stmt);
}
void EnvironmentDatabase::write_param(DataStruct::dbenv_param& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [param] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.index);
sqlite3_bind_text(stmt, 2, data.guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 3, data.derived_from.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, data.type_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, data.default_size);
sqlite3_bind_int(stmt, 6, (int)data.func_CreateDefault);
sqlite3_bind_int(stmt, 7, (int)data.func_Delete);
sqlite3_bind_int(stmt, 8, (int)data.func_SaveLoad);
sqlite3_bind_int(stmt, 9, (int)data.func_Check);
sqlite3_bind_int(stmt, 10, (int)data.func_Copy);
sqlite3_bind_int(stmt, 11, (int)data.func_String);
sqlite3_bind_int(stmt, 12, (int)data.func_UICreator);
sqlite3_bind_int(stmt, 13, data.creator_dll_index);
sqlite3_bind_int(stmt, 14, data.creator_plugin_index);
sqlite3_bind_int(stmt, 15, data.dw_param);
sqlite3_bind_int(stmt, 16, data.dw_flags);
sqlite3_bind_int(stmt, 17, data.cid);
sqlite3_bind_text(stmt, 18, data.saver_manager.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
}
void EnvironmentDatabase::write_attr(DataStruct::dbenv_attr& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [attr] VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.index);
sqlite3_bind_text(stmt, 2, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.category_index);
sqlite3_bind_text(stmt, 4, data.category_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, data.flags);
sqlite3_bind_int(stmt, 6, data.param_index);
sqlite3_bind_int(stmt, 7, data.compatible_classid);
sqlite3_bind_text(stmt, 8, data.default_value.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
}
void EnvironmentDatabase::write_plugin(DataStruct::dbenv_plugin& data) {
if (mDb == NULL) return;
sqlite3_stmt* stmt = GetStmt("INSERT INTO [plugin] VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_int(stmt, 1, data.dll_index);
sqlite3_bind_text(stmt, 2, data.dll_name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.plugin_index);
sqlite3_bind_text(stmt, 4, data.category.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 5, data.active);
sqlite3_bind_text(stmt, 6, data.guid.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 7, data.desc.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 8, data.author.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 9, data.summary.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 10, data.version);
sqlite3_bind_int(stmt, 11, (int)data.func_init);
sqlite3_bind_int(stmt, 12, (int)data.func_exit);
sqlite3_step(stmt);
}
void EnvironmentDatabase::write_variable(DataStruct::dbenv_variable& data) {
if (mDb == NULL) return;
#if !defined(VIRTOOLS_21)
sqlite3_stmt* stmt = GetStmt("INSERT INTO [variable] VALUES (?, ?, ?, ?, ?, ?)");
sqlite3_reset(stmt);
sqlite3_bind_text(stmt, 1, data.name.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, data.desciption.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_int(stmt, 3, data.flags);
sqlite3_bind_int(stmt, 4, data.type);
sqlite3_bind_text(stmt, 5, data.representation.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 6, data.data.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_step(stmt);
#endif
}
#pragma endregion
}
}

View File

@@ -1,357 +0,0 @@
#pragma once
#include <sqlite3.h>
#include "stdafx.h"
#include "virtools_compatible.hpp"
#include <string>
#include <unordered_map>
#include <set>
namespace SSMaterializer {
namespace DataStruct {
#pragma region data struct
typedef long EXPAND_CK_ID;
enum bLinkInputOutputType {
bLinkInputOutputType_INPUT,
bLinkInputOutputType_OUTPUT
};
enum pLinkInputOutputType {
pLinkInputOutputType_PIN,
pLinkInputOutputType_POUT,
pLinkInputOutputType_PLOCAL, //when using pLocal, omit [index] and [input_is_bb], [input_index] set -1
pLinkInputOutputType_PTARGET, //when using pTarget, omit [index] and [input_is_bb], [input_index] set -1
pLinkInputOutputType_PATTR //when using pAttr, omit [index], and [input_is_bb] will become [input_is_dataarray]
};
// =================== doc mDb
struct dbdoc_script {
EXPAND_CK_ID thisobj;
std::string host_name;
int index;
EXPAND_CK_ID behavior;
};
struct dbdoc_script_behavior {
EXPAND_CK_ID thisobj;
std::string name;
CK_BEHAVIOR_TYPE type;
std::string proto_name;
std::string proto_guid;
CK_BEHAVIOR_FLAGS flags;
int priority;
CKDWORD version;
//pTarget, pIn, pOut, bIn, bOut
std::string pin_count;
EXPAND_CK_ID parent;
};
struct dbdoc_script_bIO {
EXPAND_CK_ID thisobj;
int index;
std::string name;
EXPAND_CK_ID parent;
};
typedef dbdoc_script_bIO dbdoc_script_bIn;
typedef dbdoc_script_bIO dbdoc_script_bOut;
struct dbdoc_script_pTarget {
EXPAND_CK_ID thisobj;
std::string name;
std::string type;
std::string type_guid;
EXPAND_CK_ID parent;
EXPAND_CK_ID direct_source;
EXPAND_CK_ID shared_source;
};
struct dbdoc_script_pIn {
EXPAND_CK_ID thisobj;
int index;
std::string name;
std::string type;
std::string type_guid;
EXPAND_CK_ID parent;
EXPAND_CK_ID direct_source;
EXPAND_CK_ID shared_source;
};
struct dbdoc_script_pOut {
EXPAND_CK_ID thisobj;
int index;
std::string name;
std::string type;
std::string type_guid;
EXPAND_CK_ID parent;
};
struct dbdoc_script_bLink {
EXPAND_CK_ID input;
EXPAND_CK_ID output;
int delay;
EXPAND_CK_ID parent;
//additional field
EXPAND_CK_ID input_obj;
bLinkInputOutputType input_type;
int input_index;
EXPAND_CK_ID output_obj;
bLinkInputOutputType output_type;
int output_index;
};
struct dbdoc_script_pLocal {
EXPAND_CK_ID thisobj;
std::string name;
std::string type;
std::string type_guid;
BOOL is_setting;
EXPAND_CK_ID parent;
};
struct dbdoc_script_pAttr {
EXPAND_CK_ID thisobj;
std::string name;
std::string type;
std::string type_guid;
};
struct dbdoc_script_pLink {
EXPAND_CK_ID input;
EXPAND_CK_ID output;
EXPAND_CK_ID parent;
//additional field
EXPAND_CK_ID input_obj;
pLinkInputOutputType input_type;
BOOL input_is_bb;
int input_index;
EXPAND_CK_ID output_obj;
pLinkInputOutputType output_type;
BOOL output_is_bb;
int output_index;
};
struct dbdoc_script_pOper {
EXPAND_CK_ID thisobj;
std::string op;
std::string op_guid;
EXPAND_CK_ID parent;
};
struct dbdoc_script_eLink {
EXPAND_CK_ID export_obj;
EXPAND_CK_ID internal_obj;
BOOL is_in;
int index;
EXPAND_CK_ID parent;
};
struct dbdoc_msg {
CKMessageType index;
std::string name;
};
struct dbdoc_obj {
EXPAND_CK_ID id;
std::string name;
CK_CLASSID classid;
std::string classtype;
};
struct dbdoc_data {
std::string field;
std::string data;
EXPAND_CK_ID parent;
};
// =================== env mDb
struct dbenv_op {
CK_PARAMETEROPERATION funcPtr;
std::string in1_guid;
std::string in2_guid;
std::string out_guid;
std::string op_guid;
std::string op_name;
CKOperationType op_code;
};
struct dbenv_param {
CKParameterType index;
std::string guid;
std::string derived_from;
std::string type_name;
int default_size;
CK_PARAMETERCREATEDEFAULTFUNCTION func_CreateDefault;
CK_PARAMETERDELETEFUNCTION func_Delete;
CK_PARAMETERSAVELOADFUNCTION func_SaveLoad;
CK_PARAMETERCHECKFUNCTION func_Check;
CK_PARAMETERCOPYFUNCTION func_Copy;
CK_PARAMETERSTRINGFUNCTION func_String;
CK_PARAMETERUICREATORFUNCTION func_UICreator;
int creator_dll_index;
int creator_plugin_index;
CKDWORD dw_param;
CKDWORD dw_flags;
CKDWORD cid;
std::string saver_manager;
};
struct dbenv_attr {
CKAttributeType index;
std::string name;
CKAttributeCategory category_index;
std::string category_name;
CK_ATTRIBUT_FLAGS flags;
CKParameterType param_index;
CK_CLASSID compatible_classid;
std::string default_value;
};
struct dbenv_plugin {
int dll_index;
std::string dll_name;
int plugin_index;
std::string category;
CKBOOL active;
std::string guid;
std::string desc;
std::string author;
std::string summary;
DWORD version;
CK_INITINSTANCEFCT func_init;
CK_EXITINSTANCEFCT func_exit;
};
struct dbenv_variable {
std::string name;
std::string desciption;
XWORD flags;
UNIVERSAL_VAR_TYPE type;
std::string representation;
std::string data;
};
#pragma endregion
namespace Helper {
class DocumentHelper {
public:
DocumentHelper(CKParameterManager* paramManager);
~DocumentHelper();
CKParameterManager* param_manager;
dbdoc_script script;
dbdoc_script_behavior script_behavior;
dbdoc_script_bIn script_bIn;
dbdoc_script_bOut script_bOut;
dbdoc_script_pIn script_pIn;
dbdoc_script_pOut script_pOut;
dbdoc_script_bLink script_bLink;
dbdoc_script_pLocal script_pLocal;
dbdoc_script_pAttr script_pAttr;
dbdoc_script_pLink script_pLink;
dbdoc_script_pOper script_pOper;
dbdoc_script_eLink script_eLink;
dbdoc_script_pTarget script_pTarget;
dbdoc_msg msg;
dbdoc_obj obj;
dbdoc_data data;
};
class EnvironmentHelper {
public:
EnvironmentHelper();
~EnvironmentHelper();
dbenv_op op;
dbenv_param param;
dbenv_attr attr;
dbenv_plugin plugin;
dbenv_variable variable;
};
}
}
namespace Database {
class SSMaterializerDatabase {
public:
SSMaterializerDatabase();
virtual ~SSMaterializerDatabase();
protected:
sqlite3_stmt* GetStmt(const char* stmt);
void FakeConstructor(const char* file);
void FakeDeconstructor();
virtual BOOL Init();
virtual BOOL Finalize();
sqlite3* mDb;
std::unordered_map<uintptr_t, sqlite3_stmt*> mStmtCache;
};
class DocumentDatabase : public SSMaterializerDatabase {
public:
DocumentDatabase(const char* file, CKParameterManager* paramManager);
virtual ~DocumentDatabase();
DataStruct::Helper::DocumentHelper mDbHelper;
void write_script(DataStruct::dbdoc_script& data);
void write_script_behavior(DataStruct::dbdoc_script_behavior& data);
void write_script_pTarget(DataStruct::dbdoc_script_pTarget& data);
void write_script_pIn(DataStruct::dbdoc_script_pIn& data);
void write_script_pOut(DataStruct::dbdoc_script_pOut& data);
void write_script_bIn(DataStruct::dbdoc_script_bIn& data);
void write_script_bOut(DataStruct::dbdoc_script_bOut& data);
void write_script_bLink(DataStruct::dbdoc_script_bLink& data);
void write_script_pLocal(DataStruct::dbdoc_script_pLocal& data);
void write_script_pLink(DataStruct::dbdoc_script_pLink& data);
void write_script_pOper(DataStruct::dbdoc_script_pOper& data);
void write_script_eLink(DataStruct::dbdoc_script_eLink& data);
void write_script_pAttr(DataStruct::dbdoc_script_pAttr& data);
void write_msg(DataStruct::dbdoc_msg& data);
void write_obj(DataStruct::dbdoc_obj& data);
void write_data(DataStruct::dbdoc_data& data);
BOOL is_attr_duplicated(DataStruct::EXPAND_CK_ID parents);
//BOOL is_obj_duplicated(DataStruct::EXPAND_CK_ID parents);
protected:
virtual BOOL Init() override;
virtual BOOL Finalize() override;
std::set<DataStruct::EXPAND_CK_ID> mUniqueAttr;
//std::set<DataStruct::EXPAND_CK_ID> mUniqueObj;
};
class EnvironmentDatabase : public SSMaterializerDatabase {
public:
EnvironmentDatabase(const char* file);
virtual ~EnvironmentDatabase();
DataStruct::Helper::EnvironmentHelper mDbHelper;
void write_op(DataStruct::dbenv_op& data);
void write_param(DataStruct::dbenv_param& data);
void write_attr(DataStruct::dbenv_attr& data);
void write_plugin(DataStruct::dbenv_plugin& data);
void write_variable(DataStruct::dbenv_variable& data);
protected:
virtual BOOL Init() override;
virtual BOOL Finalize() override;
};
}
}

View File

@@ -1,698 +0,0 @@
#include "doc_export.hpp"
#include "string_helper.hpp"
// some shitty features process
//disable shit tip
#pragma warning(disable:26812)
// disable microsoft shitty macro to avoid build error
#undef GetClassName
namespace SSMaterializer {
namespace DocumentExporter {
#pragma region script
/*
* `Generate` mean that this function will analyse something to generate some objects which are not existed in original Virtools document.
* `Proc` meath that this function only just export something which is already existed in original Virtools document, or with slight modifications.
*/
/// <summary>
/// Generate pLink and eLink from pIn
/// </summary>
/// <param name="ctx"></param>
/// <param name="analysed_pin"></param>
/// <param name="mDb"></param>
/// <param name="parents"></param>
/// <param name="grandparents"></param>
/// <param name="pin_index"></param>
/// <param name="executedFromBB"></param>
/// <param name="isTarget"></param>
void Generate_pLink(CKContext* ctx, CKParameterIn* analysed_pin, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int pin_index, BOOL executedFromBB, BOOL isTarget) {
CKParameter* directSource = NULL;
CKObject* ds_Owner = NULL;
CKParameterIn* sharedSource = NULL;
CKObject* ss_Owner = NULL;
// first, we analyse eLink
// check whether this is export parameter and write to database
// if the behavior graph where this pIn locate, also include this pIn, we can simply
// assume there is a eLink between them
if (((CKBehavior*)ctx->GetObject(grandparents))->GetInputParameterPosition(analysed_pin) != -1) {
mDb->mDbHelper.script_eLink.export_obj = analysed_pin->GetID();
mDb->mDbHelper.script_eLink.internal_obj = parents;
mDb->mDbHelper.script_eLink.is_in = TRUE;
mDb->mDbHelper.script_eLink.index = pin_index;
mDb->mDbHelper.script_eLink.parent = grandparents;
mDb->write_script_eLink(mDb->mDbHelper.script_eLink);
// if a eLink has been detected successfully, we returned immediately
// and do not analyse any pLink anymore.
return;
}
// start to analyse pLink
// first, analyse direct_src
if (directSource = analysed_pin->GetDirectSource()) {
mDb->mDbHelper.script_pLink.input = directSource->GetID();
// for almost pin, it is connected to a pLocal, so we use a if to test it first
if (directSource->GetClassID() == CKCID_PARAMETERLOCAL || directSource->GetClassID() == CKCID_PARAMETERVARIABLE) {
//pLocal
mDb->mDbHelper.script_pLink.input_obj = directSource->GetID(); // the owner of pLocal is itself.
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PLOCAL;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE;
mDb->mDbHelper.script_pLink.input_index = -1;
} else {
// according to Virtools SDK document, there are 4 possible value gotten by us:
// bb pOut / pOper pOut / CKObject Attribute / CKDataArray
// however, the last 2 returned values have NOT been tested perfectly.
ds_Owner = directSource->GetOwner();
switch (ds_Owner->GetClassID()) {
case CKCID_BEHAVIOR:
mDb->mDbHelper.script_pLink.input_obj = ds_Owner->GetID();
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_POUT;
mDb->mDbHelper.script_pLink.input_is_bb = TRUE;
mDb->mDbHelper.script_pLink.input_index = ((CKBehavior*)ds_Owner)->GetOutputParameterPosition((CKParameterOut*)directSource);
break;
case CKCID_PARAMETEROPERATION:
mDb->mDbHelper.script_pLink.input_obj = ds_Owner->GetID();
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_POUT;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE;
mDb->mDbHelper.script_pLink.input_index = 0; // pOper only have 1 pOut
break;
case CKCID_DATAARRAY:
// CKDataArray, see as virtual bb pLocal shortcut
mDb->mDbHelper.script_pLink.input_obj = directSource->GetID();
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PATTR;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE; // omit
mDb->mDbHelper.script_pLink.input_index = -1; // omit
Proc_pAttr(ctx, mDb, directSource);
break;
default:
// CKObject, because CKDataArray also a CKObject, so we test it first.
// see as virtual bb pLocal shortcut
mDb->mDbHelper.script_pLink.input_obj = directSource->GetID();
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PATTR;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE; // omit
mDb->mDbHelper.script_pLink.input_index = -1; // omit
Proc_pAttr(ctx, mDb, directSource);
break;
}
}
}
// direct_src reflect the real source of current analysed pIn,
// however direct_src do not reflact export link
// so we need to analyse shared_src now.
//
// if this pIn has established some export relation, its shared_src must be filled.
// so we can detect it here. once its shared_src is not NULL
// we should consider export link here.
//
// we do not need to analyse any export link here, we just need to export some info
// to indicate this phenomeno.
if (sharedSource = analysed_pin->GetSharedSource()) {
//pIn from BB
mDb->mDbHelper.script_pLink.input = sharedSource->GetID();
ss_Owner = sharedSource->GetOwner();
mDb->mDbHelper.script_pLink.input_obj = ss_Owner->GetID();
switch (ss_Owner->GetClassID()) {
case CKCID_BEHAVIOR: // CKBehavior
{
if (((CKBehavior*)ss_Owner)->IsUsingTarget() && (((CKBehavior*)ss_Owner)->GetTargetParameter() == sharedSource)) {
//pTarget
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PTARGET;
mDb->mDbHelper.script_pLink.input_is_bb = TRUE;
mDb->mDbHelper.script_pLink.input_index = -1; // omit
} else {
//pIn
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PIN;
mDb->mDbHelper.script_pLink.input_is_bb = TRUE;
mDb->mDbHelper.script_pLink.input_index = ((CKBehavior*)ss_Owner)->GetInputParameterPosition(sharedSource);
}
break;
}
case CKCID_PARAMETEROPERATION: // CKParameterOperation
{
//pOper only have pIn.
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_PIN;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE;
mDb->mDbHelper.script_pLink.input_index = ((CKParameterOperation*)ss_Owner)->GetInParameter1() == sharedSource ? 0 : 1;
break;
}
default:
// the unexpected value. according to SDK manual,
// there are only 2 possible types
return;
}
}
// if the header of pLink has been analysed successfully,
// we can add tail info and push into database
if (sharedSource != NULL || directSource != NULL) {
mDb->mDbHelper.script_pLink.output = analysed_pin->GetID();
mDb->mDbHelper.script_pLink.output_obj = parents;
mDb->mDbHelper.script_pLink.output_type = isTarget ? DataStruct::pLinkInputOutputType_PTARGET : DataStruct::pLinkInputOutputType_PIN;
mDb->mDbHelper.script_pLink.output_is_bb = executedFromBB;
mDb->mDbHelper.script_pLink.output_index = pin_index;
mDb->mDbHelper.script_pLink.parent = grandparents;
mDb->write_script_pLink(mDb->mDbHelper.script_pLink);
}
}
void Generate_pLink(CKContext* ctx, CKParameterOut* analysed_pout, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int pout_index, BOOL executedFromBB) {
// check eLink first
// check whether expoer parameter and write to database
if (((CKBehavior*)ctx->GetObject(grandparents))->GetOutputParameterPosition(analysed_pout) != -1) {
mDb->mDbHelper.script_eLink.export_obj = analysed_pout->GetID();
mDb->mDbHelper.script_eLink.internal_obj = parents;
mDb->mDbHelper.script_eLink.is_in = FALSE;
mDb->mDbHelper.script_eLink.index = pout_index;
mDb->mDbHelper.script_eLink.parent = grandparents;
mDb->write_script_eLink(mDb->mDbHelper.script_eLink);
// if an eLink has been generated, skip following pLink generation
return;
}
// try generate pLink
CKParameter* cache_Dest = NULL;
CKObject* cache_DestOwner = NULL;
for (int j = 0, jCount = analysed_pout->GetDestinationCount(); j < jCount; j++) {
cache_Dest = analysed_pout->GetDestination(j);
mDb->mDbHelper.script_pLink.input = analysed_pout->GetID();
mDb->mDbHelper.script_pLink.input_obj = parents;
mDb->mDbHelper.script_pLink.input_type = DataStruct::pLinkInputOutputType_POUT;
mDb->mDbHelper.script_pLink.input_is_bb = executedFromBB;
mDb->mDbHelper.script_pLink.input_index = pout_index;
mDb->mDbHelper.script_pLink.output = cache_Dest->GetID();
if (cache_Dest->GetClassID() == CKCID_PARAMETERLOCAL) {
//pLocal
mDb->mDbHelper.script_pLink.output_obj = cache_Dest->GetID();
mDb->mDbHelper.script_pLink.output_type = DataStruct::pLinkInputOutputType_PLOCAL;
mDb->mDbHelper.script_pLink.output_is_bb = FALSE; // omit
mDb->mDbHelper.script_pLink.output_index = -1; // omit
} else {
//pOut, it must belong to a graph BB (pOut can not be shared, and prototype bb or pOper do not have link-able pOut).
cache_DestOwner = cache_Dest->GetOwner();
switch (cache_DestOwner->GetClassID()) {
case CKCID_BEHAVIOR:
mDb->mDbHelper.script_pLink.output_obj = cache_DestOwner->GetID();
mDb->mDbHelper.script_pLink.output_type = DataStruct::pLinkInputOutputType_POUT;
mDb->mDbHelper.script_pLink.output_is_bb = TRUE;
mDb->mDbHelper.script_pLink.output_index = ((CKBehavior*)cache_DestOwner)->GetOutputParameterPosition((CKParameterOut*)cache_Dest);
break;
case CKCID_DATAARRAY:
// CKDataArray, see as virtual bb pLocal shortcut
mDb->mDbHelper.script_pLink.output_obj = cache_Dest->GetID();
mDb->mDbHelper.script_pLink.output_type = DataStruct::pLinkInputOutputType_PATTR;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE; // omit
mDb->mDbHelper.script_pLink.input_index = -1; // omit
Proc_pAttr(ctx, mDb, cache_Dest);
break;
default:
// CKObject, because CKDataArray also a CKObject, so we test it first.
// see as virtual bb pLocal shortcut
mDb->mDbHelper.script_pLink.output_obj = cache_Dest->GetID();
mDb->mDbHelper.script_pLink.output_type = DataStruct::pLinkInputOutputType_PATTR;
mDb->mDbHelper.script_pLink.input_is_bb = FALSE; // omit
mDb->mDbHelper.script_pLink.input_index = -1; // omit
Proc_pAttr(ctx, mDb, cache_Dest);
break;
}
}
mDb->mDbHelper.script_pLink.parent = grandparents;
mDb->write_script_pLink(mDb->mDbHelper.script_pLink);
}
}
void Proc_pTarget(CKContext* ctx, CKParameterIn* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents) {
mDb->mDbHelper.script_pTarget.thisobj = cache->GetID();
Utils::CopyCKString(mDb->mDbHelper.script_pTarget.name, cache->GetName());
Utils::CopyCKParamTypeStr(mDb->mDbHelper.script_pTarget.type, cache->GetType(), mDb->mDbHelper.param_manager);
Utils::CopyGuid(mDb->mDbHelper.script_pTarget.type_guid, cache->GetGUID());
mDb->mDbHelper.script_pTarget.parent = parents;
mDb->mDbHelper.script_pTarget.direct_source = cache->GetDirectSource() ? cache->GetDirectSource()->GetID() : -1;
mDb->mDbHelper.script_pTarget.shared_source = cache->GetSharedSource() ? cache->GetSharedSource()->GetID() : -1;
mDb->write_script_pTarget(mDb->mDbHelper.script_pTarget);
// try generate pLink and eLink
Generate_pLink(ctx, cache, mDb, parents, grandparents, -1, TRUE, TRUE);
}
void Proc_pIn(CKContext* ctx, CKParameterIn* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int index, BOOL executedFromBB) {
mDb->mDbHelper.script_pIn.thisobj = cache->GetID();
mDb->mDbHelper.script_pIn.index = index;
Utils::CopyCKString(mDb->mDbHelper.script_pIn.name, cache->GetName());
Utils::CopyCKParamTypeStr(mDb->mDbHelper.script_pIn.type, cache->GetType(), mDb->mDbHelper.param_manager);
Utils::CopyGuid(mDb->mDbHelper.script_pIn.type_guid, cache->GetGUID());
mDb->mDbHelper.script_pIn.parent = parents;
mDb->mDbHelper.script_pIn.direct_source = cache->GetDirectSource() ? cache->GetDirectSource()->GetID() : -1;
mDb->mDbHelper.script_pIn.shared_source = cache->GetSharedSource() ? cache->GetSharedSource()->GetID() : -1;
mDb->write_script_pIn(mDb->mDbHelper.script_pIn);
// try generate pLink and eLink
Generate_pLink(ctx, cache, mDb, parents, grandparents, index, executedFromBB, FALSE);
}
void Proc_pOut(CKContext* ctx, CKParameterOut* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int index, BOOL executedFromBB) {
mDb->mDbHelper.script_pOut.thisobj = cache->GetID();
mDb->mDbHelper.script_pOut.index = index;
Utils::CopyCKString(mDb->mDbHelper.script_pOut.name, cache->GetName());
Utils::CopyCKParamTypeStr(mDb->mDbHelper.script_pOut.type, cache->GetType(), mDb->mDbHelper.param_manager);
Utils::CopyGuid(mDb->mDbHelper.script_pOut.type_guid, cache->GetGUID());
mDb->mDbHelper.script_pOut.parent = parents;
mDb->write_script_pOut(mDb->mDbHelper.script_pOut);
// try generate pLink and eLink
Generate_pLink(ctx, cache, mDb, parents, grandparents, index, executedFromBB);
}
void Proc_bIn(CKBehaviorIO* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, int index) {
mDb->mDbHelper.script_bIn.thisobj = cache->GetID();
mDb->mDbHelper.script_bIn.index = index;
Utils::CopyCKString(mDb->mDbHelper.script_bIn.name, cache->GetName());
mDb->mDbHelper.script_bIn.parent = parents;
mDb->write_script_bIn(mDb->mDbHelper.script_bIn);
}
void Proc_bOut(CKBehaviorIO* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, int index) {
mDb->mDbHelper.script_bOut.thisobj = cache->GetID();
mDb->mDbHelper.script_bOut.index = index;
Utils::CopyCKString(mDb->mDbHelper.script_bOut.name, cache->GetName());
mDb->mDbHelper.script_bOut.parent = parents;
mDb->write_script_bOut(mDb->mDbHelper.script_bOut);
}
void Proc_bLink(CKBehaviorLink* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
CKBehaviorIO* io = cache->GetInBehaviorIO();
CKBehavior* beh = io->GetOwner();
mDb->mDbHelper.script_bLink.input = io->GetID();
mDb->mDbHelper.script_bLink.input_obj = beh->GetID();
mDb->mDbHelper.script_bLink.input_type = (io->GetType() == CK_BEHAVIORIO_IN ? DataStruct::bLinkInputOutputType_INPUT : DataStruct::bLinkInputOutputType_OUTPUT);
mDb->mDbHelper.script_bLink.input_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io));
io = cache->GetOutBehaviorIO();
beh = io->GetOwner();
mDb->mDbHelper.script_bLink.output = io->GetID();
mDb->mDbHelper.script_bLink.output_obj = beh->GetID();
mDb->mDbHelper.script_bLink.output_type = (io->GetType() == CK_BEHAVIORIO_IN ? DataStruct::bLinkInputOutputType_INPUT : DataStruct::bLinkInputOutputType_OUTPUT);
mDb->mDbHelper.script_bLink.output_index = (io->GetType() == CK_BEHAVIORIO_IN ? io->GetOwner()->GetInputPosition(io) : io->GetOwner()->GetOutputPosition(io));
mDb->mDbHelper.script_bLink.delay = cache->GetActivationDelay();
mDb->mDbHelper.script_bLink.parent = parents;
mDb->write_script_bLink(mDb->mDbHelper.script_bLink);
}
void Proc_pLocal(CKParameterLocal* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, BOOL is_setting) {
mDb->mDbHelper.script_pLocal.thisobj = cache->GetID();
Utils::CopyCKString(mDb->mDbHelper.script_pLocal.name, cache->GetName());
Utils::CopyCKParamTypeStr(mDb->mDbHelper.script_pLocal.type, cache->GetType(), mDb->mDbHelper.param_manager);
Utils::CopyGuid(mDb->mDbHelper.script_pLocal.type_guid, cache->GetGUID());
mDb->mDbHelper.script_pLocal.is_setting = is_setting;
mDb->mDbHelper.script_pLocal.parent = parents;
mDb->write_script_pLocal(mDb->mDbHelper.script_pLocal);
//export plocal metadata
DigParameterData(cache, mDb, cache->GetID());
}
void Proc_pOper(CKContext* ctx, CKParameterOperation* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
mDb->mDbHelper.script_pOper.thisobj = cache->GetID();
mDb->mDbHelper.script_pOper.op = mDb->mDbHelper.param_manager->OperationGuidToName(cache->GetOperationGuid());
Utils::CopyGuid(mDb->mDbHelper.script_pOper.op_guid, cache->GetOperationGuid());
mDb->mDbHelper.script_pOper.parent = parents;
mDb->write_script_pOper(mDb->mDbHelper.script_pOper);
//export 2 input param and 1 output param
Proc_pIn(ctx, cache->GetInParameter1(), mDb, cache->GetID(), parents, 0, FALSE);
Proc_pIn(ctx, cache->GetInParameter2(), mDb, cache->GetID(), parents, 1, FALSE);
Proc_pOut(ctx, cache->GetOutParameter(), mDb, cache->GetID(), parents, 0, FALSE);
}
/*
* pAttr do not have any explict interface to get them
* so they only can be find via pLink analyse.
* 2 pLink analyse funcstions will call this function to record each pAttr
* due to this mechanism, it might cause a duplication problem so
* we need check possible duplication here.
*/
void Proc_pAttr(CKContext* ctx, Database::DocumentDatabase* mDb, CKParameter* cache) {
// check duplication
if (mDb->is_attr_duplicated(cache->GetID())) return;
// write self first to detect conflict
mDb->mDbHelper.script_pAttr.thisobj = cache->GetID();
Utils::CopyCKString(mDb->mDbHelper.script_pAttr.name, cache->GetName());
Utils::CopyCKParamTypeStr(mDb->mDbHelper.script_pAttr.type, cache->GetType(), mDb->mDbHelper.param_manager);
Utils::CopyGuid(mDb->mDbHelper.script_pAttr.type_guid, cache->GetGUID());
mDb->write_script_pAttr(mDb->mDbHelper.script_pAttr);
// continue write some properties to indicate the host of this attribute
CKObject* host = cache->GetOwner();
// write owner id
DataDictWritter("attr.owner", (long)host->GetID(), mDb, cache->GetID());
}
void Proc_Behavior(CKContext* ctx, CKBehavior* bhv, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
//write self data
mDb->mDbHelper.script_behavior.thisobj = bhv->GetID();
Utils::CopyCKString(mDb->mDbHelper.script_behavior.name, bhv->GetName());
mDb->mDbHelper.script_behavior.type = bhv->GetType();
Utils::CopyCKString(mDb->mDbHelper.script_behavior.proto_name, bhv->GetPrototypeName());
Utils::CopyGuid(mDb->mDbHelper.script_behavior.proto_guid, bhv->GetPrototypeGuid());
mDb->mDbHelper.script_behavior.flags = bhv->GetFlags();
mDb->mDbHelper.script_behavior.priority = bhv->GetPriority();
mDb->mDbHelper.script_behavior.version = bhv->GetVersion();
mDb->mDbHelper.script_behavior.parent = parents;
Utils::StdstringPrintf(mDb->mDbHelper.script_behavior.pin_count, "%d,%d,%d,%d,%d",
(bhv->IsUsingTarget() ? 1 : 0),
bhv->GetInputParameterCount(),
bhv->GetOutputParameterCount(),
bhv->GetInputCount(),
bhv->GetOutputCount());
mDb->write_script_behavior(mDb->mDbHelper.script_behavior);
//write target
if (bhv->IsUsingTarget())
Proc_pTarget(ctx, bhv->GetTargetParameter(), mDb, bhv->GetID(), parents);
int count = 0, i = 0;
//pIn
for (i = 0, count = bhv->GetInputParameterCount(); i < count; i++)
Proc_pIn(ctx, bhv->GetInputParameter(i), mDb, bhv->GetID(), parents, i, TRUE);
//pOut
for (i = 0, count = bhv->GetOutputParameterCount(); i < count; i++)
Proc_pOut(ctx, bhv->GetOutputParameter(i), mDb, bhv->GetID(), parents, i, TRUE);
//bIn
for (i = 0, count = bhv->GetInputCount(); i < count; i++)
Proc_bIn(bhv->GetInput(i), mDb, bhv->GetID(), i);
//bOut
for (i = 0, count = bhv->GetOutputCount(); i < count; i++)
Proc_bOut(bhv->GetOutput(i), mDb, bhv->GetID(), i);
//bLink
for (i = 0, count = bhv->GetSubBehaviorLinkCount(); i < count; i++)
Proc_bLink(bhv->GetSubBehaviorLink(i), mDb, bhv->GetID());
//pLocal
for (i = 0, count = bhv->GetLocalParameterCount(); i < count; i++)
Proc_pLocal(bhv->GetLocalParameter(i), mDb, bhv->GetID(),
bhv->IsLocalParameterSetting(i));
//pOper
for (i = 0, count = bhv->GetParameterOperationCount(); i < count; i++)
Proc_pOper(ctx, bhv->GetParameterOperation(i), mDb, bhv->GetID());
//iterate sub bb
for (i = 0, count = bhv->GetSubBehaviorCount(); i < count; i++)
Proc_Behavior(ctx, bhv->GetSubBehavior(i), mDb, bhv->GetID());
}
void IterateScript(CKContext* ctx, Database::DocumentDatabase* mDb) {
// get all CKBeObject to try to get all scripts.
// because only CKBeObject can load script.
CKBeObject* beobj = NULL;
CKBehavior* beh = NULL;
XObjectPointerArray objArray = ctx->GetObjectListByType(CKCID_BEOBJECT, TRUE);
int len = objArray.Size();
int scriptLen = 0;
for (int i = 0; i < len; i++) {
beobj = (CKBeObject*)objArray.GetObjectA(i);
if ((scriptLen = beobj->GetScriptCount()) == 0) continue;
for (int j = 0; j < scriptLen; j++) {
//write script table
beh = beobj->GetScript(j);
mDb->mDbHelper.script.thisobj = beobj->GetID();
mDb->mDbHelper.script.host_name = beobj->GetName();
mDb->mDbHelper.script.index = j;
mDb->mDbHelper.script.behavior = beh->GetID();
mDb->write_script(mDb->mDbHelper.script);
//iterate script
Proc_Behavior(ctx, beh, mDb, -1);
}
}
}
#pragma endregion
#pragma region message & obj
void IterateMessage(CKContext* ctx, Database::DocumentDatabase* mDb) {
CKMessageManager* msgManager = ctx->GetMessageManager();
int count = msgManager->GetMessageTypeCount();
for (int i = 0; i < count; i++) {
mDb->mDbHelper.msg.index = i;
Utils::CopyCKString(mDb->mDbHelper.msg.name, msgManager->GetMessageTypeName(i));
mDb->write_msg(mDb->mDbHelper.msg);
}
}
static std::vector<CK_CLASSID> g_CommonClassId{
#if defined(VIRTOOLS_50) || defined(VIRTOOLS_40) || defined(VIRTOOLS_35)
// export video for non-21/25 virtools ver
CKCID_VIDEO,
#endif
// export beobj object will export almost objects
CKCID_OBJECTANIMATION, CKCID_ANIMATION, CKCID_BEOBJECT
};
void IterateObj(CKContext* ctx, Database::DocumentDatabase* mDb) {
for (auto it = g_CommonClassId.begin(); it != g_CommonClassId.end(); ++it) {
XObjectPointerArray objArray = ctx->GetObjectListByType(*it, TRUE);
int len = objArray.Size();
int scriptLen = 0;
for (int i = 0; i < len; i++) {
CKSceneObject* scene_obj = (CKSceneObject*)objArray.GetObjectA(i);
mDb->mDbHelper.obj.id = scene_obj->GetID();
Utils::CopyCKString(mDb->mDbHelper.obj.name, scene_obj->GetName());
mDb->mDbHelper.obj.classid = scene_obj->GetClassID();
Utils::CopyCKClassId(mDb->mDbHelper.obj.classtype, scene_obj->GetClassID(), mDb->mDbHelper.param_manager);
mDb->write_obj(mDb->mDbHelper.obj);
}
}
}
#pragma endregion
#pragma region data process
void DigParameterData(CKParameter* p, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
// due to our algorithm, parameter can not be duplicated
// so we don't need to check its duplication.
CKGUID t = p->GetGUID();
CKParameterType pt = p->GetType();
// export guid and type name corresponding with guid
static std::string str_guid;
static std::string str_typename;
Utils::CopyGuid(str_guid, t);
DataDictWritter("guid", str_guid.c_str(), mDb, parents);
Utils::CopyCKParamTypeStr(str_typename, pt, mDb->mDbHelper.param_manager);
DataDictWritter("typename", str_typename.c_str(), mDb, parents);
// value object
if (p->GetParameterClassID() && p->GetValueObject(false)) {
CKObject* vobj = p->GetValueObject(false);
// write its id
DataDictWritter("vobj", (long)vobj->GetID(), mDb, parents);
return;
}
//nothing
if (t == CKPGUID_NONE) return;
//float
if (t == CKPGUID_FLOAT || t == CKPGUID_ANGLE || t == CKPGUID_PERCENTAGE || t == CKPGUID_TIME
#if defined(VIRTOOLS_50) || defined(VIRTOOLS_40) || defined(VIRTOOLS_35)
|| t == CKPGUID_FLOATSLIDER
#endif
) {
DataDictWritter("float", *(float*)(p->GetReadDataPtr(false)), mDb, parents);
return;
}
//int
if (t == CKPGUID_INT || t == CKPGUID_KEY || t == CKPGUID_BOOL || t == CKPGUID_ID || t == CKPGUID_POINTER
|| t == CKPGUID_MESSAGE || t == CKPGUID_ATTRIBUTE || t == CKPGUID_BLENDMODE || t == CKPGUID_FILTERMODE
|| t == CKPGUID_BLENDFACTOR || t == CKPGUID_FILLMODE || t == CKPGUID_LITMODE || t == CKPGUID_SHADEMODE
|| t == CKPGUID_ADDRESSMODE || t == CKPGUID_WRAPMODE || t == CKPGUID_3DSPRITEMODE || t == CKPGUID_FOGMODE
|| t == CKPGUID_LIGHTTYPE || t == CKPGUID_SPRITEALIGN || t == CKPGUID_DIRECTION || t == CKPGUID_LAYERTYPE
|| t == CKPGUID_COMPOPERATOR || t == CKPGUID_BINARYOPERATOR || t == CKPGUID_SETOPERATOR
|| t == CKPGUID_OBSTACLEPRECISION || t == CKPGUID_OBSTACLEPRECISIONBEH) {
DataDictWritter("int", (long)(*(int*)(p->GetReadDataPtr(false))), mDb, parents);
return;
}
if (t == CKPGUID_VECTOR) {
VxVector vec;
memcpy(&vec, p->GetReadDataPtr(false), sizeof(vec));
static std::string str_vector;
Utils::StdstringPrintf(str_vector, "%f, %f, %f",
vec.x, vec.y, vec.z);
DataDictWritter("vector", str_vector.c_str(), mDb, parents);
return;
}
if (t == CKPGUID_2DVECTOR) {
Vx2DVector vec;
memcpy(&vec, p->GetReadDataPtr(false), sizeof(vec));
static std::string str_2dvector;
Utils::StdstringPrintf(str_2dvector, "%f, %f",
vec.x, vec.y);
DataDictWritter("2dvector", str_2dvector.c_str(), mDb, parents);
return;
}
if (t == CKPGUID_MATRIX) {
VxMatrix mat;
memcpy(&mat, p->GetReadDataPtr(false), sizeof(mat));
static std::string str_matrix;
Utils::StdstringPrintf(str_matrix, "%f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f",
mat[0][0], mat[0][1], mat[0][2], mat[0][3],
mat[1][0], mat[1][1], mat[1][2], mat[1][3],
mat[2][0], mat[2][1], mat[2][2], mat[2][3],
mat[3][0], mat[3][1], mat[3][2], mat[3][3]
);
DataDictWritter("matrix", str_matrix.c_str(), mDb, parents);
return;
}
if (t == CKPGUID_COLOR) {
VxColor col;
memcpy(&col, p->GetReadDataPtr(false), sizeof(col));
static std::string str_color;
Utils::StdstringPrintf(str_color, "%f, %f, %f, %f",
col.r, col.g, col.b, col.a);
DataDictWritter("color", str_color.c_str(), mDb, parents);
return;
}
if (t == CKPGUID_2DCURVE) {
//CK2dCurve* c;
CK2dCurve* c = NULL;
memcpy(&c, p->GetReadDataPtr(false), sizeof(c));
// we need construct a fake json body as our data
static std::string str_2dcurve;
static std::string str_2dcurve_entry;
str_2dcurve = "[";
int cpcount = c->GetControlPointCount();
for (int i = 0; i < cpcount; ++i) {
if (i != 0) str_2dcurve += ','; // extra splitter
str_2dcurve += '{'; // object start
CK2dCurvePoint* cp = c->GetControlPoint(i);
Utils::StdstringPrintf(str_2dcurve_entry, "\"x\": %f, \"y\": %f,", cp->GetPosition().x, cp->GetPosition().y);
str_2dcurve += str_2dcurve_entry.c_str();
if (cp->IsLinear()) str_2dcurve += "\"linear\": true,";
else str_2dcurve += "\"linear\": false,";
if (cp->IsTCB()) {
str_2dcurve += "\"tcb\": true,";
Utils::StdstringPrintf(str_2dcurve_entry, "\"bias\": %f,", cp->GetBias());
str_2dcurve += str_2dcurve_entry.c_str();
Utils::StdstringPrintf(str_2dcurve_entry, "\"continuity\": %f,", cp->GetContinuity());
str_2dcurve += str_2dcurve_entry.c_str();
Utils::StdstringPrintf(str_2dcurve_entry, "\"tension\": %f", cp->GetTension());
str_2dcurve += str_2dcurve_entry.c_str();
} else {
str_2dcurve += "\"tcb\": false,";
Utils::StdstringPrintf(str_2dcurve_entry, "\"intangent\": {\"x\": %f, \"y\": %f},", cp->GetInTangent().x, cp->GetInTangent().y);
str_2dcurve += str_2dcurve_entry.c_str();
Utils::StdstringPrintf(str_2dcurve_entry, "\"outtangent\": {\"x\": %f, \"y\": %f}", cp->GetOutTangent().x, cp->GetOutTangent().y);
str_2dcurve += str_2dcurve_entry.c_str();
}
str_2dcurve += '}';
}
str_2dcurve = "]";
DataDictWritter("2dcurve", str_2dcurve.c_str(), mDb, parents);
return;
}
if (t == CKPGUID_STRING) {
char* cptr = (char*)p->GetReadDataPtr(false);
int cc = p->GetDataSize();
// virtools internal data may not have null terminal, so we use raw add function here
// resize data and copy
mDb->mDbHelper.data.data.resize(cc);
memcpy((void*)mDb->mDbHelper.data.data.data(), cptr, cc);
mDb->mDbHelper.data.field = "string";
mDb->mDbHelper.data.parent = parents;
mDb->write_data(mDb->mDbHelper.data);
return;
}
//if it gets here, we have no idea what it really is. so simply dump it.
//buffer-like
if (t == CKPGUID_VOIDBUF
#if defined(VIRTOOLS_50) || defined(VIRTOOLS_40) || defined(VIRTOOLS_35)
|| t == CKPGUID_SHADER || t == CKPGUID_TECHNIQUE || t == CKPGUID_PASS
#endif
) {
// raw data also need use raw export feature
// we use base64 encode to encode all data
char* cptr = (char*)p->GetReadDataPtr(false);
int ds = p->GetDataSize();
// dump data
static std::string str_raw;
if (ds > 10240) {
// data is too big, clamp it to 10240
Utils::StdstringGetBase64(str_raw, cptr, 10240);
DataDictWritter("raw.partial_data", str_raw.c_str(), mDb, parents);
} else {
Utils::StdstringGetBase64(str_raw, cptr, ds);
DataDictWritter("raw.data", str_raw.c_str(), mDb, parents);
}
//dump data length
DataDictWritter("dump.length", (long)ds, mDb, parents);
return;
}
}
void DataDictWritter(const char* field, const char* data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
mDb->mDbHelper.data.field = field;
mDb->mDbHelper.data.data = data;
mDb->mDbHelper.data.parent = parents;
mDb->write_data(mDb->mDbHelper.data);
}
void DataDictWritter(const char* field, float data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
static std::string float_conv;
Utils::StdstringPrintf(float_conv, "%f", data);
DataDictWritter(field, float_conv.c_str(), mDb, parents);
}
void DataDictWritter(const char* field, long data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents) {
static std::string int_conv;
Utils::StdstringPrintf(int_conv, "%d", data);
DataDictWritter(field, int_conv.c_str(), mDb, parents);
}
#pragma endregion
}
}

View File

@@ -1,33 +0,0 @@
#pragma once
#include "stdafx.h"
#include "database.hpp"
namespace SSMaterializer {
namespace DocumentExporter {
void Generate_pLink(CKContext* ctx, CKParameterIn* analysed_pin, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int pin_index, BOOL executedFromBB, BOOL isTarget);
void Generate_pLink(CKContext* ctx, CKParameterOut* analysed_pout, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int pout_index, BOOL executedFromBB);
void Proc_pTarget(CKContext* ctx, CKParameterIn* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents);
void Proc_pIn(CKContext* ctx, CKParameterIn* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int index, BOOL executedFromBB);
void Proc_pOut(CKContext* ctx, CKParameterOut* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, DataStruct::EXPAND_CK_ID grandparents, int index, BOOL executedFromBB);
void Proc_bIn(CKBehaviorIO* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, int index);
void Proc_bOut(CKBehaviorIO* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, int index);
void Proc_bLink(CKBehaviorLink* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void Proc_pLocal(CKParameterLocal* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents, BOOL is_setting);
void Proc_pOper(CKContext* ctx, CKParameterOperation* cache, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void Proc_pAttr(CKContext* ctx, Database::DocumentDatabase* mDb, CKParameter* cache);
void Proc_Behavior(CKContext* ctx, CKBehavior* bhv, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void IterateScript(CKContext* ctx, Database::DocumentDatabase* mDb);
void IterateMessage(CKContext* ctx, Database::DocumentDatabase* mDb);
void IterateObj(CKContext* ctx, Database::DocumentDatabase* mDb);
void DigParameterData(CKParameter* p, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void DataDictWritter(const char* field, long data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void DataDictWritter(const char* field, float data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
void DataDictWritter(const char* field, const char* data, Database::DocumentDatabase* mDb, DataStruct::EXPAND_CK_ID parents);
}
}

View File

@@ -1,145 +0,0 @@
#include "env_export.hpp"
#include "string_helper.hpp"
//disable shit tip
#pragma warning(disable:26812)
namespace SSMaterializer {
namespace EnvironmentExporter {
void IterateParameterOperation(CKParameterManager* parameterManager, Database::EnvironmentDatabase* mDb) {
int count = parameterManager->GetParameterOperationCount();
CKOperationDesc* opList = NULL;
CKGUID _guid;
int listCount = 0, cacheListCount = 0;
for (int i = 0; i < count; i++) {
//fill basic data
mDb->mDbHelper.op.op_code = i;
_guid = parameterManager->OperationCodeToGuid(i);
Utils::CopyGuid(mDb->mDbHelper.op.op_guid, _guid);
mDb->mDbHelper.op.op_name = parameterManager->OperationCodeToName(i);
//allocate mem
cacheListCount = parameterManager->GetAvailableOperationsDesc(_guid, NULL, NULL, NULL, NULL);
if (cacheListCount > listCount) {
listCount = cacheListCount;
opList = (CKOperationDesc*)realloc(opList, listCount * sizeof(CKOperationDesc));
if (opList == NULL) return;
}
parameterManager->GetAvailableOperationsDesc(_guid, NULL, NULL, NULL, opList);
for (int j = 0; j < cacheListCount; j++) {
Utils::CopyGuid(mDb->mDbHelper.op.in1_guid, opList[j].P1Guid);
Utils::CopyGuid(mDb->mDbHelper.op.in2_guid, opList[j].P2Guid);
Utils::CopyGuid(mDb->mDbHelper.op.out_guid, opList[j].ResGuid);
mDb->mDbHelper.op.funcPtr = opList[j].Fct;
mDb->write_op(mDb->mDbHelper.op);
}
}
if (opList != NULL) free(opList);
}
void IterateParameter(CKParameterManager* parameterManager, Database::EnvironmentDatabase* mDb) {
int count = parameterManager->GetParameterTypesCount();
CKParameterTypeDesc* desc = NULL;
for (int i = 0; i < count; i++) {
desc = parameterManager->GetParameterTypeDescription(i);
mDb->mDbHelper.param.index = desc->Index;
Utils::CopyGuid(mDb->mDbHelper.param.guid, desc->Guid);
Utils::CopyGuid(mDb->mDbHelper.param.derived_from, desc->DerivedFrom);
mDb->mDbHelper.param.type_name = desc->TypeName.CStr();
mDb->mDbHelper.param.default_size = desc->DefaultSize;
mDb->mDbHelper.param.func_CreateDefault = desc->CreateDefaultFunction;
mDb->mDbHelper.param.func_Delete = desc->DeleteFunction;
mDb->mDbHelper.param.func_SaveLoad = desc->SaveLoadFunction;
mDb->mDbHelper.param.func_Check = desc->CheckFunction;
mDb->mDbHelper.param.func_Copy = desc->CopyFunction;
mDb->mDbHelper.param.func_String = desc->StringFunction;
mDb->mDbHelper.param.func_UICreator = desc->UICreatorFunction;
CKPluginEntry* plgEntry = desc->CreatorDll;
if (plgEntry != NULL) {
mDb->mDbHelper.param.creator_dll_index = plgEntry->m_PluginDllIndex;
mDb->mDbHelper.param.creator_plugin_index = plgEntry->m_PositionInDll;
} else {
mDb->mDbHelper.param.creator_dll_index = -1;
mDb->mDbHelper.param.creator_plugin_index = -1;
}
mDb->mDbHelper.param.dw_param = desc->dwParam;
mDb->mDbHelper.param.dw_flags = desc->dwFlags;
mDb->mDbHelper.param.cid = desc->Cid;
Utils::CopyGuid(mDb->mDbHelper.param.saver_manager, desc->Saver_Manager);
mDb->write_param(mDb->mDbHelper.param);
}
}
void IterateAttribute(CKAttributeManager* attrManager, Database::EnvironmentDatabase* mDb) {
int count = attrManager->GetAttributeCount();
for (int i = 0; i < count; i++) {
mDb->mDbHelper.attr.index = i;
mDb->mDbHelper.attr.name = attrManager->GetAttributeNameByType(i);
mDb->mDbHelper.attr.category_index = attrManager->GetAttributeCategoryIndex(i);
Utils::CopyCKString(mDb->mDbHelper.attr.category_name, attrManager->GetAttributeCategory(i));
mDb->mDbHelper.attr.flags = attrManager->GetAttributeFlags(i);
mDb->mDbHelper.attr.param_index = attrManager->GetAttributeParameterType(i);
mDb->mDbHelper.attr.compatible_classid = attrManager->GetAttributeCompatibleClassId(i);
Utils::CopyCKString(mDb->mDbHelper.attr.default_value, attrManager->GetAttributeDefaultValue(i));
mDb->write_attr(mDb->mDbHelper.attr);
}
}
void IteratePlugin(CKPluginManager* plgManager, Database::EnvironmentDatabase* mDb) {
for (int i = 0; i <= 7; i++) {
int catCount = plgManager->GetPluginCount(i);
mDb->mDbHelper.plugin.category = plgManager->GetCategoryName(i);
for (int j = 0; j < catCount; j++) {
CKPluginEntry* plgEntry = plgManager->GetPluginInfo(i, j);
CKPluginInfo* plgInfo = &(plgEntry->m_PluginInfo);
CKPluginDll* plgDll = plgManager->GetPluginDllInfo(plgEntry->m_PluginDllIndex);
mDb->mDbHelper.plugin.dll_index = plgEntry->m_PluginDllIndex;
mDb->mDbHelper.plugin.dll_name = plgDll->m_DllFileName.CStr();
mDb->mDbHelper.plugin.plugin_index = plgEntry->m_PositionInDll;
mDb->mDbHelper.plugin.active = plgEntry->m_Active;
Utils::CopyGuid(mDb->mDbHelper.plugin.guid, plgInfo->m_GUID);
mDb->mDbHelper.plugin.desc = plgInfo->m_Description.CStr();
mDb->mDbHelper.plugin.author = plgInfo->m_Author.CStr();
mDb->mDbHelper.plugin.summary = plgInfo->m_Summary.CStr();
mDb->mDbHelper.plugin.version = plgInfo->m_Version;
mDb->mDbHelper.plugin.func_init = plgInfo->m_InitInstanceFct;
mDb->mDbHelper.plugin.func_exit = plgInfo->m_ExitInstanceFct;
mDb->write_plugin(mDb->mDbHelper.plugin);
}
}
}
#if !defined(VIRTOOLS_21)
void IterateVariable(CKVariableManager* varManager, Database::EnvironmentDatabase* mDb) {
CKVariableManager::Iterator it = varManager->GetVariableIterator();
CKVariableManager::Variable* varobj = NULL;
XString dataCopyCache;
for (; !it.End(); it++) {
varobj = it.GetVariable();
mDb->mDbHelper.variable.name = it.GetName();
Utils::CopyCKString(mDb->mDbHelper.variable.desciption, varobj->GetDescription());
mDb->mDbHelper.variable.flags = varobj->GetFlags();
mDb->mDbHelper.variable.type = varobj->GetType();
Utils::CopyCKString(mDb->mDbHelper.variable.representation, varobj->GetRepresentation());
varobj->GetStringValue(dataCopyCache);
mDb->mDbHelper.variable.data = dataCopyCache.CStr();
mDb->write_variable(mDb->mDbHelper.variable);
}
}
#endif
}
}

View File

@@ -1,19 +0,0 @@
#pragma once
#include "stdafx.h"
#include "database.hpp"
namespace SSMaterializer {
namespace EnvironmentExporter {
void IterateParameterOperation(CKParameterManager* parameterManager, Database::EnvironmentDatabase* mDb);
void IterateParameter(CKParameterManager* parameterManager, Database::EnvironmentDatabase* mDb);
void IterateAttribute(CKAttributeManager* attrManager, Database::EnvironmentDatabase* mDb);
void IteratePlugin(CKPluginManager* plgManager, Database::EnvironmentDatabase* mDb);
#if !defined(VIRTOOLS_21)
void IterateVariable(CKVariableManager* varManager, Database::EnvironmentDatabase* mDb);
#endif
}
}

View File

@@ -1,57 +0,0 @@
#include "stdafx.h"
#include "vt_menu.hpp"
#include "vt_player.hpp"
#if defined(VIRTOOLS_PLUGIN)
PluginInterface* s_Plugininterface = NULL;
PluginInfo g_PluginInfo0;
int GetVirtoolsPluginInfoCount() {
return 1;
}
PluginInfo* GetVirtoolsPluginInfo(int index) {
switch (index) {
case 0:
return &g_PluginInfo0;
}
return NULL;
}
class SuperScriptMaterializer : CWinApp {
public:
virtual BOOL InitInstance();
virtual int ExitInstance();
};
SuperScriptMaterializer theApp;
BOOL SuperScriptMaterializer::InitInstance() {
CWinApp::InitInstance();
strcpy(g_PluginInfo0.m_Name, "SSMaterializer");
g_PluginInfo0.m_PluginType = PluginInfo::PT_EDITOR;
g_PluginInfo0.m_PluginType = (PluginInfo::PLUGIN_TYPE)(g_PluginInfo0.m_PluginType | PluginInfo::PTF_RECEIVENOTIFICATION);
g_PluginInfo0.m_PluginCallback = PluginCallback;
return TRUE;
}
int SuperScriptMaterializer::ExitInstance() {
return CWinApp::ExitInstance();
}
#elif defined(VIRTOOLS_STANDALONE)
int main(int argc, char* argv[]) {
if (argc != 4) {
printf("Arguments too less!\n");
printf("Format: SuperScriptMaterializer.exe [virtools composition] [script db path] [env db path]\n");
ExitProcess(1);
}
PlayerMain(argv[1], argv[2], argv[3]);
return 0;
}
#endif

View File

@@ -1,49 +0,0 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#define _WIN32_WINNT 0x0A00
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#include <afxwin.h> // MFC core and standard components
#include <afxext.h> // MFC extensions
#ifndef _AFX_NO_OLE_SUPPORT
#include <afxole.h> // MFC OLE classes
#include <afxodlgs.h> // MFC OLE dialog classes
#include <afxdisp.h> // MFC Automation classes
#endif // _AFX_NO_OLE_SUPPORT
#ifndef _AFX_NO_DB_SUPPORT
#include <afxdb.h> // MFC ODBC SSMaterializerDatabase classes
#endif // _AFX_NO_DB_SUPPORT
#ifndef _AFX_NO_DAO_SUPPORT
#include <afxdao.h> // MFC DAO SSMaterializerDatabase classes
#endif // _AFX_NO_DAO_SUPPORT
#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls
#ifndef _AFX_NO_AFXCMN_SUPPORT
#include <afxcmn.h> // MFC support for Windows Common Controls
#endif // _AFX_NO_AFXCMN_SUPPORT
//PLUGIN PRECOMPILED HEADER INCLUDED
#include "CKAll.h"
#if defined(VIRTOOLS_PLUGIN)
#include "VIControls.h"
#include "CKControlsAll.h"
#include "VEP_ScriptActionMenu.h"
#include "VEP_KeyboardShortcutManager.h"
#include "VEP_All.h"
using namespace CKControl;
#elif defined(VIRTOOLS_STANDALONE)
#endif

View File

@@ -1,58 +0,0 @@
#include "string_helper.hpp"
#include <cstdint>
namespace SSMaterializer {
namespace Utils {
void StdstringPrintf(std::string& strl, const char* format, ...) {
va_list argptr;
va_start(argptr, format);
StdstringVPrintf(strl, format, argptr);
va_end(argptr);
}
void StdstringVPrintf(std::string& strl, const char* format, va_list argptr) {
int count = _vsnprintf(NULL, 0, format, argptr);
count++;
strl.resize(count);
strl[count - 1] = '\0';
int write_result = _vsnprintf((char*)strl.data(), count, format, argptr);
if (write_result < 0 || write_result >= count) {
//something goes wrong
strl.clear();
}
}
// Reference: https://stackoverflow.com/questions/342409/how-do-i-base64-encode-decode-in-c
void StdstringGetBase64(std::string& strl, const char* data, size_t datalen) {
static const char* base64_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const int mod_table[] = { 0, 2, 1 };
// compute size
size_t output_length = 4 * ((datalen + 2) / 3);
strl.resize(output_length);
// compute
for (size_t i = 0, j = 0; i < datalen;) {
uint32_t octet_a = i < datalen ? (unsigned char)data[i++] : 0;
uint32_t octet_b = i < datalen ? (unsigned char)data[i++] : 0;
uint32_t octet_c = i < datalen ? (unsigned char)data[i++] : 0;
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
strl[j++] = base64_table[(triple >> 3 * 6) & 0x3F];
strl[j++] = base64_table[(triple >> 2 * 6) & 0x3F];
strl[j++] = base64_table[(triple >> 1 * 6) & 0x3F];
strl[j++] = base64_table[(triple >> 0 * 6) & 0x3F];
}
// fill blank
for (int i = 0; i < mod_table[datalen % 3]; i++)
strl[output_length - 1 - i] = '=';
}
}
}

View File

@@ -1,31 +0,0 @@
#pragma once
#include "stdafx.h"
#include <string>
namespace SSMaterializer {
namespace Utils {
constexpr const char g_Unknow[] = "!!UNKNOW!!";
void StdstringPrintf(std::string& strl, const char* format, ...);
void StdstringVPrintf(std::string& strl, const char* format, va_list argptr);
void StdstringGetBase64(std::string& strl, const char* data, size_t datalen);
inline void CopyGuid(std::string& str, CKGUID& guid) {
StdstringPrintf(str, "0x%08X, 0x%08X", guid.d1, guid.d2);
}
inline void CopyCKString(std::string& storage, const char* str) {
storage = str == NULL ? g_Unknow : str;
}
inline void CopyCKParamTypeStr(std::string& strl, CKParameterType ckpt, CKParameterManager* pm) {
if (ckpt != -1) strl = pm->ParameterTypeToName(ckpt);
else strl = g_Unknow;
}
inline void CopyCKClassId(std::string& strl, CK_CLASSID clsid, CKParameterManager* pm) {
CKSTRING ckstr = pm->ParameterGuidToName(pm->ClassIDToGuid(clsid));
strl = ckstr == NULL ? g_Unknow : ckstr;
}
}
}

View File

@@ -1,16 +0,0 @@
#include "virtools_compatible.hpp"
#if defined(VIRTOOLS_50) && defined(VIRTOOLS_STANDALONE)
//#define stdin (__acrt_iob_func(0))
//#define stdout (__acrt_iob_func(1))
//#define stderr (__acrt_iob_func(2))
//
//FILE _iob[] = { *stdin, *stdout, *stderr };
//extern "C" FILE * __cdecl __iob_func(void) { return _iob; }
#endif
//void __declspec(noreturn) FAKE_THROW() {
// throw "Unimplemented function called.";
//}

View File

@@ -1,11 +0,0 @@
#pragma once
#include "stdafx.h"
//void __declspec(noreturn) FAKE_THROW();
#if defined(VIRTOOLS_21)
#define UNIVERSAL_VAR_TYPE void*
#elif defined(VIRTOOLS_25) || defined(VIRTOOLS_35) || defined(VIRTOOLS_40) || defined(VIRTOOLS_50)
#define UNIVERSAL_VAR_TYPE CKVariableManager::Variable::Type
#endif

View File

@@ -1,165 +0,0 @@
#include "vt_menu.hpp"
#include "database.hpp"
#include "doc_export.hpp"
#include "env_export.hpp"
#if defined(VIRTOOLS_PLUGIN)
extern PluginInterface* s_Plugininterface;
CMenu* s_MainMenu = NULL;
void PluginCallback(PluginInfo::CALLBACK_REASON reason, PluginInterface* plugininterface) {
switch (reason) {
case PluginInfo::CR_LOAD:
{
s_Plugininterface = plugininterface;
InitMenu();
UpdateMenu();
}break;
case PluginInfo::CR_UNLOAD:
{
RemoveMenu();
s_Plugininterface = NULL;
}break;
case PluginInfo::CR_NEWCOMPOSITIONNAME:
{
}break;
case PluginInfo::CR_NOTIFICATION:
{
}break;
}
}
void InitMenu() {
if (!s_Plugininterface)
return;
s_MainMenu = s_Plugininterface->AddPluginMenu("SSMaterializer", 20, NULL, (VoidFunc1Param)PluginMenuCallback);
}
void RemoveMenu() {
if (!s_Plugininterface || !s_MainMenu)
return;
s_Plugininterface->RemovePluginMenu(s_MainMenu);
}
void UpdateMenu() {
s_Plugininterface->ClearPluginMenu(s_MainMenu); //clear menu
s_Plugininterface->AddPluginMenuItem(s_MainMenu, 0, "Export Document");
s_Plugininterface->AddPluginMenuItem(s_MainMenu, 1, "Export Environment");
s_Plugininterface->AddPluginMenuItem(s_MainMenu, -1, NULL, TRUE);
s_Plugininterface->AddPluginMenuItem(s_MainMenu, 2, "Report Bug");
s_Plugininterface->AddPluginMenuItem(s_MainMenu, 3, "Plugin Homepage");
s_Plugininterface->UpdatePluginMenu(s_MainMenu); //update menu,always needed when you finished to update the menu
//unless you want the menu not to have Virtools Dev main menu color scheme.
}
void PluginMenuCallback(int commandID) {
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CKContext* ctx = s_Plugininterface->GetCKContext();
//switch mode
#if defined(_RELEASE)
try {
#endif
switch (commandID) {
case 0:
{
//Init file
std::string file;
OpenFileDialog(&file);
if (file.empty())
break;
DeleteFile(file.c_str());
//Init resources
SSMaterializer::Database::DocumentDatabase* db =
new SSMaterializer::Database::DocumentDatabase(file.c_str(), ctx->GetParameterManager());
//iterate item
SSMaterializer::DocumentExporter::IterateScript(ctx, db);
SSMaterializer::DocumentExporter::IterateMessage(ctx, db);
SSMaterializer::DocumentExporter::IterateObj(ctx, db);
//Close all resources
delete db;
ctx->OutputToConsole("[SSMaterializer] Done");
}
break;
case 1:
{
//Init file
std::string file;
OpenFileDialog(&file);
if (file.empty())
break;
DeleteFile(file.c_str());
//Init
SSMaterializer::Database::EnvironmentDatabase* db =
new SSMaterializer::Database::EnvironmentDatabase(file.c_str());
//iterate parameter operation/param
SSMaterializer::EnvironmentExporter::IterateParameterOperation(ctx->GetParameterManager(), db);
SSMaterializer::EnvironmentExporter::IterateParameter(ctx->GetParameterManager(), db);
SSMaterializer::EnvironmentExporter::IterateAttribute(ctx->GetAttributeManager(), db);
SSMaterializer::EnvironmentExporter::IteratePlugin(CKGetPluginManager(), db);
#if !defined(VIRTOOLS_21)
SSMaterializer::EnvironmentExporter::IterateVariable(ctx->GetVariableManager(), db);
#endif
//release all
delete db;
ctx->OutputToConsole("[SSMaterializer] Done");
}
break;
case 2:
ShellExecute(NULL, "open", "https://github.com/yyc12345/SuperScriptMaterializer/issues", NULL, NULL, SW_SHOWNORMAL);
break;
case 3:
ShellExecute(NULL, "open", "https://github.com/yyc12345/SuperScriptMaterializer", NULL, NULL, SW_SHOWNORMAL);
break;
}
#if defined(_RELEASE)
} catch (const std::exception & e) {
std::string errstr;
errstr = "An error occurs, application will exit. Please report to developer with this window and reproduce step.\nError message: ";
errstr += e.what();
AfxMessageBox(errstr.c_str(), MB_OK | MB_ICONSTOP);
exit(1);
}
#endif
}
BOOL OpenFileDialog(std::string* returned_file) {
returned_file->clear();
char* file = (char*)malloc(1024 * sizeof(char));
BOOL status;
OPENFILENAME OpenFileStruct;
ZeroMemory(&OpenFileStruct, sizeof(OPENFILENAME));
OpenFileStruct.lStructSize = sizeof(OPENFILENAME);
OpenFileStruct.lpstrFile = file;
OpenFileStruct.lpstrFile[0] = '\0';
OpenFileStruct.nMaxFile = 1024;
OpenFileStruct.lpstrFilter = "Database file(*.db)\0*.db\0";
OpenFileStruct.lpstrDefExt = "db";
OpenFileStruct.lpstrFileTitle = NULL;
OpenFileStruct.nMaxFileTitle = 0;
OpenFileStruct.lpstrInitialDir = NULL;
OpenFileStruct.Flags = OFN_EXPLORER;
if (status = GetSaveFileName(&OpenFileStruct))
*returned_file = file;
free(file);
return status;
}
#endif

View File

@@ -1,15 +0,0 @@
#pragma once
#if defined(VIRTOOLS_PLUGIN)
#include "stdafx.h"
#include "database.hpp"
void PluginCallback(PluginInfo::CALLBACK_REASON reason, PluginInterface* plugininterface);
void InitMenu();
void RemoveMenu();
void UpdateMenu();
void PluginMenuCallback(int commandID);
BOOL OpenFileDialog(std::string* returned_file);
#endif

View File

@@ -1,107 +0,0 @@
#include "vt_player.hpp"
#include "doc_export.hpp"
#include "env_export.hpp"
#if defined(VIRTOOLS_STANDALONE)
void PlayerMain(const char* virtools_composition, const char* script_db_path, const char* env_db_path) {
printf("Super Script Materializer\n");
printf("Homepage: https://github.com/yyc12345/SuperScriptMaterializer\n");
printf("Report bug: https://github.com/yyc12345/SuperScriptMaterializer/issues\n");
// ====================== Init ck2 engine
#if defined(VIRTOOLS_21)
CommonAssert(LoadLibrary("CK2.dll") != NULL, "Error loading CK2.dll");
#endif
CommonAssert(!CKStartUp(), "CKStartUp Error");
CKPluginManager* pluginManager = CKGetPluginManager();
CommonAssert(pluginManager != NULL, "PluginManager = null");
CommonAssert(pluginManager->ParsePlugins("RenderEngines") > 0, "Error loading RenderEngines");
CommonAssert(pluginManager->ParsePlugins("Managers") > 0, "Error loading Managers");
CommonAssert(pluginManager->ParsePlugins("BuildingBlocks") > 0, "Error loading BuildingBlocks");
CommonAssert(pluginManager->ParsePlugins("Plugins") > 0, "Error loading Plugins");
// ====================== create context and load file
CKContext* context = NULL;
CommonAssert(!CKCreateContext(&context, NULL), "CKCreateContext Error");
CKObjectArray* array = CreateCKObjectArray();
CommonAssert(!context->Load((char*)virtools_composition, array), "CKContext->Load() Error");
#if defined(_RELEASE)
try {
#endif
printf("Parsing %s...\n", virtools_composition);
// ====================== do SSMaterializerDatabase export
// define and Init
scriptDatabase* _script_db = new scriptDatabase();
dbScriptDataStructHelper* _script_helper = new dbScriptDataStructHelper();
envDatabase* _env_db = new envDatabase();
dbEnvDataStructHelper* _env_helper = new dbEnvDataStructHelper();
DeleteFile(script_db_path);
DeleteFile(env_db_path);
_script_db->open(script_db_path);
_script_helper->init(context->GetParameterManager());
_env_db->open(env_db_path);
_env_helper->init();
// export
IterateScript(context, _script_db, _script_helper);
IterateParameterOperation(context->GetParameterManager(), _env_db, _env_helper);
IterateParameter(context->GetParameterManager(), _env_db, _env_helper);
IterateMessage(context->GetMessageManager(), _env_db, _env_helper);
IterateAttribute(context->GetAttributeManager(), _env_db, _env_helper);
IteratePlugin(CKGetPluginManager(), _env_db, _env_helper);
#if !defined(VIRTOOLS_21)
IterateVariable(context->GetVariableManager(), _env_db, _env_helper);
#endif
// free
_script_helper->dispose();
_script_db->close();
_env_helper->dispose();
_env_db->close();
delete _script_helper;
delete _script_db;
delete _env_helper;
delete _env_db;
printf("Done!");
#if defined(_RELEASE)
} catch (const std::exception & e) {
std::string errstr;
errstr = "An error occurs, application will exit. Please report to developer with this window and reproduce step.\nError message: ";
errstr += e.what();
printf("[ERROR] %s", errstr.c_str());
ExitProcess(1);
}
#endif
// ====================== free resources and shutdown engine
DeleteCKObjectArray(array);
context->Reset();
context->ClearAll();
// todo: Virtools 4.0 standalone version throw exception in there, but i don't knwo why
// but it doesn't affect SSMaterializerDatabase export, perhaps
CKCloseContext(context);
CKShutdown();
// todo: Virtools 2.5 standalone version throw exception in there, but i don't knwo why
// but it doesn't affect SSMaterializerDatabase export, perhaps
}
void CommonAssert(BOOL condition, const char* desc) {
if (!condition) {
printf("[ERROR] %s\n", desc);
ExitProcess(1);
}
}
#endif

View File

@@ -1,10 +0,0 @@
#pragma once
#if defined(VIRTOOLS_STANDALONE)
#include "stdafx.h"
#include "database.hpp"
void PlayerMain(const char* virtools_composition, const char* script_db_path, const char* env_db_path);
void CommonAssert(BOOL condition, const char* desc);
#endif

View File

@@ -1,18 +0,0 @@
import locale
class DatabaseType:
SQLite = 0
MySQL = 1
database_type = DatabaseType.SQLite
sqlite_path = "decorated.db"
'''
database_type = DatabaseType.MySQL
mysql_url = "http://yyc.bkt.moe:10000"
mysql_username = "test"
mysql_password = "test"
mysql_database = "test_database"
'''
debug_mode = False

View File

@@ -1,11 +0,0 @@
import CustomConfig
class EmptyDatabase:
def __init__(self):
pass
def CreateDatabase():
return EmptyDatabase()
def CloseDatabase(db):
pass

View File

@@ -1,101 +0,0 @@
import CustomConfig
import Database
from flask import Flask
from flask import g
from flask import render_template
from flask import url_for
from flask import request
from flask import abort
from flask import redirect
app = Flask(__name__)
# =============================================database
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = Database.CreateDatabase()
return db
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
Database.CloseDatabase(db)
# =============================================route
# =========== default
@app.route('/', methods=['GET'])
def handle_nospec():
return redirect(url_for('handle_index'))
# =========== basic pages
@app.route('/index', methods=['GET'])
def handle_index():
return app.send_static_file("html/index.html")
@app.route('/script', methods=['GET'])
def handle_script():
return redirect(url_for('handle_index'))
@app.route('/array', methods=['GET'])
def handle_array():
return redirect(url_for('handle_index'))
@app.route('/environment', methods=['GET'])
def handle_environment():
return redirect(url_for('handle_index'))
@app.route('/help', methods=['GET'])
def handle_help():
return app.send_static_file("html/help.html")
@app.route('/about', methods=['GET'])
def handle_about():
return app.send_static_file("html/about.html")
# =========== viewer
# script and array should have at least 2 items splitted by slash(/)
# the first one is document id and the second one is the real CK_ID of viewing object.
# however, environment do not have this, environment only allow one item, the id of environment.
@app.route('/script/<path:script_path>', methods=['GET'])
def handle_script_viewer(script_path):
# check invalid url
if len(script_path.split('/')) < 2:
return redirect(url_for('handle_index'))
return app.send_static_file("html/viewer_script.html")
@app.route('/array/<path:array_path>', methods=['GET'])
def handle_array_viewer(array_path):
# check invalid url
if len(script_path.split('/')) < 2:
return redirect(url_for('handle_index'))
return app.send_static_file("html/viewer_array.html")
@app.route('/environment/<path:environment_path>', methods=['GET'])
def handle_environment_viewer(environment_path):
# check invalid url
if len(script_path.split('/')) > 1:
return redirect(url_for('handle_index'))
return app.send_static_file("html/viewer_environment.html")
# =========== viewer
@app.route('/api/index/getList', methods=['POST'])
def handle_api_index_getList(scriptPath):
return {
"document": [],
"script": [],
"array": [],
"environment": []
}
# =========== startup
def run():
app.run()

View File

@@ -1,10 +0,0 @@
import ServerCore
import os
import sys
import getopt
import logging
# todo: load db and cfg
# todo: start flask
ServerCore.run()

View File

@@ -1,17 +0,0 @@
table.envOutput {
border: 1px solid black;
}
table.envOutput tr:nth-child(odd) {
background:#cfcfcf;
}
table.envOutput tr:nth-child(2n) {
background:white;
}
table.envOutput tr:nth-child(1) td {
background: blue;
color: white;
border: 1px solid black;
}

View File

@@ -1,16 +0,0 @@
body {
background: silver;
font-size: 1rem;
}
div.simple-menu {
display: flex;
flex-flow: row;
}
div.simple-menu > p {
margin: 5px;
}
h1 {
margin: 0;
}

View File

@@ -1,14 +0,0 @@
/*side panel style*/
div.tabitem-activated {
background: #0000ff;
}
div.tabitem-activated b {
color: white;
}
div.tabitem-deactivated {
background: #ffffff00;
}
div.tabitem-deactivated b {
color: black;
}

View File

@@ -1,114 +0,0 @@
/*navigation style*/
p.hamburger {
margin: 0 5px 0 5px;
padding: 0;
}
/*graph style*/
div.block-target {
position: absolute;
background: green;
}
div.block-b {
position: absolute;
background: yellow;
}
div.block-p {
position: absolute;
background: blue;
}
p.block-text {
position: absolute;
margin: 0;
padding: 0;
font-size: 12px;
color: black;
}
p.block-expandable-text {
position: absolute;
margin: 0;
padding: 0;
font-size: 12px;
color: #5f5f5f;
}
p.block-asstext {
position: absolute;
margin: 0;
padding: 0;
font-size: 9px;
color: white;
}
div.block-body {
position: absolute;
background: #8f8f8f;
border: 1px solid #cfcfcf;
}
div.cell-ptarget {
position: absolute;
background: green;
border: 1px solid #cfcfcf;
}
div.cell-plocal {
position: absolute;
background: #8f8f8f;
border: 1px solid #cfcfcf;
}
div.cell-shortcut {
position: absolute;
background: purple;
border: 1px solid #cfcfcf;
}
div.cell-pio {
position: absolute;
background: blue;
border: 1px solid #cfcfcf;
}
div.cell-bio {
position: absolute;
background: yellow;
border: 1px solid #cfcfcf;
}
text.link-delay {
font-size: 12px;
color: black;
}
/* property list*/
pre.propertyItem {
border: 1px solid black;
border-radius: 2px;
padding: 5px;
background: #3f3f3f;
color: white;
white-space: pre-wrap;
word-wrap: break-word;
}
code.propertyItem {
border: 1px solid black;
border-radius: 2px;
padding: 5px;
margin: 5px;
background: gray;
color: white;
}
div.propertyItem {
margin: 5px;
border: 1px solid gray;
border-radius: 2px;
padding: 5px;
}

View File

@@ -1,39 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>About - SuperScriptMaterializer</title>
<link rel="shortcut icon" type="image/jpg" href="/static/imgs/icon.jpg" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.js"></script>
<script type="text/javascript" src="/static/js/global.js"/></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xp.css@0.3.0/dist/98.css">
<link rel="stylesheet" href="/static/css/global.css">
</head>
<body>
<h1><img src="/static/imgs/icon.jpg" width="64" height="64" style="margin: 0 10px 0 10px;"/>Super Script Materializer</h1>
<p>There are no secret script behind Virtools. Super Script Materializer will destroy all locks and show you the real code.<br />
But Super Script Materializer only show you code. It couldn't analyse the result and touch author's heart and intention. This is your work.<br />
So, let we crack all scripts and destroy close-source illusion.</p>
<p><a href="https://github.com/yyc12345/SuperScriptMaterializer">SuperScriptMaterializer</a>. All codes are under GPLv3.<br />
Web frontend is powered by <a href="https://gulpjs.com/">gulp</a>, <a href="https://jquery.com/">jQuery</a>, <a href="https://www.jsviews.com/">JsRender/JsViews</a> and <a href="https://botoxparty.github.io/XP.css/">98.css</a>.<br />
Web backend is powered by <a href="https://github.com/pallets/flask">Flask</a>.<br />
Ancestor projects: <a href="https://github.com/BearKidsTeam/VirtoolsScriptDeobfuscation">BearKidsTeam/VirtoolsScriptDeobfuscation</a> and <a href="https://github.com/BearKidsTeam/Script-Materializer">BearKidsTeam/Script-Materializer</a>.<br />
Thank <a href="https://github.com/chirs241097">chirs241097</a> and <a href="https://github.com/instr3">2jjy</a>.<br />
Icon is created by <a href="https://github.com/ShadowPower">ShadowPower</a> via diffusion.</p>
<p>Super Script Materializer version: 2.0</p>
<div class="simple-menu">
<p><a href="/index">Hierarchy</a></p>
<p>|</p>
<p><a href="/help">Help</a></p>
<p>|</p>
<p><a href="/about">About</a></p>
</div>
</body>
</html>

View File

@@ -1,173 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Help - SuperScriptMaterializer</title>
<link rel="shortcut icon" type="image/jpg" href="/static/imgs/icon.jpg" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.js"></script>
<script type="text/javascript" src="/static/js/global.js"/></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xp.css@0.3.0/dist/98.css">
<link rel="stylesheet" href="/static/css/global.css">
</head>
<body>
<h1>Help Center</h1>
<div class="simple-menu">
<p><a href="/index">Hierarchy</a></p>
<p>|</p>
<p><a href="/help">Help</a></p>
<p>|</p>
<p><a href="/about">About</a></p>
</div>
<p>This page is help center, providing useful link for some detailed help page. Choose what you want to use and enter corresponding tabs.</p>
<section class="tabs">
<menu role="tablist" aria-label="help-tab">
<button role="tab" aria-selected="true" aria-controls="tab-legend">Legend</button>
<button role="tab" aria-controls="tab-misc1">Misc Help</button>
<button role="tab" aria-controls="tab-misc2">Misc Help2</button>
</menu>
<!-- the tab content -->
<article role="tabpanel" id="tab-legend">
<h2>Layout</h2>
<p>In viewer page, it can be divided into 3 panels:</p>
<table border="1">
<tr style="height: 50px;">
<td style="width: 200px;">Navigation panel</td>
<td style="width: 100px;" rowspan="2">Information & tools panel</td>
</tr>
<tr style="height: 50px;">
<td>Graph panel</td>
</tr>
</table>
<ul>
<li><b>Navigation panel</b>: Display current script's hierarchy. And you can click all layers which located in this panel to jump into it.</li>
<li><b>Information & tools panel</b>: Provide property data, display configuration and some useful tools.</li>
<li><b>Graph panel</b>: Core panel. Display current browsing behavior graph's data. Some legend will be desscribe in the follwing sector.</li>
</ul>
<h2>Graph legend</h2>
<h3>Block</h3>
<div style="background: #7f7f7f; padding: 20px;">
<div style="display: flex; flex-flow: row; align-items: center; margin-top: 10px; margin-bottom: 10px;">
<div style="height: 5px; width: 15px;background: #8f8f8f;border: 1px solid #cfcfcf;"></div>
<div style="margin-left: 10px;">pLocal (including arrtibute) (ParameterLocal abbr.)</div>
</div>
<div style="display: flex; flex-flow: row; align-items: center; margin-top: 10px; margin-bottom: 10px;">
<div style="height: 5px; width: 15px;background: purple;border: 1px solid #cfcfcf;"></div>
<div style="margin-left: 10px;">Shortcut (Only shortcut output)</div>
</div>
<div style="display: flex; flex-flow: row; align-items: center; margin-top: 10px; margin-bottom: 10px;">
<div style="height: 6px; width: 6px;background: yellow;border: 1px solid #cfcfcf;"></div>
<div style="margin-left: 10px;">bIn / bOut (BehaviorIn / BehaviorOut abbr.)</div>
</div>
<div style="display: flex; flex-flow: row; align-items: center; margin-top: 10px; margin-bottom: 10px;">
<div style="height: 6px; width: 6px;background: blue;border: 1px solid #cfcfcf;"></div>
<div style="margin-left: 10px;">pIn / pOut (ParameterIn / ParameterOut abbr.)</div>
</div>
<div style="display: flex; flex-flow: row; align-items: center; margin-top: 10px; margin-bottom: 10px;">
<div style="height: 6px; width: 6px;background: green;border: 1px solid #cfcfcf;"></div>
<div style="margin-left: 10px;">pTarget (ParameterTarget abbr.)</div>
</div>
</div>
<h3>Building block</h3>
<p>Building block (abbr. BB)</p>
<p>All building block can be devided into 2 types: prototype building block and behavior graph</p>
<div style="background: #7f7f7f; padding: 20px; width: 500px;">
<div style="height: 72.0px; width: 104.0px;background: #8f8f8f;border: 1px solid #cfcfcf;position: relative; top: 0; left: 0;">
<div class="block-target" style="height: 6px; width: 6px; top: 0; left: 0;position: absolute;background: green;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 20px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 46px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; bottom: 0; left: 20px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 10px; left: 0;position: absolute;background: yellow;"></div>
<div style="height: 6px; width: 6px; top: 10px; right: 0;position: absolute;background: yellow;"></div>
<div style="height: 6px; width: 6px; top: 36px; right: 0;position: absolute;background: yellow;"></div>
<p style="top: 10px; left: 20px;position: absolute;margin: 0;padding: 0;font-size: 12px;color: black;">Get Cell</p>
<p style="top: 24px; left: 20px;position: absolute; margin: 0;padding: 0;font-size: 9px;color: white;">Get Cell</p>
</div>
</div>
<p>This is a typical prototype building block. Some port are attached into this building block.<br />
pIn and pTarget are at the top, pOut are at the bottom, bIn are on the left, and bOut are on the right.<br />
In the middle of building block, the name of this building block is written in black font, and the name of this building block's prototype is written in white font.</p>
<div style="background: #7f7f7f; padding: 20px; width: 500px;">
<div class="block-body" style="height: 72.0px; width: 196.0px;background: #8f8f8f;border: 1px solid #cfcfcf;position: relative; top: 0; left: 0;">
<div style="height: 6px; width: 6px; top: 0; left: 20px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 46px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 72px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 98px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 124px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 0; left: 150px;position: absolute;background: blue;"></div>
<div style="height: 6px; width: 6px; top: 10px; left: 0;position: absolute;background: yellow;"></div>
<div style="height: 6px; width: 6px; top: 10px; right: 0;position: absolute;background: yellow;"></div>
<div style="height: 6px; width: 6px; top: 36px; right: 0;position: absolute;background: yellow;"></div>
<p style="top: 10px; left: 20px;position: absolute;margin: 0;padding: 0;font-size: 12px;color: black;"><a href="/help/legend">vt2obj</a></p>
<p style="top: 24px; left: 20px;position: absolute; margin: 0;padding: 0;font-size: 9px;color: white;"></p>
</div>
</div>
<p>This is a typical behavior graph. It is very similar to prototype building block.<br />
It don't have the name of prototype. Instead, you can click on the name to see what is inside this graph(jump into this graph).</p>
<h3>Link</h3>
<svg version="1.1" width="500px" height="350px" style="position: relative; top: 0; left: 0;background: #7f7f7f; padding: 20px;">
<line x1="0" y1="20" x2="100" y2="20" stroke="black" stroke-width="1px"></line>
<text x="50" y="20" fill="black" style="font-size: 12px; color: black;">0</text>
<text x="120" y="20" fill="black">bLink (BehaviorLink)</text>
<line x1="0" y1="70" x2="100" y2="70" stroke="blue" stroke-width="1px" stroke-dasharray="5, 1"></line>
<text x="120" y="70" fill="black">pLink (ParameterLink)</text>
<line x1="0" y1="120" x2="100" y2="120" stroke="cyan" stroke-width="1px" stroke-dasharray="5, 1"></line>
<text x="120" y="120" fill="black">eLink (ExportParameterLink)</text>
<line x1="0" y1="170" x2="100" y2="170" stroke="yellow" stroke-width="1px"></line>
<text x="50" y="170" fill="yellow" style="font-size: 12px;">0</text>
<text x="120" y="170" fill="black">Highlight bLink</text>
<line x1="0" y1="220" x2="100" y2="220" stroke="orange" stroke-width="1px" stroke-dasharray="5, 1"></line>
<text x="120" y="220" fill="black">Highlight pLink</text>
<line x1="0" y1="270" x2="100" y2="270" stroke="orangered" stroke-width="1px" stroke-dasharray="5, 1"></line>
<text x="120" y="270" fill="black">Highlight eLink</text>
</svg>
<h3>Operation</h3>
<ul>
<li>You can highlight the associated links by clicking Block or BB, and click again to cancel the highlight.</li>
<li>You can double-click Block or prototoye BB to get the properties associated with it.</li>
<li>You can hover over the Block to view its name and type through tooltip.</li>
</ul>
<h2>Properties</h2>
<p>Properties can be visited in Information & tools panel. It can display the information of the object currently being double-clicked.</p>
<div style="margin: 5px;border: 1px solid gray;border-radius: 2px;padding: 5px; width: 400px;">
<p><code style="border: 1px solid black; border-radius: 2px;padding: 5px;margin: 5px;background: gray;color: white;">S</code><b>Rectangle/Box Mode</b><i>(176)</i></p>
<p>dump.data</p>
<pre style="border: 1px solid black;border-radius: 2px;padding: 5px;background: #3f3f3f;color: white;white-space: pre-wrap;word-wrap: break-word;">0x01, 0x00, 0x00, 0x00</pre>
<p>dump.length</p>
<pre style="border: 1px solid black;border-radius: 2px;padding: 5px;background: #3f3f3f;color: white;white-space: pre-wrap;word-wrap: break-word;">4</pre>
</div>
<p>This is a typical property unit. You may see more than 1 property unit in property list. A property unit may contain more than 1 key-value pair to describe it.<br />
In the first line, the name of the current property unit (actually a pLocal) will be displayed. The number in brackets is CK_ID. If an S is displayed in front of it (as shown in the figure above), then it is also a setting.</p>
</article>
<article role="tabpanel" hidden id="tab-misc1">
<p>No Content</p>
</article>
<article role="tabpanel" hidden id="tab-misc2">
<p>No Content</p>
</article>
</section>
</body>
</html>

View File

@@ -1,32 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Hierarchy - SuperScriptMaterializer</title>
<link rel="shortcut icon" type="image/jpg" href="/static/imgs/icon.jpg" />
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/jquery@3.4.1/dist/jquery.js"></script>
<script type="text/javascript" src="/static/js/global.js"/></script>
<script type="text/javascript" src="/static/js/index.js"/></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xp.css@0.3.0/dist/98.css">
<link rel="stylesheet" href="/static/css/global.css">
<link rel="stylesheet" href="/static/css/index.css">
</head>
<body>
<h1>Hierarchy</h1>
<p>Choose a script to read it.</p>
<p>Generated by SuperScriptMaterializer</p>
<div class="simple-menu">
<p><a href="/index">Hierarchy</a></p>
<p>|</p>
<p><a href="/help">Help</a></p>
<p>|</p>
<p><a href="/about">About</a></p>
</div>
</body>
</html>

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#000000" d="M13,9V3.5L18.5,9M6,2C4.89,2 4,2.89 4,4V20A2,2 0 0,0 6,22H18A2,2 0 0,0 20,20V8L14,2H6Z" />
</svg>

Before

Width:  |  Height:  |  Size: 184 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#000000" d="M18 2H12V9L9.5 7.5L7 9V2H6C4.9 2 4 2.9 4 4V20C4 21.1 4.9 22 6 22H18C19.1 22 20 21.1 20 20V4C20 2.89 19.1 2 18 2M17.68 18.41C17.57 18.5 16.47 19.25 16.05 19.5C15.63 19.79 14 20.72 14.26 18.92C14.89 15.28 16.11 13.12 14.65 14.06C14.27 14.29 14.05 14.43 13.91 14.5C13.78 14.61 13.79 14.6 13.68 14.41S13.53 14.23 13.67 14.13C13.67 14.13 15.9 12.34 16.72 12.28C17.5 12.21 17.31 13.17 17.24 13.61C16.78 15.46 15.94 18.15 16.07 18.54C16.18 18.93 17 18.31 17.44 18C17.44 18 17.5 17.93 17.61 18.05C17.72 18.22 17.83 18.3 17.68 18.41M16.97 11.06C16.4 11.06 15.94 10.6 15.94 10.03C15.94 9.46 16.4 9 16.97 9C17.54 9 18 9.46 18 10.03C18 10.6 17.54 11.06 16.97 11.06Z" />
</svg>

Before

Width:  |  Height:  |  Size: 752 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#000000" d="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" />
</svg>

Before

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#000000" d="M17.8,20C17.4,21.2 16.3,22 15,22H5C3.3,22 2,20.7 2,19V18H5L14.2,18C14.6,19.2 15.7,20 17,20H17.8M19,2H8C6.3,2 5,3.3 5,5V16H16V17C16,17.6 16.4,18 17,18H18V5C18,4.4 18.4,4 19,4C19.6,4 20,4.4 20,5V6H22V5C22,3.3 20.7,2 19,2Z" />
</svg>

Before

Width:  |  Height:  |  Size: 318 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="#000000" d="M5,4H19A2,2 0 0,1 21,6V18A2,2 0 0,1 19,20H5A2,2 0 0,1 3,18V6A2,2 0 0,1 5,4M5,8V12H11V8H5M13,8V12H19V8H13M5,14V18H11V14H5M13,14V18H19V14H13Z" />
</svg>

Before

Width:  |  Height:  |  Size: 238 B

View File

@@ -1,220 +0,0 @@
// ============================= conv 1
function doConv1_I2O() {
var textSp = $("#conv1Input").val().split("\n");
var result = new Array();
for (var index = 0; index < textSp.length; index++) {
var lines = textSp[index];
var successful = true;
var resultCache = new Array();
lineSp = lines.split(',');
var innerIndex = lineSp.length - 1;
for (var forwardIndex = 0; forwardIndex < lineSp.length; forwardIndex++) {
var words = lineSp[forwardIndex];
words = words.trim().toLowerCase();
if (!checkByteUnit(words)) {
resultCache.length = 0;
successful = false;
break;
} else
resultCache[innerIndex] = words;
innerIndex--;
}
if (successful)
result[index] = resultCache.join(", ");
else
result[index] = "";
}
$("#conv1Output").val(result.join("\n"));
}
// ============================= conv 2
function doConv2_I2O() {
var textSp = $("#conv2Input").val().split("\n");
var result = new Array();
for (var index = 0; index < textSp.length; index++) {
var lines = textSp[index];
var successful = true;
var resultCache = "";
lineSp = lines.split(',');
var innerIndex = lineSp.length - 1;
for (var forwardIndex = 0; forwardIndex < lineSp.length; forwardIndex++) {
var words = lineSp[forwardIndex];
words = words.trim().toLowerCase();
if (!checkByteUnit(words)) {
resultCache.length = 0;
successful = false;
break;
} else
resultCache = words.substr(2, 2) + resultCache;
innerIndex--;
}
if (successful)
result[index] = resultCache;
else
result[index] = "";
}
$("#conv2Output").val(result.join("\n"));
}
function doConv2_O2I() {
var textSp = $("#conv2Output").val().split("\n");
var result = new Array();
for (var index = 0; index < textSp.length; index++) {
var lines = textSp[index].toLowerCase();
var resultCache = new Array();
if (!checkHexInput(lines)) {
result[index] = "";
continue;
}
var sectorCount = parseInt(lines.length / 2);
var remainCount = lines.length % 2;
for (var innerIndex = 0; innerIndex < sectorCount; innerIndex++) {
if (innerIndex == 0)
resultCache[innerIndex] = "0x" + lines.slice(-(innerIndex + 1) * 2);
else
resultCache[innerIndex] = "0x" + lines.slice(-(innerIndex + 1) * 2, -innerIndex * 2);
}
if (remainCount != 0)
resultCache[sectorCount] = "0x0" + lines[0];
for (var addedIndex = resultCache.length; addedIndex < 4; addedIndex++) {
resultCache[addedIndex] = "0x00";
}
result[index] = resultCache.join(", ");
}
$("#conv2Input").val(result.join("\n"));
}
// ============================= conv 3
function doConv3_I2O() {
var textSp = $("#conv3Input").val().split("\n");
var result = new Array();
for (var index = 0; index < textSp.length; index++) {
var lines = textSp[index];
var successful = true;
var resultCache = "";
lineSp = lines.split(',');
var innerIndex = lineSp.length - 1;
for (var forwardIndex = 0; forwardIndex < lineSp.length; forwardIndex++) {
var words = lineSp[forwardIndex];
words = words.trim().toLowerCase();
if (!checkByteUnit(words)) {
resultCache.length = 0;
successful = false;
break;
} else
resultCache = words.substr(2, 2) + resultCache;
innerIndex--;
}
if (successful) {
var bigInt = BigInt("0x" + resultCache);
result[index] = bigInt.toString(10);
}
else
result[index] = "";
}
$("#conv3Output").val(result.join("\n"));
}
function doConv3_O2I() {
var textSp = $("#conv3Output").val().split("\n");
var result = new Array();
for (var index = 0; index < textSp.length; index++) {
var declines = textSp[index];
var resultCache = new Array();
if (!checkDecInput(declines)) {
result[index] = "";
continue;
}
var bigInt = BigInt(declines);
var lines = bigInt.toString(16).toLowerCase();
var sectorCount = parseInt(lines.length / 2);
var remainCount = lines.length % 2;
for (var innerIndex = 0; innerIndex < sectorCount; innerIndex++) {
if (innerIndex == 0)
resultCache[innerIndex] = "0x" + lines.slice(-(innerIndex + 1) * 2);
else
resultCache[innerIndex] = "0x" + lines.slice(-(innerIndex + 1) * 2, -innerIndex * 2);
}
if (remainCount != 0)
resultCache[sectorCount] = "0x0" + lines[0];
for (var addedIndex = resultCache.length; addedIndex < 4; addedIndex++) {
resultCache[addedIndex] = "0x00";
}
result[index] = resultCache.join(", ");
}
$("#conv3Input").val(result.join("\n"));
}
// ============================= conv 4
function doConv4_I2O() {
$("#conv4Output").val($("#conv4Input").val().toUpperCase());
}
function doConv4_O2I() {
$("#conv4Input").val($("#conv4Output").val().toLowerCase());
}
// ============================= utils
function checkDecInput(s) {
var legalWords = "0123456789";
if (s.length == 0) return false;
for (var i = 0; i < s.length; i++) {
if (legalWords.indexOf(s[i]) == -1)
return false;
}
return true;
}
function checkHexInput(s) {
var legalWords = "0123456789abcdef";
for (var i = 0; i < s.length; i++) {
if (legalWords.indexOf(s[i]) == -1)
return false;
}
return true;
}
function checkByteUnit(s) {
var legalWords = "0123456789abcdefABCDEF";
if (s.length != 4) return false;
if (s[0] != '0') return false;
if (s[1] != 'x') return false;
if (legalWords.indexOf(s[2]) == -1) return false;
if (legalWords.indexOf(s[3]) == -1) return false;
return true;
}

View File

@@ -1,45 +0,0 @@
function doQuery(fieldIndex, queryTag) {
// collect data
var readyData = {};
$("#queryTable_" + fieldIndex + " tr:not(:first-child)").each(function() {
var isEnabled = $(this).find(":nth-child(1) input").prop("checked");
if (!isEnabled) return;
var fieldName = $(this).find(":nth-child(2)").attr("queryName");
var fieldValue = $(this).find(":nth-child(3) input").val();
readyData[fieldName] = fieldValue;
});
var jsonData = JSON.stringify(readyData);
// raise post
$.post(window.location,
{
tag: queryTag,
data: jsonData
},
function (data, status) {
// remove data
$("#resultTable_" + fieldIndex + " tr:not(:first-child)").remove();
// check
if (!data['status']) {
alert("Fail to query!");
return;
}
// check overflow
if (data['overflow']) $("#resultTableOverflow_" + fieldIndex).show();
else $("#resultTableOverflow_" + fieldIndex).hide();
// insert data
for(var i = 0; i < data['data'].length; i++) {
$("#resultTable_" + fieldIndex).append("<tr></tr>");
for(var j = 0; j < data['data'][i].length; j++) {
$("#resultTable_" + fieldIndex + " tr:last").append("<td></td>");
$("#resultTable_" + fieldIndex + " tr:last td:last").text(data['data'][i][j]);
}
}
});
}

View File

@@ -1,12 +0,0 @@
// tab switcher
$(document).ready(function() {
// References
// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Tab_Role
$('[role="tab"]').click(function() {
$('[aria-selected="true"]').attr('aria-selected', false);
$(this).attr('aria-selected', true);
$('[role="tabpanel"]').attr('hidden', true);
$(`#${$(this).attr('aria-controls')}`).removeAttr('hidden');
});
});

View File

@@ -1,13 +0,0 @@
function tabControlSwitcher(tabcontrolIndex, neededIndex) {
//disable all
$(".tabnavigation_" + tabcontrolIndex).each(function () {
$(this).removeClass("tabitem-activated").addClass("tabitem-deactivated");
});
$(".tabpanel_" + tabcontrolIndex).each(function () {
$(this).hide();
});
// set current
$("#tabnavigation_" + tabcontrolIndex + "_" + neededIndex).removeClass("tabitem-deactivated").addClass("tabitem-activated");
$("#tabpanel_" + tabcontrolIndex + "_" + neededIndex).show();
}

View File

@@ -1,158 +0,0 @@
//=======================================settings
currentSettings = {
"plink": true,
"properties": true,
"highlight": true,
"move": true
};
$(document).ready(function () {
//read settings and apply it
for (var key in currentSettings) {
currentSettings[key] = localstorageAssist_Get("ssm-settings-" + key, "true") == "true";
if (currentSettings[key]) $("#sidepanel-display-" + key).prop("checked", true);
else $("#sidepanel-display-" + key).removeProp("checked");
}
//additional settings
if (!currentSettings["plink"]) {
$(".link-elink").hide();
$(".link-plink").hide();
}
// read sidepanel display property
var sidepanelDisplay = localstorageAssist_Get("ssm-settings-sidepanelDisplay", "true") == "true";
if (sidepanelDisplay){
$("#sidepanelContainer").show();
$("#sidepanelToggle").text(">>>");
} else {
$("#sidepanelContainer").hide();
$("#sidepanelToggle").text("<<<");
}
});
function settingChange(target) {
newValue = $("#sidepanel-display-" + target).prop("checked");
currentSettings[target] = newValue;
localstorageAssist_Set("ssm-settings-" + target, newValue);
if (target == "plink") {
if (currentSettings["plink"]) {
$(".link-elink").show();
$(".link-plink").show();
} else {
$(".link-elink").hide();
$(".link-plink").hide();
}
}
}
function sidepanelDisplayChange() {
$("#sidepanelContainer").toggle();
if ($("#sidepanelContainer").is(":hidden")) {
$("#sidepanelToggle").text("<<<");
localstorageAssist_Set("ssm-settings-sidepanelDisplay", false)
} else {
$("#sidepanelToggle").text(">>>");
localstorageAssist_Set("ssm-settings-sidepanelDisplay", true)
}
}
function localstorageAssist_Get(index, defaultValue) {
var cache = localStorage.getItem(index);
if (cache == null) {
localstorageAssist_Set(index, defaultValue);
return defaultValue;
} else return cache;
}
function localstorageAssist_Set(index, value) {
localStorage.setItem(index, value);
}
//=======================================internal event
previousHighlight = "";
function highlightLink(target) {
realTarget = ".target" + target;
if (previousHighlight != "") {
//need restore
$(previousHighlight).each(function () {
if ($(this).hasClass("link-blink")) {
$(this).attr("stroke", "black");
}
if ($(this).hasClass("link-blinkDelay")) {
$(this).attr("fill", "black");
}
if ($(this).hasClass("link-plink")) {
$(this).attr("stroke", "blue");
}
if ($(this).hasClass("link-elink")) {
$(this).attr("stroke", "cyan");
}
});
}
// double one-click, only cancel highlight and don't apply any hightlight
// or user disable hightlight
if ((realTarget == previousHighlight) || !currentSettings["highlight"]) {
previousHighlight = "";
} else {
//apply new highlight
$(realTarget).each(function () {
if ($(this).hasClass("link-blink")) {
$(this).attr("stroke", "yellow");
}
if ($(this).hasClass("link-blinkDelay")) {
$(this).attr("fill", "yellow");
}
if ($(this).hasClass("link-plink")) {
$(this).attr("stroke", "orange");
}
if ($(this).hasClass("link-elink")) {
$(this).attr("stroke", "orangered");
}
});
previousHighlight = realTarget;
}
//cancel event seperate
event.stopPropagation();
}
// type = 0: call from cell
// type = 1: call from bb
function queryInfo(type, obj) {
// confirm user enable this function
if (!currentSettings["properties"])
return;
$.post(window.location,
{
operation: "info",
tag: type,
target: obj
},
function (data, status) {
//set target
$("#sidepanel-properties-target b").text(obj);
//set data
$("#sidepanel-properties-container").empty();
for (var key in data) {
$("#sidepanel-properties-container").append("<div class=\"propertyItem\"></div>");
var box = $("#sidepanel-properties-container div:last");
if (data[key]["is_setting"])
$(box).append("<p><code class=\"propertyItem\">S</code><b></b><i></i></p>");
else
$(box).append("<p><b></b><i></i></p>");
$(box).find("p b").text(data[key]["name"]);
$(box).find("p i").text("(" + key + ")");
for (var i = 0; i < data[key]['data'].length; i++) {
$(box).append("<p></p><pre class=\"propertyItem\"></pre>");
$(box).find("p:last").text(data[key]['data'][i][0]);
$(box).find("pre:last").text(data[key]['data'][i][1]);
}
}
});
}

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>About Super Script Materializer</title>
</head>
<body>
<h1><img src="{{ static_icon }}" width="64" height="64" style="margin: 0 10px 0 10px;"/>Super Script Materializer</h1>
<p>There are no secret script behind Virtools. Super Script Materializer will destroy all locks and show you the real code.<br />
But Super Script Materializer only show you code. It couldn't analyse the result and touch author's heart and intention. This is your work.<br />
So, let we crack all scripts and destroy close-source illusion.</p>
<br />
<p><a href="https://github.com/yyc12345/SuperScriptMaterializer">SuperScriptMaterializer</a>. All codes are under GPLv3.<br />
Web interface is powered by <a href="https://github.com/pallets/flask">Flask</a>.<br />
Ancestor projects: <a href="https://github.com/BearKidsTeam/VirtoolsScriptDeobfuscation">BearKidsTeam/VirtoolsScriptDeobfuscation</a> and <a href="https://github.com/BearKidsTeam/Script-Materializer">BearKidsTeam/Script-Materializer</a>.<br />
Thank <a href="https://github.com/chirs241097">chirs241097</a> and <a href="https://github.com/instr3">2jjy</a>.</p>
<br />
<p>Current Super Script Materializer version: 1.0</p>
</body>
</html>

View File

@@ -1,31 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Super Script Viewer Help</title>
</head>
<body>
<h1>Super Script Viewer Help</h1>
<p>This page is help center, providing useful link for some detailed help page. Choose what you want to use and enter corresponding page.</p>
<br />
<br />
<h2>Converter</h2>
<ul>
<li><a href="/help/converter">Converter</a>: The page containing converter which can convert the data with various style for some convenient operations.</li>
</ul>
<h2>Environment database query</h2>
<ul>
<li><a href="/help/env">Environment data query</a>: The page which can query environment data.</li>
</ul>
<h2>Viewer legend</h2>
<ul>
<li><a href="/help/legend">Viewer legend</a>: The page which introduce how to use viewer page.</li>
</ul>
<br />
<br />
<!-- todo: finish this-->
</body>
</html>

View File

@@ -1,133 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Help - Converter</title>
<link rel="stylesheet" href="{{tabcontrol_css}}">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
<script src="{{tabcontrol_js}}"></script>
<script src="{{converter_js}}"></script>
</head>
<body>
<h1>Converter</h1>
<p>This page provide some useful converter for your decoding work.</p>
<br />
<div style="display: flex; flex-flow: row; height: 30px; width: 100%; margin: 0; padding: 0; border-bottom: 1px solid black;">
<div id="tabnavigation_1_1" class="tabnavigation_1 tabitem-activated" style="height: 100%; padding-left: 20px; padding-right: 20px;" onclick="tabControlSwitcher(1, 1);"><b>Reverse C style byte array</b></div>
<div id="tabnavigation_1_2" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; padding-left: 20px; padding-right: 20px;" onclick="tabControlSwitcher(1, 2);"><b>C style byte array to HEX</b></div>
<div id="tabnavigation_1_3" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; padding-left: 20px; padding-right: 20px;" onclick="tabControlSwitcher(1, 3);"><b>C style byte array to DEC</b></div>
<div id="tabnavigation_1_4" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; padding-left: 20px; padding-right: 20px;" onclick="tabControlSwitcher(1, 4);"><b>Lowcase upcase converter</b></div>
</div>
<div id="tabpanel_1_1" class="tabpanel_1">
<p>This converter will reverse your inputed C style byte array. Actually, it take responsibility for the convert between big-endian and little-endian.<br />
Typical and legal input just like this: <code>0x00, 0xBb, 0xff, 0xFF</code><br />
Support multi-input. Use line break to split each input.</p>
<table>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv1Input" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
<tr>
<td align="left">Input</td>
<th colspan="2">&nbsp;</th>
</tr>
<tr>
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv1_I2O();">v</button></td>
<td style="width: 150px;">&nbsp;</td>
<td style="width: 100px;" align="right">&nbsp;</td>
</tr>
<tr>
<th colspan="2">&nbsp;</th>
<td align="right">Output</td>
</tr>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv1Output" style="width: 100%; height: 100%; resize: none;" readonly="true"></textarea></th>
</tr>
</table>
</div>
<div id="tabpanel_1_2" class="tabpanel_1" style="display: none;">
<p>This converter will converte provided C style byte array into HEX number. It is double interactive.<br />
Acceptable byte array should follow little-endian format.<br />
Support multi-input. Use line break to split each input.</p>
<table>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv2Input" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
<tr>
<td align="left">Byte array</td>
<th colspan="2">&nbsp;</th>
</tr>
<tr>
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv2_I2O();">v</button></td>
<td style="width: 150px;">&nbsp;</td>
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv2_O2I();">^</button></td>
</tr>
<tr>
<th colspan="2">&nbsp;</th>
<td align="right">HEX number</td>
</tr>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv2Output" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
</table>
</div>
<div id="tabpanel_1_3" class="tabpanel_1" style="display: none;">
<p>This converter will converte provided C style byte array into DEC number. It is double interactive.<br />
Acceptable byte array should follow little-endian format.<br />
Support multi-input. Use line break to split each input.</p>
<table>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv3Input" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
<tr>
<td align="left">Byte array</td>
<th colspan="2">&nbsp;</th>
</tr>
<tr>
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv3_I2O();">v</button></td>
<td style="width: 150px;">&nbsp;</td>
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv3_O2I();">^</button></td>
</tr>
<tr>
<th colspan="2">&nbsp;</th>
<td align="right">DEC number</td>
</tr>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv3Output" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
</table>
</div>
<div id="tabpanel_1_4" class="tabpanel_1" style="display: none;">
<p>This converter will provide the convert between lowcase and upcase string. It is double interactive.</p>
<table>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv4Input" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
<tr>
<td align="left">Lowcase</td>
<th colspan="2">&nbsp;</th>
</tr>
<tr>
<td style="width: 100px;" align="left"><button style="width: 50px;" onclick="doConv4_I2O();">v</button></td>
<td style="width: 150px;">&nbsp;</td>
<td style="width: 100px;" align="right"><button style="width: 50px;" onclick="doConv4_O2I();">^</button></td>
</tr>
<tr>
<th colspan="2">&nbsp;</th>
<td align="right">Upcase</td>
</tr>
<tr>
<th colspan="3" style="height: 150px;"><textarea id="conv4Output" style="width: 100%; height: 100%; resize: none;"></textarea></th>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -1,65 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Help - Environment data query</title>
<link rel="stylesheet" href="{{tabcontrol_css}}">
<link rel="stylesheet" href="{{env_css}}">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
<script src="{{tabcontrol_js}}"></script>
<script src="{{env_js}}"></script>
</head>
<body>
<h1>Environment data query</h1>
<p>This page can query environment data.</p>
<br />
<div style="display: flex; flex-flow: row; height: 30px; width: 100%; margin: 0; padding: 0; border-bottom: 1px solid black;">
{% for item in database_data %}
<div id="tabnavigation_1_{{ loop.index }}" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; padding-left: 20px; padding-right: 20px;" onclick="tabControlSwitcher(1, {{ loop.index }});"><b>{{ item.name }}</b></div>
{% endfor %}
</div>
{% for item in database_data %}
<div id="tabpanel_1_{{ loop.index }}" class="tabpanel_1" style="display: none;">
<p>Query field:</p>
<table id="queryTable_{{ loop.index }}" border="1" cellspacing="0" cellpadding="5" style="margin: 10px;">
<tr>
<td><b>Use this</b></td>
<td><b>Field name</b></td>
<td style="width: 150px;"><b>Value</b></td>
<td><b>Example</b></td>
<td><b>Description</b></td>
</tr>
{% for innerItem in item.data %}
<tr>
<td><input type="checkbox" value="1"></input></td>
<td queryName="{{ innerItem[0]|e }}">{{ innerItem[0]|e }}</td>
<td><input type="text"></input></td>
<td>{{ innerItem[1]|e }}</td>
<td>{{ innerItem[2]|e }}</td>
</tr>
{% endfor %}
</table>
<button style="padding: 5px;" onclick="doQuery({{ loop.index }}, &quot;{{ item.queryKey }}&quot;);">Query</button>
<p>Query result:</p>
<p id="resultTableOverflow_{{ loop.index }}" style="color: red; display: none;">The count of query result is more than 100 items(Only the first 100 items will be shown). Please give more limitation.</p>
<table id="resultTable_{{ loop.index }}" class="envOutput" cellspacing="0" cellpadding="5" style="margin: 10px;">
<tr>
{% for innerItem in item.data %}
<td>{{ innerItem[0]|e }}</td>
{% endfor %}
</tr>
</table>
</div>
{% endfor %}
</body>
</html>

View File

@@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Help - Viewer legend</title>
</head>
<body>
<h1>Viewer legend</h1>
<p>This page introduce how to use viewer page.</p>
<br />
</body>
</html>

View File

@@ -1,8 +0,0 @@
{% for key, value in scripts.items() %}
<h2>{{ key|e }}</h2>
<ol>
{% for i in value %}
<li><a href="{{ "/viewer/%s"|format(i.id) }}">{{ i.name }}</a></li>
{% endfor %}
</ol>
{% endfor %}

View File

@@ -1,126 +0,0 @@
<!DOCTYPE html>
<html style="height: 100%; margin: 0; padding: 0;">
<head>
<meta charset="utf-8">
<title>Script Viewer</title>
<link rel="stylesheet" href="{{viewer_css}}">
<link rel="stylesheet" href="{{tabcontrol_css}}">
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.0/dist/jquery.min.js"></script>
<script src="{{viewer_js}}"></script>
<script src="{{tabcontrol_js}}"></script>
</head>
<body style="display: flex; flex-flow: row; height: 100%; width: 100%; margin: 0; padding: 0;">
<div style="display: flex; flex-flow: column; height: 100%; width: 100%; margin: 0; padding: 0;">
<div style="display: flex; flex-flow: row; width: 100%;">
<div id="hamburgerMenu" style="display: flex; background: #cfcfcf; flex-flow: row; width: 100%; height: 50px; overflow: scroll;">
<p class="hamburger"><a href="/index"><b>Script Hierarchy</b></a></p>
{% for i in hamburgerHistory %}
<p class="hamburger">&gt;&gt;</p>
<p class="hamburger"><a href="{{ "/viewer%s"|format(i.path) }}">{{ i.name|e }}</a></p>
{% endfor %}
<p class="hamburger">&gt;&gt;</p>
<p class="hamburger"><b>{{ hamburgerCurrent|e }}</b></p>
</div>
<button id="sidepanelToggle" style="width: 50px;" title="Toggle sidepanel display" onclick="sidepanelDisplayChange();"></button>
</div>
<div id="graphContainer" style="background: #7f7f7f; width: 100%; height: 100%; overflow: scroll; position: relative;">
<div>
{# blocks content #}
{% for i in blocks %}
<div class="block-body" style="height: {{ i[12] }}px; width: {{ i[11] }}px; top: {{ i[10] }}px; left: {{ i[9] }}px;" ondblclick="queryInfo(1,{{ i[1] }});" onclick="highlightLink({{ i[1] }});">
{% if i[4] != '{}' %}
<div class="block-target" title="{{ "Name: %s\nType: %s"|format(*pinDecoder2(i[4])) }}" style="height: 6px; width: 6px; top: 0; left: 0;" onclick="highlightLink({{ pinDecoder(i[4]).id }});"></div>
{% endif %}
{% for pin in pinDecoder(i[5]) %}
<div class="block-p" title="{{ "Name: %s\nType: %s"|format(pin.name, pin.type) }}" style="height: 6px; width: 6px; top: 0; left: {{ 20 + loop.index0 * ( 6 + 20) }}px;" onclick="highlightLink({{ pin.id }});"></div>
{% endfor %}
{% for pout in pinDecoder(i[6]) %}
<div class="block-p" title="{{ "Name: %s\nType: %s"|format(pout.name, pout.type) }}" style="height: 6px; width: 6px; bottom: 0; left: {{ 20 + loop.index0 * ( 6 + 20) }}px;" onclick="highlightLink({{ pout.id }});"></div>
{% endfor %}
{% for bin in pinDecoder(i[7]) %}
<div class="block-b" title="{{ "Name: %s\nType: %s"|format(bin.name, bin.type) }}" style="height: 6px; width: 6px; top: {{ 10 + loop.index0 * ( 6 + 20) }}px; left: 0;" onclick="highlightLink({{ bin.id }});"></div>
{% endfor %}
{% for bout in pinDecoder(i[8]) %}
<div class="block-b" title="{{ "Name: %s\nType: %s"|format(bout.name, bout.type) }}" style="height: 6px; width: 6px; top: {{ 10 + loop.index0 * ( 6 + 20) }}px; right: 0;" onclick="highlightLink({{ bout.id }});"></div>
{% endfor %}
{% if i[13] != -1 %}
<p class="block-expandable-text" style="top: 10px; left: 20px;"><a href="{{ "/viewer/%s/%s"|format(currentPath, i[13]) }}">{{ i[2]|e }}</a></p>
{% else %}
<p class="block-text" style="top: 10px; left: 20px;">{{ i[2]|e }}</p>
{% endif %}
<p class="block-asstext" style="top: 24px; left: 20px;">{{ i[3]|e }}</p>
</div>
{% endfor %}
{# cells content #}
{% for i in cells %}
<div class="{% if i[6] == 0 %}cell-plocal{% elif i[6] == 1 %}cell-shortcut{% elif i[6] == 2 %}cell-pio{% elif i[6] == 3 %}cell-bio{% else %}cell-ptarget{% endif %}"
style="height: {% if i[6] == 2 or i[6] == 3 %}6{% else %}5{% endif %}px; width: {% if i[6] == 2 or i[6] == 3 %}6{% else %}15{% endif %}px; top: {{ i[5] }}px; left: {{ i[4] }}px;"
title="{{ "Name: %s\nType: %s"|format(i[2], i[3]) }}" ondblclick="queryInfo(0,{{ i[1] }});" onclick="highlightLink({{ i[1] }});"></div>
{% endfor %}
<svg version="1.1" width="{{ gWidth }}px" height="{{ gHeight }}px" style="position: absolute; top: 0; left: 0;pointer-events: none;">
{# links content #}
{% for i in links %}
{% if i[1] == -2 %}
<line class="link-elink target{{ i[2] }} target{{ i[3] }} target{{ i[4] }} target{{ i[5] }}" x1="{{ i[10] }}" y1="{{ i[11] }}" x2="{{ i[12] }}" y2="{{ i[13] }}" stroke="cyan" stroke-width="1px" stroke-dasharray="5, 1"></line>
{% elif i[1] == -1 %}
<line class="link-plink target{{ i[2] }} target{{ i[3] }} target{{ i[4] }} target{{ i[5] }}" x1="{{ i[10] }}" y1="{{ i[11] }}" x2="{{ i[12] }}" y2="{{ i[13] }}" stroke="blue" stroke-width="1px" stroke-dasharray="5, 1"></line>
{% else %}
<line class="link-blink target{{ i[2] }} target{{ i[3] }} target{{ i[4] }} target{{ i[5] }}" x1="{{ i[10] }}" y1="{{ i[11] }}" x2="{{ i[12] }}" y2="{{ i[13] }}" stroke="black" stroke-width="1px"></line>
<text class="link-blinkDelay target{{ i[2] }} target{{ i[3] }} link-delay target{{ i[4] }} target{{ i[5] }}" x="{{ (i[10] + i[12]) / 2 }}" y="{{ (i[11] + i[13]) / 2 }}" fill="black">{{ i[1] }}</text>
{% endif %}
{% endfor %}
</svg>
</div>
</div>
</div>
<div id="sidepanelContainer" style="display: flex; flex-flow: column; background: #cfcfcf; height: 100%; width: 25%; margin: 0; padding: 0; border-left: 1px solid black;">
<div style="display: flex; flex-flow: row; height: 30px; width: 100%; margin: 0; padding: 0; border-bottom: 1px solid black;">
<div id="tabnavigation_1_1" class="tabnavigation_1 tabitem-activated" style="height: 100%; width: 33.33%; text-align: center;" onclick="tabControlSwitcher(1, 1);"><b style="margin: 0;">Properties</b></div>
<div id="tabnavigation_1_2" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; width: 33.33%; text-align: center;" onclick="tabControlSwitcher(1, 2);"><b style="margin: 0;">Display</b></div>
<div id="tabnavigation_1_3" class="tabnavigation_1 tabitem-deactivated" style="height: 100%; width: 33.33%; text-align: center;" onclick="tabControlSwitcher(1, 3);"><b style="margin: 0;">Tools</b></div>
</div>
<div id="tabpanel_1_1" class="tabpanel_1" style="display: flex; flex-flow: column;width: 100%; height: 100%; display: flex; flex-flow: column; overflow-x: hidden;">
<p style="margin: 5px;" id="sidepanel-properties-target">Selected target: <b></b></p>
<div id="sidepanel-properties-container" style="width: 100%; height: 100%; overflow: scroll;">
</div>
</div>
<div id="tabpanel_1_2" class="tabpanel_1" id="sidepanel-display" style="width: 100%; height: 100%; display: flex; flex-flow: column; overflow: scroll; overflow-x: hidden; display: none;">
<p style="margin: 5px;">Render:<br />
<input type="checkbox" id="sidepanel-display-plink" value="1" onclick="settingChange(&quot;plink&quot;);">Show pLink and eLink</input>
</p>
<p style="margin: 5px;">Action:<br />
<input type="checkbox" id="sidepanel-display-properties" value="1" onclick="settingChange(&quot;properties&quot;);">Interactive property inspector</input><br />
<input type="checkbox" id="sidepanel-display-highlight" value="1" onclick="settingChange(&quot;highlight&quot;);">Highlight focused object</input><br />
<input type="checkbox" id="sidepanel-display-move" value="1" onclick="settingChange(&quot;move&quot;);" disabled="true">Move objects</input>
</p>
</div>
<div id="tabpanel_1_3" class="tabpanel_1" style="width: 100%; height: 100%; display: flex; flex-flow: column; overflow: scroll; overflow-x: hidden; display: none;">
<p style="margin: 5px;">Object finder:<br />
<input type="text" id="sidepanel-tools-objfinder" disabled="true"></input><br />
<button style="height: 30px; margin: 10px 0 10px 0;" disabled="true">Find</button>
</p>
<p style="margin: 5px;">Misc:<br />
<button style="height: 30px; margin: 10px 0 10px 0;" onclick="window.open(&quot;/help&quot;);">Help</button><br />
<button style="height: 30px; margin: 10px 0 10px 0;" onclick="window.open(&quot;/about&quot;);">About</button>
</p>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,24 @@
# Check Windows platform
if (NOT WIN32)
message(FATAL_ERROR "VirtoolsSchematicWeaver::Materializer only supports Windows platform.")
endif ()
# Check MSVC toolchain
if (NOT MSVC)
message(FATAL_ERROR "VirtoolsSchematicWeaver::Materializer only supports MSVC build toolchain.")
endif ()
# Check architecture
if (NOT CMAKE_SIZEOF_VOID_P EQUAL 4)
message(FATAL_ERROR "VirtoolsSchematicWeaver::Materializer only supports 32-bit platform.")
endif ()
# Check build type
set(VSW_MATERIALIZER_BUILD_TYPES
"plugin" "standalone"
)
if (VSW_MATERIALIZER_BUILD_TYPE IN_LIST VSW_MATERIALIZER_BUILD_TYPES)
message( "VirtoolsSchematicWeaver::Materializer build type: ${VSW_MATERIALIZER_BUILD_TYPE}")
else ()
message(FATAL_ERROR
"VirtoolsSchematicWeaver::Materializer do not have correct type."
"Please assign a legal value (\"plugin\" or \"standalone\") to VSW_MATERIALIZER_BUILD_TYPE."
)
endif ()

View File

View File

@@ -0,0 +1,35 @@
# ========== Check Variables ==========
# Check Virtools version variable
set(SPECIAL_VIRTOOLS_VERSIONS
"21"
)
set(LEGACY_VIRTOOLS_VERSIONS
"25"
"30"
"35"
"40"
"50"
)
if (VIRTOOLS_VERSION IN_LIST SPECIAL_VIRTOOLS_VERSIONS)
message(
"Specified Virtools version: ${VIRTOOLS_VERSION}."
"Please note in this verions, your provided Virtools root path must be the root of GitHub repository: doyaGu/Virtools-SDK-2.1"
)
elseif (VIRTOOLS_VERSION IN_LIST LEGACY_VIRTOOLS_VERSIONS)
message("Specified Virtools version: ${VIRTOOLS_VERSION}.")
else ()
message(FATAL_ERROR
"You must set VIRTOOLS_VERSION variable to specify the version of your target Virtools before configurating this project."
"The valid Virtools version are 21, 25, 30, 35, 40, 50."
)
endif ()
# Check Virtools path variable
if (NOT DEFINED VIRTOOLS_PATH)
message(FATAL_ERROR
"You must set VIRTOOLS_PATH variable to specify the root folder of Virtools before configurating this project."
"Please note this path is different when you picking Virtools 2.1 version."
)
endif()
# ========== Import library ==========

View File

@@ -0,0 +1,10 @@
# Check YYCC path variable
if (NOT DEFINED YYCC_PATH)
message(FATAL_ERROR "You must set YYCC_PATH variable to one of CMake distribution of YYCC installation path.")
endif()
# Find YYCC library
find_package(YYCCommonplace REQUIRED
HINTS ${YYCC_PATH} NO_DEFAULT_PATH
)

44
decorator/CMakeLists.txt Normal file
View File

@@ -0,0 +1,44 @@
# Create executable
add_executable(VSWDecorator "")
# Setup source files
target_sources(VSWDecorator
PRIVATE
# Sources
main.cpp
)
# Setup header files
target_sources(VSWDecorator
PUBLIC
FILE_SET HEADERS
FILES
# Headers
)
# Setup header infomations
target_include_directories(VSWDecorator
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
# Setup C++ standard
set_target_properties(VSWDecorator
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# MSVC specific correction
target_compile_definitions(VSWDecorator
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
# Order build as UTF-8 in MSVC
target_compile_options(VSWDecorator
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install binary
install(TARGETS VSWDecorator
CONFIGURATIONS Release
RUNTIME DESTINATION ${VSW_INSTALL_BIN_PATH}
)

0
decorator/main.cpp Normal file
View File

View File

@@ -1,65 +0,0 @@
# 编译
本文档将指导您编译或调试`SuperScriptMaterializer`以及对`SuperScriptViewer`的编译。
## SuperScriptMaterializer
### 需求
- Visual Studio 2010即VC++ v100的工具集不能使用Virtools 2015及以上版本进行编译在编译Virtools 5.0 Standalone版本的时候亲测会出错且无法解决但对于其他版本您可以尝试使用高版本的工具集进行编译
- Virtools SDK 或 Ballance Mod Loader如果以Virtools 2.1作为目标)
- SQlite SDK
- Python 3.x
### 编译之前
编译之前对于SQLite SDK您可以从[sqlite.org](http://www.sqlite.org/)下载然后使用Visual C++的工具集执行`LIB /DEF:sqlite3.def /machine:IX86`以获取可以用于编译的文件。
然后您需要先进入项目根目录下在此处打开终端我们首先需要生成编译的参数。自上一个版本以来我们将编译时需要的一些参数全部转为Visual Studio可识别的宏定义在独立的`Virtools.props`中,此步操作便是生成这个文件,以确定编译文件的相关参数。
按如下格式运行指令:
```
python3 mk_materializer_cfg.py [plugin|standalone] [21|25|35|40|50] [virtools_root_path] [sqlite_header] [sqlite_lib] [bml path]
```
每一项参数的含义:
* `[plugin|standalone]`:编译为插件还是独立程序
* `[21|25|35|40|50]`Virtools版本
* `[virtools_root_path]`Virtools Dev的根目录用于Virtools SDK的头文件链接库的寻找也决定程序编译后的输出位置
* `[sqlite_header]`SQlite头文件路径通常来说指向SQlite头文件所在的文件夹
* `[sqlite_lib]`SQlite链接库的路径通常来说是指向`sqlite3.lib`的路径
* `[bml path]`BML的路径只有在以Virtools 2.1为目标编译时才有用
以下是一些指令示例:
```
python3 .\mk_materializer_cfg.py plugin 50 "E:\Virtools\Virtools Dev 5.0" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py standalone 50 "E:\Virtools\Virtools Dev 5.0" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py plugin 40 "E:\Virtools\Virtools Dev 4.0" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py standalone 40 "E:\Virtools\Virtools Dev 4.0" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py plugin 35 "E:\Virtools\Virtools Dev 3.5" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py standalone 35 "E:\Virtools\Virtools Dev 3.5" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py standalone 25 "E:\Virtools\Virtools Dev 2.5" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
python3 .\mk_materializer_cfg.py standalone 21 "E:\Virtools\Virtools Dev 2.1" "D:\CppLib\SQLite\sqlite-amalgamation-3310100" "D:\CppLib\SQLite\sqlite-dll-win32-x86-3310100" sqlite3.lib "D:\BallanceModLoader"
```
### 编译
使用`Visual Studio`打开`SuperScriptMaterializer.sln`,选择`SuperScriptMaterializer`工程。然后选择编译模式Debug或Release然后编译即可基本上只要配置无误编译会很快完成
## SuperScriptViewer
### 需求
* Node.js
* gulp
* gulp插件待补充
### 编译
`SuperScriptViewer`本身分为2个部分由Python配合Flask所写的后端以及前端。后端无需编译而前端需要通过**gulp**进行操作,以减少文档本身的大小,进而减小传输开销。
编译的方法很简单,在`Viewer`目录下执行`gulp xxxx`即可让gulp自动完成相关操作。

View File

@@ -1,27 +0,0 @@
# 部署
本文档将指导您部署属于您的`SuperScriptMaterializer`。它可以让您摆脱Virtools的限制在所有平台上都可以浏览到Virtools的脚本。您需要先了解README中标准的操作方式然后我们会根据部署的一些特殊性对标准步骤进行修改。
## 导出脚本
首先我们需要使用`SuperScriptMaterializer`将我们需要查看的脚本导出。众所周知Virtools各个版本之间的兼容性很差为一个版本的所作的文档可能在另一个版本中就无法打开或者是丢失相关的Building Block因此首先您需要根据您所需要查看的Virtools文件的对应版本来选取合适版本的插件这样可以获得更好的导出效果因为一旦文档中出现一些Building Block丢失之类的错误那么Virtools会让一些本可读的字段变成完全不可读的Binary格式。这也是我们的`Materializer`提供如此多版本选项的原因,为的是让每一份可能的文档都可以被正确地加载。
此外如果您遇到了NMS文件那么您可能需要使用Virtools创作环境并配合插件模式的`Materializer`来导出通过新建一个随意物件然后让脚本加载在其上进而导出。您可能无法在NMS文件上使用独立模式的`Materializer`因为它没有办法识别NMS文件。
当然您如果遇到了很多文件的情况您可以将需要的文件放在一起然后编写一个Shell脚本然后使用独立模式的`Materializer`来进行批量导出如果可以的话。这是一个针对Ballance游戏所有文件的脚本导出的Shell脚本和其生成器的示例可供您参考。
// todo: 贴上链接
如果您有来自不同Virtools版本您需要分别用对应的导出器进行导出然后将他们整理归类以供下一级的输入。无需担心不同版本的Virtools导出会导致错误`Decorator`会正确处理它们。
## 分析脚本
您需要准备好`SuperScriptDecorator`,和一份`import.txt`。正如标准操作方式中所言,您需要把需要综合的所有的导出数据库及各个文件的名字写入`import.txt`。我的操作是在上一步生成批处理的时候一并生成`import.txt`,因为它们之间联系很紧密。当然,您完全手写`import.txt`也是可以的。在完成之后,与标准操作方式内所述一致,直接运行即可。分析脚本的时间与您输入的脚本的数量和脚本的复杂度相关。
## 发布脚本
分析脚本完成后,我们就该将数据输入到`SuperScriptViewer`中了。与普通运行方式不同我们需要以非调试模式启动Flask部署后端并同时完成前端部署。您可以参阅[Flask部署文档](https://flask.palletsprojects.com/en/2.0.x/deploying/)来根据您的情况来进行选择。
我所作的Ballance脚本展示网页使用Gunicorn部署指令是`gunicorn ServerCore:app`,其中唯一需要注意的是`ServerCore:app`这个程序入口点在您选择不同于我的部署方式时这个入口点将不会改变。与此同时我使用Nginx做了反向代理具体配置可参考这里
// todo: 贴上链接

View File

@@ -1,480 +0,0 @@
# 开发帮助
此文档将叙述一些开发SuperScriptMaterializer中需要被记忆的一些原则。
# 可能的连线
该程序中最重要的事情之一是生成链接而最困难的是pLink。 下图显示了将在此程序中分析的所有pLink情况。
```
+--------------+ +-----------------+
| pLocal +--------------> |
+--------------+ | |
| pIn (bb/oper) |
+----------------+ | |
| pIn (bb/oper) +------------> / |
+----------------+ | |
| pTarget (bb) |
+----------------+ | |
| pOut (bb/oper) +------------> |
+----------------+ +-----------------+
+------------------+ +-----------------+
| +-----------> pOut (bb/oper) |
| | +-----------------+
| pOut (bb/oper) |
| | +--------------+
| +-----------> pLocal |
+------------------+ +--------------+
```
如果链接的一个端点不在当前图形中,则此端点将创建为快捷方式。 但是如果链接的一个端点是当前分析的Building Graph的pIO并且与另一个端点具有相同的CK_ID则应创建一个eLink。
# 数据库
SuperScriptMaterializer处理流程里会涉及很多不同的数据库文件以下是这些数据库和其内表的格式。
其中这些是Materializer直接输出的基于文档的数据库
* doc.db
* env.db
这些数据库是上面数据库经过Decorator处理可以被Viewer接受的数据库
* decorated.db
* sheet.db
* query.db
* composition.db
## doc.db 格式
doc.db导出的是当前Virtools文档内的脚本及其它重要数据。
表列表:
- script文档里的每个脚本
- script_behaviorbehavior本身包括behavior graph和prototype behavior之类的
- script_bInbehavior的行为输入
- script_bOutbehavior的行为输出
- script_eLinkexport link
- script_pAttrattribute类型的parameter
- script_pInbehavior的parameter输入
- script_pLinkparameter link
- script_pLocallocal parameter
- script_pOperparameter operator
- script_pOutbehavior的parameter输出
- script_pTargetbehavior的target输入实际上是一个特殊的parameter输入
- msg文档内定义的message标号与数值的对应
- array文档里的每个CKDataArray
- array_headerCKDataArray的表头
- array_cellCKDataArray的数据体
- data文档中所有涉及导出的parameter参数属性以类似字典的形式存储每个parameter参数的各个部分
### script
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|脚本依附对象的`CK_ID`|
|name|TEXT|脚本依附对象的名字|
|index|INTEGER|脚本在依附对象的排序序号|
|behavior|INTEGER|真正的脚本Behavior的`CK_ID`|
### script_behavior
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|name|TEXT|当前对象的名字|
|type|INTEGER|`CKBehavior::GetType`|
|proto_name|TEXT|原型名称,没有原型则留空。`CKBehavior::GetPrototypeName`|
|proto_guid|TEXT|原型的GUID如果没有原型则填写`0,0`,格式为`guid1,guid2`用逗号分隔Virtools的GUID的两部分|
|flags|INTEGER|`CKBehavior::GetFlags`|
|priority|INTEGER|`CKBehavior::GetPriority`|
|version|INTEGER|`CKBehavior::GetVersion`|
|pin_count|TEXT|Behavior的接口个数由5部分组成`,`分隔分别代表pTarget, pIn, pOut, bIn, bOut|
|parent|INTEGER|当前对象父级Behavior的`CK_ID`如是顶层Behavior则填写-1|
### script_bIn / script_bOut
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|index|INTEGER|bIn/bOut在所属Behavior的次序号|
|name|TEXT|bIn/bOut名称|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
### script_bLink
|字段|类型|含义|
|:---|:---|:---|
|input|INTEGER|连线输入端的`CK_ID`,不能确认此`CK_ID``bOut`还是`bIn`,由于连线也可以是从`parent``bIn`连接到子元素的`bIn`|
|output|INTEGER|连线输出端的`CK_ID`,不能确认是`bOut`还是`bIn`,理由同上|
|delay|INTEGER|连线时延`CKBehaviorLink::GetActivationDelay()`|
|input_obj|INTEGER|输入端所属Behavior的`CK_ID`|
|input_type|INTEGER|指示输入端类型0为bIn1为bOut|
|input_index|INTEGER|指示连线位于输入端所在Behavior的第几个bIO口|
|output_obj|INTEGER|输出端所属Behavior的`CK_ID`|
|output_type|INTEGER|指示输出端类型0为bIn1为bOut|
|output_index|INTEGER|指示连线位于输出端所在Behavior的第几个bIO口|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
### script_eLink
|字段|类型|含义|
|:---|:---|:---|
|export_obj|INTEGER|需要被导出的`pIn``pOut``CK_ID`|
|internal_obj|INTEGER|导出连线中`pIn``pOut`所属Behavior中层次较深者的`CK_ID`|
|is_in|INTEGER|指示连线是对`pIn`还是`pOut`进行导出,如果是`pIn`则设置为1否则设置为0|
|index|INTEGER|导出连线`pIn``pOut`在所属Behavior中层次较深者中的参数序号|
|parent|INTEGER|导出连线中`pIn``pOut`所属Behavior中层次较浅者的`CK_ID`同时也就是导出连线所归属的Behavior的`CK_ID`|
导出连线eLink是一种将父级的pIn或pOut链接至器内部Behavior的pIn与pOut的连线。pIn只能链接pInpOut只能链接pOut。导出连线一旦链接完成则意味着两端的pIn或pOut将具有相同的`CK_ID`
### script_pAttr
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|name|TEXT|pAttr名称|
|type|TEXT|Attribute的类型名|
|type_guid|TEXT|Attribute类型的GUID|
### script_pIn
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|index|INTEGER|pIn在所属Behavior中的序号|
|name|TEXT|名称|
|type|TEXT|类型名|
|type_guid|TEXT|类型GUID|
|parent|INTEGER|当前对象所归属的Behavior或Operator的`CK_ID`|
|direct_source|INTEGER|`CKParameterIn::GetDirectSource()`|
|shared_source|INTEGER|`CKParameterIn::GetSharedSource()`|
### script_pLink
|字段|类型|含义|
|:---|:---|:---|
|input|INTEGER|pLink起点parameter的`CK_ID`|
|output|INTEGER|pLink终点parameter的`CK_ID`|
|input_obj|INTEGER|起点parameter所属behavior或operator的`CK_ID`|
|input_type|INTEGER|起点来源类型|
|input_is_bb|INTEGER|指示起点parameter所属是Behavior还是Operator如果是Behavior则填写为1否则为0|
|input_index|INTEGER|起点parameter所属Behavior的序号值|
|output_obj|INTEGER|终点parameter所属behavior或operator的`CK_ID`|
|output_type|INTEGER|终点来源类型|
|output_is_bb|INTEGER|指示终点parameter所属是Behavior还是Operator|
|output_index|INTEGER|终点parameter所属Behavior的序号值|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
`input_type``output_type`使用下列数值:
* pIn0
* pOut1
* pLocal2
* pTarget3
* pAttr4
当其值不是`pIn``pOut`中任何一个时,忽略对应输入或输出的`is_bb``index`值。
### script_pLocal
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|name|TEXT|名称|
|type|TEXT|类型名|
|type_guid|TEXT|类型GUID|
|is_setting|INTEGER|是否是所属Behavior的Setting调用所属Behavior的`CKBehavior::IsLocalParameterSetting()`|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
### script_pOper
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|op|TEXT|名称|
|op_guid|TEXT|Operator采用的转换函数的GUID|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
### script_pOut
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|index|INTEGER|在所属Behavior中的序号|
|name|TEXT|名称|
|type|TEXT|类型名|
|type_guid|TEXT|类型GUID|
|parent|INTEGER|当前对象所归属的Behavior或Operator的`CK_ID`|
### script_pTarget
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|name|TEXT|名称|
|type|TEXT|类型名|
|type_guid|TEXT|类型GUID|
|parent|INTEGER|当前对象所归属的Behavior的`CK_ID`|
|direct_source|INTEGER|`CKParameterIn::GetDirectSource()`|
|shared_source|INTEGER|`CKParameterIn::GetSharedSource()`|
`pIn`类似,仅缺少`index`描述因为对于一个BehaviorpTarget至多只能有1个。
### msg
|字段|类型|含义|
|:---|:---|:---|
|index|INTEGER|message的标号|
|name|TEXT|message的名称|
### array
|字段|类型|含义|
|:---|:---|:---|
|thisobj|INTEGER|当前对象的`CK_ID`|
|name|TEXT|表的名称|
|rows|INTEGER|表的行数|
|columns|INTEGER|表的列数|
### array_header
|字段|类型|含义|
|:---|:---|:---|
|index|INTEGER|当前表头的是第几列|
|name|TEXT|名称|
|type|INTEGER|列类型,`CKDataArray::GetColumnType`|
|param_type|TEXT|列的类型|
|param_type_guid|TEXT|列的类型的GUID|
|parent|INTEGER|表头所属表的`CK_ID`|
当列类型为Parameter时`param_type``param_type_guid`为其所属CKParameterType的类型文本和GUID当列类型为Object时`param_type``param_type_guid`均无效因为无法确认对应CKObject的类型。列类型为其它类型时`param_type``param_type_guid`也均无效。
### array_cell
|字段|类型|含义|
|:---|:---|:---|
|row|INTEGER|当前单元格所在行|
|column|INTEGER|当前单元格所在列|
|showcase|TEXT|单元格可视化文本|
|inner_param|INTEGER|单元格内部数据为对应CKParameter或CKObject的`CK_ID`|
|parent|INTEGER|单元格所属表的`CK_ID`|
当且仅当对应列的类型为Parameter或Object时`inner_param`才有效。
### data
|字段|类型|含义|
|:---|:---|:---|
|field|TEXT|键值对的键|
|data|TEXT|键值对的值|
|parent|INTEGER|键值对所描述对象的`CK_ID`|
## env.db 格式
env.db导出的是当前Virtools环境的数据与文档无关这部分如果是多个文件共用一个环境那么只需要导出和在`Decorator`里综合一次即可
表列表:
- attrattribute
- opoperatorparameter转换的定义
- paramparameter的定义
- plugin当前环境插件
- variable全局变量数据
### attr
|字段|类型|含义|
|:---|:---|:---|
|index|INTEGER|序号,总数由`CKAttributeManager::GetAttributeCount()`获取|
|name|TEXT|`CKAttributeManager::GetAttributeNameByType()`|
|category_index|INTEGER|`CKAttributeManager::GetAttributeCategoryIndex()`|
|category_name|TEXT|`CKAttributeManager::GetAttributeCategory()`|
|flags|INTEGER|`CKAttributeManager::GetAttributeFlags()`|
|param_index|INTEGER|`CKAttributeManager::GetAttributeParameterType()`|
|compatible_classid|INTEGER|`CKAttributeManager::GetAttributeCompatibleClassId()`|
|default_value|TEXT|`CKAttributeManager::GetAttributeDefaultValue()`|
### op
|字段|类型|含义|
|:---|:---|:---|
|funcptr|INTEGER|`CKOperationDesc::Fct`|
|in1_guid|TEXT|`CKOperationDesc::P1Guid`|
|in2_guid|TEXT|`CKOperationDesc::P2Guid`|
|out_guid|TEXT|`CKOperationDesc::ResGuid`|
|op_guid|TEXT|`CKParameterManager::OperationCodeToGuid()`|
|op_name|TEXT|`CKParameterManager::OperationCodeToName`|
|op_code|INTEGER|序号,总数由`CKParameterManager::GetParameterOperationCount()`获取|
### param
|字段|类型|含义|
|:---|:---|:---|
|index|INTEGER|`CKParameterTypeDesc::Index`|
|guid|TEXT|`CKParameterTypeDesc::Guid`|
|derived_from|TEXT|`CKParameterTypeDesc::DerivedFrom`|
|type_name|TEXT|`CKParameterTypeDesc::TypeName`|
|default_size|INTEGER|`CKParameterTypeDesc::DefaultSize`|
|func_CreateDefault|INTEGER|`CKParameterTypeDesc::CreateDefaultFunction`|
|func_Delete|INTEGER|`CKParameterTypeDesc::DeleteFunction`|
|func_SaveLoad|INTEGER|`CKParameterTypeDesc::SaveLoadFunction`|
|func_Check|INTEGER|`CKParameterTypeDesc::CheckFunction`|
|func_Copy|INTEGER|`CKParameterTypeDesc::CopyFunction`|
|func_String|INTEGER|`CKParameterTypeDesc::StringFunction`|
|func_UICreator|INTEGER|`CKParameterTypeDesc::UICreatorFunction`|
|creator_dll_index|INTEGER|`CKParameterTypeDesc::CreatorDll``CKPluginEntry::m_PluginDllIndex`|
|creator_plugin_index|INTEGER|`CKParameterTypeDesc::CreatorDll``CKPluginEntry::m_PositionInDll`|
|dw_param|INTEGER|`CKParameterTypeDesc::dwParam`|
|dw_flags|INTEGER|`CKParameterTypeDesc::dwFlags`|
|cid|INTEGER|`CKParameterTypeDesc::Cid`|
|saver_manager|TEXT|`CKParameterTypeDesc::Saver_Manager`|
### plugin
|字段|类型|含义|
|:---|:---|:---|
|dll_index|INTEGER|`CKPluginEntry::m_PluginDllIndex`|
|dll_name|TEXT|以`CKPluginEntry::m_PluginDllIndex`为参,使用`CKPluginManager::GetPluginDllInfo()`,获得的`CKPluginDll::m_DllFileName`|
|plugin_index|INTEGER|`CKPluginEntry::m_PositionInDll`|
|active|INTEGER|`CKPluginEntry::m_Active`|
|guid|TEXT|`CKPluginEntry::m_PluginInfo``CKPluginInfo::m_GUID`|
|desc|TEXT|`CKPluginEntry::m_Description`|
|author|TEXT|`CKPluginEntry::m_Author`|
|summary|TEXT|`CKPluginEntry::m_Summary`|
|version|INTEGER|`CKPluginEntry::m_Version`|
|func_init|INTEGER|`CKPluginEntry::m_InitInstanceFct`|
|func_exit|INTEGER|`CKPluginEntry::m_ExitInstanceFct`|
### variable
|字段|类型|含义|
|:---|:---|:---|
|name|TEXT|`CKVariableManager::Iterator::GetName()`|
|description|TEXT|`CKVariableManager::Variable::GetDescription()`|
|flags|INTEGER|`CKVariableManager::Variable::GetFlags()`|
|type|INTEGER|`CKVariableManager::Variable::GetType()`|
|representation|TEXT|`CKVariableManager::Variable::GetRepresentation()`|
|data|TEXT|`CKVariableManager::Variable::GetStringValue()`|
## composition.db 格式
composition.db是`Decorator`输出的所有被综合的文档与接下来三个数据库分别的内部的编号的的对应表为每一个被综合的数据库分配一个编号但是因为有些部分文档共用一个Virtools环境等就需要将这些编号转换成共用的
使用此表是为了保证网页URL基于编号的命名方式可以在三个表中正常通行而不会出现在这个表中的编号在另一个表里指示的是另一个Virtools文件。
因此在查询其他数据库前需要先读取此数据库获得对应各个数据库的内部编号,进而在剩下的数据库中以内部编号继续查询。
表只有一个composition。
## decorated.db 格式
decorated.db是`Decorator`输出的脚本综合的数据库,包含了所有脚本的连线和图形位置。
表列表:
- blockbehavior的图形结构
- cell类似local parameter的结构
- graph脚本schematic图形
- link脚本内的所有连线
- param脚本里的parameter的数据
### block
|字段|类型|含义|
|:---|:---|:---|
|parent_graph|INTEGER||
|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||
### cell
|字段|类型|含义|
|:---|:---|:---|
|parent_graph|INTEGER||
|thisobj|INTEGER||
|name|TEXT||
|assist_text|TEXT||
|x|REAL||
|y|REAL||
|type|INTEGER||
### graph
|字段|类型|含义|
|:---|:---|:---|
|graph|INTEGER||
|graph_name|TEXT||
|width|INTEGER||
|height|INTEGER||
|index|INTEGER||
|parent|TEXT||
### param
param为原来的info
|字段|类型|含义|
|:---|:---|:---|
|target|INTEGER||
|attach_bb|INTEGER||
|is_setting|INTEGER||
|name|TEXT||
|field|TEXT||
|data|TEXT||
### link
|字段|类型|含义|
|:---|:---|:---|
|parent_graph|INTEGER||
|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||
## sheet.db 格式
sheet.db是`Decorator`输出的文档数据综合的数据库,包含了所有脚本的连线和图形位置。
表列表:
- data同下
- header同下
- body同下
- param与data.db几乎一致
## query.db 格式
query.db是`Decorator`输出的数据查询综合的数据库包含了所有脚本内的数据部分还有Virtools环境的可查询数据。
表列表:
- msg从data.db - msg综合
- attr同下
- op同下
- param同下
- plugin同下
- variable从env.db综合

View File

@@ -1,2 +0,0 @@
Ballance/vt2obj "example.nmo" "export.db" "env.db"
"Ballance/vt2obj mirror" Gameplay.nmo export.db env.db

View File

@@ -0,0 +1,53 @@
# Check build environment
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/check_materializer_env.cmake)
# Import virtools sdk
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/custom_import_virtools.cmake)
# Create library or executable according to build type
if (VSW_MATERIALIZER_BUILD_TYPE STREQUAL "plugin")
add_library(VSWMaterializer STATIC "")
else ()
add_executable(VSWMaterializer "")
endif ()
# Setup static library sources
target_sources(VSWMaterializer
PRIVATE
# Sources
main.cpp
)
target_sources(VSWMaterializer
PUBLIC
FILE_SET HEADERS
FILES
# Headers
stdafx.hpp
resources.h
)
# Setup header infomations
target_include_directories(VSWMaterializer
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
# Setup C++ standard
set_target_properties(VSWMaterializer
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# MSVC specific correction
target_compile_definitions(VSWMaterializer
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
target_compile_options(VSWMaterializer
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)
# Install binary and headers
install(TARGETS VSWMaterializer
CONFIGURATIONS Release
RUNTIME DESTINATION ${VSW_INSTALL_BIN_PATH}
)

0
materializer/main.cpp Normal file
View File

0
materializer/stdafx.hpp Normal file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 KiB

View File

@@ -1,331 +0,0 @@
import vs_props_writer, vs_vcxproj_modifier
import os, enum, sys, argparse
#region Constant Declarations
class BuildType(enum.Enum):
Standalone: str = "standalone"
Plugin: str = "plugin"
class VirtoolsVersion(enum.Enum):
V21 = '21'
V25 = '25'
V30 = '30'
V35 = '35'
V40 = '40'
V50 = '50'
VT_HEADER_PATH: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: 'Include',
VirtoolsVersion.V25: 'Virtools_SDK\\Includes',
VirtoolsVersion.V30: 'Sdk\\Includes',
VirtoolsVersion.V35: 'Sdk\\Includes',
VirtoolsVersion.V40: 'Sdk\\Includes',
VirtoolsVersion.V50: 'Sdk\\Includes'
}
VT_LIB_PATH: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: 'Lib',
VirtoolsVersion.V25: 'Virtools_SDK\\Lib',
VirtoolsVersion.V30: 'Sdk\\Lib',
VirtoolsVersion.V35: 'Sdk\\Lib\\Win32\\Release',
VirtoolsVersion.V40: 'Sdk\\Lib\\Win32\\Release',
VirtoolsVersion.V50: 'Sdk\\Lib\\Win32\\Release'
}
VT_STANDALONE_ATTACHED_LIBS: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: "VxMath.lib;CK2.lib",
VirtoolsVersion.V25: "VxMath.lib;CK2.lib",
VirtoolsVersion.V30: "VxMath.lib;CK2.lib",
VirtoolsVersion.V35: "VxMath.lib;CK2.lib",
VirtoolsVersion.V40: "VxMath.lib;CK2.lib",
VirtoolsVersion.V50: "VxMath.lib;CK2.lib"
}
VT_PLUGIN_ATTACHED_LIBS: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: "",
VirtoolsVersion.V25: "",
VirtoolsVersion.V30: "VxMath.lib;DllEditor.lib;CK2.lib;InterfaceControls.lib;CKControls.lib",
VirtoolsVersion.V35: "VxMath.lib;DllEditor.lib;CK2.lib;InterfaceControls.lib;CKControls.lib",
VirtoolsVersion.V40: "VxMath.lib;DllEditor.lib;CK2.lib;InterfaceControls.lib;CKControls.lib",
VirtoolsVersion.V50: "VxMath.lib;DllEditor.lib;CK2.lib;InterfaceControls.lib;CKControls.lib"
}
VT_PLUGIN_MACROS: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE",
VirtoolsVersion.V25: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE",
VirtoolsVersion.V30: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE",
VirtoolsVersion.V35: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE",
VirtoolsVersion.V40: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE",
VirtoolsVersion.V50: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE"
}
VT_STANDALONE_MACROS: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V21: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG",
VirtoolsVersion.V25: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG",
VirtoolsVersion.V30: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG",
VirtoolsVersion.V35: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG",
VirtoolsVersion.V40: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG",
VirtoolsVersion.V50: "_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_DEBUG;VIRTOOLS_USER_SDK"
}
VT_PLUGIN_SUPPORTED_VER: set[VirtoolsVersion] = set((
VirtoolsVersion.V30,
VirtoolsVersion.V35,
VirtoolsVersion.V40,
VirtoolsVersion.V50,
))
VT_STANDALONE_SUPPORTED_VER: set[VirtoolsVersion] = set((
VirtoolsVersion.V21,
VirtoolsVersion.V25,
VirtoolsVersion.V30,
VirtoolsVersion.V35,
VirtoolsVersion.V40,
VirtoolsVersion.V50,
))
VT_EXECUTABLE_DEV: dict[VirtoolsVersion, str] = {
VirtoolsVersion.V25: "Dev.exe",
VirtoolsVersion.V30: "devr.exe",
VirtoolsVersion.V35: "devr.exe",
VirtoolsVersion.V40: "devr.exe",
VirtoolsVersion.V50: "devr.exe"
}
#endregion
#region Assist Functions
def get_project_root() -> str:
# build project root path and return
return os.path.dirname(os.path.dirname(__file__))
def check_project_root() -> None:
"""
Check whether this script is executed in correct folder.
If check failed, this function will exit script, otherwise, return directly.
"""
project_root: str = get_project_root()
# check whether have readme file
if not os.path.isfile(os.path.join(project_root, 'README.md')):
print('Fail to get project root folder. This script may be placed at wrong location.')
sys.exit(1)
def validate_combination(build_type: BuildType, vt_version: VirtoolsVersion) -> None:
"""
Check whether the given combination of build type and Virtools version is OK.
Some combination of build type and Virtools version is invalid.
For example, because Virtools 2.5 do not have UI register so plugin build type is not available in Virtools 2.1
If validation failed, this function will exit script, otherwise, return directly.
"""
# fetch result
is_okey: bool
match(build_type):
case BuildType.Standalone:
is_okey = vt_version in VT_STANDALONE_SUPPORTED_VER
case BuildType.Plugin:
is_okey = vt_version in VT_PLUGIN_SUPPORTED_VER
# output result
if not is_okey:
print(f'The combination of "{build_type.value}" and "{vt_version.value}" is not compatible currently.')
sys.exit(1)
def ensure_trailing_slash(given_path: str) -> str:
"""
Ensure given path is end with slash or backslash.
@param given_path The path for checking.
@return The path with trailing slash or backslash,
or the given path self if it already has.
"""
# make sure return value is end with slash or backslash
if given_path[-1] != '\\' or given_path[-1] != '/':
return given_path + '\\'
else:
return given_path
def get_header_path(vt_version: VirtoolsVersion, vt_root: str) -> str:
return os.path.join(vt_root, VT_HEADER_PATH[vt_version])
def get_lib_path(vt_version: VirtoolsVersion, vt_root: str) -> str:
return os.path.join(vt_root, VT_LIB_PATH[vt_version])
def get_attached_libs(build_type: BuildType, vt_version: VirtoolsVersion) -> str:
match(build_type):
case BuildType.Standalone:
return VT_STANDALONE_ATTACHED_LIBS[vt_version]
case BuildType.Plugin:
return VT_PLUGIN_ATTACHED_LIBS[vt_version]
def get_macros(build_type: BuildType, vt_version: VirtoolsVersion) -> str:
match(build_type):
case BuildType.Standalone:
return VT_STANDALONE_MACROS[vt_version]
case BuildType.Plugin:
return VT_PLUGIN_MACROS[vt_version]
def get_executable_dev(vt_version: VirtoolsVersion, vt_root: str) -> str:
"""
Return the path to executable Virtools Dev according to given Virtools version.
Usually it is `Dev.exe` or `devr.exe`.
@param vt_version The version of Virtools.
@param vt_root The path to Virtools root folder.
@return The path to executable Virtools Dev.
"""
return os.path.join(vt_root, VT_EXECUTABLE_DEV[vt_version])
def get_output_path(build_type: BuildType, vt_root: str) -> str:
"""
Get the output path for plugin.
For plugin build type, script will try output binary into `InterfacePlugins` folder in Virtools environment.
For standalone build type, script will try output binary in the root path of Virtools.
@param vt_version The version of Virtools.
@param vt_root The path to Virtools root folder.
@return The path where the compiled project binary will be placed.
"""
# fetch output path by build type
ret: str
match(build_type):
case BuildType.Standalone:
ret = vt_root
case BuildType.Plugin:
ret = os.path.join(vt_root, 'InterfacePlugins')
# make sure return value is end with slash or backslash
return ensure_trailing_slash(ret)
def get_binary_suffix(build_type: BuildType) -> str:
match(build_type):
case BuildType.Standalone:
return 'exe'
case BuildType.Plugin:
return 'dll'
def get_module_define(build_type: BuildType) -> str:
match(build_type):
case BuildType.Standalone:
return ''
case BuildType.Plugin:
return 'SuperScriptMaterializer.def'
#endregion
def main() -> None:
# ========== Check Environment ==========
check_project_root()
# ========== Accept User Input ==========
# build args parser
parser = argparse.ArgumentParser(description='Project Configuration Maker')
parser.add_argument(
'-b', '--build-type', required=True, action='store', dest='build_type', choices=tuple(item.value for item in BuildType),
help='The build type of project.'
)
parser.add_argument(
'-t', '--virtools-version', required=True, action='store', dest='virtools_version', choices=tuple(item.value for item in VirtoolsVersion),
help='The Virtools version you picked.'
)
parser.add_argument(
'-p', '--virtools-path', required=True, action='store', dest='virtools_path',
help='''
The path to the root folder of you picked Virtools version where you can find "Dev.exe".
If you select Virtools 2.1, this path should be the root folder of GitHub project "doyaGu/Virtools-SDK-2.1".
'''
)
parser.add_argument(
'-a', '--sqlite-amalgamation-path', required=True, action='store', dest='sqlite_amalgamation_path',
help='The path to downloaded sqlite amalgamation folder where you can find "sqlite3.h"'
)
parser.add_argument(
'-d', '--sqlite-dll-path', required=True, action='store', dest='sqlite_dll_path',
help='The path to downloaded sqlite dll folder where you can find "sqlite3.dll" and "sqlite3.lib" you just built a few minutes ago.'
)
# parse arguments
args = parser.parse_args()
# ========== Analyse Arguments ==========
# extract arguments
arg_virtools_version: VirtoolsVersion = VirtoolsVersion(args.virtools_version)
arg_build_type: BuildType = BuildType(args.build_type)
arg_virtools_path: str = args.virtools_path
arg_sqlite_amalgamation_path: str = args.sqlite_amalgamation_path
arg_sqlite_dll_path: str = args.sqlite_dll_path
# validate the combination
validate_combination(arg_build_type, arg_virtools_version)
# build macros values
# virtools version and build type macro
macro_virtools_ver: str = f'VIRTOOLS_{arg_virtools_version.value}'
macro_virtools_build_type: str = f'VIRTOOLS_{arg_build_type.value.upper()}'
# virtools header and lib
macro_virtools_header_path: str = get_header_path(arg_virtools_version, arg_virtools_path)
macro_virtools_lib_path: str = get_lib_path(arg_virtools_version, arg_virtools_path)
macro_virtools_attcahed_libs: str = get_attached_libs(arg_build_type, arg_virtools_version)
# sqlite header and lib
macro_sqlite_header_path: str = arg_sqlite_amalgamation_path
macro_sqlite_lib_path: str = arg_sqlite_dll_path
# output path macro
macro_virtools_output_path: str = get_output_path(arg_build_type, arg_virtools_path)
# virtools used macros
macro_virtools_macros: str = get_macros(arg_build_type, arg_virtools_version)
# misc
macro_virtools_binary_suffix: str = get_binary_suffix(arg_build_type)
macro_virtools_module_define: str = get_module_define(arg_build_type)
# ========== Create Property File ==========
props = vs_props_writer.VsPropsWriter()
# write subsystem
match(arg_build_type):
case BuildType.Standalone:
props.SetSubSystem(vs_props_writer.VsSubSystem.Console)
case BuildType.Plugin:
props.SetSubSystem(vs_props_writer.VsSubSystem.Windows)
# write macro and misc
# build type distinguish macro
props.AddMacro('VIRTOOLS_VER', macro_virtools_ver)
props.AddMacro('VIRTOOLS_BUILD_TYPE', macro_virtools_build_type)
# header and libs
props.AddMacro('VIRTOOLS_HEADER_PATH', macro_virtools_header_path)
props.AddMacro('VIRTOOLS_LIB_PATH', macro_virtools_lib_path)
props.AddMacro('VIRTOOLS_ATTACHED_LIBS', macro_virtools_attcahed_libs)
props.AddMacro('SQLITE_HEADER_PATH', macro_sqlite_header_path)
props.AddMacro('SQLITE_LIB_PATH', macro_sqlite_lib_path)
# output
props.AddMacro('VIRTOOLS_OUTPUT_PATH', macro_virtools_output_path)
# essential build macro
props.AddMacro('VIRTOOLS_MACROS', macro_virtools_macros)
# misc macro
props.AddMacro('VIRTOOLS_BINARY_SUFFIX', macro_virtools_binary_suffix)
props.AddMacro('VIRTOOLS_MODULE_DEFINE', macro_virtools_module_define)
# output
props.Generate(os.path.join(get_project_root(), 'Virtools.props'))
# ========== Modify ==========
vcxproj = vs_vcxproj_modifier.VsVcxprojModifier(
os.path.join(get_project_root(), 'SuperScriptMaterializer/SuperScriptMaterializer.vcxproj')
)
# write build type
match(arg_build_type):
case BuildType.Standalone:
vcxproj.SetBuildType(vcxproj.BUILDTYPE_EXE)
case BuildType.Plugin:
vcxproj.SetBuildType(vcxproj.BUILDTYPE_DLL)
# output
vcxproj.Modify()
# ========== Done ==========
print("Configuration OK!")
if __name__ == '__main__':
main()

View File

@@ -1,80 +0,0 @@
import xml.dom.minidom as minidom
import enum, os, sys
class VsSubSystem(enum.Enum):
Windows = 'Windows'
Console = 'Console'
class VsPropsWriter():
__mMacroList: dict[str, str]
__mSubSystem: VsSubSystem
def __init__(self):
self.__mMacroList = {}
self.__mSubSystem = VsSubSystem.Windows
def AddMacro(self, key: str, value: str):
if key in self.__mMacroList:
raise Exception(f'Duplicated Set Macro "{key}".')
self.__mMacroList[key] = value
def SetSubSystem(self, subsys: VsSubSystem):
self.__mSubSystem = subsys
def Generate(self, filename: str):
# create some header
document = minidom.getDOMImplementation().createDocument(None, 'Project', None)
root: minidom.Element = document.documentElement
root.setAttribute('ToolsVersion', '4.0')
root.setAttribute('xmlns', 'http://schemas.microsoft.com/developer/msbuild/2003')
cache = document.createElement('ImportGroup')
cache.setAttribute('Label', 'PropertySheets')
root.appendChild(cache)
# write sub system
for bt in ('Debug', 'Release'):
node_IDG = document.createElement('ItemDefinitionGroup')
node_IDG.setAttribute('Condition', f"'$(Configuration)|$(Platform)'=='{bt}|Win32'")
node_link = document.createElement('Link')
node_sub_system = document.createElement('SubSystem')
node_sub_system.appendChild(document.createTextNode(self.__mSubSystem.value))
node_link.appendChild(node_sub_system)
node_IDG.appendChild(node_link)
root.appendChild(node_IDG)
# write macro
node_PG = document.createElement('PropertyGroup') # macro node 1
node_PG.setAttribute('Label', 'UserMacros')
root.appendChild(node_PG)
cache = document.createElement('PropertyGroup') # dummy structure
root.appendChild(cache)
cache = document.createElement('ItemDefinitionGroup') #dummy structure
root.appendChild(cache)
node_IG = document.createElement('ItemGroup') # macro node 2
root.appendChild(node_IG)
for key, value in self.__mMacroList.items():
# create for PropertyGroup
node_macro_decl = document.createElement(key)
if value != '': # check whether data is empty.
node_macro_decl.appendChild(document.createTextNode(value))
node_PG.appendChild(node_macro_decl)
# create for ItemGroup
node_macro_ref = document.createElement("BuildMacro")
node_macro_ref.setAttribute('Include', key)
node_inner_macro_ref = document.createElement('Value')
node_inner_macro_ref.appendChild(document.createTextNode("$({})".format(key)))
node_macro_ref.appendChild(node_inner_macro_ref)
node_IG.appendChild(node_macro_ref)
# write to file
with open(filename, 'w', encoding='utf-8') as f:
document.writexml(f, addindent='\t', newl='\n', encoding='utf-8')

View File

@@ -1,51 +0,0 @@
import xml.dom.minidom as minidom
import xml.dom
import os
import sys
class VsVcxprojModifier():
BUILDTYPE_EXE: str = 'Application'
BUILDTYPE_DLL: str = 'DynamicLibrary'
def __init__(self, vcfile: str):
self.__Dom = minidom.parse(vcfile)
self.__FileName: str = vcfile
self.__BuildType: str = None
def SetBuildType(self, bt: str):
self.__BuildType = bt
def Modify(self):
# if no spec build type, do not modify
if self.__BuildType is None:
return
# get corresponding entry
dom = self.__Dom
node_project = dom.documentElement
for node_PG in node_project.getElementsByTagName('PropertyGroup'):
attr_label = node_PG.getAttribute('Label')
attr_condition = node_PG.getAttribute('Condition')
# skip invalid node
if attr_label != 'Configuration':
continue
if attr_condition != "'$(Configuration)|$(Platform)'=='Debug|Win32'" and attr_condition != "'$(Configuration)|$(Platform)'=='Release|Win32'":
continue
# this is valid node, process it
node_CT = node_PG.getElementsByTagName('ConfigurationType')
if len(node_CT) != 0:
# have node, change it
node_CT[0].childNodes[0].nodeValue = self.__BuildType
else:
# don't have node, add one
node_CT = dom.createElement('ConfigurationType')
node_CT.appendChild(dom.createTextNode(self.__BuildType))
node_PG.appendChild(node_CT)
# write file
with open(self.__FileName, 'w', encoding='utf-8') as f:
dom.writexml(f, encoding='utf-8')

37
shared/CMakeLists.txt Normal file
View File

@@ -0,0 +1,37 @@
# Create static library
add_library(VSWShared STATIC "")
# Setup source files
target_sources(VSWShared
PRIVATE
# Sources
)
# Setup header files
target_sources(VSWShared
PUBLIC
FILE_SET HEADERS
FILES
# Headers
DataTypes.hpp
)
# Setup include directory
target_include_directories(VSWShared
PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)
# Setup C++ standard
set_target_properties(VSWShared
PROPERTIES
CXX_STANDARD 20
CXX_STANDARD_REQUIRED 20
CXX_EXTENSION OFF
)
# MSVC specific correction
target_compile_definitions(VSWShared
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:UNICODE>
$<$<CXX_COMPILER_ID:MSVC>:_UNICODE>
)
target_compile_options(VSWShared
PRIVATE
$<$<CXX_COMPILER_ID:MSVC>:/utf-8>
)

0
shared/DataTypes.hpp Normal file
View File